/**
 * The shell read STATION — the gate input that judges where a shell command reads, before approval, on
 * every shell face (`createShellReadCheck`), and the pre-spawn admission the shell tools call with the
 * same establishment (`ShellReadAdmission`). ONE pipeline, one call:
 *
 *     planShellReads(text) → establish(plan, env) → judgeRead ×N → foldShellReadFindings → decideShellRead(seat)
 *
 * The station is a POLICY-class member of the gate fold: a `deny_hit` refuses outright (composing under
 * `deny > ask > allow`, so it outranks a hook's or a policy's ask), a mandated finding tightens a surviving
 * allow to a MANDATED ask (or marks an existing ask mandated), an ordinary finding tightens to an ORDINARY
 * ask (or marks the pass `probeBoundaryDeclined`), and `none` leaves the decision untouched. The three
 * tools' execute legs judge nothing: what they run is what this station admitted, and the admission only
 * re-establishes the SAME candidates (a symlink re-pointed while the approver was thinking) — it never
 * parses text or judges a word the station did not.
 *
 * That pipeline is written ONCE (`runShellReadStation`) and has two entries: the gate input above, and
 * {@link judgeShellRead}, the offline face. The steps between stay private — the station's working, not
 * its answer, and a caller composing them would be a second judgment of the same question.
 */
import type { ExecutionEnv } from "../../internal/harness-types.js";
import { violationDetails } from "./safety.js";
import { type ShellReadPlan } from "./shell-read-plan.js";
import { type HomeViewSource } from "./read-deny-home.js";
import { type EstablishedRead, type ShellReadBoundary, type ShellReadDisposition, type ShellReadFinding, type ShellReadSeat } from "./shell-read-judge.js";
import type { ReadRootGrantCandidate } from "../../core/tool-spec.js";
import type { ToolCallLike } from "../../core/tool-registry.js";
/** The ONE mint of the containment card — the targets a finding established OUTSIDE the roots (an out-of-root read, a
 *  target that resolves elsewhere by the spawn). */
declare function containmentDetails(paths: readonly string[]): {
    readonly type: "readonly_out_of_root";
    readonly code: "readonly_out_of_root";
    readonly paths: readonly string[];
};
/** The ONE mint of the card of a finding that established nothing: where the command reads could not be established
 *  (an unreadable or re-entered program text, a program named from its input, a station that could not answer). */
declare function unestablishedDetails(): {
    readonly type: "read_unestablished";
    readonly code: "read_unestablished";
};
/** The structured details a refusal or a mandated card carries: the deny card is the read faces' own (`violationDetails`,
 *  safety.ts), the containment and the unestablished cards are minted above. */
export type ShellReadRefusalDetails = NonNullable<ReturnType<typeof violationDetails>> | ReturnType<typeof containmentDetails> | ReturnType<typeof unestablishedDetails>;
/**
 * What the station answers for ONE call: a VOUCH — the finding `none`, nothing beside it but the facts — or a QUESTION, a
 * disposition the decision table gives its finding ({@link import("./shell-read-judge.js").dispositionsOfRow}). A vouch carries no
 * finding, no silence mark and no card: the table vouches on the `none` row alone
 * ({@link import("./shell-read-judge.js").VouchOnlyOnTheNoneRow}), so a vouch beside anything else is a contradiction — one this
 * type cannot spell, and one every reader of a station's answer refuses where an untyped station spells it anyway
 * ({@link import("../../core/shell-read-silence.js").readStationAnswer}).
 */
