Archive CIDM-v2 reproducible b2_r8_equal_exposure_audit.py
Browse files
cidm_v2/source/B2_R8_P0/b2_r8_equal_exposure_audit.py
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""CIDM-v2 B2-R8/P0: frozen, issue-time, equal-realized-RMS perturbation audit.
|
| 2 |
+
|
| 3 |
+
NO TRAINING. Truth is used only AFTER producing autoregressive forecasts to score
|
| 4 |
+
physical-space MSE. Same per-sample/per-step RMS exposure for Natural and Rotated.
|
| 5 |
+
This diagnostic on B0-preselected validation windows is NOT an independent skill claim.
|
| 6 |
+
"""
|
| 7 |
+
from __future__ import annotations
|
| 8 |
+
import csv,hashlib,io,json,math,zipfile
|
| 9 |
+
from pathlib import Path
|
| 10 |
+
import torch
|
| 11 |
+
from benchmark import Config, Windows, UnifiedModel, make_synthetic_cache
|
| 12 |
+
from b2_r1_flux_control import check_zip
|
| 13 |
+
from b2_r6_causal_spatial_controller import (
|
| 14 |
+
sha, make_cache_checked, CausalCoefficientHead, orthogonal_matrix, effect_basis,
|
| 15 |
+
TASK_LIST, SEED, LEADS, RATIO_BUDGET,
|
| 16 |
+
)
|
| 17 |
+
from b2_r7_frozen_controller_gain_audit import load_heads, forecast_scaled, validate_r6, write_json, write_csv
|
| 18 |
+
|
| 19 |
+
# Hash pinned to the user-provided actual real run, not the original Notebook.
|
| 20 |
+
R7_REAL_ZIP_SHA='9c7891b0784ce63c95dad6eb52c073ea69495f2e99adf38a4f187255397f987a'
|
| 21 |
+
R6_REAL_ZIP_SHA='d923eb6af43c294f28ec4f236c707feb0c4bcf1e6e5fed519bf697599730ef89'
|
| 22 |
+
PARENT_SHA='69552b29e169ec22ee85d9c1b1a678fdb188f6f25dc18f33b927b88f4dddffd4'
|
| 23 |
+
# Magnitudes are fractions of the current autoregressive model's own latent RMS.
|
| 24 |
+
BUDGETS=(0.,0.0005,0.001,0.003,0.005,0.01)
|
| 25 |
+
SIGNS=(1,-1)
|
| 26 |
+
PRE_REGISTERED_BUDGET=0.003
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def validate_r7(r7zip):
|
| 30 |
+
if sha(r7zip)!=R7_REAL_ZIP_SHA:raise RuntimeError('B2_R7_REAL_REPORT_SHA_MISMATCH')
|
| 31 |
+
with zipfile.ZipFile(r7zip) as z:
|
| 32 |
+
if z.testzip():raise RuntimeError('B2_R7_CRC_FAILED')
|
| 33 |
+
r=json.loads(z.read('report.json'))
|
| 34 |
+
if r['status']!='FROZEN_CONTROLLER_SENSITIVITY_COMPLETED_NO_TRAINING':raise RuntimeError('B2_R7_SCIENTIFIC_STATE_INVALID')
|
| 35 |
+
if {v['task'] for v in r['tasks']}!=set(TASK_LIST):raise RuntimeError('B2_R7_TASK_COVERAGE_MISSING')
|
| 36 |
+
for item in json.loads(z.read('FILE_SHA256_MANIFEST.json')):
|
| 37 |
+
if hashlib.sha256(z.read(item['path'])).hexdigest()!=item['sha256']:
|
| 38 |
+
raise RuntimeError('B2_R7_INNER_MANIFEST_MISMATCH:'+item['path'])
|
| 39 |
+
parsed=list(csv.DictReader(io.StringIO(z.read('gain_lead_curves.csv').decode('utf-8'))))
|
| 40 |
+
assert len(parsed)==285
|
| 41 |
+
ref={(v['task'],v['method'],int(v['lead'])):float(v['mse_physical']) for v in parsed}
|
| 42 |
+
return r,ref
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
def _norm(t):
|
| 46 |
+
return t.square().mean(dim=(1,2,3),keepdim=True).sqrt()
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
@torch.no_grad()
|
| 50 |
+
def rollout_budget(core, head, h, *, rotate=False, Q=None, budget=0., sign=1, steps=12):
|
| 51 |
+
mm=core.model; one_d=(h.ndim==4); hh=h.unsqueeze(-2) if one_d else h
|
| 52 |
+
B,L,C,H,W=hh.shape; coeff=mm.coefficients()
|
| 53 |
+
z=mm.encode(hh.reshape(B,L*C,H,W)); prev=hh[:,-1]; initial=prev
|
| 54 |
+
skew=mm.skew-mm.skew.T
|
| 55 |
+
preds=[]; diag={}; min_raw=float('inf')
|
| 56 |
+
for lead in range(1,steps+1):
|
| 57 |
+
f=coeff['flux']*mm.flux(z)
|
| 58 |
+
l=coeff['local']*torch.tanh(mm.local(z))
|
| 59 |
+
s=.035*torch.einsum('ij,bjhw->bihw',skew,z)
|
| 60 |
+
base=z+f+l+s
|
| 61 |
+
if head is None or float(budget)==0.:
|
| 62 |
+
change=torch.zeros_like(base); realized=base.new_zeros((B,))
|
| 63 |
+
raw_rms=base.new_zeros((B,)); gates=base.new_zeros((B,)); inactive=base.new_zeros((B,))
|
| 64 |
+
else:
|
| 65 |
+
basis,amps=effect_basis(f,l,s,Q if rotate else None)
|
| 66 |
+
coeff_local=head(base,prev,initial,amps,lead)
|
| 67 |
+
raw=(coeff_local.unsqueeze(2)*basis).sum(dim=1)/math.sqrt(3)
|
| 68 |
+
raw_rms=_norm(raw)
|
| 69 |
+
if not torch.isfinite(raw_rms).all():raise RuntimeError('NONFINITE_HEAD_VECTOR')
|
| 70 |
+
# Near-zero controller vectors cannot be safely normalized.
|
| 71 |
+
active=(raw_rms>=1e-9)
|
| 72 |
+
change=sign*float(budget)*_norm(base).clamp_min(1e-4)*raw/raw_rms.clamp_min(1e-9)
|
| 73 |
+
change=torch.where(active,change,torch.zeros_like(change))
|
| 74 |
+
realized=(_norm(change)/_norm(base).clamp_min(1e-4)).flatten()
|
| 75 |
+
raw_rms=raw_rms.flatten()
|
| 76 |
+
gates=coeff_local.abs().mean(dim=(1,2,3))
|
| 77 |
+
inactive=(~active).flatten().float()
|
| 78 |
+
# Assert exact equal exposure before any ground-truth loss is observed.
|
| 79 |
+
if active.any() and (realized[active.flatten()]-float(budget)).abs().max()>max(1e-6,float(budget)*2e-3):
|
| 80 |
+
raise RuntimeError('EXPOSURE_MATCH_CONTRACT_FAIL')
|
| 81 |
+
z=base+change
|
| 82 |
+
out=prev+coeff['out']*torch.tanh(mm.decode(z));prev=out
|
| 83 |
+
preds.append(out.squeeze(-2) if one_d else out)
|
| 84 |
+
if lead in LEADS:
|
| 85 |
+
diag[lead]={'used_rel':realized.cpu(), 'raw_norm':raw_rms.cpu(),
|
| 86 |
+
'gate_abs':gates.cpu(),'inactive':inactive.cpu()}
|
| 87 |
+
return torch.stack(preds,1),diag
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
def _name(head,budget,sign):
|
| 91 |
+
if head is None:return 'baseline'
|
| 92 |
+
return f'{head}__b{budget*100:.3f}pct__s{sign:+d}'
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
@torch.no_grad()
|
| 96 |
+
def evaluate(core,heads,Q,val,indices,device,*,smoke=False):
|
| 97 |
+
# Fully preregistered grid. All methods issue-time; never use truth for tuning.
|
| 98 |
+
budgets=(0.,.001,.003) if smoke else BUDGETS
|
| 99 |
+
specs=[(None,None,0.,1,False)]
|
| 100 |
+
for method in ('operator','rotated'):
|
| 101 |
+
for b in budgets:
|
| 102 |
+
if b==0: continue # baseline is shared and has exact zero correction
|
| 103 |
+
for sign in SIGNS:
|
| 104 |
+
specs.append((method,heads[method],b,sign,method=='rotated'))
|
| 105 |
+
records=[]; sums={_name(n,b,sign):{int(t):[0.,0] for t in LEADS} for n,_,b,sign,_ in specs}
|
| 106 |
+
stats={_name(n,b,sign):{int(t):[0.,0.,0.,0] for t in LEADS} for n,_,b,sign,_ in specs}
|
| 107 |
+
parity=0.
|
| 108 |
+
for pos in range(0,len(indices),2):
|
| 109 |
+
ids=indices[pos:pos+2]
|
| 110 |
+
h=torch.stack([val[int(i)][0] for i in ids]).to(device)
|
| 111 |
+
truth=torch.stack([val[int(i)][1] for i in ids]).to(device)
|
| 112 |
+
scale=val.sd.to(device).reshape(1,-1,*([1]*(truth.ndim-3)))
|
| 113 |
+
# Verify B2-R6 1x head and B2-R7 1x replay on the same issue-time windows.
|
| 114 |
+
prior={}
|
| 115 |
+
for kind in ('operator','rotated'):
|
| 116 |
+
prior[kind],_=forecast_scaled(core,heads[kind],h,rotate=(kind=='rotated'),Q=Q,steps=12,gain=1.,sign=1)
|
| 117 |
+
for typ,head,b,sign,rot in specs:
|
| 118 |
+
name=_name(typ,b,sign)
|
| 119 |
+
pred,d=rollout_budget(core,head,h,rotate=rot,Q=Q,budget=b,sign=sign)
|
| 120 |
+
if typ is None:
|
| 121 |
+
parent_base,_=forecast_scaled(core,None,h,steps=12,gain=0.,sign=1)
|
| 122 |
+
parity=max(parity,float((pred-parent_base).abs().max()))
|
| 123 |
+
for lead in LEADS:
|
| 124 |
+
err=((pred[:,lead-1]-truth[:,lead-1])*scale).square().flatten(1).mean(1)
|
| 125 |
+
sums[name][lead][0]+=float(err.sum());sums[name][lead][1]+=err.numel()
|
| 126 |
+
for idx,loss in zip(ids,err.cpu().tolist()):
|
| 127 |
+
records.append({'window_index':int(idx),'method':name,'lead':int(lead),'mse_physical':float(loss)})
|
| 128 |
+
if head is not None:
|
| 129 |
+
di=d[int(lead)];stat=stats[name][int(lead)]
|
| 130 |
+
stat[0]+=float(di['used_rel'].sum());stat[1]+=float(di['inactive'].sum());
|
| 131 |
+
stat[2]+=float(di['gate_abs'].sum());stat[3]+=len(ids)
|
| 132 |
+
# No time leakage: prior forecasts only scored retrospectively here.
|
| 133 |
+
for kind in ('operator','rotated'):
|
| 134 |
+
for lead in LEADS:
|
| 135 |
+
err=((prior[kind][:,lead-1]-truth[:,lead-1])*scale).square().flatten(1).mean(1)
|
| 136 |
+
key=f'original__{kind}__g1'
|
| 137 |
+
if key not in sums:sums[key]={int(t):[0.,0] for t in LEADS}
|
| 138 |
+
sums[key][int(lead)][0]+=float(err.sum());sums[key][int(lead)][1]+=err.numel()
|
| 139 |
+
if parity>2e-6:raise RuntimeError('ORIGINAL_OUTPUT_PARITY_FAIL')
|
| 140 |
+
curves=[]
|
| 141 |
+
for name,lead_metrics in sums.items():
|
| 142 |
+
for lead,(total,n) in lead_metrics.items():
|
| 143 |
+
ss,ns=sums['baseline'][lead]
|
| 144 |
+
s=stats.get(name,{}).get(lead,[0,0,0,0])
|
| 145 |
+
curves.append({'method':name,'lead':lead,'mse_physical':total/max(n,1),
|
| 146 |
+
'ratio_to_baseline':(total/max(n,1))/(ss/max(ns,1)),
|
| 147 |
+
'realized_relative_rms':s[0]/max(s[3],1),
|
| 148 |
+
'inactive_fraction':s[1]/max(s[3],1),
|
| 149 |
+
'gate_abs_mean':s[2]/max(s[3],1)})
|
| 150 |
+
return curves,records,parity
|
| 151 |
+
|
| 152 |
+
|
| 153 |
+
def check_replay(curves,ref,task):
|
| 154 |
+
for method in ('baseline','operator__g1__s+1','rotated__g1__s+1'):
|
| 155 |
+
current_name='baseline' if method=='baseline' else 'original__'+method.split('__')[0]+'__g1'
|
| 156 |
+
for lead in LEADS:
|
| 157 |
+
current=next(row['mse_physical'] for row in curves if row['method']==current_name and row['lead']==lead)
|
| 158 |
+
old=ref[(task,method,int(lead))]
|
| 159 |
+
if abs(current-old)>max(1e-8,abs(old)*0.003):
|
| 160 |
+
raise RuntimeError(f'B2_R7_REPLAY_MISMATCH {task} {method} {lead}: {current} vs {old}')
|
| 161 |
+
|
| 162 |
+
|
| 163 |
+
def posthoc_gate(curves,task):
|
| 164 |
+
# A diagnosis gate only, NOT authorization for full training or deployment.
|
| 165 |
+
get=lambda m,lead:next(r for r in curves if r['method']==m and r['lead']==lead)
|
| 166 |
+
bud=PRE_REGISTERED_BUDGET;natural=_name('operator',bud,1);rot=_name('rotated',bud,1)
|
| 167 |
+
rev=_name('operator',bud,-1)
|
| 168 |
+
late=[9,12]
|
| 169 |
+
late_nat=sum(get(natural,l)['mse_physical'] for l in late)
|
| 170 |
+
late_rot=sum(get(rot,l)['mse_physical'] for l in late)
|
| 171 |
+
late_base=sum(get('baseline',l)['mse_physical'] for l in late)
|
| 172 |
+
early=max(get(natural,l)['ratio_to_baseline'] for l in (1,3))
|
| 173 |
+
return {'task':task,'diagnostic_budget_percent':bud*100,
|
| 174 |
+
'late_vs_baseline_gain_pct':100*(1-late_nat/late_base),
|
| 175 |
+
'late_vs_rotated_gain_pct':100*(1-late_nat/late_rot),
|
| 176 |
+
'early_max_ratio_to_baseline':early,
|
| 177 |
+
'directional_sign_consistency':all(get(natural,l)['mse_physical']<get(rev,l)['mse_physical'] for l in late),
|
| 178 |
+
'exposure_nat_minus_rot_at_12':get(natural,12)['realized_relative_rms']-get(rot,12)['realized_relative_rms'],
|
| 179 |
+
'local_diagnostic_signal':bool((late_nat/late_rot)<=0.99 and early<=1.02)}
|
| 180 |
+
|
| 181 |
+
|
| 182 |
+
def sample_risk(samples, budget=PRE_REGISTERED_BUDGET):
|
| 183 |
+
"""Posthoc paired risk; zero-error windows have an absolute+relative floor."""
|
| 184 |
+
out={}
|
| 185 |
+
for lead in (1,3,9,12):
|
| 186 |
+
table={}
|
| 187 |
+
for row in samples:
|
| 188 |
+
if row['lead']==lead:
|
| 189 |
+
table.setdefault(row['method'],{})[row['window_index']]=float(row['mse_physical'])
|
| 190 |
+
baseline=table['baseline']
|
| 191 |
+
for typ in ('operator','rotated'):
|
| 192 |
+
key=_name(typ,budget,1)
|
| 193 |
+
active=table[key]
|
| 194 |
+
assert set(active)==set(baseline),'UNPAIRED_SAMPLE_IDS'
|
| 195 |
+
ids=sorted(baseline)
|
| 196 |
+
improv=[active[i]<baseline[i] for i in ids]
|
| 197 |
+
small_floor=max(1e-12,sum(baseline.values())/len(ids)*1e-4)
|
| 198 |
+
ratios=sorted(active[i]/max(baseline[i],small_floor) for i in ids)
|
| 199 |
+
out[f'{typ}_lead{lead}']={
|
| 200 |
+
'windows':len(ids), 'window_win_fraction':sum(improv)/len(ids),
|
| 201 |
+
'sample_ratio_p90':ratios[min(len(ids)-1,math.ceil(.9*len(ids))-1)],
|
| 202 |
+
'regression_over_2pct_fraction':sum(active[i]>baseline[i]*1.02+small_floor for i in ids)/len(ids),
|
| 203 |
+
'denominator_floor':small_floor,
|
| 204 |
+
}
|
| 205 |
+
return out
|
| 206 |
+
|
| 207 |
+
|
| 208 |
+
def run(parent,r6zip,r7zip,work,output,*,smoke=False,device='cpu'):
|
| 209 |
+
work=Path(work);output=Path(output)
|
| 210 |
+
work.mkdir(parents=True,exist_ok=True);output.mkdir(parents=True,exist_ok=True)
|
| 211 |
+
rr,refs=validate_r7(r7zip)
|
| 212 |
+
if sha(r6zip)!=R6_REAL_ZIP_SHA:raise RuntimeError('R6_WEIGHTS_ARCHIVE_SHA_MISMATCH')
|
| 213 |
+
validate_r6(r6zip)
|
| 214 |
+
all_curves=[];all_samples=[];cases=[]; gates=[]
|
| 215 |
+
if smoke:
|
| 216 |
+
cfg=Config(profile='smoke');cache1=make_synthetic_cache(cfg)
|
| 217 |
+
for split in ('train','val','test'):
|
| 218 |
+
cache1['splits'][split]['h']=cache1['splits'][split]['h'].mean(dim=-2)
|
| 219 |
+
cache1['splits'][split]['y']=cache1['splits'][split]['y'].mean(dim=-2)
|
| 220 |
+
inputs=[('smoke_1d',cache1),('smoke_2d',make_synthetic_cache(cfg))]
|
| 221 |
+
for task,cache in inputs:
|
| 222 |
+
core=UnifiedModel('V2_Ported_R5',1,8,12,4).to(device).eval().requires_grad_(False)
|
| 223 |
+
hch=1
|
| 224 |
+
heads=load_heads(r6zip,'burgers_1d' if task=='smoke_1d' else 'swe_2d',hch,device)
|
| 225 |
+
Q=orthogonal_matrix(int(core.model.skew.shape[0]),32207,device,torch.float32)
|
| 226 |
+
val=Windows(cache['splits']['val']['h'],cache['splits']['val']['y'],cache['mean'],cache['std'])
|
| 227 |
+
curves,samples,parity=evaluate(core,heads,Q,val,[0,1],device,smoke=True)
|
| 228 |
+
for item in curves:item['task']=task
|
| 229 |
+
for item in samples:item['task']=task
|
| 230 |
+
all_curves.extend(curves);all_samples.extend(samples)
|
| 231 |
+
cases.append({'task':task,'forward_parity_max':parity})
|
| 232 |
+
status='PROGRAM_ONLY_SMOKE_NO_SCIENCE'
|
| 233 |
+
else:
|
| 234 |
+
if parent is None or sha(parent)!=PARENT_SHA:raise RuntimeError('PINNED_18_MODEL_PARENT_REQUIRED')
|
| 235 |
+
with zipfile.ZipFile(parent) as z:
|
| 236 |
+
m,contract=check_zip(z);cfg=Config(**m['config'])
|
| 237 |
+
for task in TASK_LIST:
|
| 238 |
+
core,cache,replay=make_cache_checked(task,z,cfg,work,device)
|
| 239 |
+
old=next(x for x in rr['tasks'] if x['task']==task)
|
| 240 |
+
if replay['checkpoint_sha256']!=old['replay']['checkpoint_sha256']:
|
| 241 |
+
raise RuntimeError('CHECKPOINT_SHA_CHANGED:'+task)
|
| 242 |
+
hch=int(cache['splits']['val']['h'].shape[2]);heads=load_heads(r6zip,task,hch,device)
|
| 243 |
+
Q=orthogonal_matrix(int(core.model.skew.shape[0]),32207,device,torch.float32)
|
| 244 |
+
val=Windows(cache['splits']['val']['h'],cache['splits']['val']['y'],cache['mean'],cache['std'])
|
| 245 |
+
ix=old['readout_windows']
|
| 246 |
+
if ix!=list(range(16,32)):raise RuntimeError('AUDIT_WINDOW_CONTRACT_CHANGED')
|
| 247 |
+
curves,samples,parity=evaluate(core,heads,Q,val,ix,device,smoke=False)
|
| 248 |
+
check_replay(curves,refs,task)
|
| 249 |
+
if parity>2e-6:raise RuntimeError('PARENT_FORWARDS_CHANGED')
|
| 250 |
+
diagnostic_gate=posthoc_gate(curves,task)
|
| 251 |
+
diagnostic_gate['paired_window_risk']=sample_risk(samples)
|
| 252 |
+
gates.append(diagnostic_gate)
|
| 253 |
+
cases.append({'task':task,'replay':replay,'baseline_parity_max':parity,
|
| 254 |
+
'audit_windows':ix,'frozen_controller_only':True})
|
| 255 |
+
for item in curves:item['task']=task
|
| 256 |
+
for item in samples:item['task']=task
|
| 257 |
+
all_curves.extend(curves);all_samples.extend(samples)
|
| 258 |
+
write_csv(output/'equal_rms_lead_curves.csv',all_curves)
|
| 259 |
+
write_csv(output/'sample_mse.csv',all_samples)
|
| 260 |
+
write_json(output/'live_progress.json',{'completed_tasks':[v['task'] for v in cases]})
|
| 261 |
+
status='FROZEN_EQUAL_RMS_AUDIT_COMPLETED_NO_TRAINING'
|
| 262 |
+
write_csv(output/'equal_rms_lead_curves.csv',all_curves)
|
| 263 |
+
write_csv(output/'sample_mse.csv',all_samples)
|
| 264 |
+
write_json(output/'matched_exposure_gate.json',{'status':'DIAGNOSTIC_ONLY','per_task':gates,
|
| 265 |
+
'does_not_authorize': ['full-training','hyperparameter deployment','outer-holdout claims'],
|
| 266 |
+
'registered_budget_fraction':PRE_REGISTERED_BUDGET})
|
| 267 |
+
report={'experiment':'CIDM_v2_B2_R8_P0_FrozenEqualRMS_CausalControl_Diagnostic',
|
| 268 |
+
'status':status,'cases':cases,'training_steps':0,
|
| 269 |
+
'r6_real_archive_sha256':R6_REAL_ZIP_SHA,'r7_real_archive_sha256':R7_REAL_ZIP_SHA,
|
| 270 |
+
'expected_parent_sha256':PARENT_SHA,
|
| 271 |
+
'budgets':list(BUDGETS),'signs':list(SIGNS),'num_curves':len(all_curves),
|
| 272 |
+
'num_samples':len(all_samples),'registered_decision_budget':PRE_REGISTERED_BUDGET,
|
| 273 |
+
'no_future_truth_used_in_control':True,'labels_scoring_only':True,
|
| 274 |
+
'outer_holdout':False,
|
| 275 |
+
'notes':['Unit-norm controller action is evaluated at equal per-step/per-window latent-RMS exposure.',
|
| 276 |
+
'Natural vs Rotated comparison is exposure-matched, not trained-policy matched.',
|
| 277 |
+
'No validation budget maximization or deployment tuning; B0 checkpoint was val-selected.',
|
| 278 |
+
'Oracle gradient geometry from B2-R5 is not used in causal corrections.']}
|
| 279 |
+
write_json(output/'report.json',report)
|
| 280 |
+
return report
|