"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.setEvidenceAppendHook = setEvidenceAppendHook;
exports.clearEvidenceAppendHooks = clearEvidenceAppendHooks;
exports.appendRunEvidence = appendRunEvidence;
exports.readRunEvidence = readRunEvidence;
const fs = __importStar(require("fs/promises"));
const path = __importStar(require("path"));
const readline = __importStar(require("readline"));
const fs_1 = require("fs");
const silentFailureSink_1 = require("../observability/silentFailureSink");
const MAX_STORED_RUN_EVIDENCE = 1_000;
const knownRunEvidenceCounts = new Map();
const evidenceAppendHooks = [];
function setEvidenceAppendHook(hook) {
    evidenceAppendHooks.push(hook);
}
function clearEvidenceAppendHooks() {
    evidenceAppendHooks.length = 0;
}
async function appendRunEvidence(projectDir, evidence) {
    const filePath = runEvidencePath(projectDir);
    await fs.mkdir(path.dirname(filePath), { recursive: true });
    await fs.appendFile(filePath, JSON.stringify(evidence) + '\n', 'utf-8');
    await pruneRunEvidence(projectDir, MAX_STORED_RUN_EVIDENCE).catch((err) => (0, silentFailureSink_1.recordSwallowed)('evidenceStore.prune', err));
    for (const hook of evidenceAppendHooks) {
        try {
            await hook(projectDir, evidence);
        }
        catch (err) {
            (0, silentFailureSink_1.recordSwallowed)('evidenceStore.appendHook', err);
        }
    }
    return filePath;
}
async function readRunEvidence(projectDir, limit = 100) {
    const filePath = runEvidencePath(projectDir);
    try {
        await fs.access(filePath);
    }
    catch {
        return [];
    }
    // Stream the file line-by-line so large JSONL files do not load entirely
    // into memory. We keep the last `limit` entries in a ring buffer.
    const entries = [];
    const rl = readline.createInterface({ input: (0, fs_1.createReadStream)(filePath, 'utf-8'), crlfDelay: Infinity });
    for await (const line of rl) {
        if (!line.trim())
            continue;
        try {
            entries.push(JSON.parse(line));
            if (entries.length > limit * 2) {
                // Periodically trim to avoid unbounded growth during read.
                entries.splice(0, entries.length - limit);
            }
        }
        catch { /* skip corrupt lines */ }
    }
    return entries.slice(-limit).reverse();
}
function runEvidencePath(projectDir) {
    return path.join(projectDir, '.harness', 'evidence', 'runs.jsonl');
}
async function pruneRunEvidence(projectDir, maxEntries) {
    const filePath = runEvidencePath(projectDir);
    const knownCount = knownRunEvidenceCounts.get(filePath);
    const count = knownCount === undefined ? await countRunEvidenceLines(filePath) : knownCount + 1;
    knownRunEvidenceCounts.set(filePath, count);
    if (count <= maxEntries)
        return;
    const entries = await readRunEvidence(projectDir, maxEntries);
    if (entries.length < maxEntries)
        return;
    await fs.writeFile(filePath, entries.reverse().map((entry) => JSON.stringify(entry)).join('\n') + '\n', 'utf-8');
    knownRunEvidenceCounts.set(filePath, maxEntries);
}
async function countRunEvidenceLines(filePath) {
    const rl = readline.createInterface({ input: (0, fs_1.createReadStream)(filePath), crlfDelay: Infinity });
    let count = 0;
    for await (const line of rl) {
        if (line.trim())
            count++;
    }
    return count;
}
//# sourceMappingURL=evidenceStore.js.map