/**
 * Retrospect schemas + pure helpers for `totem retrospect <pr>`
 * (mmnto-ai/totem#1713).
 *
 * Substrate of the bot-tax cluster — the deterministic circuit-breaker
 * that fires when a PR has accumulated enough bot-review rounds to
 * suggest the loop has stalled. Reuses `recurrence-stats.ts` primitives
 * (`computeSignature`, `normalizeFindingBody`, `toSeverityBucket`) so
 * the bot-tax cluster (#1715 / #1714 / #1713) has a single severity +
 * signature vocabulary.
 *
 * Everything in this file is pure: Zod schemas + deterministic helpers.
 * No I/O, no command logic. No LLM. No GitHub API writes.
 */
import { z } from 'zod';
/** A push-grouped review round on the target PR. */
export declare const RetrospectRoundSchema: z.ZodObject<{
    /** 1-based, monotonically increasing in submission order. */
    roundNumber: z.ZodNumber;
    /** ISO 8601 timestamp of the earliest review submission for this round. */
    submittedAt: z.ZodString;
    /** PR head SHA at review time; absent when the upstream review record lacks `commit_id`. */
    headSha: z.ZodOptional<z.ZodString>;
    /** Number of bot findings tied to this round. */
    findingCount: z.ZodNumber;
}, "strip", z.ZodTypeAny, {
    roundNumber: number;
    submittedAt: string;
    findingCount: number;
    headSha?: string | undefined;
}, {
    roundNumber: number;
    submittedAt: string;
    findingCount: number;
    headSha?: string | undefined;
}>;
export type RetrospectRound = z.infer<typeof RetrospectRoundSchema>;
/**
 * Classification verdict for a single bot finding.
 *
 * - `route-out` — finding is better tracked as a follow-up issue than blocking the current PR.
 * - `in-pr-fix` — finding should be addressed before merge.
 * - `undetermined` — no heuristic signal fired; contributor judgment.
 */
export declare const RetrospectClassificationSchema: z.ZodEnum<["route-out", "in-pr-fix", "undetermined"]>;
export type RetrospectClassification = z.infer<typeof RetrospectClassificationSchema>;
/**
 * Closed catalog of `route-out` reasons. The Zod-side mirror of
 * `RETROSPECT_ROUTE_OUT_REASONS` (defined later in the file). Used by the
 * discriminated `RetrospectFindingSchema` to enforce the deterministic
 * contract: every `route-out` finding carries a reason from this enum, and
 * non-route-out findings forbid the field entirely. Per CR mmnto-ai/totem#1734
 * round-2.
 */
export declare const RetrospectRouteOutReasonSchema: z.ZodEnum<["covered by existing compiled rule", "rule-covered class flagged late — retroactive shouldn’t block ship", "frequent across other PRs — file follow-up to compile into a rule", "low/nit severity flagged late in the bot-review loop"]>;
/**
 * Discriminated union on `classification`: `route-out` requires a reason from
 * the closed catalog; `in-pr-fix` and `undetermined` forbid the field entirely.
 * Per CR mmnto-ai/totem#1734 round-2 — the prior `routeOutReason: z.string().optional()`
 * leaked the deterministic contract.
 */
