import { type RuleToolNameVerdict } from "./tool-name-aliases.js";
import type { ToolCallRequest } from "./tool-policy.js";
import { type AllowRuleMember, type AllowRuleShadow } from "./allow-rule-shadow.js";
import { type AdmissionPosture, type PathRuleBases, type PersistedRule } from "./permission-rule-model.js";
import { type AskClass, type AssertAllKeysHandled, type PermissionMode, type PersistedRuleMandate } from "./ask-origin.js";
import { type ToolNameListReading } from "./tool-name-list.js";
import { type EngineNotice } from "./engine-notice.js";
/** Why an entry grants (or refuses) nothing — the closed set the start-of-run notice names, for every list. `tool_name`: the
 *  entry's tool name is one the name judgment reads as stale against the run's roster (`verdict` says which); `near_miss`: the
 *  run mounts no tool of that exact name but mounts one that differs only by case (`currentName` is its spelling);
 *  `earlier_grammar`: a session's stored rules are written in an earlier rule grammar, in which the entry named no tool, or which
 *  read an entry this grammar reads as no rule (the session store's list reading, `compileSessionRuleBucket` — this reader never
 *  answers it). */
export declare const ALLOW_ENTRY_INERT_REASONS: readonly ["wildcard_all", "namespace_wildcard", "content_unsupported", "grammar", "tool_name", "near_miss", "earlier_grammar"];
export type AllowEntryInertReason = (typeof ALLOW_ENTRY_INERT_REASONS)[number];
/** The facts beside a reason: for `tool_name` / `near_miss` the judgment's word, the judgment's own one-line sentence when it has
 *  one (`guidance`, byte for byte — `retired` and `unmintable_segment` carry one, `unprefixed_namespace` none) and the spelling to
 *  write instead when there is one; for a list member that is not a string (`grammar`) the TYPE of the value (`a number`, `null`,
 *  `an object`…) — `entry` then holds {@link nonStringMemberLabel}, never the value. */
export interface AllowEntryInertDetail {
    readonly verdict?: Exclude<RuleToolNameVerdict["kind"], "current">;
    readonly guidance?: string;
    readonly currentName?: string;
    readonly valueType?: string;
    /** Where the spelling of a `near_miss` comes from, when the station that read it reads more than the run's roster
     *  ({@link NearMissCarrier}); absent ⇒ the roster the run mounts. A sentence only — never a field of a wire detail. */
    readonly carriedBy?: NearMissCarrier;
}
/** Who carries the spelling a near miss reads as another spelling of: the roster the run mounts, a delegation tool's pool, or
 *  only the engine's tool catalog (a tool the engine may mount, which this run's roster does not carry). */
export type NearMissCarrier = "run" | "pool" | "catalog";
/**
 * How a list member that is not a string is named wherever a list's entries are named (the inert record's `entry`, the Skill
 * card's binding): its TYPE, in a spelling no readable entry can have — a readable entry's name holds no whitespace and a
 * name-only entry holds no parenthesis, and this label holds a space and none. It can equal only another entry that reads as
 * nothing, so a binding that holds it never stands for an entry that grants or refuses.
 */
export declare function nonStringMemberLabel(value: unknown): string;
/** How a tool-name list's VALUE that is not a list stands as one entry (the same kind of spelling as {@link nonStringMemberLabel}: it
 *  reads as `grammar`): its TYPE, or that its entries could not be read — never the value. */
export declare function nonListValueLabel(read: Exclude<ToolNameListReading, {
    kind: "entries";
}>): string;
/** One entry a list reads as nothing. */
export type AllowEntryInert = {
    readonly entry: string;
    readonly reason: AllowEntryInertReason;
} & AllowEntryInertDetail;
/** One entry the grammar reads (kind closed): a whole non-shell tool; a protocol namespace; the whole shell tool; and one
 *  kind per rule grammar (`ruleToolGrammarOf`) — a shell command rule, a path rule, a name rule, a host rule — each the row
 *  the persisted grammar parses, its `behavior` the list's direction. */
