import type { ExecutionEnv } from "../internal/harness-types.js";
import type { PermissionResult, ToolPolicy } from "./tool-policy.js";
import { type PathGuardRow } from "./path-guard-rows.js";
/** One write domain SOURCE as an allow row of the one table: it reaches every location at or below one of its admitted keys.
 *  The write gate's three sources, and a session rule's `allowDirs` (the confinement that admits a write only inside them). */
export declare function domainRow(source: "advertised" | "configured" | "accepted" | "session", dirs: readonly string[]): PathGuardRow;
/** design/388 B22 — the identity triple the exemption probe hands the store beside the name. */
export interface ToolCallIdentity {
    capabilityId: string;
    contractId: string;
    shapeDigest: string;
}
/** Options for {@link createFsWriteGatePolicy}. */
export interface FsWriteGatePolicyOptions {
    /** The task's real execution env (the one the hands run against) — canonicalization must see the
     *  actual filesystem (a remote/E2B task resolves in its container). */
    env: ExecutionEnv;
    /** The FALLBACK base a relative path resolves against (omit = paths resolve as given). The
     *  call's TARGET prefers the live tracked cwd when the engine stamps one ({@link ToolCallRequest.cwd});
     *  the `acceptDirs`/`exemptDirs` entries below always resolve against THIS value. */
    rootPath?: string;
    /** Writes whose canonical target lands inside one of these dirs are ALLOWED (the accept-session
     *  domain, e.g. the cwd subtree after "allow all edits during this session"). */
    acceptDirs?: readonly string[];
    /** Writes whose canonical target lands inside one of these dirs are ALLOWED and never asked
     *  (auto-approved working areas: the scratchpad dir, plan files). Checked before `acceptDirs`
     *  (same verdict — the split is intent/observability, exemptions are structural not session-won).
     *  An entry that RESOLVES onto `rootPath` — or above it — grants nothing: a domain that holds the
     *  root is not a working area but the whole workspace, and a symlinked scratchpad is all it takes.
     *  Same rule, same predicate as the prompt's advertised writable directories; say "every write here
     *  is pre-approved" with `defaultWrite: "allow"` instead. `acceptDirs` is NOT judged by it (a person
     *  may grant the whole root for a session — see the module header). */
    exemptDirs?: readonly string[];
    /** Verdict for a covered write OUTSIDE every domain: `"ask"` (the manual-mode default) routes it
     *  to the ask-resolution chain (live onAsk / durable park / headless deny); `"allow"` is the
     *  acceptEdits-mode shape (domain checks still run so a sensitive-path deny composes unchanged). */
    defaultWrite: "ask" | "allow";
    /** The ask the default verdict mints in place of the gate's ordinary write question — a permission mode's own
     *  sentence over the resolved `path`, with the gate's domain note (a configured domain that was not honored) to
     *  append when there is one. Read only where `defaultWrite` is `"ask"`. */
    defaultAsk?: (path: string, note: string | undefined) => PermissionResult;
    /**
     * Session-exemption lookup ("allow all for this session" grants recorded by the deployment's approval
     * surface). Consulted ONCE per covered write, after the domain checks and immediately BEFORE the gate
     * would produce its `ask`/default verdict — a `true` return short-circuits to `allow` (with a message
     * naming the exemption source for the audit trail) so an already-granted write does not re-ask/park.
     *
     *  · `toolName` is the CANONICAL tool name (same normalization this gate matches on), so an exemption
     *    recorded under either alias of a tool matches both — key your store with the same normalization.
     *  · `canonicalPath` is the CANONICALIZED real target (the exact key the gate's own symlink-safe
     *    containment judged) — a symlink alias of an exempted file therefore still hits the exemption,
     *    and an exemption can never be minted for a raw alias that resolves elsewhere.
     *  · FAIL-CLOSED: a throwing/rejecting lookup counts as "not exempt" (the write asks as before) —
     *    an exemption-store outage must never widen the gate.
     *  · Cannot override a DENY: this factory never denies; a sensitive-path deny composed alongside via
     *    `combinePolicies` outranks this `allow` under the deny > ask > allow fold, and the two fail-closed
     *    asks for an UNRESOLVABLE target fire before any canonical key exists, so they are never exempted.
     */
    isExempt?: (toolName: string, canonicalPath: string, identity?: ToolCallIdentity) => boolean | Promise<boolean>;
    /**
     * design/380 O13 — the deployment HARD-CLOSE knob for guarded writes. Armed (`true`), a covered
     * write whose env does NOT provide `writeFileGuarded` is REFUSED (deny, typed message) — never the
     * plain-writeFile fallback: for a deployment that exists to close the adjudicate→write TOCTOU
     * window, a silent advisory downgrade would open the hole right beside its patch. The version-skew
     * arm is the same refusal (an older adapter without the method IS an env without the capability).
     * Default off = every verdict ACTION exactly as before (the capability's ABSENCE is still disclosed
     * on the ask face either way — see the advisory sentence at the ask sites). The knob lives on the
     * deployment's gate options, not in core-global state: core stays lane-agnostic (no device concept
     * here); the deployment that runs guarded-capable envs arms it.
     *
     * WHAT ARMED DOES AND DOES NOT CLOSE (honesty boundary): armed guarantees every covered write lands
     * through an ATOMIC precondition-verified backend step, closing the tool's own canonicalize→write
     * window. It does NOT bind THIS GATE's adjudicated canonical key across an approval wait: the tool
     * re-canonicalizes at execute time, so a symlink swapped between this gate's verdict and the tool's
     * execution is re-resolved (then atomically verified against the NEW resolution). Closing that
     * remaining window needs the adjudicated key carried through a trusted approval receipt into tool
     * execution — a separate seat, deliberately not smuggled into this knob.
     */
    requireGuardedWrite?: boolean;
}
/** The coded refusal a gate wired with a root-covering exempt domain throws at CONSTRUCTION — the
 *  `config.*` prepare-refusal family (one exported spelling per member, thrown so the task never
 *  starts), so a deployment can compare against this constant instead of matching message text. */
export declare const WRITE_EXEMPT_DIR_COVERS_ROOT_CODE = "config.write_exempt_dir_covers_root";
/**
 * Build the file-write approval gate policy. Mount via `combinePolicies` alongside the deployment's
 * other layers (sensitive-path deny, session rules, caller policy) — see the module header for the
 * layering contract. Idempotent + side-effect free per {@link combinePolicies}'s requirement.
 */
export declare function createFsWriteGatePolicy(opts: FsWriteGatePolicyOptions): ToolPolicy;