export declare const RetrospectFindingSchema: z.ZodDiscriminatedUnion<"classification", [z.ZodObject<{
    /** Stable signature hash (16-char) — matches the recurrence-stats vocabulary. */
    signature: z.ZodString;
    /** Source bot/tool. */
    tool: z.ZodEnum<["coderabbit", "gca", "greptile", "sarif", "override", "unknown"]>;
    /** Normalized severity bucket. */
    severityBucket: z.ZodEnum<["critical", "high", "medium", "low", "nit"]>;
    /** First 280 chars of the raw body (for human triage). */
    bodyExcerpt: z.ZodString;
    /** File path attached to the finding (`(review body)` for CR outside-diff/nits). */
    file: z.ZodString;
    /** Best-effort line number. */
    line: z.ZodOptional<z.ZodNumber>;
    /** Round number assigned by `groupFindingsByRound`. */
    roundNumber: z.ZodNumber;
    /** Count of OTHER PRs sharing this signature (target PR excluded). */
    crossPrRecurrence: z.ZodNumber;
    /** True if the signature heuristically maps to an existing compiled rule (Jaccard ≥ 0.6). */
    coveredByRule: z.ZodBoolean;
} & {
    classification: z.ZodLiteral<"route-out">;
    /** Reason from the closed catalog (`RETROSPECT_ROUTE_OUT_REASONS`). */
    routeOutReason: z.ZodEnum<["covered by existing compiled rule", "rule-covered class flagged late — retroactive shouldn’t block ship", "frequent across other PRs — file follow-up to compile into a rule", "low/nit severity flagged late in the bot-review loop"]>;
}, "strip", z.ZodTypeAny, {
    file: string;
    signature: string;
    tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
    severityBucket: "high" | "critical" | "medium" | "low" | "nit";
    coveredByRule: boolean;
    roundNumber: number;
    bodyExcerpt: string;
    crossPrRecurrence: number;
    classification: "route-out";
    routeOutReason: "covered by existing compiled rule" | "rule-covered class flagged late — retroactive shouldn’t block ship" | "frequent across other PRs — file follow-up to compile into a rule" | "low/nit severity flagged late in the bot-review loop";
    line?: number | undefined;
}, {
    file: string;
    signature: string;
    tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
    severityBucket: "high" | "critical" | "medium" | "low" | "nit";
    coveredByRule: boolean;
    roundNumber: number;
    bodyExcerpt: string;
    crossPrRecurrence: number;
    classification: "route-out";
    routeOutReason: "covered by existing compiled rule" | "rule-covered class flagged late — retroactive shouldn’t block ship" | "frequent across other PRs — file follow-up to compile into a rule" | "low/nit severity flagged late in the bot-review loop";
    line?: number | undefined;
}>, z.ZodObject<{
    /** Stable signature hash (16-char) — matches the recurrence-stats vocabulary. */
    signature: z.ZodString;
    /** Source bot/tool. */
    tool: z.ZodEnum<["coderabbit", "gca", "greptile", "sarif", "override", "unknown"]>;
    /** Normalized severity bucket. */
    severityBucket: z.ZodEnum<["critical", "high", "medium", "low", "nit"]>;
    /** First 280 chars of the raw body (for human triage). */
    bodyExcerpt: z.ZodString;
    /** File path attached to the finding (`(review body)` for CR outside-diff/nits). */
    file: z.ZodString;
    /** Best-effort line number. */
    line: z.ZodOptional<z.ZodNumber>;
    /** Round number assigned by `groupFindingsByRound`. */
    roundNumber: z.ZodNumber;
    /** Count of OTHER PRs sharing this signature (target PR excluded). */
    crossPrRecurrence: z.ZodNumber;
    /** True if the signature heuristically maps to an existing compiled rule (Jaccard ≥ 0.6). */
    coveredByRule: z.ZodBoolean;
} & {
    classification: z.ZodLiteral<"in-pr-fix">;
}, "strict", z.ZodTypeAny, {
    file: string;
    signature: string;
    tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
    severityBucket: "high" | "critical" | "medium" | "low" | "nit";
    coveredByRule: boolean;
    roundNumber: number;
    bodyExcerpt: string;
    crossPrRecurrence: number;
    classification: "in-pr-fix";
    line?: number | undefined;
}, {
    file: string;
    signature: string;
    tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
    severityBucket: "high" | "critical" | "medium" | "low" | "nit";
    coveredByRule: boolean;
    roundNumber: number;
    bodyExcerpt: string;
    crossPrRecurrence: number;
    classification: "in-pr-fix";
    line?: number | undefined;
}>, z.ZodObject<{
    /** Stable signature hash (16-char) — matches the recurrence-stats vocabulary. */
    signature: z.ZodString;
    /** Source bot/tool. */
    tool: z.ZodEnum<["coderabbit", "gca", "greptile", "sarif", "override", "unknown"]>;
    /** Normalized severity bucket. */
    severityBucket: z.ZodEnum<["critical", "high", "medium", "low", "nit"]>;
    /** First 280 chars of the raw body (for human triage). */
    bodyExcerpt: z.ZodString;
    /** File path attached to the finding (`(review body)` for CR outside-diff/nits). */
    file: z.ZodString;
    /** Best-effort line number. */
    line: z.ZodOptional<z.ZodNumber>;
    /** Round number assigned by `groupFindingsByRound`. */
    roundNumber: z.ZodNumber;
    /** Count of OTHER PRs sharing this signature (target PR excluded). */
    crossPrRecurrence: z.ZodNumber;
    /** True if the signature heuristically maps to an existing compiled rule (Jaccard ≥ 0.6). */
    coveredByRule: z.ZodBoolean;
} & {
    classification: z.ZodLiteral<"undetermined">;
}, "strict", z.ZodTypeAny, {
    file: string;
    signature: string;
    tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
    severityBucket: "high" | "critical" | "medium" | "low" | "nit";
    coveredByRule: boolean;
    roundNumber: number;
    bodyExcerpt: string;
    crossPrRecurrence: number;
    classification: "undetermined";
    line?: number | undefined;
}, {
    file: string;
    signature: string;
    tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
    severityBucket: "high" | "critical" | "medium" | "low" | "nit";
    coveredByRule: boolean;
    roundNumber: number;
    bodyExcerpt: string;
    crossPrRecurrence: number;
    classification: "undetermined";
    line?: number | undefined;
}>]>;
export type RetrospectFinding = z.infer<typeof RetrospectFindingSchema>;
/** Top-level shape emitted by `runRetrospect` and optionally written via `--out`. */
export declare const RetrospectReportSchema: z.ZodObject<{
    /** Schema version for forward-compat. */
    version: z.ZodLiteral<1>;
    /** Target PR number (string for parity with recurrence-stats prsScanned). */
    prNumber: z.ZodString;
    /** Open / closed / merged at fetch time. */
    prState: z.ZodString;
    /** ISO 8601 generation timestamp. */
    generatedAt: z.ZodString;
    /** Resolved threshold (after option clamping). */
    threshold: z.ZodNumber;
    /** True iff `.totem/recurrence-stats.json` was loaded successfully. */
    substrateAvailable: z.ZodBoolean;
    /** True iff `compiled-rules.json` was loaded successfully. */
    compiledRulesAvailable: z.ZodBoolean;
    /** Push-grouped rounds (ordered by earliest submittedAt per head_sha). */
    rounds: z.ZodArray<z.ZodObject<{
        /** 1-based, monotonically increasing in submission order. */
        roundNumber: z.ZodNumber;
        /** ISO 8601 timestamp of the earliest review submission for this round. */
        submittedAt: z.ZodString;
        /** PR head SHA at review time; absent when the upstream review record lacks `commit_id`. */
        headSha: z.ZodOptional<z.ZodString>;
        /** Number of bot findings tied to this round. */
        findingCount: z.ZodNumber;
    }, "strip", z.ZodTypeAny, {
        roundNumber: number;
        submittedAt: string;
        findingCount: number;
        headSha?: string | undefined;
    }, {
        roundNumber: number;
        submittedAt: string;
        findingCount: number;
        headSha?: string | undefined;
    }>, "many">;
    /** Total bot findings (inline + review-body). */
    totalFindings: z.ZodNumber;
    /** `1 - uniqueSignatures/totalFindings`, clamped to [0,1]; 0 when totalFindings == 0. */
    dedupRate: z.ZodNumber;
    /** Distribution counts. */
    findingDistribution: z.ZodObject<{
        byTool: z.ZodRecord<z.ZodString, z.ZodNumber>;
        bySeverity: z.ZodRecord<z.ZodString, z.ZodNumber>;
        byClassification: z.ZodRecord<z.ZodString, z.ZodNumber>;
    }, "strip", z.ZodTypeAny, {
        byTool: Record<string, number>;
        bySeverity: Record<string, number>;
        byClassification: Record<string, number>;
    }, {
        byTool: Record<string, number>;
        bySeverity: Record<string, number>;
        byClassification: Record<string, number>;
    }>;
    /** Findings classified as `route-out`. */
    routeOutCandidates: z.ZodArray<z.ZodDiscriminatedUnion<"classification", [z.ZodObject<{
        /** Stable signature hash (16-char) — matches the recurrence-stats vocabulary. */
        signature: z.ZodString;
        /** Source bot/tool. */
        tool: z.ZodEnum<["coderabbit", "gca", "greptile", "sarif", "override", "unknown"]>;
        /** Normalized severity bucket. */
        severityBucket: z.ZodEnum<["critical", "high", "medium", "low", "nit"]>;
        /** First 280 chars of the raw body (for human triage). */
        bodyExcerpt: z.ZodString;
        /** File path attached to the finding (`(review body)` for CR outside-diff/nits). */
        file: z.ZodString;
        /** Best-effort line number. */
        line: z.ZodOptional<z.ZodNumber>;
        /** Round number assigned by `groupFindingsByRound`. */
        roundNumber: z.ZodNumber;
        /** Count of OTHER PRs sharing this signature (target PR excluded). */
        crossPrRecurrence: z.ZodNumber;
        /** True if the signature heuristically maps to an existing compiled rule (Jaccard ≥ 0.6). */
        coveredByRule: z.ZodBoolean;
    } & {
        classification: z.ZodLiteral<"route-out">;
        /** Reason from the closed catalog (`RETROSPECT_ROUTE_OUT_REASONS`). */
        routeOutReason: z.ZodEnum<["covered by existing compiled rule", "rule-covered class flagged late — retroactive shouldn’t block ship", "frequent across other PRs — file follow-up to compile into a rule", "low/nit severity flagged late in the bot-review loop"]>;
    }, "strip", z.ZodTypeAny, {
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "route-out";
        routeOutReason: "covered by existing compiled rule" | "rule-covered class flagged late — retroactive shouldn’t block ship" | "frequent across other PRs — file follow-up to compile into a rule" | "low/nit severity flagged late in the bot-review loop";
        line?: number | undefined;
    }, {
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "route-out";
        routeOutReason: "covered by existing compiled rule" | "rule-covered class flagged late — retroactive shouldn’t block ship" | "frequent across other PRs — file follow-up to compile into a rule" | "low/nit severity flagged late in the bot-review loop";
        line?: number | undefined;
    }>, z.ZodObject<{
        /** Stable signature hash (16-char) — matches the recurrence-stats vocabulary. */
        signature: z.ZodString;
        /** Source bot/tool. */
        tool: z.ZodEnum<["coderabbit", "gca", "greptile", "sarif", "override", "unknown"]>;
        /** Normalized severity bucket. */
        severityBucket: z.ZodEnum<["critical", "high", "medium", "low", "nit"]>;
        /** First 280 chars of the raw body (for human triage). */
        bodyExcerpt: z.ZodString;
        /** File path attached to the finding (`(review body)` for CR outside-diff/nits). */
        file: z.ZodString;
        /** Best-effort line number. */
        line: z.ZodOptional<z.ZodNumber>;
        /** Round number assigned by `groupFindingsByRound`. */
        roundNumber: z.ZodNumber;
        /** Count of OTHER PRs sharing this signature (target PR excluded). */
        crossPrRecurrence: z.ZodNumber;
        /** True if the signature heuristically maps to an existing compiled rule (Jaccard ≥ 0.6). */
        coveredByRule: z.ZodBoolean;
    } & {
        classification: z.ZodLiteral<"in-pr-fix">;
    }, "strict", z.ZodTypeAny, {
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "in-pr-fix";
        line?: number | undefined;
    }, {
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "in-pr-fix";
        line?: number | undefined;
    }>, z.ZodObject<{
        /** Stable signature hash (16-char) — matches the recurrence-stats vocabulary. */
        signature: z.ZodString;
        /** Source bot/tool. */
        tool: z.ZodEnum<["coderabbit", "gca", "greptile", "sarif", "override", "unknown"]>;
        /** Normalized severity bucket. */
        severityBucket: z.ZodEnum<["critical", "high", "medium", "low", "nit"]>;
        /** First 280 chars of the raw body (for human triage). */
        bodyExcerpt: z.ZodString;
        /** File path attached to the finding (`(review body)` for CR outside-diff/nits). */
        file: z.ZodString;
        /** Best-effort line number. */
        line: z.ZodOptional<z.ZodNumber>;
        /** Round number assigned by `groupFindingsByRound`. */
        roundNumber: z.ZodNumber;
        /** Count of OTHER PRs sharing this signature (target PR excluded). */
        crossPrRecurrence: z.ZodNumber;
        /** True if the signature heuristically maps to an existing compiled rule (Jaccard ≥ 0.6). */
        coveredByRule: z.ZodBoolean;
    } & {
        classification: z.ZodLiteral<"undetermined">;
    }, "strict", z.ZodTypeAny, {
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "undetermined";
        line?: number | undefined;
    }, {
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "undetermined";
        line?: number | undefined;
    }>]>, "many">;
    /** Findings classified as `in-pr-fix`. */
    inPrFixes: z.ZodArray<z.ZodDiscriminatedUnion<"classification", [z.ZodObject<{
        /** Stable signature hash (16-char) — matches the recurrence-stats vocabulary. */
        signature: z.ZodString;
        /** Source bot/tool. */
        tool: z.ZodEnum<["coderabbit", "gca", "greptile", "sarif", "override", "unknown"]>;
        /** Normalized severity bucket. */
        severityBucket: z.ZodEnum<["critical", "high", "medium", "low", "nit"]>;
        /** First 280 chars of the raw body (for human triage). */
        bodyExcerpt: z.ZodString;
        /** File path attached to the finding (`(review body)` for CR outside-diff/nits). */
        file: z.ZodString;
        /** Best-effort line number. */
        line: z.ZodOptional<z.ZodNumber>;
        /** Round number assigned by `groupFindingsByRound`. */
        roundNumber: z.ZodNumber;
        /** Count of OTHER PRs sharing this signature (target PR excluded). */
        crossPrRecurrence: z.ZodNumber;
        /** True if the signature heuristically maps to an existing compiled rule (Jaccard ≥ 0.6). */
        coveredByRule: z.ZodBoolean;
    } & {
        classification: z.ZodLiteral<"route-out">;
        /** Reason from the closed catalog (`RETROSPECT_ROUTE_OUT_REASONS`). */
        routeOutReason: z.ZodEnum<["covered by existing compiled rule", "rule-covered class flagged late — retroactive shouldn’t block ship", "frequent across other PRs — file follow-up to compile into a rule", "low/nit severity flagged late in the bot-review loop"]>;
    }, "strip", z.ZodTypeAny, {
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "route-out";
        routeOutReason: "covered by existing compiled rule" | "rule-covered class flagged late — retroactive shouldn’t block ship" | "frequent across other PRs — file follow-up to compile into a rule" | "low/nit severity flagged late in the bot-review loop";
        line?: number | undefined;
    }, {
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "route-out";
        routeOutReason: "covered by existing compiled rule" | "rule-covered class flagged late — retroactive shouldn’t block ship" | "frequent across other PRs — file follow-up to compile into a rule" | "low/nit severity flagged late in the bot-review loop";
        line?: number | undefined;
    }>, z.ZodObject<{
        /** Stable signature hash (16-char) — matches the recurrence-stats vocabulary. */
        signature: z.ZodString;
        /** Source bot/tool. */
        tool: z.ZodEnum<["coderabbit", "gca", "greptile", "sarif", "override", "unknown"]>;
        /** Normalized severity bucket. */
        severityBucket: z.ZodEnum<["critical", "high", "medium", "low", "nit"]>;
        /** First 280 chars of the raw body (for human triage). */
        bodyExcerpt: z.ZodString;
        /** File path attached to the finding (`(review body)` for CR outside-diff/nits). */
        file: z.ZodString;
        /** Best-effort line number. */
        line: z.ZodOptional<z.ZodNumber>;
        /** Round number assigned by `groupFindingsByRound`. */
        roundNumber: z.ZodNumber;
        /** Count of OTHER PRs sharing this signature (target PR excluded). */
        crossPrRecurrence: z.ZodNumber;
        /** True if the signature heuristically maps to an existing compiled rule (Jaccard ≥ 0.6). */
        coveredByRule: z.ZodBoolean;
    } & {
        classification: z.ZodLiteral<"in-pr-fix">;
    }, "strict", z.ZodTypeAny, {
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "in-pr-fix";
        line?: number | undefined;
    }, {
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "in-pr-fix";
        line?: number | undefined;
    }>, z.ZodObject<{
        /** Stable signature hash (16-char) — matches the recurrence-stats vocabulary. */
        signature: z.ZodString;
        /** Source bot/tool. */
        tool: z.ZodEnum<["coderabbit", "gca", "greptile", "sarif", "override", "unknown"]>;
        /** Normalized severity bucket. */
        severityBucket: z.ZodEnum<["critical", "high", "medium", "low", "nit"]>;
        /** First 280 chars of the raw body (for human triage). */
        bodyExcerpt: z.ZodString;
        /** File path attached to the finding (`(review body)` for CR outside-diff/nits). */
        file: z.ZodString;
        /** Best-effort line number. */
        line: z.ZodOptional<z.ZodNumber>;
        /** Round number assigned by `groupFindingsByRound`. */
        roundNumber: z.ZodNumber;
        /** Count of OTHER PRs sharing this signature (target PR excluded). */
        crossPrRecurrence: z.ZodNumber;
        /** True if the signature heuristically maps to an existing compiled rule (Jaccard ≥ 0.6). */
        coveredByRule: z.ZodBoolean;
    } & {
        classification: z.ZodLiteral<"undetermined">;
    }, "strict", z.ZodTypeAny, {
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "undetermined";
        line?: number | undefined;
    }, {
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "undetermined";
        line?: number | undefined;
    }>]>, "many">;
    /** Findings classified as `undetermined`. */
    undetermined: z.ZodArray<z.ZodDiscriminatedUnion<"classification", [z.ZodObject<{
        /** Stable signature hash (16-char) — matches the recurrence-stats vocabulary. */
        signature: z.ZodString;
        /** Source bot/tool. */
        tool: z.ZodEnum<["coderabbit", "gca", "greptile", "sarif", "override", "unknown"]>;
        /** Normalized severity bucket. */
        severityBucket: z.ZodEnum<["critical", "high", "medium", "low", "nit"]>;
        /** First 280 chars of the raw body (for human triage). */
        bodyExcerpt: z.ZodString;
        /** File path attached to the finding (`(review body)` for CR outside-diff/nits). */
        file: z.ZodString;
        /** Best-effort line number. */
        line: z.ZodOptional<z.ZodNumber>;
        /** Round number assigned by `groupFindingsByRound`. */
        roundNumber: z.ZodNumber;
        /** Count of OTHER PRs sharing this signature (target PR excluded). */
        crossPrRecurrence: z.ZodNumber;
        /** True if the signature heuristically maps to an existing compiled rule (Jaccard ≥ 0.6). */
        coveredByRule: z.ZodBoolean;
    } & {
        classification: z.ZodLiteral<"route-out">;
        /** Reason from the closed catalog (`RETROSPECT_ROUTE_OUT_REASONS`). */
        routeOutReason: z.ZodEnum<["covered by existing compiled rule", "rule-covered class flagged late — retroactive shouldn’t block ship", "frequent across other PRs — file follow-up to compile into a rule", "low/nit severity flagged late in the bot-review loop"]>;
    }, "strip", z.ZodTypeAny, {
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "route-out";
        routeOutReason: "covered by existing compiled rule" | "rule-covered class flagged late — retroactive shouldn’t block ship" | "frequent across other PRs — file follow-up to compile into a rule" | "low/nit severity flagged late in the bot-review loop";
        line?: number | undefined;
    }, {
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "route-out";
        routeOutReason: "covered by existing compiled rule" | "rule-covered class flagged late — retroactive shouldn’t block ship" | "frequent across other PRs — file follow-up to compile into a rule" | "low/nit severity flagged late in the bot-review loop";
        line?: number | undefined;
    }>, z.ZodObject<{
        /** Stable signature hash (16-char) — matches the recurrence-stats vocabulary. */
        signature: z.ZodString;
        /** Source bot/tool. */
        tool: z.ZodEnum<["coderabbit", "gca", "greptile", "sarif", "override", "unknown"]>;
        /** Normalized severity bucket. */
        severityBucket: z.ZodEnum<["critical", "high", "medium", "low", "nit"]>;
        /** First 280 chars of the raw body (for human triage). */
        bodyExcerpt: z.ZodString;
        /** File path attached to the finding (`(review body)` for CR outside-diff/nits). */
        file: z.ZodString;
        /** Best-effort line number. */
        line: z.ZodOptional<z.ZodNumber>;
        /** Round number assigned by `groupFindingsByRound`. */
        roundNumber: z.ZodNumber;
        /** Count of OTHER PRs sharing this signature (target PR excluded). */
        crossPrRecurrence: z.ZodNumber;
        /** True if the signature heuristically maps to an existing compiled rule (Jaccard ≥ 0.6). */
        coveredByRule: z.ZodBoolean;
    } & {
        classification: z.ZodLiteral<"in-pr-fix">;
    }, "strict", z.ZodTypeAny, {
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "in-pr-fix";
        line?: number | undefined;
    }, {
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "in-pr-fix";
        line?: number | undefined;
    }>, z.ZodObject<{
        /** Stable signature hash (16-char) — matches the recurrence-stats vocabulary. */
        signature: z.ZodString;
        /** Source bot/tool. */
        tool: z.ZodEnum<["coderabbit", "gca", "greptile", "sarif", "override", "unknown"]>;
        /** Normalized severity bucket. */
        severityBucket: z.ZodEnum<["critical", "high", "medium", "low", "nit"]>;
        /** First 280 chars of the raw body (for human triage). */
        bodyExcerpt: z.ZodString;
        /** File path attached to the finding (`(review body)` for CR outside-diff/nits). */
        file: z.ZodString;
        /** Best-effort line number. */
        line: z.ZodOptional<z.ZodNumber>;
        /** Round number assigned by `groupFindingsByRound`. */
        roundNumber: z.ZodNumber;
        /** Count of OTHER PRs sharing this signature (target PR excluded). */
        crossPrRecurrence: z.ZodNumber;
        /** True if the signature heuristically maps to an existing compiled rule (Jaccard ≥ 0.6). */
        coveredByRule: z.ZodBoolean;
    } & {
        classification: z.ZodLiteral<"undetermined">;
    }, "strict", z.ZodTypeAny, {
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "undetermined";
        line?: number | undefined;
    }, {
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "undetermined";
        line?: number | undefined;
    }>]>, "many">;
    /** Deterministic stop-condition templates (no prose generation). */
    stopConditions: z.ZodArray<z.ZodString, "many">;
    /** Trap-ledger override events read for this PR (read-only count). */
    overrideEventsObserved: z.ZodNumber;
}, "strip", z.ZodTypeAny, {
    version: 1;
    undetermined: ({
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "route-out";
        routeOutReason: "covered by existing compiled rule" | "rule-covered class flagged late — retroactive shouldn’t block ship" | "frequent across other PRs — file follow-up to compile into a rule" | "low/nit severity flagged late in the bot-review loop";
        line?: number | undefined;
    } | {
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "in-pr-fix";
        line?: number | undefined;
    } | {
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "undetermined";
        line?: number | undefined;
    })[];
    prNumber: string;
    prState: string;
    generatedAt: string;
    threshold: number;
    substrateAvailable: boolean;
    compiledRulesAvailable: boolean;
    rounds: {
        roundNumber: number;
        submittedAt: string;
        findingCount: number;
        headSha?: string | undefined;
    }[];
    totalFindings: number;
    dedupRate: number;
    findingDistribution: {
        byTool: Record<string, number>;
        bySeverity: Record<string, number>;
        byClassification: Record<string, number>;
    };
    routeOutCandidates: ({
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "route-out";
        routeOutReason: "covered by existing compiled rule" | "rule-covered class flagged late — retroactive shouldn’t block ship" | "frequent across other PRs — file follow-up to compile into a rule" | "low/nit severity flagged late in the bot-review loop";
        line?: number | undefined;
    } | {
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "in-pr-fix";
        line?: number | undefined;
    } | {
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "undetermined";
        line?: number | undefined;
    })[];
    inPrFixes: ({
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "route-out";
        routeOutReason: "covered by existing compiled rule" | "rule-covered class flagged late — retroactive shouldn’t block ship" | "frequent across other PRs — file follow-up to compile into a rule" | "low/nit severity flagged late in the bot-review loop";
        line?: number | undefined;
    } | {
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "in-pr-fix";
        line?: number | undefined;
    } | {
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "undetermined";
        line?: number | undefined;
    })[];
    stopConditions: string[];
    overrideEventsObserved: number;
}, {
    version: 1;
    undetermined: ({
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "route-out";
        routeOutReason: "covered by existing compiled rule" | "rule-covered class flagged late — retroactive shouldn’t block ship" | "frequent across other PRs — file follow-up to compile into a rule" | "low/nit severity flagged late in the bot-review loop";
        line?: number | undefined;
    } | {
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "in-pr-fix";
        line?: number | undefined;
    } | {
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "undetermined";
        line?: number | undefined;
    })[];
    prNumber: string;
    prState: string;
    generatedAt: string;
    threshold: number;
    substrateAvailable: boolean;
    compiledRulesAvailable: boolean;
    rounds: {
        roundNumber: number;
        submittedAt: string;
        findingCount: number;
        headSha?: string | undefined;
    }[];
    totalFindings: number;
    dedupRate: number;
    findingDistribution: {
        byTool: Record<string, number>;
        bySeverity: Record<string, number>;
        byClassification: Record<string, number>;
    };
    routeOutCandidates: ({
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "route-out";
        routeOutReason: "covered by existing compiled rule" | "rule-covered class flagged late — retroactive shouldn’t block ship" | "frequent across other PRs — file follow-up to compile into a rule" | "low/nit severity flagged late in the bot-review loop";
        line?: number | undefined;
    } | {
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "in-pr-fix";
        line?: number | undefined;
    } | {
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "undetermined";
        line?: number | undefined;
    })[];
    inPrFixes: ({
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "route-out";
        routeOutReason: "covered by existing compiled rule" | "rule-covered class flagged late — retroactive shouldn’t block ship" | "frequent across other PRs — file follow-up to compile into a rule" | "low/nit severity flagged late in the bot-review loop";
        line?: number | undefined;
    } | {
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "in-pr-fix";
        line?: number | undefined;
    } | {
        file: string;
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        coveredByRule: boolean;
        roundNumber: number;
        bodyExcerpt: string;
        crossPrRecurrence: number;
        classification: "undetermined";
        line?: number | undefined;
    })[];
    stopConditions: string[];
    overrideEventsObserved: number;
}>;
export type RetrospectReport = z.infer<typeof RetrospectReportSchema>;
/** Minimal review-submission shape (subset of GitHub's `pulls/N/reviews`). */
export interface RetrospectReviewSubmission {
    id: number;
    /** PR head SHA at review submission time; may be absent for some review states. */
    commit_id?: string | null;
    /** ISO 8601 timestamp. */
    submitted_at?: string | null;
    /** Bot login. */
    user_login: string;
}
/** Minimal review-comment shape (subset of `StandardReviewComment`). */
export interface RetrospectReviewComment {
    id: number;
    author: string;
    createdAt?: string;
}
/**
 * Group bot review submissions by `commit_id` (head SHA).
 *
 * - Two reviews on the same `commit_id` → same round.
 * - Reviews missing `commit_id` are bucketed into a single synthetic
 *   round (head SHA `undefined`) so they don't double-count as N rounds.
 * - Round ordering is by EARLIEST `submitted_at` within each SHA bucket.
 * - Round numbers are 1-based.
 *
 * `findingCount` requires `groupFindingsByRound` to receive the corresponding
 * inline-comment list keyed by SHA via `findingShaBySubmissionId`. The mapping
 * is computed by the caller because `pulls/N/comments` and `pulls/N/reviews`
 * are separate GH endpoints and the join is push-based, not in-memory native.
 *
 * To keep the helper pure, this function returns the round index ONLY.
 * Callers walk findings + assign each to a round by submission timestamp.
 */
