import { type PathGuardFold, type PathGuardRow, type PathRowsHit, type TargetViews } from "../../core/path-guard-rows.js";
/**
 * One deny entry: a `/`-separated run of path SEGMENTS. `*` matches any run of non-separator
 * characters within one segment and is the ONLY metacharacter (everything else is literal). The run
 * may match ANYWHERE in the judged path (`.ssh` covers `~/.ssh/…` and any other `.ssh` directory) —
 * unless the pattern opens with the HOME word ({@link READ_DENY_HOME_WORD}): `~/<run>` matches only where
 * the run starts right below the execution environment's home directory (`~/.sema/settings.json` is the
 * home's file, never a project's `.sema/settings.json`). Only a FIRST segment that is exactly `~` is the
 * word; `~user` and a `~` further along are literal segments. A pattern that opens with `/` (and is not home-anchored)
 * is ROOTED, the same kind of anchor with the filesystem root as its place: `/app/config-lkg.json` names the file
 * at exactly that location, never a project's `app/config-lkg.json` — the run must start at the first segment of an
 * absolute path (a path that is not absolute is not placed, and the row does not judge it).
 * String shorthand ≡ `{ pattern }`. Matching is ASCII-case-insensitive by default (a case-insensitive
 * filesystem serves `.SSH` and `.ssh` as the same directory); `caseSensitive: true` opts a single
 * entry out. Unicode normalization (NFC/NFD) and volume-level case semantics are NOT modeled (v1
 * residual, shared with the write guard; the canonical view — realpath returns the on-disk spelling —
 * covers half of it).
 */
export type ReadDenyEntry = string | {
    pattern: string;
    caseSensitive?: boolean;
};
/** The HOME word of the pattern grammar ({@link ReadDenyEntry}): a FIRST segment spelled exactly this anchors the run
 *  right below the execution environment's home directory. */
export declare const READ_DENY_HOME_WORD = "~";
/** A pattern read as its anchor and its run: `~/a/b` ⇒ the run `a/b`, home-anchored; any other pattern ⇒ itself,
 *  unanchored. The one reader of the home word — the compiler, the traversal globs, the classifier's rendering and the
 *  write face's mirror all take the run from here. */
export declare function readDenyPatternRun(pattern: string): {
    readonly homeAnchored: boolean;
    readonly run: string;
};
/** How many leading segments of a run are LITERAL — the run's head before the first segment carrying `*`. A home-anchored
 *  row's head names one location below the home, which a mount resolves to where it really leads
 *  ({@link compileReadDeny}'s `linked`); the segments after it are matched below that location as the run matches. */
export declare function readDenyRunHead(run: string): number;
/** The normalized (validated, defaulted) form of one entry. */
export interface NormalizedReadDenyEntry {
    pattern: string;
    caseSensitive: boolean;
}
/** A deny verdict: which entry's pattern matched. */
export interface ReadDenyHit {
    pattern: string;
    /** The view string the pattern actually matched (set by {@link CompiledReadDeny.matchTarget}: the
     *  canonical key, or the lexical view when only the SPELLING matched). Disclosure must cite the
     *  matched view — under a symlink/case alias the two strings differ, and naming the other one
     *  sends the reader chasing a path the pattern does not match. */
    matchedView?: string;
}
/** A recursive read's root relation to the table ({@link ReadDenyMatcher.rowUnderRoot}): the row the root NAMES or contains
 *  (`unplaced` absent), or — when it names none — a home-anchored row compiled under no home (`unplaced: true`), which cannot be
 *  placed and so may lie under any root. */
export type ReadDenyRootHit = ReadDenyHit & {
    readonly unplaced?: true;
};
/** The same relation as the shell read boundary takes it ({@link ReadDenySeat.denyUnder}): the pattern of the row the root
 *  names (a deny), `{ unplaced }` for a row the root may hold that no home places, or null. */
export type ReadDenyRootAnswer = string | {
    readonly unplaced: string;
} | null;
/** The two faces of the deny table: what a READ must not reach, and what a WRITE must not reach. */
export declare const DENY_FACES: readonly ["read", "write"];
export type DenyFace = (typeof DENY_FACES)[number];
/**
 * A deny row in the rule DSL's PATH grammar — a `Read(<pattern>)` / `Edit(<pattern>)` deny rule, compiled by the
 * rule compiler against its own bases (`createPermissionRulePolicy`). It joins the SAME table as the segment rows: one
 * judge (`matchPath` / `matchTarget`), one refusal sentence, one classifier rendering — only the row's reach is the
 * rule grammar's (the path it names and everything under a directory it names), not a segment run.
 *  · `rule` — the rule as written, the row's name wherever a refusal or the classifier names it;
 *  · `tool` / `pattern` — the rule's two parts, for a rendering that states the pattern inertly;
 *  · `faces` — which faces the row guards (`Read` ⇒ read and write: a path whose reads are denied is not written
 *    either; `Edit` ⇒ write);
 *  · `reaches` — the rule compiler's own reach over an ABSOLUTE path.
 */
