import io,re,subprocess,json,collections
files=subprocess.run(['git','ls-files','*.rs'],capture_output=True,text=True).stdout.split()
corpus=[f for f in files if '/tests/' in f or f.startswith('xtask/')]
# expiry vocabulary: the sentence a burned budget prints
EXPIRY=re.compile(r'(never\s|never"|timed out|timeout waiting|did not (appear|arrive|converge|start|become|show)|failed to .{0,40}within|gave up|no .{0,30} within|exceeded)',re.I)
PANIC=re.compile(r'\b(panic!|unreachable!|assert!|assert_eq!|expect\(|bail!|anyhow!)')
CLOCK=re.compile(r'(elapsed|\.as_millis|\.as_secs|iterations|iters|attempts|polls|budget)',re.I)
rows=[];per=collections.Counter()
for f in corpus:
    try: L=io.open(f,'r',encoding='utf-8',errors='replace').read().split('\n')
    except Exception: continue
    for i,l in enumerate(L):
        if EXPIRY.search(l) and PANIC.search(l):
            w='\n'.join(L[max(0,i-6):i+7])
            has=bool(CLOCK.search(w))
            rows.append((f,i+1,has,l.strip()[:110]))
            per[f]+=0 if has else 1
tot=len(rows);clocked=sum(1 for r in rows if r[2])
print(f"EXPIRY SITES (test corpus, {len(corpus)} files scanned): {tot}")
print(f"  report a clock within +/-6 lines : {clocked}")
print(f"  report NO clock                  : {tot-clocked}  <-- IR-95 population")
print()
print("TOP FILES BY UNCLOCKED EXPIRY SITES:")
for f,c in per.most_common(12):
    if c: print(f"  {c:3d}  {f}")
io.open('C:/Users/decid/AppData/Local/Temp/claude/C--Users-decid-Documents-projects-spt-core/951e0680-f9c9-4677-bee3-318dea146e10/scratchpad/ir95_sites.tsv','w',encoding='utf-8').write('\n'.join(f"{'CLOCK' if h else 'BLIND'}\t{f}:{n}\t{t}" for f,n,h,t in rows))