export type CompiledAllowEntry = {
    readonly kind: "tool";
    readonly name: string;
} | {
    readonly kind: "namespace";
    readonly pattern: string;
} | {
    readonly kind: "shell";
    readonly name: string;
} | {
    readonly kind: "command";
    readonly rule: PersistedRule;
} | {
    readonly kind: "path";
    readonly rule: PersistedRule;
} | {
    readonly kind: "name";
    readonly rule: PersistedRule;
} | {
    readonly kind: "domain";
    readonly rule: PersistedRule;
};
/**
 * THE near-miss reading of a tool name the judgment calls current: the spelling the run mounts when the run mounts no tool of this
 * exact name but one that differs from it only by case (`BASH` beside `Bash`), else `undefined`. Two kinds of name are never a near
 * miss, because the roster they would be read against is not the final one: an engine tool's (the engine mounts some of its tools
 * after a list is read) and a protocol tool's (a refresh mounts and unmounts them while the run goes on) — in both the exact
 * spelling can be the right one by the time it matters. Every station that asks "is this name a case twin of a mounted tool" reads
 * this answer: an entry list ({@link readRuleEntry}), a tool policy's name lists (the prepare-time policy-name audit).
 */
export declare function nearMissSpellingOf(name: string, roster: ReadonlySet<string>): string | undefined;
/**
 * THE universe a ROOT-facing tool-name list is read against: every name the engine's catalog carries, and the names the reader knows
 * are carried (`carried`). A list is root-facing when it bounds the tools of the run that holds it — the run's own `allowTools` /
 * `excludeTools` (also the ceiling of its children), a tool policy's name lists, a session's stored rules — and its reader is that
 * run (`carried`: its roster, the caller's own tools, and the exact names of the pools its reachable delegation tools declare and can
 * list) or the store that writes the rules (`carried`: the tools its deployment declared). Another spelling of a carried name is
 * always refused there, whatever a delegation tool injects per spawn: the run's own tools are known, and an entry that is a case
 * twin of one of them names the other tool by mistake. A delegation tool's pool that cannot be listed carries nothing here.
 */
export declare function rootFacingToolNames(carried: Iterable<string>): Set<string>;
/** What one rule entry means under one direction ({@link readRuleEntry}): the row the grammar compiles it to, or the reason it
 *  reads as nothing with the facts a sentence about it names. */
export type RuleEntryReading = {
    readonly kind: "row";
    readonly compiled: CompiledAllowEntry;
} | ({
    readonly kind: "inert";
    readonly reason: AllowEntryInertReason;
} & AllowEntryInertDetail);
/**
 * THE ONE READER of a rule entry — a member of an entry list in either direction: a skill's `allowed-tools` /
 * `disallowed-tools`, a sub-agent's deny list, the request's and the deployment's `allowedTools`, a session's `toolDeny` /
 * `toolAllow`. Every station that compiles, validates, compares or names such an entry reads this answer and no other.
 * `roster` = the tool names the reader knows are mounted (aliases included): given, the entry's tool name is also read against
 * it (a stale name, or one that differs from a mounted tool's only by case, reads as `tool_name` / `near_miss`); absent, the
 * grammar alone is read — what a resume's pre-claim screen can read before the leg has a roster.
 */
export declare function readRuleEntry(raw: unknown, behavior: "allow" | "deny", roster?: ReadonlySet<string>): RuleEntryReading;
/** The tool name a compiled entry speaks for — its tool, its namespace spelling, or its rule's tool (what a name audit reads). */
export declare function compiledEntryName(compiled: CompiledAllowEntry): string;
/**
 * Compile one list WHOLE through {@link readRuleEntry}: the entries it reads and the ones it reads as nothing (each with its
 * reason and, for a name the roster refuses, the judgment's word and the spelling to write). An allow list holding `*` voids
 * the list (every other entry on it reads as nothing too: the list grants nothing — the safe direction) — `*` as the lenient
 * rule parser names it ({@link namesWholeRoster}), so an entry the stricter entry grammar refuses (`* (*)`) still voids. A
 * `*` on a deny list reads as nothing by itself and the rest of that list still refuses: a deny list never loses an entry to
 * a wildcard beside it. `roster` as in {@link readRuleEntry}.
 */