export interface PathRuleDenyRow {
    readonly rule: string;
    readonly tool: string;
    readonly pattern: string;
    readonly faces: readonly DenyFace[];
    readonly reaches: (absolutePath: string) => boolean;
    /** The row's HEAD — the absolute location its reach starts at (the rule model's `pathRuleHeadOf`: the pattern's
     *  literal prefix under its base, a directory rule's directory), spelled so the execution environment can resolve it.
     *  A leg judges the row where that location LEADS too ({@link withRuleRowsWhereTheyLead}). Absent on a hand-built
     *  row, or one whose head cannot be read: it is judged as spelled. */
    readonly head?: string;
}
/** A row's reach over ONE absolute spelling, three-valued: `unreadable` = the row cannot be judged there (a base its anchor
 *  lacks) — a tightening judgment holds on it, an allow grants nothing on it. */
export type PathRowReach = {
    readonly reach: "reached" | "not_reached";
} | {
    readonly reach: "unreadable";
    readonly reason: string;
};
/** A rule row as the one judgment reads it: the deny-table row, and — on a row a rule binding produced — its three-valued
 *  reach (a row built by hand answers through `reaches` alone: reached or not). */
export interface JudgedPathRow extends PathRuleDenyRow {
    readonly reach?: (absolutePath: string) => PathRowReach;
}
/**
 * Rule rows judged by THE one judgment ({@link judgePathRows}): each rule row read as a guarded row whose reach over a view
 * is the rule's own reach over the view's spelling (never exemptible — a rule says exactly where it reaches). Same rows
 * outer, views inner, same tighten / allow law as every other row; the hit names the rule row itself.
 */
export declare function judgeRuleRows<R extends JudgedPathRow>(rows: readonly R[], views: TargetViews, direction: "tighten" | "allow"): PathRowsHit<R> | undefined;
/** The locations a row is also judged at (each leading part of its HEAD: the anchor's children down to the head itself,
 *  a share's root for a UNC head) — what a leg resolves once, for every row whose head it holds. */
export declare function ruleHeadParts(rows: readonly Pick<PathRuleDenyRow, "head">[]): string[];
/**
 * The rule rows as a leg judges them: each row as spelled, and — for every location on the way to the row's HEAD (each
 * leading part of it) that the environment resolves to another spelling (a link or firmlink: `/tmp` → `/private/tmp`,
 * `/var` → `/private/var`, a project root, a home entry or a directory inside the rule reached through a symlink) — the
 * same row at that spelling, right after it: a path at or below the resolved location is judged as its spelling at or
 * below that part. Every part, not the head alone: a link inside the rule's literal prefix that is re-pointed after the
 * rows were placed still meets the row through the parts above it. One rule for every row form and every judge (the
 * gate's lanes and the deny tables): the reference compiles the same "physical twin" of every deny / ask rule's literal
 * prefix (cli280.js `ei` 9766583, compiled in `mt` 9767083). `leads` is the leg's resolution of each part (absent or
 * `undefined` = no twin there); a part that only extends its parent's resolution adds no row. A twin is the row's own
 * kind (it keeps every member but the head), so a judgment reports the rule the twin stands for.
 */
export declare function rowsWhereTheyLead<R extends JudgedPathRow>(rows: readonly R[], leads: ReadonlyMap<string, string | undefined>): R[];
/** Where the location `path` itself leads in a leg's resolution (`leads`, keyed by each leading part — the parts
 *  {@link ruleHeadParts} names): `undefined` when the leg did not resolve it or it leads to its own spelling. */
