agent-harness GitHub

Learning evaluator evidence boundaries

Follow-through for #521, #522 and the retrieval-metric portion of #500. This changes offline evaluation, not the runtime dispatcher or an LLM merge gate.

Independent evidence

The selected hold-out counts each input_ref once. Exact oracle clones on the same input remain deduplicated only when both variants’ output records and any judge labels agree. Missing versus present evidence also conflicts. Different oracles or contradictory observations on the same selected input refuse the run, instead of treating correlated facets as independent wins or silently picking a favourable facet. Producers needing multiple facets must provide an explicitly designed aggregate trial; this evaluator does not invent one. input_ref is still supplied metadata, not proof of real-world independence. Broader clustered inference and provenance qualification remain under #513.

Retrieval metrics

The denominator comes from selected ranked_recall cases, not from whether a variant returned usable output. Missing outputs, errors and missing item lists contribute zero recall and reciprocal rank for that arm. Both arms retain the same denominator, including an all-failed retrieval run.

A retrieval_regression gate cannot pass if either mean recall-at-k or mean reciprocal rank falls below baseline, even when unrelated case wins satisfy the existing paired sign test. The other gate types retain their existing paired policy. This is a conservative no-regression guard, not a claim to estimate rank-metric confidence intervals or to complete every concern in #500.

A named retrieval gate with no selected ranked_recall inputs is insufficient and emits no gate, even if unrelated cases all win. offline_eval remains usable for those non-retrieval suites. Mixed suites retain the declared overall-case minimum and sign policy: their measured retrieval denominator is reported as n, not represented as retrieval-only statistical power. Retrieval-specific sample size, clustered inference and policy authority remain separate work under #513; this repair does not silently invent a new threshold or count unrelated cases as ranked-recall observations.

Regular-expression oracles

Compilation and matching run in a fresh standard-library Python subprocess with -I -S; patterns and output text are JSON data on stdin, never executable source. Each worker has a two-second wall-clock deadline. A timeout kills and reaps the worker and refuses evaluation; launch failure, nonzero exit or malformed worker output likewise cannot become a passing grade. Invalid expressions refuse before grading. Repeated patterns are compiled once during one selection pass, without retaining a cross-run cache of private output text.

This bounds one regex operation, not the number of cases in a supplied suite or arbitrary policy code. The worker executes only the fixed regex helper and does not spawn descendants. The regression uses a deliberately backtracking pattern and a separate ten-second outer watchdog so a broken timeout cannot wedge tests.

Report identity and verification

Evaluator identity advances to agent-harness:scripts/learning_eval.py@2 and is included in the derived report ID. The same records evaluated by another tool revision therefore do not silently reuse an old report identity. The identity also binds the full selected case contracts, including their oracle and input/anchor fields. Outputs are explicitly bound to baseline/candidate roles, so swapping the arms cannot reuse the same ID. Recursive JSON key ordering and supplied case order do not change the identity. holdout_digest remains the digest of selected case IDs, not their contents; report schemas, contract bundle bytes and historical reports are unchanged. These consistency bindings are not authentication of the producer’s claimed provenance or of unobserved execution.

Run python -m unittest discover -s tests -p test_learning_eval.py -v for the synthetic evidence controls, and the full repository unit, smoke and Doctor commands before publication. Native hosted OS results are separate evidence from local Linux tests; no live transcripts, promotion deployment or runtime canaries are exercised by these tests.