import { LEARNING_DETERMINISTIC_THRESHOLD } from './HumanAsDetectorLog.js';
export const DEFAULT_CORRECTION_GATES = {
    minSupport: 4,
    minDistinctDaysInfraGap: 3,
    minDistinctDaysPreference: 2,
    minDistinctTopicsPreference: 2,
    deterministicThreshold: LEARNING_DETERMINISTIC_THRESHOLD,
};
export class CorrectionAnalyzer {
    ledger;
    gates;
    constructor(ledger, gates = DEFAULT_CORRECTION_GATES) {
        this.ledger = ledger;
        this.gates = gates;
    }
    /**
     * Evaluate the recurrence gate against every `open` record. Returns a verdict
     * per record. Pure read — never mutates the ledger (the driver acts on these).
     * `noise`-kind records are never gate-considered.
     */
    analyze() {
        const sinceMs = this.gates.windowDays && this.gates.windowDays > 0
            ? Date.now() - this.gates.windowDays * 86400_000
            : undefined;
        const threshold = this.gates.deterministicThreshold ?? LEARNING_DETERMINISTIC_THRESHOLD;
        const records = this.ledger
            .list({ sinceMs, status: 'open', limit: 1000 })
            .filter((r) => r.kind !== 'noise');
        const verdicts = [];
        let below = 0;
        for (const rec of records) {
            // Code-determined provenance filter: only occurrences whose Layer-0 weight
            // crossed the threshold count toward the gate.
            const counts = this.ledger.distinctCounts(rec.dedupeKey, threshold);
            const supportOk = counts.qualifyingOccurrences >= this.gates.minSupport;
            let crosses = false;
            let reason;
            if (rec.kind === 'user-preference') {
                const daysOk = counts.distinctDays >= this.gates.minDistinctDaysPreference;
                const topicsOk = counts.distinctTopics >= this.gates.minDistinctTopicsPreference;
                crosses = supportOk && daysOk && topicsOk;
                reason = crosses
                    ? `preference gate crossed: ${counts.qualifyingOccurrences} support / ${counts.distinctDays} days / ${counts.distinctTopics} topics`
                    : `below preference gate (support ${counts.qualifyingOccurrences}/${this.gates.minSupport}, days ${counts.distinctDays}/${this.gates.minDistinctDaysPreference}, topics ${counts.distinctTopics}/${this.gates.minDistinctTopicsPreference})`;
            }
            else {
                // infra-gap: minSupport AND minDistinctDays. The SECOND orthogonal prong
                // (cross-agent Rising Tide consensus) is delegated to the /feedback
                // clustering — single-agent gate-crossing routes a PROPOSAL, never an
                // auto-fleet-propagation. The driver's autoFeedback gate is where that
                // second layer applies; the single-agent gate here is days+support.
                const daysOk = counts.distinctDays >= this.gates.minDistinctDaysInfraGap;
                crosses = supportOk && daysOk;
                reason = crosses
                    ? `infra-gap gate crossed: ${counts.qualifyingOccurrences} support / ${counts.distinctDays} days (cross-agent consensus applies downstream)`
                    : `below infra-gap gate (support ${counts.qualifyingOccurrences}/${this.gates.minSupport}, days ${counts.distinctDays}/${this.gates.minDistinctDaysInfraGap})`;
            }
            const verdict = {
                record: rec,
                crosses,
                reason,
                qualifyingOccurrences: counts.qualifyingOccurrences,
                distinctDays: counts.distinctDays,
                distinctTopics: counts.distinctTopics,
            };
            verdicts.push(verdict);
            if (!crosses)
                below++;
        }
        return {
            verdicts,
            crossed: verdicts.filter((v) => v.crosses),
            considered: records.length,
            belowThreshold: below,
        };
    }
}
//# sourceMappingURL=CorrectionAnalyzer.js.map