export declare function locationLeadsTo(path: string, leads: ReadonlyMap<string, string | undefined>): string | undefined;
/** {@link rowsWhereTheyLead} with each part resolved by `leadsTo` (the leg's resolution; each part once). */
export declare function withRuleRowsWhereTheyLead<R extends JudgedPathRow>(rows: readonly R[], leadsTo: (head: string) => Promise<string | undefined>): Promise<R[]>;
/** A rule row as a row of the one table: its name is the rule text, its reach the rule's own over a view's spelling. */
export declare function ruleGuardRow<R extends JudgedPathRow>(rule: R): PathGuardRow & {
    readonly rule: R;
};
/** A compiled segment-glob row as a row of the one table (`faces`, `polarity`, `exemptible` and `origin` are the table's). */
export declare function segmentGuardRow(pat: CompiledSegmentPattern, columns: {
    readonly faces: readonly DenyFace[];
    readonly polarity: "deny" | "ask";
    readonly exemptible: boolean;
    readonly fold: PathGuardFold;
    readonly origin: PathGuardRow["origin"];
    readonly tier?: string;
}): PathGuardRow;
/**
 * The WRITE face of the deny table: the rule rows whose faces include `write` — the judge the shell station reads for a
 * command's write targets (a redirection, `tee`, `sed -i`, `cp` / `mv` / `touch` / `mkdir` / `rm` operands). Same row
 * type, same judgment ({@link judgePathRows}) as the read face's rows; a hit names the row by its rule text.
 */
export interface WriteDenyMatcher {
    /** Which face this judge is — the write tools' path resolution reads it to word and code the refusal as a write. */
    readonly face: "write";
    readonly ruleRows: readonly PathRuleDenyRow[];
    matchPath(path: string): ReadDenyHit | null;
    /** The target judgment the read face makes, on this face's rows: canonical key, lexical view, the leaf chain's hops. */
    matchTarget(canonicalKey: string, lexicalView?: string, opts?: {
        readonly aliasResolved?: boolean;
        readonly hops?: readonly string[];
    }): ReadDenyHit | null;
    /** The table ONE call judges with ({@link ReadDenyMatcher.forCall}). */
    forCall?(toolCallId: string | undefined): WriteDenyMatcher;
}
/** Compile the write face over the rule rows (the rows not on it are dropped here, once). */
export declare function compileWriteDeny(rules?: readonly PathRuleDenyRow[]): WriteDenyMatcher;
/** One compiled ripgrep glob flag for the traversal legs (`--iglob` = case-insensitive entry). */
export interface ReadDenyRgGlob {
    flag: "--glob" | "--iglob";
    glob: string;
}
/**
 * The compiled deny judge — ONE compilation, consumed by every judgment point (target judgment in
 * resolveKey, the JS walker, the rg exclusion/probe legs, the classify operand probe, the ENOENT
 * sibling filter, the attachment reader), so the legs cannot drift apart.
 */
