/**
 * ESTABLISHMENT — where a shell command's read candidates LAND once the filesystem has answered, as one
 * value the gate's shell read station holds per execution environment. The plan (`shell-read-plan.ts`)
 * decides WHICH words a command may read, `shell-read-write-targets.ts` which words it writes and at which seat;
 * this module decides WHERE each of them lands: the canonical
 * target of a spelling (symlinks resolved, a `..` applied the way the kernel applies it), the expansion of
 * a pattern (shell pathname semantics over `env.listDir`), the members of a traversal root (a bounded
 * recursive enumeration, dot files included, symlinked directories not followed), and the fail-closed arm
 * for what could not be established. The judge (`shell-read-judge.ts`) is downstream; nothing here decides
 * allow/ask/deny.
 *
 * Properties every consumer relies on:
 *  1. A NON-EXISTENT target is not a refusal — `cat nope.txt` keeps the shell's own "No such file". The
 *     deepest EXISTING ancestor is canonicalized and the missing tail rejoined, so a symlinked PARENT still
 *     cannot carry a target out. For a WRITE target a component the resolver cannot find but the filesystem
 *     still holds (a link whose target does not exist) is not absent: a write through it creates the link's
 *     target, so the target is established where the link lands (read one hop at a time, bounded) — or not at
 *     all when the environment cannot read the link.
 *  2. An unanswerable filesystem manufactures no refusal on its own: a chain no ancestor answered degrades
 *     to the lexical spelling on an environment that declares no authority for its resolver, and is
 *     `unestablishable` on one that does (`canonicalPathIsAuthoritative`).
 *  3. An ISOLATED environment stays lexical, disclosed rather than silently degraded: the sandbox is the
 *     containment there and `canonicalPath` is an RPC into a filesystem that is not this host's
 *     (`boundaryIsTheSandbox`). The split is the DECLARED isolation capability, never the remote interface's
 *     shape — a host lane or an SSH adapter implements the same interface and is resolved on its own paths.
 *  4. NO MATCH is not a refusal: an unmatched pattern is handed to the command verbatim, so an empty
 *     expansion falls back to the literal spelling.
 *  5. What it cannot enumerate is `unestablishable`, never silently vouched: an unreadable directory, a
 *     pattern construct the matcher does not model, an expansion or a traversal past
 *     {@link MAX_GLOB_DIRS} / {@link MAX_GLOB_MATCHES}.
 *  6. Cost is paid only by candidates that carry a metacharacter or a traversal, and only past the roots'
 *     own spelling. Inside one enumerated directory only the SYMLINK entries need their own `realpath`.
 *
 * NOT cached deliberately: a per-run memo keyed on the spelling would answer from a snapshot of where a
 * symlink pointed EARLIER in the run, which is the one thing establishment exists to observe. The residual
 * it cannot remove is the classic one — the link can be re-pointed between establishment and the shell's
 * own open; the pre-spawn re-establishment (`reestablish`) narrows that window to the one inside a single
 * call.
 */
import type { ExecutionEnv } from "../../internal/harness-types.js";
import type { ShellReadPlan, ShellReadSegment } from "./shell-read-plan.js";
import type { EstablishedRead, ShellReadBoundary } from "./shell-read-judge.js";
import type { HomeViewSource } from "./read-deny-home.js";
/**
 * How many directories one glob operand (or one traversal root) may enumerate, and how many names it may
 * match, before the leg gives up and answers `unestablishable`.
 *
 * Sized so the everyday shapes never hit them: 256 directories covers a two-level pattern over a source
 * tree's top level, and 8192 names covers `ls *` in a dependency directory an order of magnitude larger
 * than a normal one. Past those the answer is fail-closed, never a silent allow — an operand this leg could
 * not finish enumerating is exactly an operand whose expansion it cannot vouch for.
 */
export declare const MAX_GLOB_DIRS = 256;
export declare const MAX_GLOB_MATCHES = 8192;
/** The reads of one plan, established: per segment, in the plan's own order, with nested plans beside. */
export interface EstablishedPlan {
    readonly plan: ShellReadPlan;
    readonly reads: ReadonlyMap<ShellReadSegment, readonly EstablishedRead[]>;
    readonly nested: ReadonlyMap<ShellReadPlan, EstablishedPlan>;
    /** The roots the reads were judged against — canonical where the environment could say. */
    readonly roots: readonly string[];
}
/** ONE establishment leg per execution environment — the filesystem half of the shell read station. */
export interface ShellReadEstablisher {
    /** Whether this environment is judged lexically (an isolated sandbox — property 3). */
    readonly lexicalOnly: boolean;
    /** Establish every read candidate of `plan` (nested plans included) against `boundary`'s roots. */
    establish(plan: ShellReadPlan, boundary: ShellReadBoundary, signal?: AbortSignal): Promise<EstablishedPlan>;
    /** Establish the same plan again and report every candidate whose canonical target moved — the pre-spawn
     *  identity re-check. Candidates that were lexical or unestablishable are not compared: nothing was
     *  established to move. */
    reestablish(previous: EstablishedPlan, boundary: ShellReadBoundary, signal?: AbortSignal): Promise<{
        readonly changed: readonly EstablishedRead[];
    }>;
}
/**
 * The PURE, lexical establishment of a whole plan — what an isolated sandbox gets, and what any consumer
 * with no environment in hand (a unit pin, a lexical pre-read) can compute. Patterns and traversal roots
 * are judged on their spelling alone here (KL-934a: the sandbox's own containment is the floor there).
 */
export declare function establishShellReadsLexically(plan: ShellReadPlan, boundary: ShellReadBoundary): EstablishedPlan;
/**
 * The filesystem-resolving establisher for one environment and one root set. `readRoots` are the roots
 * as declared (canonical by contract); they are resolved once more per instance because the comparison is
 * against `realpath` output on both sides — an aliased root would otherwise refuse every read under itself.
 * `homeViews`: the home views of the placement the deny seats were compiled at (read-deny-home.ts); absent, the declared home's.
 */
export declare function createShellReadEstablisher(env: ExecutionEnv, readRoots: readonly string[], opts?: {
    readonly rootsCanonical?: boolean;
    readonly homeViews?: HomeViewSource;
}): ShellReadEstablisher;
