"""Compare fixed Project/node/port/endpoint geometry and report routing changes. Usage: python compare_probe.py OLD_JSONL NEW_JSONL NEW_OUTPUT_JSON No layout-quality pass is inferred from equal inputs or successful execution. """ from pathlib import Path import hashlib import json import sys old_path, new_path, out = map(Path, sys.argv[1:]) def read(path): rows = [json.loads(line) for line in path.read_text(encoding='utf-8').splitlines()] return {row['fixture']: row for row in rows if 'fixture' in row} old, new = read(old_path), read(new_path) assert old.keys() == new.keys() def variants(row): yield 'before', row['before_project'], row['before'] yield 'baseline', row['after_project'], row['after'] for name in ['reset_only_control', 'experimental_candidate', 'manual_planar_order_witness']: if row[name] is not None: yield name, row[name]['project'], row[name]['metrics'] def endpoints(metrics): return {e['id']: [e['points'][0], e['points'][-1]] for e in metrics['routed_edges']} keys = ['proper_crossings', 'pairwise_collinear_shared_length', 'nonterminal_pairwise_shared_length', 'unrelated_node_collisions', 'unrelated_edge_node_penetrations', 'label_node_collisions', 'label_label_collisions', 'unrelated_label_stroke_intersections', 'warning_count', 'route_bends', 'route_length', 'drawing_area'] results = [] for name in old: lhs, rhs = list(variants(old[name])), list(variants(new[name])) assert len(lhs) == len(rhs) for (variant, op, om), (other, np, nm) in zip(lhs, rhs): assert variant == other fixed = {'project':op == np, 'nodes':om['projected_nodes'] == nm['projected_nodes'], 'ports':om['projected_ports'] == nm['projected_ports'], 'route_endpoints':endpoints(om) == endpoints(nm)} results.append({'fixture':name, 'variant':variant, 'fixed_geometry':fixed, 'metrics':{key:{'old':om[key], 'new':nm[key]} for key in keys}, 'new_point_contacts':nm.get('point_contacts'), 'new_point_contact_details':nm.get('point_contact_details')}) summary = {'old_sha256':hashlib.sha256(old_path.read_bytes()).hexdigest(), 'new_sha256':hashlib.sha256(new_path.read_bytes()).hexdigest(), 'all_projects_nodes_ports_endpoints_exact':all(all(r['fixed_geometry'].values()) for r in results), 'scope':'Fixed-geometry comparison; quality vector retained, no aggregate quality pass.', 'results':results} with out.open('x',encoding='utf-8') as f: json.dump(summary,f,indent=2) f.write('\n') print(json.dumps({k:v for k,v in summary.items() if k != 'results'})) for row in results: if row['variant'] == 'experimental_candidate': print(json.dumps({'fixture':row['fixture'], 'fixed_geometry':row['fixed_geometry'], 'changed_metrics':{k:v for k,v in row['metrics'].items() if v['old'] != v['new']}, 'point_contacts':row['new_point_contacts']}))