/**
 * Headless approval policy for native runs.
 *
 * Background — issue #1 (private):
 *   Headless `runHeadless()` carried an `autoApprove` flag through CLI
 *   parsing but never installed `onToolApproval` on the conversation
 *   callbacks. Because the conversation loop only enforces a per-tool
 *   approval check when that callback exists, headless mode was effectively
 *   running with implicit auto-approve for every tool — including
 *   `bash`, `write`, `edit`, and `NotebookEdit`.
 *
 *   Interactive native REPL has separate task-scope write approval and
 *   may grow its own per-tool approval surface; headless does not, so
 *   "no callback" must mean "deny unsafe", not "allow everything".
 *
 * Policy rules — small, durable, deny-by-default:
 *   - Safe tools (read, glob, grep, list-mcp-resources, …) always allowed.
 *   - Structured file-mutation tools (write, edit, NotebookEdit) require
 *     `autoApprove: true` plus either an explicit task-contract write path
 *     or a high-confidence workspace-scoped code-change contract. The latter
 *     keeps benchmark/headless coding tasks usable while preserving the
 *     workspace boundary.
 *   - Bash/TaskCreate command execution remains classifier-gated:
 *     `safe_readonly` is allowed; needs_approval/dangerous/unknown are
 *     denied in unattended headless, even with --auto-approve.
 *   - AskUserQuestion is denied in unattended headless. A benchmark or
 *     CI run must produce a machine-readable result, not block on stdin.
 *   - The decision is recorded so `--json` output can show it (visible,
 *     bounded, test-covered per the issue's acceptance bar).
 *
 * P1 update — issue #2 (centralized bash risk classification):
 *   Bash is no longer treated as monolithically unsafe. The shared
 *   `classifyBashCommand()` is consulted; commands that classify as
 *   `safe_readonly` (pwd, ls, cat README.md, git status, rg ...) pass the
 *   gate without --auto-approve. Anything else (`needs_approval`,
 *   `dangerous`, `unknown`) is denied by default — including unknown,
 *   which preserves the P0 fail-closed contract.
 */
/**
 * Tools whose execution can mutate filesystem state, run arbitrary
 * shell, or otherwise have effects beyond reading bytes.
 *
 * Kept as a literal `Set` so the test suite can introspect it and so
 * adding a new mutating tool is one line in one place.
 *
 * Note: this is a SUPERSET of task-state's MUTATING_WRITE_TOOLS because
 * `bash` is not a "write" in task-scope terms but is unmistakably
 * "unsafe" for an unattended headless run.
 */
export declare const UNSAFE_HEADLESS_TOOLS: ReadonlySet<string>;
import { type BashRiskClassification, type BashRiskLevel } from './bash-risk.js';
import type { TaskExecutionState } from './protocol/types.js';
export type HeadlessApprovalDecision = {
    allowed: true;
    reason: 'safe-tool';
} | {
    allowed: true;
    reason: 'safe-bash';
    toolName: 'bash' | 'TaskCreate';
    bashRisk: BashRiskClassification;
} | {
    allowed: true;
    reason: 'workspace-test-bash';
    toolName: 'bash' | 'TaskCreate';
    bashRisk: BashRiskClassification;
} | {
    allowed: true;
    reason: 'task-contract-auto-approve';
    toolName: string;
} | {
    allowed: false;
    reason: 'deny-tool-explicit';
    toolName: string;
} | {
    allowed: false;
    reason: 'deny-tool-not-allowed';
    toolName: string;
} | {
    allowed: false;
    reason: 'deny-interactive';
    toolName: 'AskUserQuestion';
} | {
    allowed: false;
    reason: 'deny-by-default';
    toolName: string;
    bashRisk?: BashRiskClassification;
} | {
    allowed: false;
    reason: 'deny-bash-risk';
    toolName: 'bash' | 'TaskCreate';
    bashRisk: BashRiskClassification;
};
export interface HeadlessApprovalRecord {
    toolName: string;
    decision: HeadlessApprovalDecision;
}
export interface HeadlessApprovalPolicyOptions {
    /** When true, unsafe tools are auto-approved (headless --auto-approve). */
    autoApprove: boolean;
    /**
     * Optional per-run tool allowlist. This only narrows the base policy:
     * listed tools still have to pass their normal risk checks.
     */
    allowTools?: readonly string[];
    /** Optional per-run denylist. Deny wins over allow and base policy. */
    denyTools?: readonly string[];
    /**
     * Live task contract accessor. Headless --auto-approve is intentionally
     * narrower than TUI yolo: it can approve file mutations only when the
     * current user task declared explicit writable paths.
     */
    getTaskState?: () => TaskExecutionState | undefined;
    /** Optional sink for downstream visibility (JSON output, audit log). */
    onDecision?: (record: HeadlessApprovalRecord) => void;
}
/**
 * Build an `onToolApproval` callback that fits ConversationCallbacks.
 *
 * Returns `true` to allow execution, `false` to deny. The conversation
 * loop already turns a `false` into a non-mutating `tool_result` block
 * with `output: 'Tool execution denied by user.'` and
 * `isError: true`, so we don't need to throw or short-circuit the
 * agent loop here — denial is just first-class result data.
 */
export declare function buildHeadlessApprovalCallback(opts: HeadlessApprovalPolicyOptions): (toolName: string, input: Record<string, unknown>) => Promise<boolean>;
/**
 * Decide whether a tool call is permitted under the headless approval
 * policy. Pure: same inputs always produce the same decision.
 *
 * The optional `input` argument is consulted for `bash` so the bash
 * classifier can let safe read-only commands through without
 * `--auto-approve`. Other tools ignore `input`.
 */
export declare function decideHeadlessApproval(toolName: string, autoApprove: boolean, input?: Record<string, unknown>, taskState?: TaskExecutionState, toolPolicy?: HeadlessToolFilterPolicy): HeadlessApprovalDecision;
export declare function describeApprovalPolicy(autoApprove: boolean): string;
export interface HeadlessToolFilterPolicy {
    allowTools?: readonly string[];
    denyTools?: readonly string[];
}
export declare function normalizeHeadlessToolList(tools: readonly string[] | undefined): string[];
/**
 * Stable key into the bash risk taxonomy used for telemetry and JSON
 * serialization, kept here so that headless callers don't have to know
 * the bash-risk module exists.
 */
export type { BashRiskLevel, BashRiskClassification };