export declare function compileAllowList(entries: readonly string[], behavior: "allow" | "deny", roster?: ReadonlySet<string>): {
    rows: Array<{
        entry: string;
        compiled: CompiledAllowEntry;
    }>;
    inert: AllowEntryInert[];
};
/** The programs whose open allow rule the reference implementation drops in auto mode — its interpreter / launcher table
 *  plus the shells and the run-anything builtins (2.1.280). A program that only reaches the network is not here. */
export declare const AUTO_STRIPPED_PROGRAMS: readonly ["python", "python3", "python2", "node", "deno", "tsx", "ruby", "perl", "php", "lua", "npx", "bunx", "npm run", "yarn run", "pnpm run", "bun run", "bash", "sh", "ssh", "zsh", "fish", "eval", "exec", "env", "xargs", "sudo"];
/**
 * Does auto mode strip this allow entry for this call (see the module doc)? Read for every rule-shaped member — a list
 * entry, and a person's stored row through {@link autoStrippedRule}; a hook's allow is not an entry and is never stripped.
 * A stripped entry takes no part in the match (the reference removes it before matching), so it neither clears nor is
 * disclosed.
 */
export declare function autoStripped(compiled: CompiledAllowEntry, call: ToolCallRequest | undefined): boolean;
/** {@link autoStripped} over a person's stored ALLOW row (a deny / ask row is never stripped; a path row never is). */
export declare function autoStrippedRule(rule: PersistedRule, call: ToolCallRequest): boolean;
/** One row a list matcher reads. */
export interface AllowEntryRow {
    readonly behavior: "allow" | "deny";
    readonly entry: string;
    readonly compiled: CompiledAllowEntry;
}
/** The facts a list's content row is judged under: the leg's root and session (which rows apply), the live working
 *  directory (where a command's `cd` lands), and the ANCHORS of the list's path rows — the leg the list was installed
 *  on (its root and environment home): a path row of a list never moves with a `cd`. */
export interface AllowEntryJudgeContext {
    readonly root: string | undefined;
    readonly sessionId: string | undefined;
    readonly liveCwd: () => string | undefined;
    readonly anchors: PathRuleBases;
}
/** For a list whose allow rows admitted no call ({@link judgeAllowEntries}): the first segment of the call's command no command
 *  row covers under `posture` — the word a refusal names; `undefined` when the call carries no command or no single segment is
 *  to blame (a line the matcher cannot read at all). The same walk the matcher took. */
export declare function uncoveredCommandSegment(rows: readonly AllowEntryRow[], req: ToolCallRequest, ctx: AllowEntryJudgeContext, posture: AdmissionPosture): string | undefined;
/**
 * The ONE list matcher, both directions — the rows that speak for the call, or undefined. A tool-name row first (the first
 * that reaches the call); then the content rows, each family by the predicate the stored rows of that grammar meet:
 * COMMAND — allow: the persisted allow matcher's coverage under the list's {@link AdmissionPosture} (the whole command, or each
 * segment covered by a row — or, for a `grant` list, read-only by itself); deny: a row whose program run the call performs (the
 * wide tightening reading; a call that cannot be read against the row is refused too). PATH — the persisted path adjudication
 * (allow: the narrow reading, every view of the target inside what the row names; deny: any view reaching it). NAME / DOMAIN —
 * the one predicate of each (the name the call names, the host it fetches); a keyed tool's call naming no value for its key is
 * refused by a deny list's row of the key and granted by no allow row (the persisted walk's reading, `keyedValueAbsentReason`).
 */