export interface ReadDenyMatcher {
    /** Normalized entries (built-ins first, then additions; exact duplicates folded). The disclosure /
     *  persistence face. */
    readonly entries: readonly NormalizedReadDenyEntry[];
    /** The rule-DSL rows on the READ face ({@link PathRuleDenyRow}), judged after the segment rows. Not persisted:
     *  they are the caller policy's, which a resume re-supplies. Absent on a matcher compiled without rules. */
    readonly ruleRows?: readonly PathRuleDenyRow[];
    /** Judge ONE path view (segment-window semantics). Returns the first matching entry, or null.
     *  `aliasResolved` = the key's MINTER reports the real filesystem already collapsed any win32
     *  component alias in it (canonicalizeTarget's realpath arm); unset ⇒ both readings are judged,
     *  which is the fail-closed default. Every row of the table judges the path — a segment row (built-in tier,
     *  deployment pattern) and a rule row alike: a path is judged by what a command NAMES, never by a tree
     *  enumerated below it. */
    matchPath(path: string, opts?: {
        readonly aliasResolved?: boolean;
    }): ReadDenyHit | null;
    /** §3.3 target judgment: canonical view + lexical view + every hop of the leaf symlink chain (`hops`,
     *  each an unresolved spelling some link wrote); ANY hit decides. `aliasResolved` applies to the
     *  CANONICAL arm only — the lexical view and the hops are unresolved spellings. */
    matchTarget(canonicalKey: string, lexicalView?: string, opts?: {
        readonly aliasResolved?: boolean;
        readonly hops?: readonly string[];
    }): ReadDenyHit | null;
    /** Traversal exclusions for the rg legs: `!`-polarity glob pairs — `!**\/<p>` plus `!**\/<p>/…`
     *  (the entry itself and its descendants). An entry placed at a home carries none (a glob is relative to the
     *  search root): `matchPath` judges it on the rg leg's output and in the walker. */
    readonly rgExclusionGlobs: readonly ReadDenyRgGlob[];
    /** Positive-polarity twins of the exclusions, for the bounded existence probe (first hit = entries
     *  matching the deny list exist under the scope and were excluded). */
    readonly rgProbeGlobs: readonly ReadDenyRgGlob[];
    /** Whether an entry that carries NO traversal glob (one placed at a home) can match a path under `scope` (an absolute
     *  directory): the rg leg cannot exclude such an entry, and a search that reads it and prunes afterwards answers
     *  differently by whether the entry's content matched — so a search over such a scope takes the walker, which prunes
     *  by path before reading. A scope that is not rooted answers true. */
    unexcludableUnder?(scope: string): boolean;
    /** The segment row the absolute directory `scope` NAMES or contains, judged on locations alone, never on what exists
     *  there: a placed row (home-anchored or rooted, or where one of those really leads) whose location lies at or below the
     *  scope, or a spelled row whose run — leading wildcards dropped — starts at the scope's own segments (`secrets/**`, with or
     *  without a leading double-star segment, for `…/secrets` and for `…/secrets/sub`; not for `…/sub` that merely holds a `secrets` directory below
     *  it, and a double-star-led `.env` row names no directory at all). A home-anchored row compiled under NO home names a root
     *  where its spelled run does and otherwise answers `unplaced` (a row that cannot be placed holds wider: any root may hold
     *  it), after every row the root names. Rule rows never answer here: a person's `Read(<path>)` rule judges explicit operands
     *  only. `null` for a scope that is not rooted. The one answer a recursive read's root gets about the table
     *  ({@link unexcludableUnder} asks the placed subset for the search faces). */
    rowUnderRoot?(scope: string): ReadDenyRootHit | null;
    /** A row that lies AT or BELOW `path` — the path is inside one of the row's matches, or a match would run on below the
     *  path from its own segments ({@link rowMeetsPath}) — so moving, copying or removing the path changes what the row
     *  covers. A rule row's reach below a path is not enumerable: any rule row answers. */
    rowAtOrBelow?(path: string): ReadDenyHit | null;
    /** The table ONE call judges with — the Runner's tables are one per read of the person's rules, and a call judges with
     *  the read it was pinned to (an unknown or released call: the run's latest). Absent on a table compiled once: it is
     *  every call's ({@link seatForCall}). */
    forCall?(toolCallId: string | undefined): ReadDenyMatcher;
}
/** A seat the run's tables back — a deny table, a read-root set — as ONE call takes it: the call's own where the seat
 *  carries `forCall`, the seat itself otherwise (a table compiled once, a host's own list) and for a reader that is no
 *  call (no id: the seat's own reading of the run's latest, with every refusal it carries). Taken once, where the call's
 *  judgment starts, so every judgment of the call reads one table. */
export declare function seatForCall<T>(seat: T, toolCallId: string | undefined): T;
/** Settles once the tables a seat the run's tables back stands on are ready for a reader that is no call (the seat's
 *  `ready`); any other seat is ready. Never rejects. */
export declare function seatReady(seat: unknown, signal?: AbortSignal): Promise<void>;
/** The DENY HALF of a shell read boundary, in the shape `BashReadonlyRootBoundary` declares it (structural:
 *  this module is the leaf every face depends on). `denyMatch` judges one LEXICALLY RESOLVED operand,
 *  returning the matched pattern or null; PRESENT-IFF there is something to judge. */
export interface ReadDenySeat {
    denyMatch?: (resolvedPath: string) => string | null;
    /** {@link ReadDenyMatcher.rowUnderRoot} for one lexically resolved directory, as {@link ReadDenyRootAnswer}; present exactly
     *  when `denyMatch` is. */
    denyUnder?: (resolvedPath: string) => ReadDenyRootAnswer;
    /** {@link ReadDenyMatcher.rowAtOrBelow} for one lexically resolved path; present exactly when `denyMatch` is. */
    denyAtOrBelow?: (resolvedPath: string) => string | null;
    denyEntries: readonly string[];
}
/** The ONE adapter from a compiled matcher to that seat, so every face mounts it the SAME way and the "wire
 *  the judge only when it has something to judge" rule is spelled once. That rule is load-bearing: the
 *  seat's PRESENCE is itself read as a fact (the recursive-read demotion mints on "a deny judge is wired" =
 *  the check a traversal would outflank is in place), so a judge over an EMPTY set must not be wired. Call
 *  ONCE per mount and reuse the result — the returned closure is then the function OBJECT every face mounted
 *  from that matcher shares, which makes "the same judge" checkable rather than argued. */
