import { readFile } from 'node:fs/promises';
import { deriveResearchTrace, normalizeResearchTrace } from '../agent-session/research-trace.js';
export async function loadResearchTraceFixture(path) {
    return JSON.parse(await readFile(path, 'utf8'));
}
export class ResearchTraceEvaluator {
    run(fixture) {
        const cases = fixture.cases.map((testCase) => this.evaluateCase(testCase));
        return {
            fixtureName: fixture.name,
            totalCases: cases.length,
            passedCases: cases.filter((testCase) => testCase.passed).length,
            cases,
        };
    }
    evaluateCase(testCase) {
        const trace = testCase.mode === 'explicit'
            ? normalizeResearchTrace(testCase.input)
            : deriveResearchTrace(testCase.input);
        const failures = evaluateTrace(trace, testCase);
        return {
            id: testCase.id,
            passed: failures.length === 0,
            derived: trace.derived,
            stepCount: trace.steps.length,
            failures,
        };
    }
}
function evaluateTrace(trace, testCase) {
    const failures = [];
    const serialized = JSON.stringify(trace);
    if (trace.derived !== testCase.expect.derived) {
        failures.push(`derived expected ${testCase.expect.derived} but got ${trace.derived}`);
    }
    if (testCase.expect.maxSteps !== undefined && trace.steps.length > testCase.expect.maxSteps) {
        failures.push(`step count ${trace.steps.length} exceeded ${testCase.expect.maxSteps}`);
    }
    for (const needle of testCase.expect.includes ?? []) {
        if (!serialized.includes(needle)) {
            failures.push(`missing expected trace text: ${needle}`);
        }
    }
    for (const needle of testCase.expect.excludes ?? []) {
        if (serialized.includes(needle)) {
            failures.push(`unexpected trace text: ${needle}`);
        }
    }
    if (trace.bytes <= 0) {
        failures.push('bytes must be positive');
    }
    return failures;
}
