/**
 * The synthetic-call judge — "would this call be refused outright?", asked without a model call, without an
 * approver and without a hook. One judge, one set of layers, for every consumer that needs the answer for a file the
 * model did not itself ask to touch. It has TWO FACES over one body (the layer walk below is written once):
 *
 *   READ  — a `Read` of a file the model did not ask for (the changed-file notice; a user's attachment). An ordinary
 *           `ask` — a person's own ask rule — is not a refusal: the person who would answer it is the one asking.
 *   WRITE — a `Write` of a path the engine itself writes in the background (the memory consolidation run). Every `ask`
 *           is an objection here: nobody is present to answer it, so a layer that would ask a person refuses the write.
 *
 * It never picks a direction. The read face answers in FOUR states:
 *
 *   deny          — some layer refuses it;
 *   mandated_ask  — no layer refuses it, and some layer would put the read to a person no rule may answer for
 *                   (the ask's own mandate reading, {@link ruleClearanceOf}: a real-approval demand, the deployment's
 *                   own question, an ancestor's, a hook's; or an organization rule's ask) — the person who must
 *                   answer is not necessarily the one asking;
 *   no_objection  — every layer it consulted answered and none objected;
 *   unanswerable  — no layer objected, and at least one could not answer (see the table below).
 *
 * The write face answers the same four, with `ask` in place of `mandated_ask`: any layer's ask, mandated or not.
 *
 * ONE PRECEDENCE on both faces: a deny anywhere wins over a held ask, and a held ask over an unanswerable layer; the walk
 * goes on past an ask (a later layer's deny is the stronger answer). The faces differ only in which asks are held. The
 * CONSUMER decides where `mandated_ask` and `unanswerable` go: a notice that merely tells the model a file changed reads
 * both as no objection (the worst case is a notice about a file it then cannot re-read); a face that would put a file's
 * contents in front of the model reads both as a refusal; a background write reads everything but `no_objection` as a
 * refusal. Every answer but `unanswerable` names the location the layers judged (`judged`, the canonical view of the
 * stamped target, when a stamp was taken), so a consumer that resolved the file itself can tell the judged file from the
 * one it opens.
 *
 * THE LAYERS (every one that can refuse a model's own call): the run's skill deny rows; the
 * deny-narrowing fold (session rules, inherited ancestor rules, frozen constraint projections); the
 * deployment's caller policy; each live inherited parent policy; the person's persisted-rule lane; the org
 * lane. Not consulted, by design: PreToolUse hooks (the deployment's screening of a model's CALL), the permission mode's write
 * gate, the integrity guards and the write-protection table (a live `Write` meets them; the read face never needs them and the
 * write face's background run is not asked), and the read-deny table and containment roots (the path's own resolution judges those first).
 *
 * FAULT → STATE (the live gate's own readings, through the same functions — never a second copy):
 *   | layer                       | fault                                                | state                         |
 *   | skill rows                  | throws                                               | unanswerable `threw`          |
 *   | narrowing fold              | throws / exceeds the judgment's budget               | unanswerable `threw`/`timed_out` |
 *   | caller / inherited policy   | throws / times out                                   | unanswerable `threw`/`timed_out` |
 *   | caller / inherited policy   | its deny carries an engine settlement (an approval   | unanswerable `approval_seat`  |
 *   |                             | seat that ended unanswered; in a combinePolicies     |                               |
 *   |                             | composition a rule deny anywhere is returned instead)|                               |
 *   | persisted lane              | a store partition (or all of it) is unreadable, the lane throws, times out (readPersistedRuleLane ⇒ `{unreadable}`) | unanswerable `store_unreadable` (both faces: a row nobody could read may forbid the call) |
 *   | persisted lane              | the call cannot be read against the rows (`reason`) — applyPersistedTightening ⇒ `unreadable` | unanswerable `call_unreadable` |
 *   | org lane                    | unavailable: throws, garbage (readOrgRuleLane)       | unanswerable `org_unavailable` |
 *   | any policy layer            | answers with a rewrite of the arguments (`updatedInput`) | unanswerable `rewritten`  |
 *   | inherited parent policy     | answers `ask` (the ancestor's approver's question)    | mandated_ask (write: ask)     |
 *   | any layer                   | the judgment's budget (one dependency timeout, or a  | unanswerable `timed_out`      |
 *   |                             | batch's shared deadline) is spent                    |                               |
 *
 * NEVER AN APPROVER. Every probe STATES that nobody can be asked about it — `approvalReach: "none"` on the request
 * (`ToolCallRequest.approvalReach`) — and every policy layer is handed a LIVE signal of its own: it ends when the judge stops
 * waiting for that layer (the layer answered, or its share of the judgment's budget is spent) or when the run's signal ends.
 * An abort means only that: the task ended, or the judge no longer waits — never "there is no approver". Every engine
 * policy factory reads the statement before reaching a seat (the approval factory answers a deny attested `no_approver`,
 * read here as `approval_seat`; the inherited PreToolUse constraint does the same before invoking its hook), and the
 * engine's own guards composed into a deployment's policy judge the probe as they judge a call — a lookup bounded by a
 * live deadline answers. A deny that carries no engine settlement is a rule's deny and stands. RESIDUALS (stated, not
 * closed): a deployment closure that ignores the statement and reaches an approver IS asked — the judge waits for it at
 * most the judgment's budget (`timed_out`: the write face refuses, the notice face stays silent), then its signal ends
 * so a closure that honors it releases its approval; a deployment wrapper that answers the statement with a deny of its
 * own (no settlement) is read as a deny — the attachment face then withholds, the notice face stays silent.
 *
 * THE PROBE'S IDENTITY. Every layer sees the probed tool's name (`Read` / `Write`), the probed arguments, the statement
 * above, and a stable synthetic call id (`<face>-visibility-probe` for a read, `<face>-write-probe` for a write;
 * {@link syntheticReadProbeId}, {@link syntheticWriteProbeId}), so a deployment's audit can tell a probe from a model's call. The write face stamps the
 * facts the live gate stamps on a write (the roster's `Write` face, the tracked cwd and root, the advertised writable
 * directories, the data root's exemption): a containment fence and a data-root exemption judge the probe as they judge the call.
 */
