/**
 * Decide which health drift becomes a ticket, and which is already tracked.
 *
 * The scheduled health consumer's whole difficulty is idempotency: a nightly
 * cron that refiles the same drift every night is worse than no cron at all,
 * because it trains people to ignore the tickets it files. Everything here
 * exists to make "the same drift" a decidable question.
 *
 * ## Dedupe is per CHECK, not per drift set
 *
 * The marker fingerprints the check id. Fingerprinting the whole finding set
 * would mean one added finding produces a brand-new ticket while the old one
 * still stands, so a slowly-degrading project accumulates near-duplicates —
 * the same "worse than no cron" outcome by a slightly different route. Per
 * check also makes partial repair behave: fix one drifting check, its ticket
 * closes, the others stay open on their own merits.
 *
 * ## A closed ticket does not suppress live drift
 *
 * Enforced by construction rather than by a conditional: this planner is given
 * only the OPEN tickets, so a closed one cannot suppress anything. It is not
 * that closed tickets are checked and then ignored — they are not in evidence.
 *
 * The alternative, treating closure as permanent suppression, means closing a
 * ticket without fixing anything makes that drift invisible forever, which is
 * the silent decay this consumer exists to prevent. Suppression should be a
 * configured declaration visible in a diff, not a side effect of somebody
 * tidying a backlog. Turning the check off in config is the sanctioned way.
 * @module health/drift-tickets
 */
import type { HealthFinding } from "./contract.js";
/** Marker prefix written into a filed ticket so the next run can find it. */
export declare const DRIFT_MARKER_PREFIX = "lisa-health-drift";
/**
 * The dedupe marker for one check.
 *
 * An HTML comment so it is invisible in rendered ticket bodies but present in
 * the raw text every tracker returns. Trackers differ in what they preserve of
 * a body; they do not differ in preserving its characters.
 * @param check - The health check id
 * @returns The marker to embed in a filed ticket
 */
export declare function driftMarker(check: string): string;
/** A ticket already open in the tracker, reduced to what dedupe needs. */
export interface OpenTicket {
    readonly id: string;
    readonly body: string;
}
/** One ticket the consumer should file. */
export interface DriftTicket {
    readonly check: string;
    readonly title: string;
    readonly body: string;
    readonly marker: string;
}
/** Drift already covered by an open ticket, reported rather than dropped. */
export interface TrackedDrift {
    readonly check: string;
    readonly ticketId: string;
}
/** What a scheduled run should do about the drift it found. */
export interface DriftTicketPlan {
    readonly file: readonly DriftTicket[];
    readonly alreadyTracked: readonly TrackedDrift[];
}
/**
 * Inputs to a planning pass.
 *
 * `openTickets` is deliberately named for its own precondition. A caller that
 * passes closed tickets defeats the ruling above, and a parameter called
 * `tickets` would not have told them so.
 */
export interface DriftTicketInput {
    readonly findings: readonly HealthFinding[];
    readonly openTickets: readonly OpenTicket[];
}
/**
 * Decide what to file for the drift a run found.
 *
 * Total and pure: every unique drifting check lands in exactly one of `file` or
 * `alreadyTracked` after duplicate findings for that check collapse, so a caller
 * reporting "nothing to do" is asserting it looked at all checks rather than
 * that its filter happened to be empty.
 * @param input - Findings from the run and the tracker's OPEN tickets
 * @returns Tickets to file, and drift already covered
 */
export declare function planDriftTickets(input: DriftTicketInput): DriftTicketPlan;
//# sourceMappingURL=drift-tickets.d.ts.map