export declare function readDenySeat(matcher: ReadDenyMatcher | undefined): ReadDenySeat;
/** The ONE naming of the deny table and the pattern that matched. Every face composes its own SUBJECT and
 *  VERB in front of it and its own DISPOSITION behind it (the verb is not shared: one face names the
 *  target, another the REQUESTED SPELLING under a symlink alias). What must not fork is the naming — a
 *  reader comparing two surfaces about one finding must not be reading two findings. A LIST of patterns is
 *  the same naming in the plural, for the one finding that names no single row: a traversal that goes PAST
 *  the judge names the table IN FORCE, never a match it did not make. Four composers: the
 *  structured read faces' refusal (`safety.ts`), the shell faces' refusal card (`readDenyRefusal`), the
 *  lexical walk's verdict sentence (`bash-readonly-classifier.ts`), and the full shell's MANDATED ask card,
 *  which is approvable and so states the finding without claiming a refusal. NOT composers, each stating
 *  its own fact: the compaction lane's withheld-attachment HTML attribute, and the traversal notes'
 *  withheld-COUNT lines, which name the table and a pattern LIST. */
export declare function sensitivePathDenyList(pattern: string | readonly string[], face?: DenyFace): string;
/** The deny table's REACH: a deny row holds INSIDE the containment roots, so no root grant answers it. */
export declare const SENSITIVE_PATH_DENY_SCOPE = "This list guards credential-class paths and applies regardless of the containment roots.";
/** The write face's reach, in the same place of the sentence: a write deny row holds under every root and every mode. */
export declare const WRITE_DENY_SCOPE = "A write deny row holds regardless of the containment roots and of the permission mode.";
/**
 * THE deny refusal sentence — five segments, one mint, every read face: the ACTION, the ABSOLUTE target as the
 * caller spelled it (with its canonical target in parentheses when the two differ), the DISPOSITION (a deny row is
 * refused, never escalated), the table BY NAME with the PATTERN verbatim ({@link sensitivePathDenyList}), and
 * one sentence of why ({@link SENSITIVE_PATH_DENY_SCOPE}). `matchedView` names the view the pattern actually hit
 * when that is the requested SPELLING rather than the target — under a symlink or case alias the two strings
 * differ, only one matches, and naming the other sends the reader chasing a path the pattern does not match.
 * A face prefixes its own `Error (<tool>): ` and may append its own closing clause; the finding itself is
 * never re-spelled.
 */
export declare function readDenySentence(finding: {
    readonly action?: string;
    readonly target: string;
    readonly canonical?: string;
    readonly pattern: string;
    readonly matchedView?: string;
    /** The table face that refused (default `read`): a write-face hit names the write list and its reach, and writes. */
    readonly face?: DenyFace;
}): string;
/** The per-part budget of the deny sentence — the gate's own card-account cap, not a second number. */
export declare const READ_DENY_SENTENCE_PART_MAX = 200;
/** `s` verbatim when it fits `budget`, else elided in its MIDDLE ({@link elideMiddle}). */
export declare function fitMiddle(s: string, budget: number): string;
/** `s` shortened to `budget` by removing its MIDDLE, marked — cut through the repo's surrogate-safe
 *  primitive, never a raw `slice` (a raw cut leaves half an astral code point on a card and in a durable
 *  row). Under a dozen characters the HEAD is taken. */
export declare function elideMiddle(s: string, budget: number): string;
/**
 * The closed set of built-in tiers. A tier is the deployment's selection unit
 * ({@link ReadDenyBuiltinConfig.tiers}); every {@link READ_FACE_BUILTIN_DENY_TABLE} row belongs to
 * exactly one. Unknown tier names refuse loudly — this array is the validation source and the
 * admin-face vocabulary, never re-spelled downstream.
 */
export declare const READ_DENY_BUILTIN_TIERS: readonly ["credentials", "shell-history", "browser", "wallet", "agent-config"];
/** One member of {@link READ_DENY_BUILTIN_TIERS}. */
export type ReadDenyBuiltinTier = (typeof READ_DENY_BUILTIN_TIERS)[number];
/**
 * One row of the built-in table: the canonical deny pattern (also the row's STABLE NAME — the
 * `readDenyBuiltinExclude` key; renaming a pattern is a semantic change and deliberately invalidates
 * configs naming the old spelling, loudly) and the tier it belongs to.
 */