import type { ToolCallRequest, ToolCallFace, ToolPolicy } from "./tool-policy.js";
import { type CallTargetStamp } from "./effective-path-target.js";
import { type SkillGrantLane } from "./skill-grant.js";
import type { OrgGateVerdict, PersistedRuleAnswer } from "./hooks.js";
/** The layers the judge consults, as named in its verdicts. */
export declare const SYNTHETIC_READ_LAYERS: readonly ["skill_rows", "narrowing", "caller_policy", "inherited_constraint", "persisted_rules", "org_rules"];
export type SyntheticReadLayer = (typeof SYNTHETIC_READ_LAYERS)[number];
/** Why a layer could not answer — the consumer's disclosure word. */
export declare const SYNTHETIC_READ_UNANSWERABLE_CAUSES: readonly ["threw", "timed_out", "approval_seat", "call_unreadable", "org_unavailable", "rewritten", "store_unreadable"];
export type SyntheticReadUnanswerableCause = (typeof SYNTHETIC_READ_UNANSWERABLE_CAUSES)[number];
export type SyntheticReadVerdict = {
    verdict: "deny";
    layer: SyntheticReadLayer;
    message?: string;
    judged?: string;
} | {
    verdict: "mandated_ask";
    layer: SyntheticReadLayer;
    message?: string;
    judged?: string;
} | {
    verdict: "no_objection";
    judged?: string;
} | {
    verdict: "unanswerable";
    layer: SyntheticReadLayer;
    cause: SyntheticReadUnanswerableCause;
    reason: string;
};
/** The write face's answer: the read face's states with `ask` — any layer's ask, mandated or not — in place of `mandated_ask`. */
export type SyntheticWriteVerdict = Exclude<SyntheticReadVerdict, {
    verdict: "mandated_ask";
}> | {
    verdict: "ask";
    layer: SyntheticReadLayer;
    message?: string;
    judged?: string;
};
export interface SyntheticReadLayers {
    skillGrants?: Pick<SkillGrantLane, "denying">;
    denyNarrowingPolicy?: ToolPolicy;
    callerPolicy?: ToolPolicy;
    inheritedPolicies?: readonly ToolPolicy[];
    persistedRuleLane?: {
        adjudicate: (req: ToolCallRequest) => PersistedRuleAnswer | Promise<PersistedRuleAnswer>;
    };
    orgRuleLane?: {
        adjudicate: (req: ToolCallRequest) => Promise<OrgGateVerdict>;
    };
    /** The leg's target-reading stamp: the probe's request carries a reading of its target, as the live gate's does. */
    stampCallTarget?: CallTargetStamp;
    /** The run's signal: its end ends the judgment's every wait (each policy layer's own signal ends with it). */
    signal?: AbortSignal;
}
/** The arguments a synthetic `Read` carries, and the facts a request stamps. */
export interface SyntheticReadCall {
    file_path: string;
    offset?: number;
    limit?: number;
    /** The tracked working directory a relative `file_path` resolves against. */
    cwd?: string;
    /** The live roster's face for `Read`, when the consumer has one. */
    face?: ToolCallFace;
}
/** The path a synthetic `Write` probes. The request's other facts come from the judge's {@link SyntheticWriteFacts}. */
export interface SyntheticWriteCall {
    file_path: string;
}
/** The facts the live gate stamps on a write, read at the moment of each judgment (the leg's cells move: the tracked cwd,
 *  the advertised-directory ledger). Every member is optional — a leg without hands has no roster face, cwd or root. */
