import csv
import hashlib
import json
import os
from pathlib import Path
from verify_final import verify_all

P=Path(__file__).resolve().parent
result=verify_all()
for lane in 'BC':
    (P/f'comparison-original-{lane}.json').write_text(json.dumps(result['original'][lane],ensure_ascii=False,indent=2)+'\n')
proposal=json.loads((P/'case-proposal.json').read_text())
with (P/'interface-ledger.csv').open('w',newline='') as handle:
    writer=csv.DictWriter(handle,fieldnames=['repo','method','path','status','business_evidence','limits'])
    writer.writeheader()
    for case in proposal['cases'][:11]:
        name=case['name'];status='dual_business_partial'
        evidence='Actual authenticated nonempty full DTO and independent original-row oracle; native original PDO SQL and source pins verified; complete effective B/C body pair'
        limits='Only measured read branches; synthetic retained fixtures; no formal writes, full RBAC, physical devices or exhaustive inputs'
        if name=='NUTRITION_FLAG':
            status='shared_source_failure';evidence=r'Both actual HTTP business500: method not exist:think\db\Query->getTrainDates';limits='Original shared undefined method; not DM-only regression; no positive business evidence'
        elif name=='UNIT':
            status='no_database_static_enum';evidence='Actual original Controller/Auth complete9-item Unit enum; HTTP business SQL0';limits='No business DB access; not database positive'
        elif name=='NUTRITION_DETAIL':
            limits+='; nonempty record retains original recommend_energy=null; emptyDate shared missing MealRecommend class remains open'
        elif name.startswith('STAFF'):
            limits+='; this legacy namespace source/actual POST reachable but no current UI direct caller proven; no nonempty nation/sport/face relations'
        writer.writerow({'repo':'ai_api','method':'POST','path':case['path'],'status':status,'business_evidence':evidence,'limits':limits})
private=[]
root=P/'private-evidence'
for directory,subdirs,files in os.walk(root):
    assert Path(directory).stat().st_mode&0o777==0o700
    for name in sorted(files):
        file=Path(directory)/name
        assert file.stat().st_mode&0o777==0o600
        private.append({'path':str(file.relative_to(P)),'bytes':file.stat().st_size,'sha256':hashlib.sha256(file.read_bytes()).hexdigest()})
public=[]
for file in sorted(P.iterdir()):
    if file.is_file() and file.name not in ['manifest.json','MANIFEST.sha256']:
        public.append({'path':file.name,'bytes':file.stat().st_size,'sha256':hashlib.sha256(file.read_bytes()).hexdigest()})
manifest={'scope':'AI remaining11 read batch, actual60 HTTP; original52 and necessary8; Root-only main/matrix writes; canonical raw only private-evidence','public':public,'private':private,
          'validation':{'HTTP':60,'wire':60,'original_red_B':0,'original_red_C':4,'original_difference_fields_C':7,'final_full_DTO_green':8,'B_old_raw_trace_only_equal':4,'complete_effective_BC_pairs':26,'fixture_INSERT_each':13,'C_IMG_DDL':2,'HTTP_DML':0,'HTTP_DDL':0,'pure_tests':4,'DTO_mutations':42,'SQL_bind_mutations':11,'fixture_mutations':8,'actual_Model_Json_assertions':571,'actual_Service_MasterModel_assertions':121},
          'private_permissions':{'directories':'0700','files':'0600'},'business_ledger_proposal':{'dual_business_partial':9,'shared_source_failure':1,'no_database_static_enum':1},'source_delta':json.loads((P/'source-final-sha.json').read_text())['accepted_changes']}
(P/'manifest.json').write_text(json.dumps(manifest,ensure_ascii=False,indent=2)+'\n')
sha=hashlib.sha256((P/'manifest.json').read_bytes()).hexdigest()
(P/'MANIFEST.sha256').write_text(sha+'  manifest.json\n')
print(json.dumps({'public':len(public),'private':len(private),'manifest_sha256':sha,'HTTP':60,'wire':60}))
