import type { PermissionResult, ToolCallRequest } from "./tool-policy.js";
import type { PermissionMode } from "./ask-origin.js";
import { type PermissionSeatInputs, type PermissionSeatReading } from "./mode-policy.js";
import type { AgentTool } from "../internal/harness-types.js";
import { type AllowEntryGateSeats, type AllowEntryInertReason, type AllowEntryJudgeContext, type CompiledAllowEntry } from "./allow-entry.js";
/** Who wrote a row: the `Skill` tool on a successful activation, prepare for a skill the person invoked by name, or a
 *  delegated child's seed from its parent. */
export declare const SKILL_GRANT_ORIGINS: readonly ["model", "user", "inherited"];
export type SkillGrantOrigin = (typeof SKILL_GRANT_ORIGINS)[number];
/** The PORTABLE form of one row — what a delegated child captures and what a park checkpoint section freezes: the
 *  skill, the list it came from, and the entry as the skill spells it. The compiled reading is re-derived wherever a
 *  record is seeded (never trusted off the record). */
export interface SkillGrantRecord {
    readonly skill: string;
    readonly behavior: "allow" | "deny";
    readonly entry: string;
    readonly origin?: SkillGrantOrigin;
}
/** One row of the table. */
export interface SkillGrantRow {
    readonly skill: string;
    readonly origin: SkillGrantOrigin;
    readonly behavior: "allow" | "deny";
    readonly entry: string;
    readonly compiled: CompiledAllowEntry;
}
/** An entry the grammar reads as granting or refusing nothing. */
export interface SkillInertEntry {
    readonly skill: string;
    readonly list: "allowed-tools" | "disallowed-tools";
    readonly entry: string;
    readonly reason: AllowEntryInertReason;
}
/** The two lists a skill declares (the shape of a `SkillSpec`, read by name). */
export interface SkillGrantSource {
    readonly name: string;
    readonly allowedTools?: readonly string[];
    readonly disallowedTools?: readonly string[];
}
/**
 * The skill a `Skill` call's arguments name among `skills`: the definition whose `name` equals `args.skill` exactly —
 * case-sensitive, no alias, no trimming, first of a name (a prepared table is already deduplicated) — or undefined (no such
 * name, or a `skill` member that is not a string). The ONE resolution: the `Skill` tool activates through it, the card is
 * asked through it ({@link skillSeatReader}), a parked approval is bound and judged through it ({@link skillGrantDigest}) and
 * the person's invoked names are read through it ({@link seedSkillGrants}).
 */
export declare function skillNamedBy<T extends Pick<SkillGrantSource, "name">>(args: unknown, skills: readonly T[]): T | undefined;
/**
 * The digest of what a Skill card disclosed — `Execute skill: <name>` and the lists approving it releases: the skill's name
 * as the table spells it ({@link skillNamedBy} resolved it, so it equals the call's `skill` exactly) and its two lists in the
 * rule grammar's canonical spelling (`Tool()` / `Tool(*)` read as the bare name), de-duplicated and sorted, hashed as the
 * approval binding is hashed (`boundInputHashOf`). `undefined` — no skill named — digests as a nameless skill declaring
 * nothing (activating it grants nothing). Any change to the name or to either list changes it; the body does not. The read
 * point a parked Skill approval binds to (stored beside the row's input binding, compared before the resumed activation).
 */
export declare function skillGrantDigest(skill: Pick<SkillGrantSource, "name" | "allowedTools" | "disallowedTools"> | undefined): string;
/**
 * The digest a parked call to the engine's `Skill` tool binds — written by the park beside the row's input binding — or
 * undefined for any other call, and when no skill is loaded (no engine `Skill` tool is mounted, so a call by that name is
 * not an activation).
 */
export declare function skillCallGrantDigest(call: {
    readonly toolName: string;
}, args: unknown, skills: readonly SkillGrantSource[], skillToolName: string): string | undefined;
/**
 * The approving resume of a parked call, judged against the card it was asked under. A row is a `Skill` approval when it
 * carries a digest (the park said so), or when the resume would run the engine's `Skill` tool on it (skills loaded, the
 * row's wire name). For such a row: the refusal sentence when the skill the arguments name — as the resume's skills define
 * it, none loaded included — does not digest as the row's `boundGrantDigest`, or the row carries none (parked before the
 * binding); undefined otherwise. ONE judgement (the digest), judged at two sites: the claim (`site: "claim"`, the decided
 * bytes — the row stays pending: deny it, then activate again) and the resumed execution boundary (`site: "execution"`, the
 * bytes that will run, after every station that can rewrite them — the approval is spent: the call does not run). The
 * sentence says which side of the digest differs, read off the row's own arguments: the arguments name another skill than
 * the card's (`row.args`), or the card's skill no longer declares the lists the card showed (or is not served). Names the
 * skills, never a path; says the way out.
 */
