/**
 * Persistent store for supersede markers (PR9b).
 *
 * Each marker records a `failureModeHash` whose root cause has supposedly
 * been fixed by a strategy patch. Future occurrences of the same hash get
 * downweighted at injection time so the agent doesn't keep tripping over
 * a failure mode the system already addressed.
 *
 * The state machine intentionally splits "patch landed on main"
 * (`active_canary`) from "patch survived the observation window" (`active`)
 * — recurrence during the canary period flips the marker to `failed` and
 * restores the old negative-pattern weight. This is the §12 design point
 * Codex flagged in Round 4: a green CI is not the same as a real fix.
 *
 * See docs/architecture/self-improving-design.md §12 (Supersede State Machine).
 */
import Database from 'better-sqlite3';
export type SupersedeState = 'pending_review' | 'active_canary' | 'active' | 'failed' | 'rejected' | 'drifted' | 'reverted';
export interface SupersedeMarker {
    id: string;
    failureModeHash: string;
    strategyFile: string;
    strategyContentHash: string;
    patchFingerprint: string;
    phaseHintId: string | null;
    gitCommit: string | null;
    prNumber: number | null;
    state: SupersedeState;
    createdAt: number;
    updatedAt: number;
    observationStartedAt: number | null;
    observationDays: number;
    observationCount: number;
    observationCountTarget: number;
    recurrenceCount: number;
    lastError: string | null;
}
export interface UpsertMarkerInput {
    failureModeHash: string;
    strategyFile: string;
    strategyContentHash: string;
    patchFingerprint: string;
    phaseHintId?: string;
    gitCommit?: string;
    prNumber?: number;
    observationDays?: number;
    observationCountTarget?: number;
}
export interface SupersedeStoreOptions {
    dbPath?: string;
}
export declare function openSupersedeStore(opts?: SupersedeStoreOptions): SupersedeStoreHandle;
export declare class SupersedeStoreHandle {
    private readonly db;
    constructor(db: Database.Database);
    /**
     * Insert a new marker in `pending_review` state, or return null if a
     * marker for the same hash already exists in an active state. Callers
     * decide whether the duplicate is a problem; this returns null silently
     * so the caller can branch without try/catch.
     */
    createPendingReview(input: UpsertMarkerInput): SupersedeMarker | null;
    /**
     * Promote a pending_review marker to active_canary because its PR merged.
     * No-op (returns null) if the marker is not in pending_review state, so
     * callers can safely retry without compensating logic.
     */
    startCanaryObservation(input: {
        failureModeHash: string;
        strategyContentHash?: string;
        patchFingerprint?: string;
        gitCommit?: string;
    }): SupersedeMarker | null;
    /**
     * Record one full-path analysis observation against the active_canary
     * marker for `failureModeHash` and return the (possibly transitioned)
     * marker. Once `observationCount` reaches `observationCountTarget` and
     * the elapsed time exceeds `observationDays`, the marker auto-promotes
     * to `active`.
     */
    recordObservation(failureModeHash: string, now?: number): SupersedeMarker | null;
    /**
     * Recurrence detected — flip an active_canary marker back to `failed` so
     * the old negative-pattern weight is restored. Returns the marker that
     * was failed (null if there was nothing to fail).
     */
    recordRecurrence(failureModeHash: string): SupersedeMarker | null;
    /** Mark the marker `rejected` because the PR was closed without merge. */
    markRejected(failureModeHash: string): SupersedeMarker | null;
    /** Drift transition (pure write — caller has already detected drift). */
    markDrifted(failureModeHash: string): SupersedeMarker | null;
    /** Patch was reverted on main — restore old weights. */
    markReverted(failureModeHash: string): SupersedeMarker | null;
    /**
     * Returns the currently active (or canary) marker for a failure-mode hash,
     * or null. "Active" here means any state in which the marker still
     * influences injection weights (i.e. excludes `failed`, `rejected`,
     * `reverted`).
     */
    findActiveByHash(failureModeHash: string): SupersedeMarker | null;
    getById(id: string): SupersedeMarker | null;
    /** Used by tests + the monitoring PR. */
    countByState(): Record<SupersedeState, number>;
    schemaVersion(): number;
    close(): void;
    private transitionTo;
}
/**
 * Read-only handle factory for callers (recall_patterns and the
 * future stdio MCP host) that must NOT create / migrate / mutate
 * the supersede store.
 *
 * Returns null when the store does not yet exist on disk, signalling
 * the caller to fall back to the no-marker default (weight 1.0).
 * This is the prerequisite from Plan 41 M1a for upgrading
 * `recall_patterns` from `internal` back to `public-readonly`
 * exposure: `openSupersedeStore` triggers `mkdir` + sqlite migration
 * which is incompatible with read-only classification, while this
 * adapter performs no writes.
 *
 * Underlying sqlite open uses `{readonly: true, fileMustExist:
 * true}` so any accidental mutation attempt throws at the SDK
 * layer rather than silently dirty-ing the database.
 */
export declare function openSupersedeStoreReadOnly(opts?: SupersedeStoreOptions): SupersedeStoreHandle | null;
/**
 * Injection-time weight modifier for a failure mode. Returns 1.0 when no
 * marker is active, the §4 weight otherwise. Pure read-only — callers are
 * the negative-pattern injection path and the monitoring dashboard.
 */
export declare function injectionWeightForSupersede(marker: SupersedeMarker | null): number;
export declare const __testing: {
    DEFAULT_OBSERVATION_DAYS: number;
    DEFAULT_OBSERVATION_COUNT_TARGET: number;
};
//# sourceMappingURL=supersedeStore.d.ts.map