"""Pure offline final normal read proof. No SQL/HTTP, preserve all prior failures."""
from pathlib import Path
import hashlib,json,re,stat
HERE=Path(__file__).resolve().parent;P=HERE.parent;RAW=Path('/tmp/cdx-ai-final-weight-read-20261011');OLD=Path('/tmp/cdx-ai-customer-weight-retest-20261011')
def load(p):return json.loads(p.read_text())
def lines(p):return [json.loads(x) for x in p.read_text().splitlines()]
checks=0
def need(ok,label):
 global checks
 checks+=1
 if not ok:raise AssertionError(label)
def phptype(v):return 'NULL' if v is None else 'boolean' if type(v) is bool else 'integer' if type(v) is int else 'double' if type(v) is float else 'string' if type(v) is str else 'array'
pins=load(P/'source-frozen-sha.json')['files'];freeze=load(HERE/'pre-HTTP-freeze-final.json');out={}
for lane in ['B','C']:
 p=RAW/f'private-{lane}-final';base=load(p/'budget-baseline.json');old=(OLD/f'private-{lane}-final/sql-budget.jsonl').read_bytes();raw=(p/'sql-budget.jsonl').read_bytes();budget=lines(p/'sql-budget.jsonl');need(raw.startswith(old) and hashlib.sha256(old).hexdigest()==base['old_SQL_SHA'],'Unmodified old budget carry-forward');need(len(budget)<=800 and [x['n'] for x in budget]==list(range(1,len(budget)+1)),'Exact cumulative800 read budget')
 pre=load(p/'preflight-read.json');final=load(p/'persistence-final.json');lease=load(p/'related-file-lease.json');need(pre['user_fullrows']==final['user_fullrows'] and pre['weight_fullrows']==final['weight_fullrows']==[] and pre['protection']==final['protection'] and lease['tenant_store_fullrows']==final['tenant_store_fullrows'] and final['unchanged'],'Whole original actor/weight/tenant config/13/financial rows conserved')
 normal=load(p/'expected.json')['WEIGHT_FINAL'];need(normal==load(OLD/f'private-{lane}-final/expected.json')['WEIGHT_RETEST'] and normal['data']==[] and normal['status']==200,'Original frozen full typed empty oracle unchanged')
 need(load(p/'run-complete.json')['actual_HTTP']==1 and list(load(p/'cases.json'))==['WEIGHT_FINAL'],'Exactly one final read/side')
 r=load(p/'response-WEIGHT_FINAL.json');client=load(p/'client-WEIGHT_FINAL.json');need(r['http_status']==client['http_status']==200 and r['raw_response_body']==client['body_raw'],'Original saved→sent/client complete bytes equal');body=json.loads(r['raw_response_body']);need(list(body)==['status','message','data','trace_id'],'Full original envelope fields/order');need(type(body['status']) is int and body['status']==normal['status'] and type(body['message']) is str and body['message']==normal['message'] and type(body['data']) is list and body['data']==normal['data'] and type(body['trace_id']) is str and re.fullmatch('[0-9a-f]{13}',body['trace_id']) is not None,'Complete original exact values/types/traceid')
 events=lines(p/'business-native.jsonl');actual=[e for e in events if e['layer']=='actual PDOStatement.execute'];formal=[e for e in events if e['scenario']=='WEIGHT_FINAL'];need(not any('error' in e for e in formal),'No swallowed formal native/tool error');need(all(e['operation'] in ['SELECT','metadata_SELECT','metadata_SHOW','metadata_CALL'] for e in actual),'0DMLDDL original native');need(not any(e.get('layer') in ['actual PDO.beginTransaction','actual PDO.commit','actual PDO.exec transaction','actual PDO.rollBack'] for e in events),'0business transaction')
 weightdata=[e for e in formal if e['layer']=='actual PDOStatement.execute' and e['operation']=='SELECT' and 'yoshop_user_weight' in e['queryString']];need(len(weightdata)==1 and 'date' in weightdata[0]['queryString'] and 'height' in weightdata[0]['queryString'] and 'bmi' in weightdata[0]['queryString'],'Actual original weight data query reached exactly once')
 warm=load(p/'constructor-warm.json');need(list(warm['models'])==['staffModel','userWeightModel','userWeightStatusModel','userModel'] and all(m['original_fields'] for m in warm['models'].values()) and warm['HTTP']==warm['DML']==warm['DDL']==0,'All four source initialize models original metadata warmed at0HTTP')
 warmevents=[e for e in events if e['scenario']=='CONSTRUCTOR_WARM'];need(not any('error' in e for e in warmevents) and all(e['operation'].startswith('metadata_') for e in warmevents if e['layer']=='actual PDOStatement.execute'),'Warm only metadata, no data/write or errors')
 tests=load(p/'metadata-gate-tests.json');need(tests['checks']==19 and tests['counterexamples']==11 and tests['SQL']==tests['HTTP']==0,'Unknown data/DDL/empty/foreign metadata pure rejection tests')
 meta=load(p/'metadata-tables.json');need(all(v['schema'] and len(v['tables'])==len(set(v['tables'])) for v in meta.values()) and 'yoshop_staff' in meta['AI']['tables'] and 'yoshop_user_weight_status' in meta['AI']['tables'],'Frozen same-schema existing metadata names')
 independent=lines(p/'independent-native.jsonl');need(sum('INFORMATION_SCHEMA.TABLES' in e['queryString'] or 'FROM USER_TABLES ORDER BY' in e['queryString'] for e in independent)==2,'Exactly one table-name catalog read per schema')
 plans={};pairs=0
 for e in events:
  key=(e['scenario'],e['connection'],e.get('queryString'))
  if e['layer']=='original framework bind plan':plans[key]=e['bind_plan']
  if e['layer']!='actual PDOStatement.execute':continue
  need(key in plans,'Native original framework binding exists')
  for k,v in (plans[key].items() if type(plans[key]) is dict else enumerate(plans[key])):
   param=str(k+1) if type(k) is int else ':'+k
   if type(v) is list:
    val,typ=v
    if typ==1 and val=='':val=0
    elif typ==21:
     if type(val) is str:val=float(val)
     typ=2
   else:val,typ=v,2
   b=e['bindValue'][param];need(type(b['value']) is type(val) and b['value']==val and b['pdo_type']==typ and b['php_type']==phptype(val),'Every exact native value/PHPtype/PDOtype pair');pairs+=1
 included=load(p/'included-WEIGHT_FINAL.json')['files']
 for n,h in included.items():need(pins.get(n)==h,'Actual included source exact')
 src=load(p/'source-actual-fileset.json');need(src['actual_regular_files']==6168 and set(src['files'])==set(pins) and src['appledouble_magic_count']==0,'Actual complete6168 fileset/magic0')
 for n,h in pins.items():need(src['files'][n]['sha256']==h,'Actual complete source SHA')
 need(load(p/'runtime-helper-sha.json')==freeze['runtime_helper_files'],'Both actual runtime helper file-set/SHA equals final pre-HTTP freeze')
 need(load(p/'guard.json')['same_token_no_renewal'] is True and len(load(p/'tokens.json'))==1,'One unique final token, same-token0HTTP auth recovery')
 need(load(p/'cleanup.json')['tokens']=={'U1':'revoked'} and load(p/'worker-stopped.json')['port_closed'] is True and len(load(p/'cache-cleanup.json')['own_cache_files_removed'])==2,'Final own token/cache/worker/port cleaned')
 need(not list(p.glob('observer-error-*.json')) and not list(p.glob('harness-error-*.json')),'No response observer/harness failure')
 errors=[e for e in events if 'error' in e and e['scenario']!='WEIGHT_FINAL'];need(errors and any('yoshop_upload_file' in e.get('queryString','') for e in errors),'0HTTP related Store.logoImage tool error preserved')
 out[lane]={'HTTP':1,'cumulative_HTTP':12,'new_SQL':len(budget)-base['old_SQL'],'cumulative_SQL':len(budget),'original_native_SQL':len(actual),'formal_native_SQL':sum(e['layer']=='actual PDOStatement.execute' for e in formal),'original_native_bind_pairs':pairs,'constructor_metadata_SQL':warm['native_SQL'],'actualincluded':len(included),'metadata_tables':{k:len(v['tables']) for k,v in meta.items()},'DML':0,'DDL':0,'result':'EMPTY_ONLY_FULL_NORMAL_DTO_PASS'}
for n,h in freeze['files'].items():need(hashlib.sha256((HERE/n).read_bytes()).hexdigest()==h,'Final pre-HTTP tool/source freeze unchanged')
need(hashlib.sha256((P/'oracle_lib.py').read_bytes()).hexdigest()==freeze['original_parent_oracle_SHA'],'Original independent oracle source unchanged')
need(hashlib.sha256((HERE/'CoreGate-before-file-lease.php').read_bytes()).hexdigest()==load(HERE/'pre-HTTP-freeze.json')['files']['tools/CoreGate.php'],'Initial related-file guard source preserved without rewrite')
print(json.dumps({'checks':checks,'lanes':out,'SQL':0,'HTTP':0,'limits':['Empty-only no nonempty typed weight rows exercised','Prior successful9 routes not replayed','Original two Weight tool failures and all prior seals preserved','Actual SignInfo source default has8 fields; prior prose9 is separate errata']},ensure_ascii=False,indent=2))