export declare function parkedSkillApprovalRefusal(row: {
    readonly toolName: string;
    readonly args: unknown;
    readonly boundGrantDigest?: string;
}, args: unknown, skills: readonly SkillGrantSource[], skillToolName: string, site?: "claim" | "execution"): string | undefined;
/** A resume's skills read ONCE: each definition copied with its two lists, so the parked Skill approval's binding and the
 *  resumed leg's prepare read one value — a later edit to the caller's own objects or arrays reaches neither. */
export declare function detachSkillLists<T extends SkillGrantSource>(skills: readonly T[]): T[];
/** Does this skill declare a list (either, non-empty)? The one test of "the Skill card is asked for this skill". */
export declare function declaresSkillLists(skill: Pick<SkillGrantSource, "allowedTools" | "disallowedTools">): boolean;
/**
 * Compile one skill's two lists into rows (`origin` stamped on each) and the entries that read as nothing. An allow list
 * holding `*` voids that list whole (every other entry on it is reported too: the list grants nothing — the safe direction).
 * A `*` on the 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.
 */
export declare function compileSkillGrant(skill: SkillGrantSource, origin: SkillGrantOrigin): {
    rows: SkillGrantRow[];
    inert: SkillInertEntry[];
};
/** What spoke for a call: the skill and the entries it stands on. */
export interface SkillGrantHit {
    readonly skill: string;
    readonly entries: readonly string[];
}
/** The refusal a deny row writes. */
export declare function skillDenyDecision(hit: SkillGrantHit): PermissionResult;
/** The run's deny rows over `req` through `lane` — the refusal they write, or undefined (no lane, no row). The one
 *  reading the gate's regular decision, its approved-edit round and the resumed execution boundary share. */
export declare function skillRowRefusal(lane: Pick<SkillGrantLane, "denying"> | undefined, req: ToolCallRequest): PermissionResult | undefined;
/** The allow a grant writes (the allow layer's skill member). */
export declare function skillAllowDecision(hit: SkillGrantHit, updatedInput: unknown): PermissionResult;
/**
 * The Skill card's question: the reference implementation's sentence (`Execute skill: <name>`), and — when approving
 * releases anything — the entries it releases for the rest of the run in this mode (an entry that grants nothing, or
 * stands down in this mode, is not named). Deployment text, sanitized and capped.
 */
export declare function skillActivationQuestion(skill: SkillGrantSource, mode: PermissionMode | undefined): string;
/** The face the gate and the resumed execution boundary read the table through, bound to the leg's call facts. */
export interface SkillGrantLane {
    /** The allow layer's skill member: what grants this call in this mode, or undefined. */
    allowing(req: ToolCallRequest, mode: PermissionMode | undefined): SkillGrantHit | undefined;
    /** The run's deny rows: what refuses this call, or undefined. */
    denying(req: ToolCallRequest): SkillGrantHit | undefined;
}
/** The gate inputs the run's skill rows ride (a member group of `ToolGateInput`). */
export interface SkillGateSeats {
    /**
     * The active skills' rows for this run. DENY rows (a skill's `disallowed-tools`) are read where a person's deny rows are
     * read — on every decision right after them, and on an approved edit's bytes — and refuse with `decisionReason: "skill"`
     * (`deniedBy: "policy"`). ALLOW rows are the allow layer's member beside a person's stored allow rows, under the same
     * consumption predicate: they clear only an ask an allow rule may clear (never a mandated one, a hook's, an ask rule's,
     * governance's or a marked call's) and are not re-read on an approved edit. `onAllowed` observes a call they cleared (the
     * allow-side attribution; never affects the outcome). Absent ⇒ no skill rows.
     */
    skillGrants?: SkillGrantLane & {
        onAllowed?: (info: {
            toolName: string;
            toolCallId: string;
            skill: string;
            entries: readonly string[];
        }) => void;
    };
}
/** The `Skill` tool's per-call seat over the loaded skills: a skill that declares a list states no permission of its own. */
export type SkillSeatReader = (args: unknown, mode: PermissionMode | undefined) => PermissionSeatReading | undefined;
/** The reader over these skills (`undefined` when none is loaded): `Execute skill: <name>` for a skill declaring a list. */
export declare function skillSeatReader(skills: readonly SkillGrantSource[]): SkillSeatReader | undefined;
/**
 * The gate's seat inputs for one call, composed in ONE place: the mounted instance's static seat (`calledName`), the `Skill`
 * tool's per-call reader in the leg's live mode (only when the call's wire name is the engine's `Skill` — `skillToolName`),
 * the run's skill rows with their attribution sink, and the request's and the deployment's entry lists with theirs.
 */
