6363``true_positives`` and ``denied_total`` — not rendered in the Markdown report (the floats and pair
6464breakdowns already cover a human reader) but read back here by ``_write_trend_log`` to pool a
6565run's precision/recall/denial_precision into one committed, append-only trend-log row per suite
66- (``eval/trend_log.py``, spec: ``docs/evaluation/eval-framework.md`` §9) — pooled by summed count
66+ (``eval/dashboard/ trend_log.py``, spec: ``docs/evaluation/eval-framework.md`` §9) — pooled by summed count
6767across every scenario that reached ``score_scenario`` in the run, not averaged per-scenario, so a
6868run with an uneven pair count per scenario isn't skewed by weighting every scenario equally. A
6969scenario whose own setup failed never recorded these, so it contributes nothing to the pooled row
8080committed trend-log row per family/tier combination -- ``suite="robustness_mechanical_invariance"``/
8181``"robustness_semantic_invariance"``/``"robustness_mechanical_sensitivity"``/
8282``"robustness_semantic_sensitivity"`` -- each carrying that row's own precision/recall/
83- denial_precision (``eval/trend_log.py``'s ``pool_correctness_metrics``, the same pooling the two
83+ denial_precision (``eval/dashboard/ trend_log.py``'s ``pool_correctness_metrics``, the same pooling the two
8484Correctness suites use, so the resulting chart is directly comparable to theirs: two measuring
8585performance against the *original* inputs, two against *deliberately edited/reworded* inputs) plus
8686that row's own pass/fail rate (``invariance_rate``/``sensitivity_rate``).
9191mismatch detail when ``True``) via ``_render_consistency_block``, on every entry, pass or fail,
9292unlike every other test in this suite besides the correctness/robustness metrics blocks above -- and
9393pooled by nodeid substring (``_CONSISTENCY_TEST_MARKERS``) into its own committed trend-log row,
94- ``suite="consistency"``, carrying an ``agreement_rate`` (``eval/trend_log.py``'s
94+ ``suite="consistency"``, carrying an ``agreement_rate`` (``eval/dashboard/ trend_log.py``'s
9595``pool_consistency_metrics`` -- its own smaller pooling function, since there's no truth table here
9696to produce a ``pool_correctness_metrics``-shaped precision/recall).
9797
107107pooled by nodeid substring (``_SCALE_TEST_MARKERS``, mapping to ``(suite, "structural" |
108108"correctness")`` rather than a bare suite name) and merged into one row per dimension/level --
109109``scale_total_corpus_prb``/``scale_per_decision_prb`` (and their ``_e2e`` counterparts) -- via
110- ``eval/trend_log.py``'s ``pool_scale_metrics`` for the structural half and the existing
110+ ``eval/dashboard/ trend_log.py``'s ``pool_scale_metrics`` for the structural half and the existing
111111``pool_correctness_metrics`` for the correctness half.
112112
113113Below the per-category drill-down, ``pytest_sessionfinish`` appends an **"Improvement
139139import pytest
140140from dotenv import load_dotenv
141141
142+ from eval .dashboard .trend_log import append_row , pool_consistency_metrics , pool_correctness_metrics , pool_scale_metrics
142143from eval .recommendations import build_recommendations
143- from eval .trend_log import append_row , pool_consistency_metrics , pool_correctness_metrics , pool_scale_metrics
144144
145145HERE = Path (__file__ ).resolve ().parent
146146REPORTS_DIR = HERE / "reports"
@@ -292,7 +292,7 @@ def _format_pairs_dict(pairs_by_gate: dict) -> str:
292292 "::test_prb_sensitive_to_semantic_perturbation[" ,
293293)
294294
295- # Nodeid substring -> trend-log suite name (eval/trend_log.py). With the five former ``eval_*``
295+ # Nodeid substring -> trend-log suite name (eval/dashboard/ trend_log.py). With the five former ``eval_*``
296296# markers collapsed to one flat ``eval`` marker, every suite under `eval/` is disambiguated by its
297297# own test function's nodeid rather than by marker — the same ``::test_prb_correctness[``/
298298# ``::test_e2e_correctness[`` substrings ``_CORRECTNESS_TEST_MARKERS`` already uses. Deliberately
@@ -347,7 +347,7 @@ def _format_pairs_dict(pairs_by_gate: dict) -> str:
347347# invariance_rate/sensitivity_rate, which _write_trend_log injects on top of pool_correctness_
348348# metrics' output separately). Kept as its own dict (not folded into _TREND_LOG_SUITES) since its
349349# entries are pooled by pool_consistency_metrics, not pool_correctness_metrics -- see
350- # eval/trend_log.py.
350+ # eval/dashboard/ trend_log.py.
351351_CONSISTENCY_TEST_MARKERS = {
352352 "::test_prb_consistent_across_repeats[" : "consistency" ,
353353}
@@ -356,7 +356,7 @@ def _format_pairs_dict(pairs_by_gate: dict) -> str:
356356# docs/evaluation/policy-eval-scale.md). Unlike every dict above, each Scale trend-log row
357357# (e.g. "scale_total_corpus_prb") is built from *two* separate test functions -- a structural test
358358# (record_property("structural_pass"/"structural_issue_count"/...), pooled by
359- # eval.trend_log.pool_scale_metrics) and a correctness test (the familiar precision/recall shape,
359+ # eval.dashboard. trend_log.pool_scale_metrics) and a correctness test (the familiar precision/recall shape,
360360# pooled by the existing pool_correctness_metrics) -- so this dict's value is a
361361# (suite, "structural" | "correctness") pair rather than a bare suite name; _write_trend_log pools
362362# each half separately then merges them into one row. Neither test function is parametrized (each
0 commit comments