export type ShellReadVerdict = ShellReadVouch | ShellReadQuestion;
/** The station has no question about the call. */
export interface ShellReadVouch extends ShellReadVerdictFacts {
    readonly disposition: "vouch";
    readonly finding: "none";
    readonly environmentSilent?: never;
    readonly rowsUnread?: never;
    readonly face?: never;
    readonly sentence?: never;
    readonly details?: never;
    readonly readRootCandidate?: never;
    readonly unestablished?: never;
}
/** The station refuses the call or puts a question about it. */
export interface ShellReadQuestion extends ShellReadVerdictFacts {
    readonly disposition: Exclude<ShellReadDisposition, "vouch">;
    readonly finding: ShellReadFinding;
    /** The environment did not answer the judgment — a resolver, a listing or an identity lookup gave no answer, a bound was
     *  reached, the judge itself did not answer: present on the `unanswered` finding the fold or the fallback gives. The gate
     *  classes the question as shell text the engine cannot read. */
    readonly environmentSilent?: true;
    /** Rows the station's boundary stands on could not be read (`ShellReadBoundary.unreadPartitions`, or a boundary the seat
     *  could not hand over): present on ANY verdict judged beside them, whatever its finding. The gate classes the question as
     *  a rule that could not be read. */
    readonly rowsUnread?: true;
    /** `write` ⇔ the finding is about where the command WRITES — its witness is a write target (a redirection's, or a word
     *  the program's row writes), judged against the write roots. Absent ⇒ a read's finding (or `vouch`). */
    readonly face?: "write";
    /** `refuse`: the refusal text (`Error (<tool>): …`, the five-segment deny sentence or the containment
     *  sentence). `mandated` / `ordinary`: the ACCOUNT of the finding, for the approval card's disclosure seat
     *  (never the ask's own message — that is the auto-mode classifier's input). Absent for `vouch`. */
    readonly sentence?: string;
    /** `refuse`: the refusal's structured details. `mandated` on an `outside_roots` / `unestablishable` finding (and
     *  `ordinary` on the file tools' out-of-root read): the finding's card, so an ask a person refuses or nobody can answer
     *  still carries WHAT was found on its `tool_end` — the targets outside the roots (`readonly_out_of_root`, or the file
     *  tools' `path_not_in_root`), or that nothing could be established (`read_unestablished`). */
    readonly details?: ShellReadRefusalDetails;
    /** `mandated` on an `outside_roots` finding: the directory whose grant would clear this ask. */
    readonly readRootCandidate?: ReadRootGrantCandidate;
    /** A FACT beside the disposition: some read of the command could not be established (an `unestablishable` or `declined`
     *  finding anywhere in it, whichever finding won). A mode that releases the call releases it past the read-deny table. */
    readonly unestablished?: true;
}
/** The FACTS a station's answer may carry beside either disposition — about what the command writes, read by the modes that
 *  answer file commands and by the write classes, never by the read table — and the admission the applying reader activates. */
export interface ShellReadVerdictFacts {
    /** A FACT beside the disposition, for the mode that answers a file command itself: every write target this command
     *  names was established inside the boundary's WRITE roots at every seat the program writes it (the entry, where it
     *  lands, or both — `WriteSeat`, shell-read-write-targets.ts), off the write-protection table and off every deployment
     *  guarded write row (the leg's one write judgment, `ShellReadBoundary.writeTargetJudge`), no removal (`rm` / `rmdir`) targets a
     *  write root or a directory containing one, every program the command runs is in its text (no `sed -f` file, no
     *  re-entered shell, no unreadable text), and the line's order keeps each segment's establishment true
     *  ({@link lineOrderPlaced}). Absent ⇒ not established — the mode does not answer; the station's own table is unchanged. */
    readonly writesPlaced?: true;
    /** A FACT beside the disposition: a write target this command names lands on the write-protection table — judged by
     *  the table's own judge, as a write tool's target is — so the command's ask carries that table's class, whichever
     *  mode reads it. Absent ⇒ no target the station established is covered (or no judge is mounted). */
    readonly writeProtected?: true;
    /** A FACT beside the disposition: a target this command's program WRITES was placed and the environment could not say
     *  where it leads ({@link EstablishedRead.unresolved}) — the reading's `target_unresolved` fact, the same one a write
     *  tool's unresolved target states, so the command's ask carries that class (no automatic lane answers it; the shell face
     *  releases it under bypassPermissions). Absent ⇒ every written target resolved, or was not placed for another reason. */
    readonly targetUnresolved?: true;
    /** A FACT beside `writesPlaced`'s absence: the command is one of the mode's file commands whose writes the station would
     *  have placed but for an OPTION WORD on a `cp` / `mv` segment ({@link UNPLACED_OPTIONS}: any word starting with `-` — the
     *  reference implementation's rule, "with flags requires manual approval to ensure path safety"). Names the first such
     *  program, so the approval card and the headless refusal can say WHY the mode did not answer. Absent ⇒ not that reason
     *  (or the writes were placed). */
    readonly unplacedOptions?: {
        readonly program: "cp" | "mv";
    };
    /** The station's admission of this call's judged target, activated only by the caller that APPLIES this verdict (the
     *  gate's fold, the resumed leg's belt): a verdict nobody received — a wait that elapsed, a judgment that threw —
     *  admits nothing, whenever it completes. */
    readonly admit?: () => void;
}
/** The station seat one tool call is judged on (the `rejudge` seat is asked for by the caller). */
export type ShellReadStationSeat = Exclude<ShellReadSeat, "rejudge">;
/**
 * The ENGINE-FILLED gate input. `judge` returns `null` SYNCHRONOUSLY when the call is not this station's
 * business — not a shell-running tool, no command string — and otherwise the verdict, a promise. The split
 * is load-bearing for the gate: a call the station does not cover must not cost the fold a suspension
 * point. `unanswered` is the verdict the fold substitutes when the wait elapsed or threw — fail-closed as
 * `unestablishable` on the call's own seat.
 *
 * Both take the CALL (`{ toolName, face }`), not a name: a station is a tighten keyed on the engine's own tool names,
 * so it holds a call made under ANY of the call's names (`ruleNamesOf` — a tool that answers to `Bash` under another
 * wire name is judged as `Bash`). The first of the names the station's membership holds keys its seat, its boundary
 * and the admission the engine's tool reads before it spawns; the sentences name the call's wire name.
 */
