/**
 * The two rule LANES' answers — the org overlay's and the person's persisted rules' — screened and read for one
 * call, shared by every consumer that judges a call against them (the live gate's lane station, the resumed
 * execution boundary, the synthetic-Read judge). One normalizer and one bounded read per lane: a second copy of
 * either would be a second answer to "what did the lane say", and the gate's fail-closed (org) / skip
 * (persisted store) readings would drift apart between consumers.
 */
import type { ToolCallRequest } from "./tool-policy.js";
import type { OrgGateVerdict, PersistedRuleAnswer, PersistedRuleHit } from "./hooks.js";
/**
 * design/252 review r3 — read a foreign {@link OrgGateVerdict} the way the personal-rule answer is read:
 * OWN DATA properties only, never the prototype chain, never an accessor.
 *
 * Unlike the personal-rule normalizer below, this one accepts ANY non-array object as the carrier —
 * not only a plain record. The two seams tighten in opposite directions when a shape is refused: the
 * personal lane is a LOOSENING seam, so refusing a class instance degrades toward asking; this answer
 * carries the org's DENY, and folding a structurally valid `{status:"available", verdict:{behavior:
 * "deny"}}` class instance into `unavailable` would LOOSEN it — from a deny nobody can approve into a
 * real-approval ask a person can clear. A class instance's fields are its own data properties, so the
 * own-data read below already gives the full pollution guarantee (inherited members never authorize);
 * the prototype test added nothing here but the downgrade.
 *
 * The two seams are the same class of trust boundary and were not being read the same way. What that
 * cost here is worse than on the personal lane, because this answer is GOVERNANCE:
 *  · an inherited `revision` (a polluted `Object.prototype`) stamped a fabricated snapshot version onto
 *    a human's approval request — a WRONG record, which is worse than an absent one;
 *  · an inherited `verdict` invented an org rule, and with it an org ask or deny the lane never gave;
 *  · an answer that is not a record at all read as "available, nothing to say", i.e. the governance
 *    fail-open the availability contract exists to prevent.
 * Anything this function cannot read as a well-formed answer becomes `unavailable` — the fail-CLOSED
 * word, never the empty one.
 */
export declare function normalizeOrgGateVerdict(answer: unknown, unreadable: string): OrgGateVerdict;
/**
 * Normalize the accepted {@link ToolGateInput.persistedRules} answers into one reading.
 *
 * `{}` = a clean negative (no rule admits this call). `{ unreadable: true }` = the lane could not read
 * its source. `{ hit }` = a match, whose `rules` is the non-empty coverage set (design/375). An answer
 * outside every accepted shape — a number, `null`, an object with neither `rules` nor `unreadable`, an
 * EMPTY `rules` array, the retired pre-375 `{ rule, dots? }` single-rule object — is read as a clean
 * negative rather than a match: this is a LOOSENING seam, so an answer nobody can name degrades toward
 * asking, never toward an allow built on it. All-or-nothing across the set's TEXTS for the same
 * reason: a set with one unreadable member is a different (smaller) claim than the lane made, and a
 * decision must not stand on a claim nobody made — one bad member drops the whole answer to the clean
 * negative. Per-member DOTS stay individually optional (identity lost ⇒ `"not_reported"`, exactly the
 * single-rule contract).
 *
 * The hit's dots are COPIED, not aliased. The array travels onto an ask that may sit in front of a
 * person for a long time; a lane that retains and mutates its own array would otherwise change what the
 * approver is looking at, and what an audit later reads, after the evidence was stamped.
 */
export declare function normalizePersistedRuleHit(hit: PersistedRuleAnswer): {
    hit?: PersistedRuleHit;
    unreadable?: true;
    reason?: string;
    coverage?: readonly import("./permission-rule-model.js").SegmentCoverage[];
};
/**
 * The ORG lane's one read for one call — every consumer's (the live gate's org layer, the synthetic-Read
 * judge). The CALL is inside the boundary (a synchronous throw — a non-function face, a revoked proxy —
 * happens before any `.catch` on its result could be installed), it is invoked directly (a lane that reads
 * its own state before its first `await` sees the same turn), it is BOUNDED by the dependency timeout and
 * the signal, and everything that is not a well-formed answer — a throw, a hang, a garbage value — reads
 * as `unavailable`, the fail-closed word, never as "no org rule spoke".
 */
export declare function readOrgRuleLane(org: {
    adjudicate: (req: ToolCallRequest) => Promise<OrgGateVerdict>;
}, req: ToolCallRequest, signal: AbortSignal | undefined, timeoutMs?: number): Promise<OrgGateVerdict>;
/**
 * The persisted-rule lane's one read for one call — every consumer's (the live gate, the synthetic-Read
 * judge), normalized once. A lane that throws, hangs past the dependency timeout, or answers something
 * unreadable is a lane that could not answer: for the DECISION its rows take no part (the tightening arms
 * do not fire — `applyPersistedTightening` reads `{ unreadable }` without a reason that way), and for
 * the RECORD it is `"unavailable"`. A call the lane could not read against the rows (`reason`) fails closed
 * in the arms. Absent lane ⇒ the clean negative.
 */
export declare function readPersistedRuleLane(lane: {
    adjudicate: (req: ToolCallRequest) => PersistedRuleAnswer | Promise<PersistedRuleAnswer>;
} | undefined, req: ToolCallRequest, signal: AbortSignal | undefined, timeoutMs?: number): Promise<{
    hit?: PersistedRuleHit;
    unreadable?: true;
    reason?: string;
    coverage?: readonly import("./permission-rule-model.js").SegmentCoverage[];
}>;
