test: versioned reader for DFG Re20 result.json (schema 1 and 2)
read_result() returns cases/provenance for the old bare-list receipts and
the new schema-2 object, and rejects unknown schemas. Existing evidence
(e.g. 70f6617) and its digest scripts stay valid for schema 1; queue and
digest scripts must use read_result(...)['cases'] for new receipts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
2220cdd157
commit
c33af7a66d
@@ -48,5 +48,7 @@ The uniform D80 control separates method error from refinement error. `--plan` w
|
||||
(per case: lattice parameters, every sample, window ranges, status, verdict).
|
||||
Receipts: `plan.json` and `result.json` carry `schema` 2 and `provenance` (HEAD, src tree,
|
||||
runner hash; clean checkout required, refused if it changes during the run). Receipts
|
||||
written before this (schema 1, e.g. evidence 70f6617) are a bare list of cases.
|
||||
written before this (schema 1, e.g. evidence 70f6617) are a bare list of cases. Read both
|
||||
with `run_dfg_re20.read_result(path)` (`["cases"][0]` replaces the old `[0]`); existing
|
||||
evidence scripts stay valid for schema-1 receipts and need this reader for new ones.
|
||||
Host contract tests: `tests/unit/test_dfg_re20.py`.
|
||||
|
||||
@@ -85,6 +85,23 @@ class Re20Provenance(unittest.TestCase):
|
||||
self.assertFalse(record["checkout_dirty"])
|
||||
self.assertEqual(v.RESULT_SCHEMA, 2)
|
||||
|
||||
def test_reader_accepts_both_schemas_and_rejects_unknown(self):
|
||||
import json
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
case = dict(case="refined", status="NOT_STEADY", verdict=None, rows=[])
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
old, new, bad = Path(d, "old.json"), Path(d, "new.json"), Path(d, "bad.json")
|
||||
old.write_text(json.dumps([case]))
|
||||
new.write_text(json.dumps(dict(schema=2, provenance=dict(src_tree="a" * 40),
|
||||
cases=[case])))
|
||||
bad.write_text(json.dumps(dict(schema=3, cases=[case])))
|
||||
self.assertEqual(v.read_result(old), dict(schema=1, provenance=None, cases=[case]))
|
||||
self.assertEqual(v.read_result(new)["cases"][0], case)
|
||||
self.assertEqual(v.read_result(new)["provenance"]["src_tree"], "a" * 40)
|
||||
with self.assertRaisesRegex(ValueError, "unknown DFG Re20 result schema"):
|
||||
v.read_result(bad)
|
||||
|
||||
def test_dirty_checkout_is_refused(self):
|
||||
from unittest.mock import patch
|
||||
with patch("source_provenance.subprocess.check_output",
|
||||
|
||||
@@ -108,6 +108,21 @@ def summarize(rows):
|
||||
verdict=inside)
|
||||
|
||||
|
||||
def read_result(path):
|
||||
"""Cases and provenance from a result.json of either schema.
|
||||
|
||||
Schema 1 (receipts before RESULT_SCHEMA=2, e.g. evidence 70f6617) is a bare list of
|
||||
cases without provenance; schema 2 is {schema, provenance, cases}. Readers that
|
||||
indexed [0] on schema 1 must use read_result(path)["cases"][0].
|
||||
"""
|
||||
data = json.loads(Path(path).read_text())
|
||||
if isinstance(data, list):
|
||||
return dict(schema=1, provenance=None, cases=data)
|
||||
if not isinstance(data, dict) or data.get("schema") != RESULT_SCHEMA:
|
||||
raise ValueError(f"unknown DFG Re20 result schema: {data.get('schema') if isinstance(data, dict) else type(data).__name__}")
|
||||
return dict(schema=RESULT_SCHEMA, provenance=data["provenance"], cases=data["cases"])
|
||||
|
||||
|
||||
def healthy(row):
|
||||
return row["max_mach"] <= 0.2 and row["rho_min"] >= 0.5 and row["rho_max"] <= 1.5
|
||||
|
||||
|
||||
Reference in New Issue
Block a user