export interface ReadDenyBuiltinRow {
    readonly pattern: string;
    readonly tier: ReadDenyBuiltinTier;
}
/**
 * READ_FACE_BUILTIN_DENY_TABLE — the FULL built-in table with tier metadata: the material basis of
 * the deployment admin face, what an org administrator "sees" before selecting tiers / excluding
 * rows. Activation is a SEPARATE fact: the tiers of {@link READ_DENY_DEFAULT_TIERS} are active unless the
 * deployment selects otherwise, the rest are inert until a deployment names their tier — so this is the
 * MENU, never the active set. Rows stay curated regardless — the menu has to be worth switching on.
 * The dotenv family is deliberately NOT here — workspace `.env` files are working material for the
 * tasks this engine runs; an `outside_workspace` tier is likewise deliberately absent.
 *
 * Each row states its tradeoff. An unanchored row is matched as a segment run anywhere in the path, so a
 * repo fixture spelled `fixtures/.ssh/id_rsa` is refused too — deliberate: the refusal names the pattern,
 * and a false refusal on a fixture is the cheap direction (deny errs strict). A home-anchored row
 * (`~/…`, {@link READ_DENY_HOME_WORD}) is matched only below the home directory.
 *
 * Two COLUMNS, one table: a name that is a credential wherever it is found is spelled unanchored (a key
 * copied into a repo is as hot as the original); a name that is the PERSON's file in the home but the
 * project's own configuration anywhere else is spelled home-anchored. `.npmrc` / `.pypirc` are the second
 * kind: `~/.npmrc` holds the person's registry tokens, while a project's `.npmrc` is read on every install
 * question and routinely carries an `${NPM_TOKEN}` placeholder — refusing it cost ordinary work in every mode
 * and bought nothing the home row does not already hold. The same file read through a link from a project
 * into the home still meets the home row on its canonical view.
 *
 * NOT listed, deliberately: `.env`/`.env.*` (ruled out — workspace material; the WRITE guard still
 * covers them; the ENGINE's own `.env` under its data root is a different file and IS listed, see the
 * agent-config tier); `*.pem`/`*.key`/`*.p12`/`*.pfx` (repo certificates/test keys are routinely
 * READ — refusing them breaks ordinary work, the write guard covers the mutation direction);
 * `.git/hooks`/`.git/config` (reads are harmless; writes are the escalation and stay guarded); the
 * engine's own data root as a WHOLE (transcript integrity policy owns it with an ask on the write
 * face, and the memory library the model is told to read and edit lives under it).
 *
 * agent-config tier — the agent's OWN user-level configuration files whose `env` / server blocks carry API
 * keys in cleartext (the shell's `settings.json` env block, an MCP server env, the engine host's data-root
 * `.env`). Unguarded, a structured read of one of these lands the key verbatim in the tool result and
 * therefore in the session record. Every row is HOME-ANCHORED: the user's own files under the home
 * directory are refused, while a PROJECT's file of the same name (`./.sema/settings.json`, `./.mcp.json`,
 * `./.claude/settings.json`) is working material the person edits with the model and reads normally — its
 * writes are the write faces' business. Rows name FILES, not the config DIRECTORIES: `.sema`/`.claude` also
 * hold agents, skills, hooks and (under the shell's layout, `~/.sema/engine-data`) the engine data root
 * with the memory library — material the model reads and edits as ordinary work, and a directory-wide row
 * would need a data-root passthrough (one more rule) to keep it readable. Token
 * STORES of the same tooling (`.credentials.json`, an agent CLI's `auth.json`, …) are credentials rows, not
 * agent-config rows: a deployment that switches this tier off to debug its agent configuration must
 * not also expose the OAuth stores beside it. The rows' RUNS are ALSO the opt-in write deny set's
 * agent-configuration block ({@link import("../../core/sensitive-path-policy.js").agentConfigDenyPatterns},
 * which reads them from here; contract sentence there), so a row added here is judged by both faces.
 */
export declare const READ_FACE_BUILTIN_DENY_TABLE: readonly ReadDenyBuiltinRow[];
/**
 * The DEFAULT tier selection — what an unconfigured deployment activates: the `credentials` tier (key
 * material, cloud and registry credential files, token stores) and the `agent-config` tier (the agent's own
 * user-level configuration files, home-anchored). The `shell-history`, `browser` and `wallet` tiers are a
 * deployment's opt-in. Activation is a deployment decision with a visible seat, and the leg's wiring
 * manifest reports which tiers it got.
 *
 * The NAMED default rather than an inline literal: `[]` and absence stay separately spellable on the
 * seat, and a deployment profile wanting a different default changes THIS expression, not call sites.
 */
