from pathlib import Path
import shutil,sys,re,json,uuid
import wx
_app=wx.App(False)
import pcbnew as k
B=Path('work/tri-product-continuation-2026-10-10.nosync').resolve();R=B/'lamp_local_decoupling_A59';R.mkdir(exist_ok=True)
if (R/'checks.json').exists():raise RuntimeError('Final candidate present: recreate only in a fresh isolated directory')
shutil.copytree(B/'lamp_VLED_width_A58/board',R/'board',dirs_exist_ok=True)
for name in ['netlist.xml','verify_board.py','run_checks.sh','audit_decoupling.py']:shutil.copy2(B/'lamp_VLED_width_A58'/name,R/name)
P=R/'board/led_driver.kicad_pcb';b=k.LoadBoard(str(P));fps={f.GetReference():f for f in b.GetFootprints()};out=[]
for ref,cx in [('C1',23),('C3',53),('C5',83)]:
 f=fps[ref];f.SetPosition(k.VECTOR2I(k.FromMM(cx+4.8),k.FromMM(40)));f.SetOrientationDegrees(90)
 out.append({'ref':ref,'center_mm':[cx+4.8,40],'rotation_deg':90})
k.SaveBoard(str(P),b)
sys.path.insert(0,str(B/'parity_metadata_closure_A22'));from prepare_candidates import forms
s=P.read_text();ids=['d65e372b-24cb-4296-92f8-b2e3a6ace5b2','a36fd5a0-f078-4b03-8600-c83f2f7b41fa','d569f83e-10b6-4ff2-82b8-b0cebac808d7']
removed=[]
for st,en,t in reversed(list(forms(s,'segment'))):
 if any(i in t for i in ids):removed.append(t);s=s[:st]+s[en:]
# Connect each local capacitor directly to the chip VDD corner.
adds=[]
for cx in [23,53,83]:
 adds.append('(segment (start %.5f 41.4) (end %.5f 40.775) (width 0.2) (layer "F.Cu") (net "/VDD_3V3") (uuid "%s"))'%(cx+3.05,cx+4.8,str(uuid.uuid4())))
 # GND through local 0.6/0.3 via placed away from supply pad and package.
 adds.append('(segment (start %.5f 39.225) (end %.5f 38.425) (width 0.2) (layer "F.Cu") (net "/GND") (uuid "%s"))'%(cx+4.8,cx+4.8,str(uuid.uuid4())))
 adds.append('(via (at %.5f 38.425) (size 0.6) (drill 0.3) (layers "F.Cu" "B.Cu") (net "/GND") (uuid "%s"))'%(cx+4.8,str(uuid.uuid4())))
s=s.rstrip()[:-1]+'\n'+'\n'.join(adds)+'\n)\n';s=s.replace('A58 POWER WIDTH CANDIDATE','A59 LOCAL DECOUPLING CANDIDATE');P.write_text(s);(R/'placement_change.json').write_text(json.dumps(out,indent=2));(R/'removed_old_cap_stubs.txt').write_text('\n'.join(removed))