export declare function judgeAllowEntries<R extends AllowEntryRow>(rows: readonly R[], req: ToolCallRequest, behavior: "allow" | "deny", ctx: AllowEntryJudgeContext, posture?: AdmissionPosture): readonly R[] | undefined;
/** The allow rows of a list, as the allow layer reads them in `mode`: the strip applied BEFORE the match (in `auto`). */
export declare function allowingRows<R extends AllowEntryRow>(rows: readonly R[], req: ToolCallRequest, mode: PermissionMode | undefined): readonly R[];
/** The two sources {@link AllowEntryTable} holds (a skill's list is the skill table's). */
export type AllowEntrySource = "request" | "deployment";
/** What spoke for a call: the entries it stands on, as the list spells them. */
export interface AllowEntryHit {
    readonly entries: readonly string[];
}
/** The face the gate reads one entry list through. */
export interface AllowEntryLane {
    /** The allow layer's member: what grants this call in this mode, or undefined. */
    allowing(req: ToolCallRequest, mode: PermissionMode | undefined): AllowEntryHit | undefined;
}
/** The gate inputs the two entry lists ride (a member group of `ToolGateInput`). Each is the allow layer's member for its
 *  source — read under the one consumption predicate beside a person's stored rows and a skill's list, clearing only what an
 *  allow rule may clear — with its attribution sink (`onAllowed` observes a call it cleared; never affects the outcome).
 *  Absent ⇒ that source has no rows. */
export interface AllowEntryGateSeats {
    deploymentAllows?: AllowEntryLane & {
        onAllowed?: (info: {
            toolName: string;
            toolCallId: string;
            entries: readonly string[];
        }) => void;
    };
    requestAllows?: AllowEntryLane & {
        onAllowed?: (info: {
            toolName: string;
            toolCallId: string;
            entries: readonly string[];
        }) => void;
    };
}
/**
 * One source's allow rows, compiled once: the request's (prepare seeds it from the spec's snapshot and, in a delegated
 * child, from the parent's capture) or the deployment's (compiled from the Runner's snapshot). Allow rows only — neither
 * list has a deny side. Identity is the contract: prepare seeds it, the delegation capture and the gate's lane read it.
 */
export declare class AllowEntryTable {
    private held;
    private readonly heldEntries;
    /** Write a list's rows (a row already held is not held twice). Returns the entries that read as nothing. `roster` as in
     *  {@link readRuleEntry}: a list the leg itself wrote is read against it, a carried one (a delegating parent's capture) is not. */
    seed(entries: readonly string[], roster?: ReadonlySet<string>): readonly AllowEntryInert[];
    /** The entries held, as written (a copy) — what a delegated child is handed. */
    entries(): readonly string[];
    /** Does the table hold a path row — must the leg read each call's target views for it? */
    holdsPathRows(): boolean;
    /** The lane over this table, bound to the leg's call facts. */
    lane(ctx: AllowEntryJudgeContext): AllowEntryLane;
}
/**
 * Seed one leg's request and deployment tables — a delegated child's captured request entries first (an entry that reads as
 * nothing was announced where it was written, and is read without the roster for the same reason), then the leg's own list
 * against `roster`; the deployment's grammar reading is announced once, at construction, so only its name readings
 * (`tool_name`, `near_miss` — facts about THIS leg's roster) are announced here — and return the dead entries of the leg's
 * OWN lists, the skills' beside the request's, for its one start-of-run notice.
 */
export declare function seedAllowEntryTables(tables: {
    readonly request: AllowEntryTable;
    readonly deployment: AllowEntryTable;
}, lists: {
    skillInert: ReadonlyArray<{
        skill: string;
        list: "allowed-tools" | "disallowed-tools";
    } & AllowEntryInert>;
    inherited: readonly string[] | undefined;
    request: readonly string[] | undefined;
    deployment: readonly string[] | undefined;
}, roster: ReadonlySet<string>): AllowEntryInertNote[];
/** The deployment's allow rules, read ONCE at construction: screened (a value that is not a list of strings refuses), frozen,
 *  and its dead entries announced once (no session). Returns the deps with the snapshot in place of the caller's list. */