export declare const READ_DENY_DEFAULT_TIERS: readonly ReadDenyBuiltinTier[];
/**
 * The deployment's built-in-table configuration — deployment seat ONLY (RunnerDeps /
 * HandsToolkitOptions; deliberately NOT a TaskSpec key and NOT in the governed workflow whitelist,
 * so no task or governed script can widen below its deployment).
 *  - `tiers` — EXACTLY-these tier selection: listed tiers are active, unlisted ones are not
 *    (`[]` = no built-in tiers at all — an explicit, legal posture; absent = {@link READ_DENY_DEFAULT_TIERS}).
 *  - `exclude` — per-row removal by canonical pattern name, applied AFTER tier selection.
 * Unknown tier names / unknown row names refuse loudly — never silently ignored.
 */
export interface ReadDenyBuiltinConfig {
    tiers?: readonly string[];
    exclude?: readonly string[];
}
/**
 * Resolve the ACTIVE built-in rows under a deployment configuration (validated, loud — all three
 * bad-value states throw: garbage shapes, unknown tier names, unknown row names). The one
 * resolution used by {@link compileReadDeny}; exported so an admin face can preview the effective
 * table under a candidate configuration with the engine's own rules.
 */
export declare function resolveReadDenyBuiltins(config?: ReadDenyBuiltinConfig): readonly ReadDenyBuiltinRow[];
/**
 * The deployment's built-in configuration as ONE validated snapshot, read off the seats' OWN values: each seat is an
 * array of names or absent — any other value (a string, the empty string included) refuses loudly, naming the seat,
 * before anything is spread or copied (a spread string reads as its characters, or as no names at all). The names are
 * then judged by {@link resolveReadDenyBuiltins}. The snapshot holds copies: a caller mutating its arrays afterwards
 * moves nothing, so every compile of one mount reads the same selection.
 */
export declare function readDenyBuiltinConfigOf(seats: {
    readonly tiers?: unknown;
    readonly exclude?: unknown;
}): ReadDenyBuiltinConfig;
/**
 * The tiers a deployment configuration ACTIVATES — the tier names of {@link resolveReadDenyBuiltins}'s
 * surviving rows, in {@link READ_DENY_BUILTIN_TIERS} order (the closed set is the ordering source, so
 * two deployments that select the same tiers in different spellings report the same list).
 *
 * MATERIAL, not intentional: a tier whose every row was removed by `exclude` activates nothing and
 * is NOT reported. An EMPTY result means the built-in table contributes nothing on this leg — the
 * unconfigured default. Same loud validation as the resolution it wraps.
 */
export declare function activeReadDenyBuiltinTiers(config?: ReadDenyBuiltinConfig): readonly ReadDenyBuiltinTier[];
/**
 * READ_FACE_DEFAULT_DENY_ENTRIES — the DEFAULT-ACTIVE built-in set: {@link READ_FACE_BUILTIN_DENY_TABLE}
 * under {@link READ_DENY_DEFAULT_TIERS} — the answer to "what does an unconfigured deployment refuse, from
 * this table". Derived, so it follows the default selection; the tier-annotated table is where a consumer
 * renders "what COULD be switched on".
 */
export declare const READ_FACE_DEFAULT_DENY_ENTRIES: readonly ReadDenyEntry[];
/** A compiled segment-run pattern (shared engine — the write guard delegates here too). */
export interface CompiledSegmentPattern {
    raw: string;
    segments: RegExp[];
    /** Fold BOTH sides through {@link asciiLower} before testing (compile lowered the pattern side). */
    foldAscii: boolean;
    /** The segment lists of the directories the run is ANCHORED at (folded as the pattern folds): the run must start
     *  right after one of them. Absent = the run matches anywhere. */
    anchors?: readonly (readonly string[])[];
    /** Judged in a ROOTED view only: an extra location of a home-anchored row (where its literal head leads), or a row that is
     *  itself rooted (anchored at the filesystem root, {@link ReadDenyEntry}). A view that is not rooted cannot be placed: a
     *  home-anchored row's own run is held anywhere in it (the row cannot be placed, so it holds wider); these two judge it not. */
    rootedOnly?: true;
    /** A home-anchored row compiled under NO home: it cannot be placed, so it holds wider on both relations a path has to it —
     *  its run matches anywhere in a path, and any recursive read's root may hold it ({@link rowNamedByRoot}). */
    unplacedHome?: true;
}
/**
 * Compile one segment-glob pattern (shared engine). `fold`:
 *  · "none"    — byte-exact segments;
 *  · "ascii"   — ASCII-case-insensitive (deny-set contract);
 *  · "unicode" — RegExp `i` flag (the write guard's historical host-keyed behavior — kept for it
 *    byte-identically; NOT used by the deny set).
 * Returns null when the pattern reduces to zero segments — the CALLER owns its loud path (the two
 * consumers refuse with their own surface-specific texts).
 */
