Files
ARCADIA-Studio/harness/experiments/traceability-view-17f1f89-20260923/native/check.py
T

85 lines
8.3 KiB
Python

"""Full-Project checkpoint comparison with one preregistered fresh placement binding."""
from pathlib import Path
import argparse,copy,datetime,json,math,subprocess,sys,uuid
sys.dont_write_bytecode=True
from stage import HERE,child_env,copy_new,read,record,verify,write,canonical
def identities(value):
found=set()
def walk(v):
if isinstance(v,dict):
for k,x in v.items():walk(k);walk(x)
elif isinstance(v,list):
for x in v:walk(x)
elif isinstance(v,str):
try:found.add(str(uuid.UUID(v)))
except ValueError:pass
walk(value);return found
def main():
p=argparse.ArgumentParser();p.add_argument('--expected',required=True,choices=['B','P']);p.add_argument('--output-prefix',required=True,type=Path);p.add_argument('--actual',type=Path);p.add_argument('--calibration',type=Path);a=p.parse_args()
staging=read(HERE/'staging-record.json');verify(staging['manifest']);manifest=read(HERE/'input-manifest.json')
if staging['source_commit']!=manifest['source_commit']:raise RuntimeError('Stage pin mismatch')
for r in manifest['immutable_files']:verify(r)
catalog_record=record(HERE/'expected/catalog.json');catalog=read(catalog_record['path']);verify(catalog['contract']);contract=read(catalog['contract']['path'])
for r in catalog['checkpoints'].values():verify(r)
baseline=read(catalog['checkpoints']['B']['path']);template=read(catalog['checkpoints']['P-template']['path']);reserved=catalog['reserved_node_uuid'];diagram=contract['diagram'];binding_path=HERE/'fresh-node-binding.json'
binding_record=record(binding_path) if binding_path.exists() else None;binding=read(binding_path) if binding_record else None
if binding:
for field,r in [('manifest',staging['manifest']),('catalog',catalog_record),('evaluator',manifest['evaluator'])]:
if any(binding[field][k]!=r[k] for k in ('bytes','sha256')):raise RuntimeError('Binding input changed')
verify(binding['first_checkpoint_receipt']);verify(binding['calibration'])
first=read(binding['first_checkpoint_receipt']['path'])
if first['failure'] or not first['full_project_exact'] or not first['inputs_unchanged'] or first['expected']!='P' or binding['source_commit']!=manifest['source_commit']:raise RuntimeError('Invalid first binding receipt')
if any(binding[key]!=first['proposed_binding'][key] for key in ('node_uuid','position','signed_error')):raise RuntimeError('Binding no longer matches its first accepted checkpoint')
prefix=a.output_prefix.resolve();outputs={suffix:Path(str(prefix)+suffix) for suffix in ('.arcadia','.project.json','.stdout.log','.stderr.log','.receipt.json')}
if any(path.exists() for path in outputs.values()):raise RuntimeError('Fresh checkpoint prefix required')
actual_path=(a.actual or Path(manifest['saved_working_path'])).resolve()
if actual_path.suffix.lower()!='.arcadia':raise RuntimeError('Save As the declared normalized source before checks')
actual=record(actual_path);prefix.parent.mkdir(parents=True,exist_ok=True);copy_new(actual_path,outputs['.arcadia'])
started=datetime.datetime.now(datetime.timezone.utc).isoformat();exit_code=None;failure=None;exact=False;unchanged=False;candidate_binding=None;calibration=None
try:
with outputs['.stdout.log'].open('xb') as stdout,outputs['.stderr.log'].open('xb') as stderr:
proc=subprocess.run([manifest['evaluator']['path'],str(outputs['.arcadia']),str(outputs['.project.json'])],cwd=HERE/'unrelated-cwd',env=child_env(),stdout=stdout,stderr=stderr)
exit_code=proc.returncode
if exit_code or outputs['.stderr.log'].stat().st_size:raise RuntimeError('Evaluator failed or emitted stderr')
observed=read(outputs['.project.json']);expected=baseline
if a.expected=='P':
if binding:
node_id=binding['node_uuid'];position=binding['position']
else:
if a.calibration is None:raise RuntimeError('First P requires the pre-input calibration record')
calibration=record(a.calibration);cal=read(a.calibration)
if cal['target']!=contract['position_rule']['target'] or cal['maximum_absolute_error_per_axis_world_units']!=1.0:raise RuntimeError('Calibration contract differs')
stamp=datetime.datetime.fromisoformat(cal['declared_utc'].replace('Z','+00:00'))
if stamp.tzinfo is None or stamp>=datetime.datetime.fromisoformat(started):raise RuntimeError('Pre-input calibration timestamp required')
if not all(k in cal for k in ('canvas_mapping','physical_pixel_scale','chosen_integer_pixel','predicted_error_bound_world')):raise RuntimeError('Calibration evidence incomplete')
pixel=cal['chosen_integer_pixel'];bound=cal['predicted_error_bound_world']
if set(pixel)!={'x','y'} or any(type(v) is not int for v in pixel.values()) or set(bound)!={'x','y'} or any(type(v) not in (int,float) or not math.isfinite(v) or not 0<=v<=1 for v in bound.values()):raise RuntimeError('Invalid predeclared targeting evidence')
nodes=observed['diagrams'][diagram]['nodes'];new_ids=set(nodes)-set(baseline['diagrams'][diagram]['nodes'])
if len(new_ids)!=1:raise RuntimeError('Require exactly one new node identity in target view')
node_id=next(iter(new_ids));u=uuid.UUID(node_id)
if str(u)!=node_id or u.version!=4 or u.variant!=uuid.RFC_4122 or node_id in identities(baseline):raise RuntimeError('New identity must be canonical fresh UUIDv4')
if nodes[node_id]['id']!=node_id:raise RuntimeError('Node key/id mismatch')
position=nodes[node_id]['position'];target=contract['position_rule']['target']
if set(position)!={'x','y'} or any(type(v) not in (int,float) or not math.isfinite(v) or abs(v-target[axis])>1.0 for axis,v in position.items()):raise RuntimeError('Placement outside fixed prelaunch precision box')
expected=copy.deepcopy(template);node=expected['diagrams'][diagram]['nodes'].pop(reserved);node['id']=node_id;node['position']=copy.deepcopy(position);expected['diagrams'][diagram]['nodes'][node_id]=node
if not binding:candidate_binding={'node_uuid':node_id,'position':position,'signed_error':{axis:position[axis]-contract['position_rule']['target'][axis] for axis in ('x','y')}}
exact=canonical(observed)==canonical(expected)
if not exact:raise RuntimeError('Entire Project differs from frozen B/P contract')
verify(actual)
for r in manifest['immutable_files']:verify(r)
verify(staging['manifest'])
if binding_record:verify(binding_record)
if calibration:verify(calibration)
unchanged=True
except Exception as e:failure=str(e)
artifacts=[record(path) for suffix,path in outputs.items() if suffix!='.receipt.json' and path.exists()]
receipt={'source_commit':manifest['source_commit'],'evaluator_source_commit':manifest['evaluator_source_commit'],'started_utc':started,'finished_utc':datetime.datetime.now(datetime.timezone.utc).isoformat(),'expected':a.expected,'catalog':catalog_record,'contract':catalog['contract'],'manifest':staging['manifest'],'evaluator':manifest['evaluator'],'input':actual,'exit_code':exit_code,'failure':failure,'inputs_unchanged':unchanged,'full_project_exact':exact,'artifacts':artifacts,'prior_binding':binding_record,'proposed_binding':candidate_binding if exact and unchanged else None,'calibration':calibration,'scope':'Complete saved Project; only first P may bind fresh UUID plus fixed-box position after full equality. Native input/freshness not proved here.'}
write(outputs['.receipt.json'],receipt)
if failure or not exact or not unchanged:raise SystemExit('Comparison failed; preserve outputs: '+str(failure))
if candidate_binding:
write(binding_path,{**candidate_binding,'source_commit':manifest['source_commit'],'manifest':staging['manifest'],'catalog':catalog_record,'baseline':catalog['checkpoints']['B'],'contract':catalog['contract'],'evaluator':manifest['evaluator'],'calibration':calibration,'first_checkpoint_receipt':record(outputs['.receipt.json']),'input':actual,'position_rule':contract['position_rule'],'scope':'Created only after full Project equality; subsequent P uses exact UUID and exact x/y without tolerance'})
print(a.expected+': complete Project exact; immutable inputs unchanged')
if __name__=='__main__':main()