imrishabh18/corne-keyboard

The code defines and renders two surface-mount chip components with SMT pads, silkscreen outlines, and 3D CAD models (OBJ and STEP) for PCB assembly.

Version
2.0.21
License
unset
Stars
1

scripts/verify-board.py

"""Run installed DRC and independent physical connectivity checks; every diagnostic fails validation."""
import sys,json,subprocess,hashlib
from pathlib import Path

project=Path(__file__).resolve().parent.parent
inputs=sys.argv[1:] or ['dist/left/circuit.json','dist/right/circuit.json']
failed=False
for arg in inputs:
 path=(project/arg).resolve();j=json.loads(path.read_text());folder=path.parent/'validation';folder.mkdir(exist_ok=True)
 raw_path=folder/'routing-errors.json'
 subprocess.run(['bun',str(project/'scripts/check-circuit.ts'),str(path),str(raw_path)],cwd=project,check=True,capture_output=True,text=True)
 raw=json.loads(raw_path.read_text());reports=[]
 keys=sorted({e['subcircuit_connectivity_map_key'] for e in j if e['type']=='source_trace'})
 for number,key in enumerate(keys):
  output=folder/f'net-{number}.json'
  result=subprocess.run([sys.executable,str(project/'scripts/audit-copper.py'),str(path),str(output),key],capture_output=True,text=True)
  if result.returncode:raise RuntimeError(result.stderr)
  reports.append(json.loads(output.read_text()))
 physical_errors=[{'type':'physical_net_disconnected','net':r['connectivity_key'],'groups':r['groups']} for r in reports if r['physical_ground_groups']!=1]
 ground_key=next(e['subcircuit_connectivity_map_key'] for e in j if e['type']=='source_net' and e['name']=='GND')
 ground=next(r for r in reports if r['connectivity_key']==ground_key)
 clearance_path=folder/'pour-clearance.json'
 subprocess.run([sys.executable,str(project/'scripts/audit-pour-clearance.py'),str(path),str(clearance_path)],capture_output=True,text=True,check=True)
 clearance=json.loads(clearance_path.read_text())
 physical_errors.extend({'type':'pour_clearance_error',**e} for e in clearance['violations'])
 physical_errors.extend({'type':'net_metadata_conflict',**e} for e in clearance['metadata_conflicts'])
 # The live checker understands pours. Never remove or reclassify diagnostics.
 compiler_errors=[e for e in j if e['type'].endswith('_error')]
 confirmed=[*raw,*compiler_errors,*physical_errors]
 if not confirmed:
  (path.parent/'circuit.validated.json').write_text(json.dumps(j,indent=2))
 summary={'circuit':str(path),'sha256':hashlib.sha256(path.read_bytes()).hexdigest(),'trace_count':sum(e['type']=='pcb_trace' for e in j),'via_count':sum(e['type']=='pcb_via' for e in j),'checked_nets':len(reports),'ground_ports':ground['ground_port_count'],'ground_physical_groups':ground['physical_ground_groups'],'confirmed_routing_errors':len(confirmed),'checker_diagnostics':len(raw),'compiler_diagnostics':len(compiler_errors),'filtered_diagnostics':0,'pour_clearance_errors':len(clearance['violations']),'scope':'Routing connectivity, trace/via/pad clearance, copper-to-board-edge clearance, and copper keepout checks. Original placement/courtyard errors are outside this routing scope.'}
 (folder/'summary.json').write_text(json.dumps(summary,indent=2))
 (folder/'confirmed-routing-errors.json').write_text(json.dumps(confirmed,indent=2))
 (folder/'all-net-connectivity.json').write_text(json.dumps(reports,indent=2))
 print(f'{path.parent.name}: {len(confirmed)} confirmed routing errors; {len(reports)} nets checked; {ground["ground_port_count"]} GND pads in {ground["physical_ground_groups"]} physical group; {len(raw)} checker diagnostics; {len(compiler_errors)} compiler diagnostics',flush=True)
 failed|=bool(confirmed)
if failed:sys.exit(1)