from pathlib import Path
from collections import Counter
import json,sys
import numpy as np
import networkx as nx
ROOT=Path(__file__).resolve().parents[1];sys.path.insert(0,str(Path(__file__).parent));from analyze import graph,stationary,ppr,dump,csvout,overlap
rows=[];tests=[]
for rp in sorted((ROOT/'analysis/runs').glob('*.json')):
 r=json.loads(rp.read_text());rid=r['summary']['run'];es=[json.loads(l) for l in (ROOT/f'analysis/traces/{rid}.jsonl').open()];g=graph(es);cache=stationary(g)
 for group in r['entry_groups']:
  if not any(s in group['function'] for s in ['download','add-activity','edit-existing','settings','create-note','global-search']):continue
  counts=group['targets'];main=max(counts,key=counts.get);members,info=ppr(g,{main:counts[main]},cached=cache)
  default=next(z for z in r['regions'] if z['method']=='PPR-G1' and z['entry']==group['id'])
  rows.append(dict(run=rid,entry=group['id'],function=group['function'],source_activity=group['source_activity'],all_target_count=len(counts),dominant_target=main,dominant_executions=counts[main],all_target_region_size=len(default['members']),single_target_region_size=len(members),single_target_status=info['status'],jaccard=overlap(members,default['members']),members=members))
  # Independent directed-flow recomputation on saved sweep prefixes; stationary row/column conservation.
  nodes,ix,P,pi=cache;F=pi[:,None]*(.85*P+.15/len(nodes));assert np.max(abs(F.sum(axis=0)-pi))<1e-9
  ranking=[x['state'] for x in info['scores']]
  for j in [0,len(info['sweep'])//2,len(info['sweep'])-1]:
   if j<0:continue
   row=info['sweep'][j];idx=[ix[s] for s in ranking[:row['k']]];other=[i for i in range(len(nodes)) if i not in idx];cut=F[np.ix_(idx,other)].sum();vol=pi[idx].sum();phi=cut/min(vol,1-vol)
   assert abs(phi-row['conductance'])<1e-7,(rid,phi,row)
  tests.append(dict(run=rid,entry=group['id'],stationary_flow_conserved=True,three_sweep_cut_recomputations=True))
 dump(f'analysis/ppr-dominant/{rid}.json',[x for x in rows if x['run']==rid])
csvout('analysis/ppr-multi-target-sensitivity.csv',rows);dump('analysis/ppr-multi-target-sensitivity.json',rows);dump('evidence/ppr-cut-validation.json',dict(status='PASS',cases=len(tests),tests=tests))
print('PPR_CUT_PASS',len(tests))