export declare function skillGateWiring(opts: {
    tools: readonly AgentTool[];
    skillToolName: string;
    seatOf: SkillSeatReader | undefined;
    mode: () => PermissionMode | undefined;
    lane: SkillGrantLane;
    onAllowed: NonNullable<SkillGateSeats["skillGrants"]>["onAllowed"];
    /** The two entry lists that are not a skill's (the request's, the deployment's), with their attribution sinks. */
    allowEntries: AllowEntryGateSeats;
}): (calledName: string, wireName: string) => PermissionSeatInputs & SkillGateSeats & AllowEntryGateSeats;
/**
 * Seed a task's table at prepare, before any call is gated: the rows from outside this leg's own writers (`inherited` — a
 * parent's capture, held until this child ends, and a resumed leg's frozen rows, which keep the word `model` where the
 * model wrote them) and the skills the person invoked by name (`user` — the invocation is the statement, so no card). Every invoked
 * name must be one of the loaded skills; anything else (or a value that is not a list of names) refuses the run loudly
 * (`config.user_invoked_skill_unknown`), never dropped. Returns the entries the grammar reads as nothing, across every
 * loaded skill — the start-of-run notice's content.
 */
export declare function seedSkillGrants(table: SkillGrantTable, opts: {
    skills: readonly SkillGrantSource[];
    userInvokedSkills: unknown;
    inherited: readonly SkillGrantRecord[] | undefined;
}): readonly SkillInertEntry[];
/** The per-task table. Identity is the contract: the `Skill` tool, prepare's seeds, the tool ctx's snapshot and the
 *  lane all hold this one object. */
export declare class SkillGrantTable {
    private rowsHeld;
    /** The table never holds the same row twice (skill, origin, list, entry) — one rule for both writers: a re-activation, a
     *  capture re-supplied beside the frozen rows that already carry it. Keyed on the ROW, not the skill: a definition that
     *  changed across a park writes its new rows when it is activated again. */
    private hold;
    /** Write a skill's rows (rows already held are not held twice). Returns the entries that read as nothing. */
    activate(skill: SkillGrantSource, origin: SkillGrantOrigin): readonly SkillInertEntry[];
    /** Seed portable records (a delegated child's capture, a resumed leg's frozen rows): a record the model wrote keeps that
     *  word, every other record seeds under `origin` — `user` is written only from this leg's own spec, never seeded. */
    seed(records: readonly SkillGrantRecord[], origin: SkillGrantOrigin): void;
    /** The rows as portable records (a copy). */
    records(): readonly SkillGrantRecord[];
    /** The lane over this table, bound to the leg's call facts. */
    lane(ctx: AllowEntryJudgeContext): SkillGrantLane;
}
/** Read a delegated child's capture ({@link readCarriedRecords}): `undefined` refuses the delegation. */
export declare function readSkillGrantCapture(snapshot: readonly unknown[] | undefined): readonly SkillGrantRecord[] | undefined;
/** The section a park freezes (`CheckpointState.skillGrants`): the table's rows under the frozen origins, or undefined
 *  when there are none (an absent section IS zero rows on every reader). */
export declare function frozenSkillGrants(table: Pick<SkillGrantTable, "records">): SkillGrantRecord[] | undefined;
/** Read a park's frozen section ({@link readCarriedRecords}): absent ⇒ none; `undefined` ⇒ damaged — the resume refuses
 *  it before the claim and prepare never seeds from it. */
export declare function readFrozenSkillGrants(section: unknown): readonly SkillGrantRecord[] | undefined;
/** The refusal for a `TaskSpec.userInvokedSkills` name the run does not carry (or a value that is not a list of names). */
export declare const USER_INVOKED_SKILL_UNKNOWN_CODE = "config.user_invoked_skill_unknown";
