/**
 * Kernel Execution — append-only ledger.
 *
 * Every step / verify / merge call writes exactly one row here. Rows are
 * never rewritten; auditing the path is just `tail -f` on a JSONL file.
 *
 * Keep this tiny. Don't grow it into an event bus — if a consumer needs
 * notifications, a narrow subscribe() goes here; no pub/sub framework.
 */
import fs from 'node:fs';
import path from 'node:path';
import { randomUUID } from 'node:crypto';
import { resolveNexusStateDir } from '../../engines/runtime-registry.js';
class JsonlLedger {
    ledgerPath;
    constructor(ledgerPath) {
        this.ledgerPath = ledgerPath;
        fs.mkdirSync(path.dirname(ledgerPath), { recursive: true });
    }
    async append(entry) {
        const full = {
            id: entry.id ?? randomUUID(),
            timestamp: entry.timestamp ?? new Date().toISOString(),
            ...entry,
        };
        await fs.promises.appendFile(this.ledgerPath, JSON.stringify(full) + '\n', 'utf8');
        return full;
    }
    async readAll() {
        let buf;
        try {
            buf = await fs.promises.readFile(this.ledgerPath, 'utf8');
        }
        catch (err) {
            if (err?.code === 'ENOENT')
                return [];
            throw err;
        }
        const out = [];
        for (const line of buf.split('\n')) {
            const trimmed = line.trim();
            if (!trimmed)
                continue;
            try {
                out.push(JSON.parse(trimmed));
            }
            catch {
                // Skip unparseable rows — ledger must never crash readers.
            }
        }
        return out;
    }
    async findLatestPassedVerify(runId, stepId) {
        const rows = await this.readAll();
        for (let i = rows.length - 1; i >= 0; i--) {
            const r = rows[i];
            if (r.op === 'verify' && r.runId === runId && r.stepId === stepId && r.status === 'passed') {
                return r;
            }
        }
        return null;
    }
    async findVerifyById(verifyId) {
        const rows = await this.readAll();
        for (const r of rows) {
            if (r.op === 'verify' && r.verifyId === verifyId)
                return r;
        }
        return null;
    }
    async findStep(runId, stepId) {
        const rows = await this.readAll();
        for (let i = rows.length - 1; i >= 0; i--) {
            const r = rows[i];
            if (r.op === 'step' && r.runId === runId && r.stepId === stepId)
                return r;
        }
        return null;
    }
}
let singleton = null;
export function getKernelLedger() {
    if (!singleton) {
        const ledgerPath = path.join(resolveNexusStateDir(), 'kernel-execution', 'ledger.jsonl');
        singleton = new JsonlLedger(ledgerPath);
    }
    return singleton;
}
/** Build a ledger rooted at a caller-chosen path. Used by tests. */
export function createKernelLedger(ledgerPath) {
    return new JsonlLedger(ledgerPath);
}
/** Reset the process-wide singleton. Test-only. */
export function __resetKernelLedgerForTests() {
    singleton = null;
}
