/**
 * report_tool_issue — automated QA tool for tracking unexpected tool behavior.
 *
 * Enabled by default; gated behind PI_AUTO_QA=1 / `dev.autoqa` so a user
 * who flips the setting off short-circuits injection entirely.
 * Always injected into every agent (including subagents) regardless of tool selection.
 * Records grievances to a local SQLite database; never throws.
 *
 * Before the first record lands, the user's consent is checked. If they've
 * never been asked (`dev.autoqa.consent === "unset"`) the process-global
 * consent handler — wired by `InteractiveMode` to a Yes/No popup — is
 * invoked exactly once and the decision is persisted. Subsequent calls
 * (including from subagents) read the cached decision without prompting.
 *
 * When the user grants consent, push is automatically active against the
 * bundled endpoint (`dev.autoqaPush.endpoint`, default `qa.omp.sh`). Each
 * insert schedules a background flush that POSTs pending rows and deletes
 * them on HTTP 2xx. `PI_AUTO_QA_PUSH=1` forces push in non-interactive
 * environments where the consent dialog never fires. Tool execution is
 * never blocked on the network and never throws.
 */
import { Database } from "bun:sqlite";
import type { AgentTool } from "@oh-my-pi/pi-agent-core";
import type { FetchImpl } from "@oh-my-pi/pi-ai";
import type { Settings } from "../index.js";
import type { ToolSession } from "./index.js";
export declare function isAutoQaEnabled(settings?: Settings): boolean;
/**
 * Resolver for the user's "share grievances?" consent.
 *
 * Return values:
 *   - `true`  — user agreed; record + ship for this run and persist.
 *   - `false` — user declined; suppress for this run and persist.
 *   - `null`  — user dismissed the dialog (ESC, click-away, …) without
 *               picking an option. The decision is NOT cached or persisted,
 *               so the next `report_tool_issue` invocation re-prompts.
 *
 * Persistence is the tool's job (so subagent invocations can persist into
 * the disk-backed `Settings` instance the host registered alongside the
 * handler), not the handler's. Implementations live in hosts that have UI
 * affordances — today only `InteractiveMode`. When no handler is
 * registered (CLI subcommands, tests, non-interactive runs) consent
 * defaults to `false` — the explicit "don't collect by default" stance.
 */
export type AutoQaConsentHandler = () => Promise<boolean | null>;
/**
 * Register the consent handler and the persistent {@link Settings} instance
 * the decision should be written to. Passing `null` clears the handler
 * (e.g. on `InteractiveMode` teardown). Re-registration is authoritative.
 */
export declare function setAutoQaConsentHandler(handler: AutoQaConsentHandler | null, persistentSettings?: Settings | null): void;
/** Test-only: clear consent cache + handler. Never call from production code. */
export declare function __resetAutoQaConsentForTests(): void;
/**
 * Resolve the user's consent for `report_tool_issue` grievances.
 *
 * Precedence (highest first):
 *   1. Process-global cache (set on first successful resolution).
 *   2. Persistent setting (`dev.autoqa.consent` on the supplied `Settings`).
 *   3. Persistent setting on the registered host `Settings`.
 *   4. Consent handler popup (single-flight; persists the answer).
 *   5. Default-deny when no handler is registered.
 *
 * Never throws — handler errors degrade to "denied for this call" without
 * caching, so a subsequent invocation can re-prompt instead of being
 * permanently locked into the false branch.
 */
export declare function resolveAutoQaConsent(settings: Settings | undefined): Promise<boolean>;
/**
 * Open (or return the cached handle for) the auto-QA SQLite database at
 * `~/.omp/agent/autoqa.db`. Idempotently runs schema creation, the
 * `pushed`-column migration, and index setup so every consumer — tool
 * execute path, manual `omp grievances push`, future debug scripts —
 * sees the same prepared schema. Returns `null` only on a hard open
 * failure (filesystem permissions, etc.); a missing file is created.
 *
 * Exported because the `omp grievances` CLI handlers need the migrated
 * handle too — having a second `openDb` in the CLI led to the column
 * never being added on the manual-push path.
 */
export declare function openAutoQaDb(): Database | null;
export interface FlushResult {
    pushed: number;
    ok: boolean;
    skipped?: boolean;
}
/**
 * Optional per-flush controls. Used by `omp grievances push` to surface
 * progress to a TTY and to skip the user-facing consent gate (manual
 * pushes are the user's explicit intent, not a side effect of a tool call).
 */
export interface FlushOptions {
    /**
     * Skip the `dev.autoqa.consent === "granted"` gate in
     * {@link resolvePushConfig}. Endpoint configuration is still required.
     * Reserved for explicit user-driven pushes (CLI `grievances push`,
     * future debug recipes); never set from the tool's auto-flush path.
     */
    bypassConsent?: boolean;
    /**
     * Fetch implementation for the push POST. Defaults to global fetch.
     */
    fetch?: FetchImpl;
    /**
     * Fires once at the start of the loop with the snapshot count of
     * unpushed rows. Subsequent inserts won't be reflected (the count is
     * a planning hint for progress reporters, not a live total).
     */
    onStart?: (totalUnpushed: number) => void;
    /**
     * Fires after every successfully shipped batch with the running pushed
     * count. Reporters compare against the `totalUnpushed` they saw in
     * `onStart` to advance their bar.
     */
    onProgress?: (pushedSoFar: number) => void;
}
/** Test-only: clear single-flight + cooldown state. Never call from production code. */
export declare function __resetAutoQaFlushStateForTests(): void;
/**
 * Flush queued grievances to the configured backend.
 *
 * Single-flight: concurrent callers share the in-flight promise. After a
 * failed push, retries are skipped for {@link FAILURE_COOLDOWN_MS} ms.
 * Never throws — all errors are caught and routed to the logger.
 */
export declare function flushGrievances(db?: Database, settings?: Settings, options?: FlushOptions): Promise<FlushResult>;
export declare function createReportToolIssueTool(session: ToolSession, activeBuiltinNames?: readonly string[]): AgentTool;