export declare function groupFindingsByRound(reviewSubmissions: ReadonlyArray<RetrospectReviewSubmission>, findingsPerRoundCount: ReadonlyMap<string, number>): RetrospectRound[];
/**
 * Coarse round-position bucket. The exact thresholds are a v0.1 heuristic
 * documented in `.totem/specs/1713.md` — early ≤ 3, mid 4-9, late ≥ 10.
 */
export type RetrospectRoundPosition = 'early' | 'mid' | 'late';
export declare function toRoundPosition(roundNumber: number): RetrospectRoundPosition;
/** Coarse cross-PR recurrence bucket. */
export type RetrospectCrossPrBucket = 'none' | 'some' | 'frequent';
export declare function toCrossPrBucket(crossPrRecurrence: number): RetrospectCrossPrBucket;
/**
 * Fixed catalog of route-out reasons. Keep deterministic — every reason
 * a classifier emits MUST come from this catalog so the report doesn't
 * accumulate a long-tail of one-off prose strings.
 */
export declare const RETROSPECT_ROUTE_OUT_REASONS: {
    readonly COVERED_BY_RULE: "covered by existing compiled rule";
    readonly RULE_COVERED_LATE: "rule-covered class flagged late — retroactive shouldn’t block ship";
    readonly FREQUENT_CROSS_PR: "frequent across other PRs — file follow-up to compile into a rule";
    readonly LOW_NIT_LATE: "low/nit severity flagged late in the bot-review loop";
};
export type RetrospectRouteOutReason = (typeof RETROSPECT_ROUTE_OUT_REASONS)[keyof typeof RETROSPECT_ROUTE_OUT_REASONS];
/** Input to the deterministic classifier. */
export interface ClassifyFindingInput {
    severityBucket: 'critical' | 'high' | 'medium' | 'low' | 'nit';
    roundNumber: number;
    crossPrRecurrence: number;
    coveredByRule: boolean;
}
/**
 * Deterministic, table-driven classifier. Same inputs → same outputs across
 * invocations. Reason strings are drawn exclusively from
 * `RETROSPECT_ROUTE_OUT_REASONS` so consumers can treat them as a closed set.
 *
 * Heuristic intent (v0.1):
 * - `critical` or `high` at any round → `in-pr-fix` (regardless of recurrence/coverage)
 * - `low`/`nit` late + (`coveredByRule` OR `crossPrRecurrence frequent`) → `route-out`
 * - `medium` late + `coveredByRule` → `route-out`
 * - `medium` early/mid → `in-pr-fix`
 * - `nit` early/mid → `in-pr-fix`
 * - else → `undetermined`
 */
export declare function classifyFinding(input: ClassifyFindingInput): {
    classification: RetrospectClassification;
    routeOutReason?: RetrospectRouteOutReason;
};
/**
 * Deterministic stop-condition templates keyed off the report shape. No
 * prose generation; only integer substitution. Returns the catalog
 * filtered to entries whose triggering condition fires for the given
 * report.
 */
export declare function buildStopConditions(report: Pick<RetrospectReport, 'rounds' | 'routeOutCandidates' | 'inPrFixes' | 'undetermined' | 'dedupRate' | 'findingDistribution'>): string[];
/**
 * Compute `1 - uniqueSignatures / totalFindings`, clamped to [0, 1].
 *
 * - 0 findings → 0 (no findings, no dedup pressure).
 * - All unique → 0.
 * - All duplicates of one signature → close to 1 (`1 - 1/N`).
 */
export declare function computeDedupRate(findings: ReadonlyArray<{
    signature: string;
}>): number;
/**
 * Compute a stable signature for a finding body using the
 * recurrence-stats normalization pipeline. Re-exported here so callers
 * outside the cli package don't need to call `normalizeFindingBody +
 * computeSignature` separately.
 */
export declare function signatureOfBody(body: string): string;
//# sourceMappingURL=retrospect.d.ts.map