Files
ARCADIA-Studio/harness/experiments/analysis-source-s2a-windows-20260913/evidence/.local/audit-analysis-s2a-legacy-cause.py
T

74 lines
5.2 KiB
Python

"""Compare serde_json Value Debug assertion operands without printing model dumps."""
from pathlib import Path
import hashlib,json,re,subprocess
base=Path(__file__).resolve().parent.parent
repo=base/'.local/as2-20260913'
pin='b2c970b4673e062e47eadd12906d2316c4b1a7b3'
folder=base/'.local/analysis-source-gates-20260913'
raw=(folder/'legacy-full-b2c970b.log').read_bytes(); log=raw.decode()
name='original_v2_text_and_json_preserve_identity_and_mixed_scenarios_after_extensions'
sections=dict(re.findall(r'^---- (\S+) stdout ----\r?\n(.*?)(?=^---- |^failures:|\Z)',log,re.M|re.S))
assert len(sections)==9
assert sum('Unsupported schema version: expected arcadia 3, 4, 5, 6 or 7.' in b for b in sections.values())==8
section=sections[name]
left=re.search(r'^ left: (.*)$',section,re.M).group(1).rstrip('\r')
right=re.search(r'^ right: (.*)$',section,re.M).group(1).rstrip('\r')
class Parser:
def __init__(self,s): self.s=s; self.i=0; self.nodes=0
def ws(self):
while self.i<len(self.s) and self.s[self.i].isspace(): self.i+=1
def take(self,x):
self.ws(); assert self.s.startswith(x,self.i),(self.i,x); self.i+=len(x)
def string(self):
self.ws(); value,n=json.JSONDecoder().raw_decode(self.s[self.i:]); assert isinstance(value,str); self.i+=n; return value
def value(self):
self.ws(); self.nodes+=1
if self.s.startswith('Object',self.i):
self.take('Object'); self.take('{'); out={}; self.ws()
while self.s[self.i]!='}':
k=self.string(); self.take(':'); assert k not in out; out[k]=self.value(); self.ws()
if self.s[self.i]=='}': break
self.take(',')
self.take('}'); return out
if self.s.startswith('Array',self.i):
self.take('Array'); self.take('['); out=[]; self.ws()
while self.s[self.i]!=']':
out.append(self.value()); self.ws()
if self.s[self.i]==']': break
self.take(',')
self.take(']'); return out
if self.s.startswith('String',self.i):
self.take('String'); self.take('('); v=self.string(); self.take(')'); return v
if self.s.startswith('Null',self.i): self.take('Null'); return None
if self.s.startswith('Bool',self.i):
self.take('Bool'); self.take('('); v=self.s.startswith('true',self.i); self.take('true' if v else 'false'); self.take(')'); return v
self.take('Number'); self.take('('); end=self.s.index(')',self.i); v=('Number',self.s[self.i:end]); self.i=end; self.take(')'); return v
def parse(self):
v=self.value(); self.ws(); assert self.i==len(self.s); return v
a=Parser(left); retained=a.parse(); b=Parser(right); original=b.parse()
differences=[]
def compare(a,b,path=''):
if isinstance(a,dict) and isinstance(b,dict):
for k in sorted(a.keys()|b.keys()):
p=path+'/'+k.replace('~','~0').replace('/','~1')
if k not in b: differences.append({'path':p,'difference':'left_only','left':a[k]})
elif k not in a: differences.append({'path':p,'difference':'right_only','right':b[k]})
else: compare(a[k],b[k],p)
elif isinstance(a,list) and isinstance(b,list):
if len(a)!=len(b): differences.append({'path':path,'difference':'array_length','left':len(a),'right':len(b)})
else:
for i,(x,y) in enumerate(zip(a,b)): compare(x,y,path+'/'+str(i))
elif type(a)!=type(b) or a!=b: differences.append({'path':path,'difference':'value','left':a,'right':b})
compare(retained,original)
assert differences==[{'path':'/definitions','difference':'left_only','left':{}}]
assert retained.pop('definitions')=={} and retained==original
source_path='crates/oa-core/tests/language.rs'
test_source=subprocess.check_output(['git','show',pin+':'+source_path],cwd=repo)
fixture_path='crates/oa-core/tests/fixtures/v2-coastal-rescue.json'
fixture=subprocess.check_output(['git','show',pin+':'+fixture_path],cwd=repo)
fixture_json=json.loads(fixture,parse_int=lambda n:('Number',n),parse_float=lambda n:('Number',n))
assert original==fixture_json
report={'source':pin,'test':name,'legacy_total':16,'legacy_passed':7,'legacy_failed':9,'unsupported8_failure_names':sorted(n for n,b in sections.items() if 'Unsupported schema version:' in b),'assertion_difference':differences,'all_other_values_and_structure_equal':True,'right_matches_pinned_original_fixture':True,'debug_nodes_left':a.nodes,'debug_nodes_right':b.nodes,'log_sha256':hashlib.sha256(raw).hexdigest(),'test_source_path':source_path,'test_source_sha256':hashlib.sha256(test_source).hexdigest(),'fixture_path':fixture_path,'fixture_sha256':hashlib.sha256(fixture).hexdigest(),'interpretation':'The historical retained-vs-original projection omits the newly explicit empty definitions catalog from its compatibility-default normalization. Source-vs-JSON equality earlier in the same test completed before this assertion. This failure is an oracle projection mismatch, not evidence of lost original V2 data; later assertions did not execute and the test remains failed.'}
with (base/'.local/analysis-source8-s2a-legacy-cause-20260913.json').open('x',encoding='utf-8') as out: json.dump(report,out,indent=2)
print(json.dumps(report,indent=2))