/**
 * CorrectionLoopDriver — the closed self-improvement loop for corrections (spec §3.6/§3.7/§3.8).
 *
 *   detect (Layer 0) → capture+distill → CorrectionLedger →
 *   gate (CorrectionAnalyzer) → ROUTE (this) → VERIFY (this).
 *
 * The headline safety property — "the loop can never change the agent's policy
 * or mint a proposal on its own" — is enforced BY CONSTRUCTION (spec §3.8). The
 * driver's injected capabilities are EXACTLY:
 *   - addAction            (open an Evolution Action — a tracked to-do)
 *   - createInitiative     (open a draft Initiative in needs-user)
 *   - feedbackLoopbackPost (POST the agent's OWN /feedback route — traverses
 *                           anomaly/quality/length guards; never FeedbackManager.submit)
 *   - recordPreference     (write .instar/preferences.json — explicit-preference
 *                           + gate-passed + policy-keyword-clean records ONLY)
 *   - attentionRoute       (route a candidate to the Attention queue for human
 *                           disposition — inferred prefs + policy-keyword matches)
 *
 * It is given NO ability to mint an EvolutionProposal (the ONLY thing the
 * autonomous auto-implement evaluator acts on) and NO direct write to MEMORY.md
 * / CLAUDE.md / feedback_*.md. So an auto-implemented policy change is
 * unreachable for anything this loop produces, regardless of
 * evolutionApprovalMode. A by-construction test pins ZERO proposals + ZERO
 * memory writes under autonomy ON.
 *
 * `kind` is signal, never authority — it routes a proposal / preferences write /
 * Attention item, never blocks or mutates on its own.
 */
import type { CorrectionLedger, CorrectionRecord } from './CorrectionLedger.js';
import type { CorrectionAnalyzer } from './CorrectionAnalyzer.js';
export declare function matchesPolicyRelaxation(learning: string): boolean;
/** The ONLY mutation capabilities the loop is given. Deliberately excludes any
 *  proposal-creation path AND any direct memory-file write (the by-construction
 *  authority guard, spec §3.8). */
