import type { TaskSpec } from "./types.js";
/** Thrown when `overrides` would LOOSEN a safety field `base` already set (a tighten-only violation). */
export declare class TaskSpecTightenError extends Error {
    constructor(message: string);
}
/**
 * Merge `overrides` onto `base` with TIGHTEN-ONLY semantics for the safety-bearing fields. Non-safety fields
 * follow plain last-wins object spread (`overrides` value wins when present, else `base`). The safety fields
 * get explicit rules:
 *
 *  - **`toolPolicy`** — both set ⇒ `combinePolicies(base, override)` (deny-wins; the base's denials survive,
 *    the override can only ADD denials/asks). Either alone ⇒ that one. This is the central fix: a blind spread
 *    would drop the base policy entirely.
 *  - **every row of the clamp table** (`CLAMP_SET`: `handsReadOnly`, `interactiveTools`, `approvalReach`, the two
 *    containment faces, `readDenyPatterns`, `oneShot`, `memoryPersistenceCapable`, `fileHistory`, `promptForm`) — a base carrying the
 *    row's restricting value meeting an override that states a different one ⇒ **throw** (loosening); otherwise the
 *    restricting value wins if either side carries it, an add-only list unions, and an override writing `undefined`
 *    erases nothing.
 *  - **`shellGate`** — one value (`"always"`, the operator floor). Either side set ⇒ the floor stands; it cannot
 *    be loosened because absence is the only other state and an override cannot unset a base value.
 *  - **`onAsk`** — no safe automatic merge (the approver and the policy must be coordinated). Both set to
 *    DIFFERENT values ⇒ **throw**; equal ⇒ keep; one set ⇒ that one.
 *  - **`mods`** — both set ⇒ both ride, base first then override (the task seat is a list and the bus composes it:
 *    a registration only ever adds a handler to the chain; names stay unique, refused at admission otherwise).
 *    One set ⇒ that one.
 *
 * @throws {TaskSpecTightenError} when an override would loosen a stricter base safety field, or when two
 * incompatible safety values are both set and cannot be merged automatically.
 */
export declare function tightenTaskSpec(base: TaskSpec, overrides: Partial<TaskSpec>): TaskSpec;
