"""Frozen scoring harness. Runs a formatter callable against a list of exemplars and aggregates: - field-level match rate (via harness.diff.field_diff) - linter pass rate (if a linter function is provided) - canary exact-match rate (on exemplars marked canary=True) The loop scalar is `field_match_rate * linter_pass_rate` (linter defaults to 1.0 when no linter is wired in yet). Canary exact-match is tracked separately and treated as a regression gate at the loop level, not folded into the scalar. This module is FROZEN with respect to the autoresearch loop — edits here are infra commits that invalidate prior scores. """ from __future__ import annotations import tomllib from dataclasses import dataclass, field from pathlib import Path from typing import Callable from harness.diff import field_diff @dataclass class Exemplar: name: str source: str type: str tags: list[str] canary: bool messy_input: str canonical: dict expected_bibliography: str @dataclass class ExemplarResult: name: str candidate: str field_match_rate: float linter_passed: bool canary: bool exact_match: bool @dataclass class ScoreResult: per_exemplar: list[ExemplarResult] = field(default_factory=list) field_match_rate: float = 0.0 linter_pass_rate: float = 1.0 canary_exact_match_rate: float = 1.0 scalar: float = 0.0 LinterFn = Callable[[str, Exemplar], bool] FormatterFn = Callable[[str], str] def _mean(values: list[float]) -> float: return sum(values) / len(values) if values else 1.0 def score( exemplars: list[Exemplar], formatter: FormatterFn, linter: LinterFn | None = None, ) -> ScoreResult: """Run `formatter` against each exemplar and aggregate a score.""" results: list[ExemplarResult] = [] for ex in exemplars: candidate = formatter(ex.messy_input) diff = field_diff(candidate, ex.canonical) linter_ok = True if linter is None else bool(linter(candidate, ex)) results.append( ExemplarResult( name=ex.name, candidate=candidate, field_match_rate=diff.rate, linter_passed=linter_ok, canary=ex.canary, exact_match=(candidate == ex.expected_bibliography), ) ) field_rate = _mean([r.field_match_rate for r in results]) linter_rate = _mean([1.0 if r.linter_passed else 0.0 for r in results]) canary_results = [r for r in results if r.canary] canary_rate = ( _mean([1.0 if r.exact_match else 0.0 for r in canary_results]) if canary_results else 1.0 ) return ScoreResult( per_exemplar=results, field_match_rate=field_rate, linter_pass_rate=linter_rate, canary_exact_match_rate=canary_rate, scalar=field_rate * linter_rate, ) def load_exemplars(directory: Path) -> list[Exemplar]: """Load every `.toml` file in `directory` as an Exemplar.""" exemplars: list[Exemplar] = [] for path in sorted(directory.glob("*.toml")): with path.open("rb") as fh: data = tomllib.load(fh) exemplars.append( Exemplar( name=path.stem, source=data["source"], type=data["type"], tags=list(data.get("tags", [])), canary=bool(data.get("canary", False)), messy_input=data["messy_input"], canonical=dict(data["canonical"]), expected_bibliography=data["expected_bibliography"], ) ) return exemplars