export interface ShellReadCheck {
    judge(call: ReadStationCall, args: unknown, cwd: string | undefined, signal: AbortSignal | undefined, opts: {
        readonly toolCallId?: string;
        readonly seat?: "rejudge";
    }): Promise<ShellReadVerdict> | null;
    unanswered(call: ReadStationCall, cause: string): ShellReadVerdict;
}
/** The call a read station judges: its wire name and the face the gate stamped (whose `names` the station reads). */
export type ReadStationCall = Pick<ToolCallLike, "toolName" | "face">;
/** The read station a call belongs to — the first of its names (the spelling first) a station's membership holds; every
 *  station reads the call's slot and seat under that one name. */
export declare function readStationMemberOf<V>(call: ReadStationCall, members: {
    get(name: string): V | undefined;
}): {
    readonly name: string;
    readonly value: V;
} | undefined;
export declare function readStationMemberOf(call: ReadStationCall, members: {
    has(name: string): boolean;
}): {
    readonly name: string;
    readonly value: true;
} | undefined;
/** The pre-spawn admission the shell tools call: re-establishes what the station established for this
 *  call and refuses when any canonical target moved. `undefined` ⇒ spawn. A call the station never judged
 *  (no gate ran) has nothing to re-establish and spawns. */
export type ShellReadAdmission = (toolName: string, toolCallId: string | undefined, command: string, signal?: AbortSignal) => Promise<{
    content: string;
    isError: true;
    details?: unknown;
} | undefined>;
export interface ShellReadStation {
    readonly check: ShellReadCheck;
    readonly admit: ShellReadAdmission;
}
export interface ShellReadStationOptions {
    readonly env: ExecutionEnv;
    /** Which tool names spawn a shell command through this leg — the station's membership. */
    readonly tools: ReadonlySet<string>;
    /** The trust-policy seat a tool is judged on. */
    readonly seatOf: (toolName: string) => ShellReadStationSeat;
    /** The boundary for a call, read per call (the tracked working directory moves; the call's own tables, by its id —
     *  `undefined` where no call is judged). `undefined` ⇒ no boundary declared, nothing to be outside of — the station
     *  vouches. */
    readonly boundaryOf: (toolName: string, cwd: string | undefined, toolCallId: string | undefined) => ShellReadBoundary | undefined;
    /** The listed read verbs (decides whether a segment is read by verb slots or word by word). */
    readonly readers?: ReadonlySet<string>;
    /** `true` ⇔ every root `boundaryOf` returns is already a canonical identity (the Runner's): the station never
     *  re-resolves one, so a root swapped for a link after it was declared or granted cannot bring in the link's target. */
    readonly rootsCanonical?: boolean;
    /** The home views of the placement the boundary's deny seats were compiled at (read-deny-home.ts) — the Runner's. Absent,
     *  the declared home alone. */
    readonly homeViews?: HomeViewSource;
    /** The engine's account of a REFUSED admission, called with the call's id before the refusal is handed back to the tool
     *  — the one trusted channel by which a refusal after the gate reaches the call's record (the tool's result is the
     *  tool's own word, and a refusal must not read as a tool failure under the gate's `allowed`). Every shell tool this
     *  station admits (both Bash faces, Monitor) refuses through {@link ShellReadStation.admit}, so this is the one
     *  place to hear it. The Runner's; absent outside one. */
    readonly onAdmissionRefused?: (toolCallId: string) => void;
}
/** What a consumer hands {@link judgeShellRead}: the command as written, the environment whose filesystem
 *  answers where its words land (symlinks resolved, patterns expanded — a `NodeExecutionEnv` over a real
 *  directory is what the gate itself runs on), the boundary it is judged against, and the trust-policy seat
 *  it is judged on. The working directory a relative operand starts from is the boundary's own `cwd`. */
