import { traceHookCrash } from "./gate-crash-trace.js";
import type { WriteProtectionVerdict } from "./write-protect.js";
/**
 * design/77 §4: resolve `p`, but REJECT (so the caller catches and fails closed) if it hasn't settled within
 * `ms` OR the `signal` aborts first (the task timed out / was cancelled — its real deadline). A rejection of
 * `p` propagates with its true cause. Both `ms` and `signal` undefined ⇒ no deadline (await `p`) — the
 * helper stays generic; every gate call site supplies a finite `ms` ({@link createGateDeadline}), so the
 * no-deadline arm is unreachable from the gate. Mirrors `tool-policy.ts withTimeout`, but REJECTS on
 * timeout (no bounded await here has a safe fallback VALUE — the gate's only safe action on an unsettled
 * one is its own fail-closed arm). `label` names the wait in the rejection, so the arm that catches it can
 * say which one elapsed.
 */
/** WHY a bounded wait ended with no answer, stated by the WAIT rather than read off an error's text:
 *  `timeout` — the bound elapsed; `aborted` — the task ended. Neither mark ⇒ the awaited work's own. */
export type GateWaitFailure = "timeout" | "aborted";
/** The mark above, read back off a rejection. `undefined` ⇒ the awaited work's own rejection. */
export declare function gateWaitFailureOf(err: unknown): GateWaitFailure | undefined;
export declare function withGateTimeout<T>(p: Promise<T>, ms: number | undefined, signal?: AbortSignal, label?: string): Promise<T>;
/**
 * The deadline used when the caller supplies no `approvalTimeoutMs`. The wait must be bounded EVERYWHERE:
 * the engine's own assembly never passes `approvalTimeoutMs`, and its only other bound is the task abort
 * signal, which a task with no walltime limit and no external cancel never fires — so a host driving the
 * public `runToolGate` with neither knob had NO bound at all and one hung probe froze the call forever. A
 * probe is an args inspection and a judgment is a path resolution, not an approval wait: 30s is generous
 * for any legitimate one, and an elapse simply takes the caller's own fail-closed arm.
 */
export declare const DEFAULT_GATE_AWAIT_TIMEOUT_MS = 30000;
/**
 * The gate's ONE deadline seat, resolved LAZILY and at most once per gate pass: a pass that makes no
 * bounded await must not sound about a seat it never read. A garbage value (NaN/Infinity/negative, or
 * above setTimeout's 2^31-1 ceiling, which it would silently clamp to ~1ms — an instant fail-closed the
 * deployment never asked for) is refused LOUDLY to the default rather than silently reinterpreted
 * (bad-value loudness discipline; the same ceiling the approve-wait seat refuses).
 */
export declare function createGateDeadline(input: {
    approvalTimeoutMs?: number;
}, notifier: Parameters<typeof traceHookCrash>[2]): () => number;
/** What ONE source of a judgment answered: its value, or its absence and why (it threw — synchronously or not — or did not
 *  answer before the judgment's signal ended the wait; `gateWaitFailureOf(cause)` says which wait ended it). */
export type SourceAnswer<T> = {
    readonly ok: true;
    readonly value: T;
} | {
    readonly ok: false;
    readonly cause: unknown;
};
/**
 * THE one way a source enters a path judgment — an environment lookup (the real target, the link chain, a root's key) or a
 * provider of rows (a deployment's guarded write rows): asked, bounded by the signal the judgment was handed (the gate's
 * deadline), and SETTLED — never thrown. A source that fails or does not answer in time is absent on its own (its view does not
 * vote, its root exempts nothing, its rows are held unplaced), and every other source's answer stands: no source's failure
 * reaches the judgment as a whole. No signal (a host calling a judge directly) ⇒ bounded by {@link DEFAULT_GATE_AWAIT_TIMEOUT_MS}.
 */
export declare function fromSource<T>(ask: () => Promise<T>, signal: AbortSignal | undefined, label: string): Promise<SourceAnswer<T>>;
/**
 * The write-protection judgment at both of its gate call sites. The gate's ONE deadline is handed DOWN as the judgment's
 * signal, so it bounds each of the judgment's sources on its own ({@link fromSource}): a view that did not answer in time takes no
 * part, an exemption root whose key did not come back exempts nothing, and a row a view already met stays met — the one
 * absence law of every path table, per lookup. `judge` returns `null` synchronously for a call it does not cover (no deadline
 * is armed, no seat read); `undefined` is returned then.
 *
 * The wait here is the LIVENESS net for a judgment that does not observe the signal it was handed, and it ends one turn of the
 * event loop AFTER the deadline: a judgment whose every lookup races the signal (the engine's) has settled by then with what it
 * found, so the net never stands in for its answer. A judgment that never came back, or threw, determined nothing about where
 * the write lands, and the table it judges for has rows: `unresolvable` (the one absence law's target arm — refused), reported
 * as a deployment callback failing.
 */
export declare function awaitWriteProtectionJudgment(judge: (signal: AbortSignal) => Promise<WriteProtectionVerdict> | null, deadlineMs: () => number, signal?: AbortSignal, onFailure?: (err: unknown) => void): Promise<WriteProtectionVerdict | undefined>;
