/**
 * Recurrence-stats schemas + pure helpers for `totem stats --pattern-recurrence`
 * (mmnto-ai/totem#1715).
 *
 * Substrate of the four-honest-signals "signal 2" instrumentation
 * (same-class-mistake frequency). The data model is consumed by the
 * recurrence-stats command and downstream by the bot-tax circuit
 * breaker (mmnto-ai/totem#1713) and the pre-flight estimator
 * (mmnto-ai/totem#1714).
 *
 * Everything in this file is pure: Zod schemas + deterministic string
 * helpers. No I/O, no command logic — that lives in the cli package.
 */
import { z } from 'zod';
/** Source classification of a clustered pattern. */
export declare const RecurrenceToolSchema: z.ZodEnum<["coderabbit", "gca", "greptile", "sarif", "override", "mixed", "unknown"]>;
export type RecurrenceTool = z.infer<typeof RecurrenceToolSchema>;
/** Normalized severity bucket across CR/GCA/override sources. */
export declare const RecurrenceSeverityBucketSchema: z.ZodEnum<["critical", "high", "medium", "low", "nit"]>;
export type RecurrenceSeverityBucket = z.infer<typeof RecurrenceSeverityBucketSchema>;
/**
 * Map a tool-specific raw severity string into the normalized
 * `RecurrenceSeverityBucket` vocabulary. Single source of truth across
 * the bot-tax cluster (mmnto-ai/totem#1715, #1714, #1713).
 *
 * Tool inputs:
 * - `'coderabbit'`: `critical` / `major` / `minor` / `*` → `critical` / `high` / `medium` / `low`
 * - `'gca'` / `'greptile'`: `critical` / `high` / `medium` / `low` → identical buckets; default `low` (greptile P0 → `critical`)
 * - `'sarif'`: SARIF level vocabulary (`error` / `warning` / `note` / `none`) → `high` / `medium` / `low` / `low`
 * - `'override'`: trap-ledger override events surface as `medium`
 * - any other tool (`'unknown'`, `undefined`): keyword-mapped from the raw severity string
 */
/**
 * Derived from `RecurrenceTool` to prevent type drift; `'mixed'` is a
 * post-cluster aggregate label that no caller passes here. Per CR
 * mmnto-ai/totem#1734 round-2.
 */