export interface ShellReadJudgeInput {
    readonly command: string;
    readonly env: ExecutionEnv;
    readonly boundary: ShellReadBoundary;
    readonly seat: ShellReadSeat;
    /** The listed read verbs — which words of a segment are read operands. Defaults to the classify face's. */
    readonly readers?: ReadonlySet<string>;
    /** The face named in a refusal sentence. Defaults to `Bash`. */
    readonly tool?: string;
    /** The home list the boundary's deny rows were compiled under (`HandsToolkitOptions.readDenyHomes`'s seat, same list, same
     *  meaning: absolute home paths, anything else rejects naming `readDenyHomes`). Present ⇒ the judgment's home views are
     *  that table's — the environment's declared home is always among them, every other entry is read once under a short
     *  bound of its own — and the account database is not asked and no home is added; `[]` leaves the declared home alone.
     *  Absent ⇒ the judgment is its own placement: the declared home and the account's home, asked once for this call. */
    readonly readDenyHomes?: readonly string[];
    /** Handed to the ENVIRONMENT's own primitives (`canonicalPath`, `listDir`) while the reads are
     *  established; whether an abort stops one is the adapter's answer, and a walk short enough to finish
     *  first finishes. It is NOT a deadline and it does not reach `boundary.alsoInside`, whose signature
     *  carries no signal — see {@link judgeShellRead} on which layer owns the bound. */
    readonly signal?: AbortSignal;
}
/** What {@link judgeShellRead} answers about ONE command. */
export interface ShellReadJudgment {
    /** What the station read out of the command's text before any filesystem was consulted. */
    readonly plan: ShellReadPlan;
    /** Every read candidate the station established, in the plan's own order, nested plans included — each
     *  carrying how far it got (`EstablishedRead.established`) and the target it was judged on. */
    readonly establishment: readonly EstablishedRead[];
    readonly verdict: ShellReadVerdict;
    /** The directory-scoped grant offer THIS STATION is willing to make — the verdict's candidate through the
     *  same validator the gate applies, so a candidate that validator drops is absent here as it is there. It
     *  is the station's offer, not the composed card's: over an ask another layer already raised, the fold
     *  adds the mandate and nothing else, so the offer does not land there. */
    readonly offer?: ReadRootGrantCandidate;
}
/**
 * The station's judgment of ONE command, OUTSIDE a run — the consumer face of everything above. Same plan,
 * same establishment, same judge, same table, same verdict the gate fold reads: this is
 * {@link createShellReadStation}'s own derivation with the admission bookkeeping left out, so a caller
 * holding a command, an environment and a boundary gets the decision the gate would reach for them.
 *
 * An ENVIRONMENT question, not a text question: a symlink that leaves the roots, a pattern that expands
 * onto a deny row, a traversal root that cannot be enumerated are answered by `env`, not guessed from the
 * spelling. {@link judgeShellReadLexically} is the no-environment reading and not a substitute — it is
 * LAXER where only a filesystem sees the escape (an in-root symlink pointing out vouches) and answers a
 * pattern on its spelling alone, so the two diverge in both directions.
 *
 * A read target is also judged at its HOME VIEW (a path spelled through a firmlink or a bind mount of a home, respelled
 * at the home). The views read the home list the boundary's rows were compiled under when the input names it
 * ({@link ShellReadJudgeInput.readDenyHomes}); without it this judgment is its own placement — the environment's declared
 * home and the account home the account database answers once, for this call (`readDenyHomesOf`'s homes). Every home
 * beside the declared one waits at most a short bound of its own.
 *
 * It carries NO deadline. Bounding an environment-facing wait and substituting a fail-closed verdict is the
 * gate FOLD's policy on the gate's one deadline seat; the station has never held one on either entry, and a
 * second default here would decide the same number twice and turn a slow-but-correct filesystem's true
 * answer into a fail-closed one unasked. A consumer wanting that posture races its own deadline and reads
 * the row the gate's fallback reads: `SHELL_READ_DECISION.unanswered[seat]`.
 */
export declare function judgeShellRead(input: ShellReadJudgeInput): Promise<ShellReadJudgment>;
/**
 * The station's verdict with NO environment — the lexical reading (what an isolated sandbox gets, and what a
 * pin or a lexical pre-read can compute): the same plan, the same judge, the same table, over the folded
 * spellings alone. `tool` names the face in the refusal sentence.
 */
export declare function judgeShellReadLexically(command: string, boundary: ShellReadBoundary, seat: ShellReadSeat, opts?: {
    readonly readers?: ReadonlySet<string>;
    readonly tool?: string;
}): ShellReadVerdict;
/** Mount the station for one execution environment. */
export declare function createShellReadStation(opts: ShellReadStationOptions): ShellReadStation;
export {};
