import * as fs from 'node:fs';
import * as readline from 'node:readline';
import { LedgerEventSchema } from '@mmnto/totem';
// ─── Public API ────────────────────────────────────
/**
 * Analyze the Trap Ledger to compute bypass rates per rule.
 *
 * Reads bypass events from the ledger (source of truth for exceptions)
 * and trigger counts from rule-metrics (only source for trigger data).
 */
export async function analyzeLedger(totemDir, onWarn) {
    // 1. Read bypass counts from ledger (streaming)
    const bypassCounts = await readLedgerBypassCounts(totemDir, onWarn);
    // 2. Read trigger counts from rule-metrics
    const { loadRuleMetrics } = await import('@mmnto/totem');
    const metrics = loadRuleMetrics(totemDir, onWarn);
    // 3. Merge into stats
    const stats = new Map();
    const allRuleIds = new Set([...bypassCounts.keys(), ...Object.keys(metrics.rules)]);
    for (const ruleId of allRuleIds) {
        const bypasses = bypassCounts.get(ruleId) ?? 0;
        const triggers = metrics.rules[ruleId]?.triggerCount ?? 0;
        const total = triggers + bypasses;
        stats.set(ruleId, {
            ruleId,
            triggerCount: triggers,
            bypassCount: bypasses,
            bypassRate: total === 0 ? 0 : bypasses / total,
            totalEvents: total,
        });
    }
    return stats;
}
// ─── Internal ──────────────────────────────────────
/**
 * Stream the ledger NDJSON file and count bypass events per ruleId.
 * Uses readline for memory-efficient parsing of large ledgers.
 */
export async function readLedgerBypassCounts(totemDir, onWarn) {
    const path = await import('node:path');
    const ledgerPath = path.join(totemDir, 'ledger', 'events.ndjson');
    const counts = new Map();
    if (!fs.existsSync(ledgerPath))
        return counts;
    const stream = fs.createReadStream(ledgerPath, 'utf-8');
    const rl = readline.createInterface({ input: stream });
    for await (const line of rl) {
        if (!line.trim())
            continue;
        try {
            const parsed = JSON.parse(line);
            const result = LedgerEventSchema.safeParse(parsed);
            if (!result.success)
                continue;
            const event = result.data;
            // Bypass-rate is rule-scoped: include only the two rule-bypass event types
            // (suppress + override). Excludes `exemption` and all A.3.a activity events
            // (mcp_call, session_start, etc.) by type rather than via the absence-of-
            // ruleId proxy. CR/GCA Round-1 catch — type-based filter is more robust
            // (the prior proxy would miscount an activity event that happened to
            // carry a ruleId).
            if (event.type !== 'suppress' && event.type !== 'override')
                continue;
            if (!event.ruleId)
                continue;
            counts.set(event.ruleId, (counts.get(event.ruleId) ?? 0) + 1);
        }
        catch {
            onWarn?.('Skipping malformed ledger line');
        }
    }
    return counts;
}
//# sourceMappingURL=ledger-analyzer.js.map