"""Strict read-only joins for optional native gate action-choice diagnostics.""" import re from ordinary_gate_evidence import join_gate_snapshots PREFIX='ERR GATE CHOICE: ' IDENT=r'([A-Za-z_][A-Za-z_0-9]{0,127}):(-?\d+)' BOOL=r'(0|1|true|false)' LINE=re.compile(r'run=([A-Za-z0-9]{1,32}) sample=(\d+) real=(\d+) selected='+IDENT+r' context='+BOOL+r' actions=(\d+) permissions=(\d+) shown=(\d+) truncated='+BOOL+r' ordered=\[(.*)\]') ENTRY=re.compile(r'(\d+)='+IDENT+r':(-?\d+)') def need(value,reason): if not value: raise ValueError(reason) def parse_choice_record(line,nonce): need(type(nonce) is str and re.fullmatch(r'[A-Za-z0-9]{1,32}',nonce),'invalid choice nonce') if PREFIX.rstrip() not in line:return None need(PREFIX in line and line.count(PREFIX)==1 and len(line)<=4096,'invalid choice line') match=LINE.fullmatch(line.split(PREFIX,1)[1].strip());need(match is not None,'malformed choice record') run,index,real,selected_class,selected_id,context,count,permissions,shown,truncated,ordered=match.groups() index,real,selected_id,count,permissions,shown=map(int,(index,real,selected_id,count,permissions,shown)) need(run==nonce and 1<=index<=450 and 0<=real<=2147483647,'choice nonce or clock mismatch') need(-1<=selected_id<=2147483647 and ((selected_class=='none')==(selected_id==-1)),'invalid selected action identity') need(0<=count<=4096 and 0<=permissions<=4096 and shown==min(count,8) and (truncated in ('1','true'))==(count>shown),'choice list bounds disagree') entries=[] if not ordered else ordered.split(',');need(len(entries)==shown,'choice entry count disagrees') actions=[] for i,text in enumerate(entries): m=ENTRY.fullmatch(text);need(m is not None,'malformed ordered action') n,cls,identity,permission=m.groups();n,identity,permission=map(int,(n,identity,permission)) need(n==i and -1<=identity<=2147483647 and ((cls=='none')==(identity==-1)),'ordered action identity/index invalid') need(permission in (-1,0,1) and ((permission==-1)==(i>=permissions)),'cached permission index mismatch') actions.append({'class':cls,'id':identity,'permitted':None if permission==-1 else bool(permission)}) return {'nonce':nonce,'sample':index,'real_ms':real,'selected_class':selected_class,'selected_id':selected_id,'context_selected':context in ('1','true'),'action_count':count,'permission_count':permissions,'truncated':truncated in ('1','true'),'actions':actions} def parse_choice_records(content,nonce): need(type(content) is str and len(content)<=32*1024*1024,'choice content bound') records={};previous_real=-1 for line in content.splitlines(): r=parse_choice_record(line,nonce) if r is None:continue need(r['sample']==len(records)+1 and r['real_ms']>previous_real,'choice sequence missing, repeated or reversed') records[r['sample']]=r;previous_real=r['real_ms'] need(records,'native choices absent') return records def join_choice_snapshots(content,nonce): data=join_gate_snapshots(content,nonce);records=parse_choice_records(content,nonce) for i,c in records.items(): need(i in data['snapshots'],'choice has no native gate peer') s=data['snapshots'][i];a=s['action'];need(c['real_ms']==s['real_ms'] and c['context_selected']==a['context_selected'],'choice/gate clock or context mismatch') if a['selected']:need(c['selected_class']=='ERR_UnlockPrisonAction','selected lock class disagrees') if c['selected_class']=='ERR_UnlockPrisonAction':need(a['selected'],'native selected lock flag disagrees') s['choices']=c return data def exact_prison_choices(snapshot): """Known non-aggregating closed Open/lock pair; not a general action sorter.""" c=snapshot.get('choices');need(type(c) is dict,'native choice snapshot absent') a=c['actions'];need(c['context_selected'] and not c['truncated'] and c['action_count']==c['permission_count']==len(a)==2,'expected exact original two-action context') need([e['class'] for e in a]==['ERR_PrisonDoorAction','ERR_UnlockPrisonAction'],'unsupported native action order') need(all(type(e['id']) is int and e['id']>=0 for e in a) and a[0]['id']!=a[1]['id'],'invalid original action IDs') need(a[0]['permitted'] is False and a[1]['permitted'] is True,'native closed-door/lock permissions changed') need((c['selected_class'],c['selected_id']) in [(e['class'],e['id']) for e in a],'selected action outside original pair') return c