evidence: digest reads DFG Re20 result.json of schema 1 or 2

final_physical_digest.py indexed [0] on the bare-list (schema 1) native
receipt. v4_cases() accepts schema 1 and the versioned schema-2 object
and rejects others. Existing outputs and final-physical-digest.json are
unchanged; that digest records the previous postprocessor hash, so a
rerun with this version is a new digest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Claude
2026-10-20 18:36:44 +00:00
co-authored by Claude Opus 5.5
parent 70f66176bc
commit f4ae028154
@@ -13,6 +13,11 @@ R = Path('/home/frank14f/CelerisLab-release-prep-20261020')
SHA = '750e8a483ec47dcf472e528edc1cf2936f0e7e83'
def read(p):
return json.loads(p.read_text())
def v4_cases(data):
"""DFG Re20 result.json: schema 1 is a bare case list, schema 2 is {schema, provenance, cases}."""
if isinstance(data, list): return data
if isinstance(data, dict) and data.get('schema') == 2: return data['cases']
raise ValueError('unknown DFG Re20 result schema')
def sha(p):
return hashlib.sha256(p.read_bytes()).hexdigest()
def cmd(*a):
@@ -50,7 +55,7 @@ for label,sj in state['jobs'].items():
c['external_manifest_hash_matches']=r['external_manifest_sha256']==sha(Q/'manifest.json')
c['hashes']={str(z.relative_to(p)):sha(z) for z in [p/'command.json',p/'result.json',*sorted((p/'output').rglob('*.json')),*sorted((p/'output').rglob('*.csv')),*sorted((p/'output').rglob('*.jsonl'))]}
if label.startswith('v4'):
n=read(p/'output/result.json')[0]; rows=n['rows']
n=v4_cases(read(p/'output/result.json'))[0]; rows=n['rows']
captured=r['native_results'][0]
c['native_receipt_matches_external_result']=all(n[k]==z for k,z in captured.items() if k not in ['last_row','rows_count']) and captured['last_row']==rows[-1] and captured['rows_count']==len(rows)
c['external_receipt_history_handling']='V4 external receipt stores row count and last row; full native rows are separately hashed'