export declare function withDeploymentAllowedTools<D extends {
    readonly allowedTools?: readonly string[];
    readonly onNotice?: ((n: EngineNotice) => void) | undefined;
}>(deps: D): D;
/** The code a list value that is not a list of strings refuses with — the policy compiler's family, with its issues. */
export declare const INVALID_PERMISSION_RULES_CODE = "config.invalid_permission_rules";
/**
 * Screen and snapshot one `allowedTools` value (`seat` names the key in the refusal): absent ⇒ undefined; a list of strings
 * ⇒ a frozen copy (the one read every later reader takes); anything else refuses loudly with
 * {@link INVALID_PERMISSION_RULES_CODE} and an issue per defect — never dropped, never read as "no entries".
 */
export declare function screenAllowedToolsValue(value: unknown, seat: string): readonly string[] | undefined;
/** The disclosure record for one member, minted from the entries it matched: each sanitized (deployment or model-authored
 *  text on a human trust boundary) and capped, the rest counted. */
export declare function allowRuleShadowOf(member: AllowRuleMember, entries: readonly string[]): AllowRuleShadow;
/** Read a disclosure value off a decision WITHOUT trusting it (a policy's own value, an ancestor's): every record a known
 *  member with a list of strings, or nothing — a display member must never throw where a card is minted. */
export declare function readAllowRuleShadows(value: unknown): readonly AllowRuleShadow[] | undefined;
/** Why a matched entry did not clear the ask, by the ask's class — one row per class, so a class added later is a
 *  compile error here rather than somebody else's reason on the card. Two facts the ask carries are read first, because
 *  they name the reason more exactly than a class shared by several: a table word (`mandate` — the exact mark) and the
 *  deployment's own authorship (`authoredBy`) — {@link allowRuleShadowSentence} is the reader that applies that order.
 *  Exported (frozen) so a host that renders the card's "why it cannot be cleared" half reads the engine's row, never a copy. */
export declare const SHADOW_REASON: Readonly<{
    readonly content_question: "the call is the engine's own question to a person";
    readonly hook: "a PreToolUse hook asks about this call — the deployment's own screening is answered by a person";
    readonly ancestor: "the task that delegated this one owns this question";
    readonly dangerous_delete: "this removal targets a protected location (the filesystem root, a top-level directory, a home directory, or a workspace directory or one of its ancestors) — it is cleared by confirming this call, never by an allow rule";
    readonly unverifiable_delete: "this removal could not be verified safe — it is cleared by confirming this call, never by an allow rule";
    readonly unverifiable_shell_text: "the text this shell will run cannot be read by the engine — it is cleared by confirming this call, never by an allow rule";
    readonly transcript_write: "this write targets the session transcript — it is cleared by confirming this call, never by an allow rule";
    readonly org_rule: "an organization policy rule requires approval for this call";
    readonly rule_unreadable: "a rule that may govern this call cannot currently be read (this deployment's organization policy, a partition of the person's standing rules, or this call against a deny or ask rule), so whether one forbids it is unknown";
    readonly ask_rule: string;
    readonly denial_limit_fallback: "the auto-mode classifier refused too many calls in a row, so a person decides";
    readonly classifier_no_ruling: "the auto-mode classifier could not judge this call, so a person decides";
    readonly requires_user_interaction: "this tool's server declares that a call must be put to a person";
    readonly operator_forced: "this call arrived already marked as requiring confirmation (an earlier layer of this run, or the task that delegated it, judged it so) — it is cleared by confirming this call, never by a standing allow rule";
    readonly shell_floor: string;
    readonly target_unresolved: string;
    readonly probe: string;
    readonly write_protection: string;
    readonly tool_marks_mcp: string;
    readonly tool_marks_a2a: string;
    readonly policy_rra: "the deployment's policy requires a real approval for this call";
    readonly artifact_shared_read: "this read targets another task's shared artifact — it is cleared by confirming this call";
    readonly mode: "the permission mode puts this question to a person";
    readonly unstated: "this call arrived already marked as requiring confirmation (an earlier layer of this run, or the task that delegated it, judged it so) — it is cleared by confirming this call, never by a standing allow rule";
    readonly ordinary: "this call arrived already marked as requiring confirmation (an earlier layer of this run, or the task that delegated it, judged it so) — it is cleared by confirming this call, never by a standing allow rule";
}>;
/** The fence over the reason table: `never` while every class has a row. */
export type ShadowReasonTableCoversEveryClass = AssertAllKeysHandled<Exclude<AskClass, keyof typeof SHADOW_REASON>>;
/**
 * The disclosure in the sentence a PERSON reads — rendered where a card or a park row is minted, never onto the decision
 * the classifier reads: "<members> match(es) this call but do(es) not clear the ask — <why>".
 */
