"""Mandatory transfer groups. Every subcase runs freshly on the explicit ROM.

Child source is public and uses explicit inputs/outputs; no imported receipts,
private source paths or prototype successes. A child failure blocks its group.
"""
from pathlib import Path
from datetime import datetime,timezone
import argparse,hashlib,json,subprocess,sys,time
GROUPS={
 'model':[('model_check',[])],
 'engine':[('core',[]),('records',[]),('transactions',[])],
 'persistence':[('store',[]),('torn',[]),('torn',['--negative'])],
 'runtime':[('runtime',[]),('getters',[]),('off',[]),('lines',[]),('negative',[]),('cards',[]),('display',[])],
 'season':[('weights',[]),('statistics',[]),('end_coach',[])],
 'journal':[('journal',[]),('journal_torn',[]),('journal_torn',['--negative'])],
 'flow':[('menu',[]),('flow',[])],
}
def run_group(name):
 ap=argparse.ArgumentParser();ap.add_argument('rom',type=Path);ap.add_argument('output',type=Path);ap.add_argument('--baseline',type=Path);a=ap.parse_args();h=Path(__file__).resolve().parent;o=a.output.resolve();o.mkdir(parents=True,exist_ok=True);rom=a.rom.resolve();sha=lambda p:hashlib.sha256(Path(p).read_bytes()).hexdigest();digest=sha(rom);report=dict(group=name,rom_sha256=digest,started_at=datetime.now(timezone.utc).isoformat(),status='running',checks=[])
 def save():(o/'results.json').write_text(json.dumps(report,indent=2)+'\n')
 save()
 for subcase,flags in GROUPS[name]:
  assert sha(rom)==digest,'ROM changed during transfer group';label=subcase+('-negative'if flags else'');p=o/label;p.mkdir(exist_ok=True);script=h/'testcases'/('transfer_'+subcase+'.py');cmd=[sys.executable,str(script),str(rom),str(p),'--abi',*flags]
  if subcase in ['off','cards']:assert a.baseline is not None;cmd+=['--baseline',str(a.baseline.resolve())]
  started=time.monotonic()
  with(o/(label+'.log')).open('w')as log:result=subprocess.run(cmd,stdout=log,stderr=log,timeout=6000)
  report['checks'].append(dict(subcase=label,returncode=result.returncode,seconds=round(time.monotonic()-started,2),rom_sha256=digest,source_sha256=sha(script),log=label+'.log'));save();print(name,label,'PASS'if result.returncode==0 else'FAIL',flush=True)
  if result.returncode:report['status']='failed';save();raise SystemExit('Transfer release blocked: '+label)
 report.update(status='passed',finished_at=datetime.now(timezone.utc).isoformat());save();print('PASS all fresh mandatory transfer '+name+' subcases; exact ROM '+digest,flush=True)