export type SeverityBucketTool = Exclude<RecurrenceTool, 'mixed'> | undefined;
export declare function toSeverityBucket(tool: SeverityBucketTool, severity: string): RecurrenceSeverityBucket;
/** A single cross-PR cluster of bot/override findings sharing one signature. */
export declare const RecurrencePatternSchema: z.ZodObject<{
    /** Stable hash of the normalized pattern body — used as cluster key */
    signature: z.ZodString;
    /** Source classification (`mixed` when one signature spans bots/overrides) */
    tool: z.ZodEnum<["coderabbit", "gca", "greptile", "sarif", "override", "mixed", "unknown"]>;
    /** Normalized severity across CR/GCA's different severity vocabularies */
    severityBucket: z.ZodEnum<["critical", "high", "medium", "low", "nit"]>;
    /** Total finding count for this signature (>= 1) */
    occurrences: z.ZodNumber;
    /** PR numbers where this pattern fired (deduped, sorted ascending numerically) */
    prs: z.ZodArray<z.ZodString, "many">;
    /** First 3 raw bodies seen — for human triage */
    sampleBodies: z.ZodArray<z.ZodString, "many">;
    /** Earliest finding timestamp (ISO 8601) */
    firstSeen: z.ZodString;
    /** Latest finding timestamp (ISO 8601) */
    lastSeen: z.ZodString;
    /** File paths where the pattern fired (deduped, ≤ 10) */
    paths: z.ZodArray<z.ZodString, "many">;
    /** True if signature heuristically maps to an existing compiled rule */
    coveredByRule: z.ZodBoolean;
}, "strip", z.ZodTypeAny, {
    paths: string[];
    signature: string;
    tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif" | "mixed";
    severityBucket: "high" | "critical" | "medium" | "low" | "nit";
    occurrences: number;
    prs: string[];
    sampleBodies: string[];
    firstSeen: string;
    lastSeen: string;
    coveredByRule: boolean;
}, {
    paths: string[];
    signature: string;
    tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif" | "mixed";
    severityBucket: "high" | "critical" | "medium" | "low" | "nit";
    occurrences: number;
    prs: string[];
    sampleBodies: string[];
    firstSeen: string;
    lastSeen: string;
    coveredByRule: boolean;
}>;
export type RecurrencePattern = z.infer<typeof RecurrencePatternSchema>;
/** Top-level shape persisted at `.totem/recurrence-stats.json`. */
export declare const RecurrenceStatsSchema: z.ZodObject<{
    /** Schema version for forward-compat */
    version: z.ZodLiteral<1>;
    /** When this run wrote the file (ISO 8601) */
    lastUpdated: z.ZodString;
    /** The `--threshold` value used; informs reproducibility */
    thresholdApplied: z.ZodNumber;
    /** Number of PRs requested via `--history-depth` */
    historyDepth: z.ZodNumber;
    /** PR numbers actually fetched (post-filter) */
    prsScanned: z.ZodArray<z.ZodString, "many">;
    /** Patterns at-or-above threshold; sorted by occurrences descending */
    patterns: z.ZodArray<z.ZodObject<{
        /** Stable hash of the normalized pattern body — used as cluster key */
        signature: z.ZodString;
        /** Source classification (`mixed` when one signature spans bots/overrides) */
        tool: z.ZodEnum<["coderabbit", "gca", "greptile", "sarif", "override", "mixed", "unknown"]>;
        /** Normalized severity across CR/GCA's different severity vocabularies */
        severityBucket: z.ZodEnum<["critical", "high", "medium", "low", "nit"]>;
        /** Total finding count for this signature (>= 1) */
        occurrences: z.ZodNumber;
        /** PR numbers where this pattern fired (deduped, sorted ascending numerically) */
        prs: z.ZodArray<z.ZodString, "many">;
        /** First 3 raw bodies seen — for human triage */
        sampleBodies: z.ZodArray<z.ZodString, "many">;
        /** Earliest finding timestamp (ISO 8601) */
        firstSeen: z.ZodString;
        /** Latest finding timestamp (ISO 8601) */
        lastSeen: z.ZodString;
        /** File paths where the pattern fired (deduped, ≤ 10) */
        paths: z.ZodArray<z.ZodString, "many">;
        /** True if signature heuristically maps to an existing compiled rule */
        coveredByRule: z.ZodBoolean;
    }, "strip", z.ZodTypeAny, {
        paths: string[];
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif" | "mixed";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        occurrences: number;
        prs: string[];
        sampleBodies: string[];
        firstSeen: string;
        lastSeen: string;
        coveredByRule: boolean;
    }, {
        paths: string[];
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif" | "mixed";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        occurrences: number;
        prs: string[];
        sampleBodies: string[];
        firstSeen: string;
        lastSeen: string;
        coveredByRule: boolean;
    }>, "many">;
    /** Patterns that hit existing rules — separate so coverage rate is observable */
    coveredPatterns: z.ZodArray<z.ZodObject<{
        /** Stable hash of the normalized pattern body — used as cluster key */
        signature: z.ZodString;
        /** Source classification (`mixed` when one signature spans bots/overrides) */
        tool: z.ZodEnum<["coderabbit", "gca", "greptile", "sarif", "override", "mixed", "unknown"]>;
        /** Normalized severity across CR/GCA's different severity vocabularies */
        severityBucket: z.ZodEnum<["critical", "high", "medium", "low", "nit"]>;
        /** Total finding count for this signature (>= 1) */
        occurrences: z.ZodNumber;
        /** PR numbers where this pattern fired (deduped, sorted ascending numerically) */
        prs: z.ZodArray<z.ZodString, "many">;
        /** First 3 raw bodies seen — for human triage */
        sampleBodies: z.ZodArray<z.ZodString, "many">;
        /** Earliest finding timestamp (ISO 8601) */
        firstSeen: z.ZodString;
        /** Latest finding timestamp (ISO 8601) */
        lastSeen: z.ZodString;
        /** File paths where the pattern fired (deduped, ≤ 10) */
        paths: z.ZodArray<z.ZodString, "many">;
        /** True if signature heuristically maps to an existing compiled rule */
        coveredByRule: z.ZodBoolean;
    }, "strip", z.ZodTypeAny, {
        paths: string[];
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif" | "mixed";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        occurrences: number;
        prs: string[];
        sampleBodies: string[];
        firstSeen: string;
        lastSeen: string;
        coveredByRule: boolean;
    }, {
        paths: string[];
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif" | "mixed";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        occurrences: number;
        prs: string[];
        sampleBodies: string[];
        firstSeen: string;
        lastSeen: string;
        coveredByRule: boolean;
    }>, "many">;
}, "strip", z.ZodTypeAny, {
    version: 1;
    patterns: {
        paths: string[];
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif" | "mixed";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        occurrences: number;
        prs: string[];
        sampleBodies: string[];
        firstSeen: string;
        lastSeen: string;
        coveredByRule: boolean;
    }[];
    lastUpdated: string;
    thresholdApplied: number;
    historyDepth: number;
    prsScanned: string[];
    coveredPatterns: {
        paths: string[];
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif" | "mixed";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        occurrences: number;
        prs: string[];
        sampleBodies: string[];
        firstSeen: string;
        lastSeen: string;
        coveredByRule: boolean;
    }[];
}, {
    version: 1;
    patterns: {
        paths: string[];
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif" | "mixed";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        occurrences: number;
        prs: string[];
        sampleBodies: string[];
        firstSeen: string;
        lastSeen: string;
        coveredByRule: boolean;
    }[];
    lastUpdated: string;
    thresholdApplied: number;
    historyDepth: number;
    prsScanned: string[];
    coveredPatterns: {
        paths: string[];
        signature: string;
        tool: "unknown" | "override" | "coderabbit" | "gca" | "greptile" | "sarif" | "mixed";
        severityBucket: "high" | "critical" | "medium" | "low" | "nit";
        occurrences: number;
        prs: string[];
        sampleBodies: string[];
        firstSeen: string;
        lastSeen: string;
        coveredByRule: boolean;
    }[];
}>;
export type RecurrenceStats = z.infer<typeof RecurrenceStatsSchema>;
/**
 * Q5 normalization pipeline for finding bodies before signature hashing.
 *
 * Strips, in order:
 * - Triple-backtick code fences (```…```)
 * - URLs (http(s)://…)
 * - Backtick-spans (`code`)
 * - File paths with optional :line / :line:col suffix
 *   (e.g. `packages/cli/src/foo.ts:42`, `src/x.ts:42:7`)
 * - Standalone line references (`line 42`, `line: 42`, ` :42`)
 * - Leading severity prefixes (`CRITICAL: `, `**Critical**`, etc.)
 *
 * Then lowercases and collapses internal whitespace.
 */
export declare function normalizeFindingBody(body: string): string;
/**
 * Compute a 16-char hex SHA-256 prefix of the normalized text.
 * Stable + deterministic; collision probability negligible at this
 * input scale (per-repo PR history).
 */
export declare function computeSignature(normalized: string): string;
/**
 * Tokenize text for Jaccard similarity:
 * - Split on whitespace + non-alphanumerics
 * - Lowercase
 * - Drop tokens of length ≤ 2
 * - Drop a small stopword list
 */
export declare function tokenizeForJaccard(text: string): Set<string>;
/**
 * Jaccard similarity |A ∩ B| / |A ∪ B|. Returns 1.0 on identical sets,
 * 0.0 on disjoint sets, undefined-protected against the empty/empty case
 * (treated as 0 — they're not "the same pattern", they're both empty).
 */
export declare function jaccard(a: Set<string>, b: Set<string>): number;
//# sourceMappingURL=recurrence-stats.d.ts.map