export declare function compileSegmentPattern(raw: string, fold: "none" | "ascii" | "unicode"): CompiledSegmentPattern | null;
/**
 * Does the path contain a compiled pattern as a CONTIGUOUS run of full path segments? (Shared engine:
 * `.git/hooks` matches `/repo/.git/hooks/pre-commit`; `.ssh` matches any `.ssh` segment.) An ANCHORED pattern
 * ({@link CompiledSegmentPattern.anchors}) matches only where the path's leading segments are one anchor's and
 * the run starts right after them. Splits on BOTH separator families — win32 canonical keys are backslash-form.
 * Returns the matched raw pattern or null.
 */
export declare function matchSegmentPatterns(path: string, compiled: readonly CompiledSegmentPattern[], opts?: {
    readonly aliasResolved?: boolean;
}): string | null;
/** One entry's refusal under the deny list's entry law ({@link normalizeEntry}, the compiler's own), or `undefined` when the
 *  entry is lawful — the law read without compiling, for a door that judges a list before anything folds it. */
export declare function readDenyEntryProblem(entry: unknown, layer: string): string | undefined;
/** Is a canonical pattern ROOTED — placed at the filesystem root ({@link ReadDenyEntry})? Only {@link canonicalReadDenyPattern}
 *  puts a leading `/` on a canonical pattern, so the text is the whole answer. */
export declare function isRootedReadDenyPattern(canonical: string): boolean;
/**
 * the PURE validation/canonicality predicate over a PERSISTED deny entry (checkpoint v9
 * face section), for the resume pre-CAS ladder: it must refuse BEFORE the approval CAS everything
 * {@link compileReadDeny} would throw on AFTER it (a post-CAS compile throw consumes the human's
 * approval and strands the row), plus non-canonical spellings (normalizeEntry canonicalizes at every
 * mint, so a persisted non-canonical pattern was not minted by any release = damaged). Returns the
 * refusal reason, or null when the entry is valid.
 */
export declare function persistedReadDenyEntryProblem(e: unknown): string | null;
/** The home spellings a home-anchored row is placed under, judged as given: an array of absolute path strings, loud
 *  otherwise and naming `readDenyHomes` — a relative or empty spelling places the row where no home is, and a bare
 *  string would be read as its characters. */
export declare function checkedReadDenyHomes(homes: unknown, seat?: string): readonly string[];
/**
 * Compile the read-face deny judge: ACTIVE built-in rows ∪ additions. Additions are add-only at every
 * task layer (`[]` additions ≡ absent, deliberately a no-op rather than a refusal: an array API
 * cannot observe a "replace" intent, and union-with-empty is the identity, not a silent fallback);
 * the built-in half is selected by the DEPLOYMENT's `builtin` config (absent = the default tier
 * selection, see {@link resolveReadDenyBuiltins}). A deployment that turned a tier off can still
 * re-add single patterns through the additions seats — they then ride as ordinary additions.
 * Bad entry shapes / zero-segment patterns / unknown tier or row names throw loudly, naming the
 * layer or knob.
 *
 * `homes` — the spellings of the execution environment's home directory a home-anchored entry
 * ({@link READ_DENY_HOME_WORD}) is placed under: the declared home, the account home and, where the environment's
 * canonical spelling of one differs, that one too (the faces judge canonical keys beside the spelled views). Absolute
 * spellings only — any other shape refuses loudly, naming `readDenyHomes`. EMPTY = the environment declares no
 * home: a home-anchored entry then matches its run anywhere and any recursive read's root may hold it
 * ({@link ReadDenyMatcher.rowUnderRoot}) — a row that cannot be placed holds wider, never narrower, on both relations.
 *
 * `linked` — where a home-anchored or a rooted row's LITERAL HEAD ({@link readDenyRunHead}) really leads, keyed by the row's
 * pattern: the canonical locations a mount resolved (`readDenyLinksOf`, read-deny-home.ts) where
 * one of the head's segments is a link (`~/.sema` linked into a dotfiles directory; `/app` a link to `/data/app`). The row is placed at each location too —
 * the same row, the same name in every refusal — with the rest of its run matched below it. The read faces judge
 * canonical keys, so every spelling that reaches the linked file meets the row there. Absolute locations only.
 */
export declare function compileReadDeny(additions?: readonly ReadDenyEntry[], layer?: string, builtin?: ReadDenyBuiltinConfig, rules?: readonly PathRuleDenyRow[], homes?: readonly string[], linked?: ReadonlyMap<string, readonly string[]>): ReadDenyMatcher;
