Scores committed agent-run fixtures against the golden corpus at (file, rule_key) granularity, building on the deterministic coordinator contract (4a). Offline: committed reviewer payloads, no live agent spawn, no LLM, no network (the LLM-in-the-loop grading is the separate 4c tier). - lib/review/gold-scorer.mjs: scoreFindings (precision/recall/f1 at (file,rule_key) granularity, line+severity ignored) + scoreVerdict; pure, with documented vacuous-set conventions. - tests/fixtures/bakeoff-rich/runs/run-perfect.json: committed run that reproduces all 5 seeded gold findings through runContract. - tests/lib/gold-eval.test.mjs: the scoring RUN (precision/recall/f1 = 1.0, verdict == expected_verdict BLOCK, nothing suppressed/skipped). - lib/util/test-census.mjs: third census category (goldEval) — a scoring run is neither behavior coverage nor a doc-pin; honest-count invariant now 3-way. - docs/eval-corpus/README.md: 4b moved from Future hardening to implemented. Suite 809 -> 822 (820/0/2). gold-scorer covers TP+FP+FN+degenerate paths. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BJQYC5vpkJWxndS55vQQZ6
89 lines
3.3 KiB
JavaScript
89 lines
3.3 KiB
JavaScript
// lib/review/gold-scorer.mjs
|
||
// SKAL-1·4b — offline gold-scored output eval scorer.
|
||
//
|
||
// Scores a recorded agent-run's findings against a golden corpus record
|
||
// (voyage-eval-gold/1, see docs/eval-corpus/README.md) at (file, rule_key)
|
||
// granularity. line and severity are deliberately NOT part of the match key:
|
||
// the eval asks "did the run surface this issue at all", and (file, rule_key)
|
||
// is the identity pair a delivered diff + the catalogue uniquely determine.
|
||
//
|
||
// Pairs with coordinator-contract.mjs (4a): that module turns committed
|
||
// reviewer payloads into the run findings scored here. This module is the
|
||
// offline counterpart to the live LLM-in-the-loop eval (4c) — pure: no I/O,
|
||
// no LLM, no network, no time, no randomness.
|
||
//
|
||
// Vacuous-set conventions (documented so the degenerate numbers are honest):
|
||
// - precision when nothing is predicted (tp+fp === 0) -> 1 (no false positives)
|
||
// - recall when there is nothing to find (tp+fn === 0) -> 1 (found all zero)
|
||
// - f1 collapses to 0 whenever precision or recall is 0, so it stays the
|
||
// honest single-number summary for the degenerate run/gold cases.
|
||
|
||
// NUL separator: file paths and rule_keys never contain it, so the join is
|
||
// an injective (file, rule_key) -> string key.
|
||
const SEP = ' |