from research import *
f=json.loads((ROOT/'model/native_mode_fields.json').read_text()); tables={t:{r['name']:r for r in rows} for t,rows in f.items()}; names=[r['name'] for r in f['MT']]
s=begin(746,'Verify composition on the full shared genealogy','Do MT→SP→LXX comparisons compose node-by-node in both modes and the modebridge?',{'shared_nodes':names,'modes':['R','C_lower','G'],'excluded_from_shared_grid':'nativeLXX-onlyCainan retained in itsownpath'},['C738–C745; Research Strategy §5D'])
residuals={m:[(tables['SP'][n][m]-tables['MT'][n][m])+(tables['LXX'][n][m]-tables['SP'][n][m])-(tables['LXX'][n][m]-tables['MT'][n][m]) for n in names] for m in ['R','C_lower','G']}
finish(s,{'composition_residuals':residuals,'typed_comparisons':60},'All60 typed shared-node comparisons compose exactly. This is consistency of a common source-coordinate representation, not independent confirmation from60matches. The native inserted row remains visible rather than being invented in the othertraditions.','Test why matchingCreation totals alone cannot recover the ordered source structure.',{'all_zero':all(v==0 for row in residuals.values() for v in row),'coverage':sum(len(v) for v in residuals.values())==60})