export declare function allowRuleShadowSentence(shadows: readonly AllowRuleShadow[], ask: {
    askClass?: AskClass;
    mandate?: PersistedRuleMandate;
    authoredBy?: "deployment";
}): string;
/** The card's two disclosure members off a surviving ask, minted at every station that builds an approval request: the
 *  sanitized records, and the message with the sentence rendered onto it. */
export declare function cardDisclosureOf(decision: {
    message?: string;
    allowRuleShadowed?: unknown;
    askClass?: AskClass;
    mandate?: PersistedRuleMandate;
    authoredBy?: "deployment";
}, fallbackMessage: string): {
    message: string;
    allowRuleShadowed?: readonly AllowRuleShadow[];
};
/** The notice for list entries that grant (or refuse) nothing — one code for every list. */
export declare const ALLOWED_TOOL_NOT_GRANTED_CODE = "permission.allowed_tool_not_granted";
/** One entry that reads as nothing, and the list it came from (a skill's names the skill and which of its two lists). */
export type AllowEntryInertNote = ({
    readonly source: "skill";
    readonly skill: string;
    readonly list: "allowed-tools" | "disallowed-tools";
} & AllowEntryInert) | ({
    readonly source: AllowEntrySource;
} & AllowEntryInert);
/**
 * A list entry spelled so a person reads what the engine read: the entry as a JSON string — quotes, backslashes and the usual
 * escapes — with every character that prints as nothing, or as a space, written as `\uXXXX` (`\u{…}` beyond the BMP) and a
 * run of spaces kept space by space. Uncapped and one-to-one (two entries never share a spelling), so a value that BINDS an
 * entry may hold it ({@link renderListEntry} is this, capped for a sentence).
 */
export declare function spelledListEntry(entry: string): string;
/**
 * THE ONE WRITER of a list entry into a sentence (the start-of-run notice, a skill's refusal and its decisions, a sub-agent
 * list's refusals and advisories): {@link spelledListEntry}, capped on what is printed.
 */
export declare function renderListEntry(entry: string): string;
/**
 * One entry that reads as nothing, as a person reads it: the entry as written (quoted, so a surrounding space shows) and why
 * — the reason word, with the spelling to write when the reading has one. The one phrasing the start-of-run notice and a
 * skill's refused activation share.
 */
export declare function inertEntryPhrase(e: AllowEntryInert): string;
/**
 * The notice for entries this grammar reads as nothing — delivered only when one exists: once per prepared task for the
 * skill and request lists (`sessionId` given), once per Runner for the deployment's list. The person whose list it is
 * reads it (audience `user`); the run goes on (an entry that grants nothing makes it ask more). A skill whose
 * `disallowed-tools` holds such an entry is named as one that does not activate.
 */
export declare function allowedToolsNotGrantedNotice(inert: readonly AllowEntryInertNote[], sessionId: string | undefined): EngineNotice;