export interface SyntheticWriteFacts {
    /** The live roster's face for `Write` (a containment fence admits a write only by the tool's own declared path target). */
    face?: ToolCallFace | undefined;
    cwd?: string | undefined;
    root?: string | undefined;
    advertisedWritableDirs?: {
        readonly roots: readonly string[];
    } | undefined;
    exemptRoots?: readonly string[] | undefined;
}
/** The stable synthetic call id a probe carries: `<face>-visibility-probe`, `face` a lowercase word
 *  (letters and hyphens) naming the consumer. */
export declare function syntheticReadProbeId(face: string): string;
/** The write face's stable synthetic call id: `<face>-write-probe`, `face` the same lowercase word. */
export declare function syntheticWriteProbeId(face: string): string;
/** One judgment's wait budget. `deadlineAt` (epoch ms) bounds the WHOLE judgment — every layer waits at most
 *  what is left of it, and a layer reached after it has passed is not consulted (`timed_out`). Absent ⇒ the
 *  dependency timeout from the start of this judgment. A consumer judging a batch passes one shared deadline,
 *  so a hung layer costs the batch one bound, not one per file per layer. */
export interface SyntheticReadBudget {
    deadlineAt?: number;
}
export type SyntheticReadJudge = (call: SyntheticReadCall, face: string, budget?: SyntheticReadBudget) => Promise<SyntheticReadVerdict>;
export type SyntheticWriteJudge = (call: SyntheticWriteCall, face: string, budget?: SyntheticReadBudget) => Promise<SyntheticWriteVerdict>;
/** The READ face: only a mandated ask is held (a person's own ask is that person's question). */
export declare function createSyntheticReadJudge(layers: SyntheticReadLayers): SyntheticReadJudge;
/** The WRITE face: every ask is held as an objection (no approver is present), and a persisted store that cannot be read is
 *  unanswerable rather than silent. */
export declare function createSyntheticWriteJudge(layers: SyntheticReadLayers, facts: () => SyntheticWriteFacts): SyntheticWriteJudge;
