"""Run the cognition eval harness. Loads cases from cognition_cases.jsonl, runs each through the CognitiveTurnPipeline, and produces an EvalReport with deterministic metrics. Each case gets a fresh pipeline instance for isolation. """ from __future__ import annotations import json from functools import partial from pathlib import Path from typing import Callable from chat.runtime import ChatRuntime from core.config import RuntimeConfig from core.cognition.pipeline import CognitiveTurnPipeline from evals.metrics import CaseResult, EvalReport from evals._parallel import run_cases_parallel from generate.intent import IntentTag _CASES_PATH = Path(__file__).parent / "cognition_cases.jsonl" def load_cases(path: Path | None = None) -> list[dict]: p = path or _CASES_PATH cases = [] for line in p.read_text().splitlines(): line = line.strip() if line: cases.append(json.loads(line)) return cases def _run_case(case: dict, pipeline: CognitiveTurnPipeline) -> CaseResult: prompt = case["prompt"] expected_intent = case["expected_intent"] expected_terms = case.get("expected_terms", []) expected_surface_contains = case.get("expected_surface_contains", []) result = pipeline.run(prompt, max_tokens=8) actual_intent = result.intent.tag if result.intent else IntentTag.UNKNOWN intent_correct = actual_intent.value == expected_intent surface_lower = result.surface.lower() terms_captured = tuple( t for t in expected_terms if t.lower() in surface_lower ) surface_contains_pass = all( s.lower() in surface_lower for s in expected_surface_contains ) versor_ok = result.versor_condition < 1e-6 return CaseResult( case_id=case["id"], category=case.get("category", "unknown"), prompt=prompt, intent_correct=intent_correct, terms_captured=terms_captured, terms_expected=tuple(expected_terms), surface_contains_pass=surface_contains_pass, versor_closure=versor_ok, versor_condition=result.versor_condition, trace_hash=result.trace_hash, surface=result.surface, ) def _build_case_runner( config: RuntimeConfig | None = None, ) -> Callable[[dict], CaseResult]: """Warm worker-local caches once, then return a per-case scorer.""" if config is None: ChatRuntime(no_load_state=True) else: ChatRuntime(config=config, no_load_state=True) def _run(case: dict) -> CaseResult: runtime = ChatRuntime(config=config, no_load_state=True) if config else ChatRuntime(no_load_state=True) pipeline = CognitiveTurnPipeline(runtime) return _run_case(case, pipeline) return _run def run_eval( cases: list[dict] | None = None, config: RuntimeConfig | None = None, *, workers: int | None = None, ) -> EvalReport: if cases is None: cases = load_cases() report = EvalReport() case_runner_builder = partial(_build_case_runner, config=config) case_results = run_cases_parallel( cases, case_runner_builder, n_workers=workers if workers is not None else 4, ) for case_result in case_results: report.total += 1 if case_result.intent_correct: report.intent_correct += 1 report.terms_expected += len(case_result.terms_expected) report.terms_captured += len(case_result.terms_captured) if case_result.surface_contains_pass: report.surface_grounded += 1 if case_result.versor_closure: report.versor_closures += 1 report.cases.append(case_result) report.trace_hashes[case_result.case_id] = case_result.trace_hash return report def check_determinism(cases: list[dict] | None = None, runs: int = 2) -> bool: if cases is None: cases = load_cases() hashes_by_run: list[dict[str, str]] = [] for _ in range(runs): report = run_eval(cases) hashes_by_run.append(dict(report.trace_hashes)) first = hashes_by_run[0] for run_hashes in hashes_by_run[1:]: if run_hashes != first: return False return True