export interface CorrectionLoopDeps {
    /** Open an Evolution Action (tracked self-improvement to-do). */
    addAction: (opts: {
        title: string;
        description: string;
        priority?: 'critical' | 'high' | 'medium' | 'low';
        source?: string;
        tags?: string[];
    }) => {
        id: string;
    };
    /** Open a draft Initiative in needs-user (a human approves turning it real). */
    createInitiative: (input: {
        id: string;
        title: string;
        description: string;
        phases: {
            name: string;
            status: string;
        }[];
        needsUser: boolean;
        needsUserReason?: string;
    }) => Promise<{
        id: string;
    }>;
    /** POST the agent's OWN /feedback route. NEVER FeedbackManager.submit()
     *  directly. May resolve to either a plain boolean (legacy: true=accepted) or a
     *  structured {posted, rateLimited} so the driver can distinguish a 429
     *  (rate-limited — carry the record to the next run) from a guard rejection
     *  (the guard doing its job — do NOT retry). The route's feedbackLimiter is
     *  10/min/IP, so a converged batch must serialize + back off (spec §10 Slice-2
     *  NEW-2). */
    feedbackLoopbackPost: (payload: {
        type: string;
        title: string;
        description: string;
    }) => Promise<boolean | FeedbackPostResult>;
    /** Write an explicit, gate-passed, policy-keyword-clean preference. */
    recordPreference: (payload: {
        learning: string;
        dedupeKey: string;
        confidence?: number;
    }) => void;
    /** Route a candidate to the Attention queue for human disposition. Resolves to
     *  true on delivery. */
    attentionRoute: (item: {
        id: string;
        title: string;
        summary: string;
        priority?: string;
    }) => Promise<boolean>;
    now?: () => number;
    /** Verify-window (preference path), default 7 days. */
    verifyWindowDaysPreference?: number;
    /** Verify-window (infra-gap path), default 14 days. */
    verifyWindowDaysInfraGap?: number;
    /** Max reopens before terminal `inconclusive` (default 2). */
    maxReopens?: number;
    /** Whether to actually POST infra-gap learnings to /feedback (default false —
     *  propose-only: queue a tracked Action + the human posts it). */
    autoFeedback?: boolean;
    /** Probe whether the loop-written preference entry still exists on disk
     *  (silence ≠ effective; verified requires the application persisted). */
    preferenceStillPresent?: (dedupeKey: string) => boolean;
    /** Max records routed per route() call (spec §10 Slice-2 NEW-5). Overflow
     *  stays `open` and is re-evaluated next run. Default 5. */
    maxRoutesPerTick?: number;
    /** Delay (ms) inserted between successive loopback /feedback POSTs so a
     *  converged infra-gap batch serializes under the route's 10/min IP limit
     *  (spec §10 Slice-2 NEW-2). Default 0 (no delay) — set in production wiring. */
    feedbackPostDelayMs?: number;
    /** Injectable sleep (testability) — defaults to a real setTimeout. */
    sleep?: (ms: number) => Promise<void>;
    /** Structured audit sink — one line per route/verify decision. Never throws. */
    audit?: (event: {
        decision: string;
        dedupeKey?: string;
        detail?: string;
    }) => void;
}
/** Structured loopback-POST result (spec §10 Slice-2 NEW-2). */
export interface FeedbackPostResult {
    /** True iff the route accepted (201). */
    posted: boolean;
    /** True iff the route returned 429 (rate-limited) — carry to the next run. */
    rateLimited?: boolean;
}
export interface RouteResult {
    routed: CorrectionRecord[];
    toFeedback: number;
    toPreferences: number;
    toAttention: number;
    /** Gate-crossing records NOT routed this run (per-tick ceiling OR a 429 cut the
     *  infra-gap batch short). They stay `open` and re-route next run. */
    overflow: number;
    /** True iff a loopback /feedback POST was rate-limited (429) this run, so the
     *  remaining infra-gap records were carried to the next run. */
    rateLimited: boolean;
}
export interface VerifyResult {
    evaluated: CorrectionRecord[];
}
export declare class CorrectionLoopDriver {
    private readonly ledger;
    private readonly analyzer;
    private readonly deps;
    constructor(ledger: CorrectionLedger, analyzer: CorrectionAnalyzer, deps: CorrectionLoopDeps);
    private now;
    private sleep;
    /**
     * ROUTE step (spec §3.6): for each gate-crossing record, route it by kind:
     *   user-preference + policy-keyword-clean → recordPreference()
     *   user-preference + policy-keyword-match → Attention (human disposes)
     *   infra-gap (autoFeedback ON)            → feedbackLoopbackPost()
     *   infra-gap (autoFeedback OFF, default)  → tracked Action + draft Initiative (propose-only)
     * Then open a verify window + move the record to acted-on. Idempotent: an
     * insight already past `open` is skipped by the analyzer's status:'open' filter.
     *
     * Bounded per run (spec §10 Slice-2):
     *  - PER-TICK CEILING (NEW-5): at most `maxRoutesPerTick` records route per run.
     *    Overflow stays `open` (re-routed next run); the overflow count is audited.
     *  - BATCHED + 429-RETRY (NEW-2): autoFeedback infra-gap POSTs serialize with
     *    `feedbackPostDelayMs` between them (the route's feedbackLimiter is 10/min/IP);
     *    on the FIRST 429 the batch stops — remaining infra-gap records stay `open`
     *    and are carried to the next run (no silent drop).
     */
    route(): Promise<RouteResult>;
    /**
     * VERIFY step (spec §3.7): for each `acted-on` record whose window has elapsed,
     * decide the outcome keyed on the SAME dedupeKey. The infra-gap path mirrors the
     * preference path's recurrence-after watcher with the path-appropriate window
     * and verdict (spec §10 Slice-2 infra-gap closed-loop verify):
     *   - recurrence-after on the SAME dedupeKey → reopen (capped at maxReopens →
     *     inconclusive). Keying on dedupeKey (not the coarse kind) prevents a
     *     false-reopen from an unrelated learning in the same regex bucket. Applies
     *     to BOTH kinds; infra-gap uses verifyWindowDaysInfraGap (default 14).
     *   - PREFERENCE silence ≠ effective. `verified` only when (a) the dedupeKey did
     *     not recur in the window AND (b) the loop-written preference entry is still
     *     present (not human-deleted as wrong). Otherwise inconclusive.
     *   - INFRA-GAP silence → `inconclusive`, NOT `verified`. Unlike a preference
     *     (where silence + persisted application closes the loop locally), the
     *     infra-gap fix is cross-org — Dawn ships it through Rising Tide. The agent
     *     cannot prove its /feedback proposal caused the fix, so silence (no
     *     recurrence, proposal still open) is inconclusive by design — never a
     *     false "verified" the agent didn't earn.
     */
    runVerification(): VerifyResult;
    /** Whether the dedupeKey logged any occurrence at/after a timestamp (recurrence). */
    private recurredSince;
}
//# sourceMappingURL=CorrectionLoopDriver.d.ts.map