abse/smartwatch-flex-top-only
Three-panel flex smartwatch with two parallel R3.9 bends, all components flat-top, low-profile JST connector harnesses, split heartbeat optical windows and screw-retained PCB mounting. Modeled 39 × 50.5 × 14.5mm prototype; 100% routing, zero native DRC and shorts. Hardware qualification pending.
- Version
- 0.2.20
- License
- unset
- Stars
- 0
scripts/run-short-audits.py
from pathlib import Path
from concurrent.futures import ThreadPoolExecutor, as_completed
import hashlib, json, os, re, subprocess, sys
root = Path(__file__).resolve().parent.parent
full, external = (root / p for p in sys.argv[1:3])
out = root / 'reports/shorts'
out.mkdir(parents=True, exist_ok=True)
env = dict(os.environ, XDG_CONFIG_HOME='/workspace/.cloud-tools/config',
XDG_CACHE_HOME='/workspace/.cache', XDG_STATE_HOME='/workspace/.cloud-tools/state',
NODE_USE_ENV_PROXY='1')
bun = '/workspace/.cloud-tools/node_modules/.bin/bun'
sha = lambda p: hashlib.sha256(p.read_bytes()).hexdigest()
def run(job):
scope, mode, layer = job
source = full if scope == 'full' else external
name = f'{scope}-{mode}-{layer}'
cwd = out / 'runs' / name
cwd.mkdir(parents=True, exist_ok=True)
log = out / f'{name}.log'
result = subprocess.run([bun, str(root/'scripts/check-shorts-complete.mjs'), str(source),
'--mode', mode, '--layer', layer, '--pixels-per-mm', '25'],
cwd=cwd, env=env, stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
log.write_text(result.stdout)
match = re.search(r'Detected (\d+) shorts? in ', result.stdout)
count = 0 if 'No shorts detected in ' in result.stdout else int(match[1]) if match else None
record = dict(scope=scope, mode=mode, layer=layer, pixelsPerMM=25,
sourceFile=str(source.relative_to(root)), sourceSha256=sha(source),
log=str(log.relative_to(root)), logSha256=sha(log),
artifactsDirectory=str(cwd.relative_to(root)),
exitCode=result.returncode, reportedShorts=count)
print(f'{name}: exit {result.returncode}, reported shorts {count}', flush=True)
return record
jobs = [(scope, mode, layer) for scope in ['full', 'external']
for mode in ['pcb', 'gerber'] for layer in ['top', 'inner1', 'inner2', 'bottom']]
records = []
if (out/'manifest.json').exists():
for prior in json.loads((out/'manifest.json').read_text())['runs']:
source=full if prior['scope']=='full' else external
if prior['exitCode']==0 and prior['reportedShorts']==0 and prior['sourceSha256']==sha(source):
records.append(prior)
completed={(r['scope'],r['mode'],r['layer']) for r in records}
jobs=[job for job in jobs if job not in completed]
with ThreadPoolExecutor(max_workers=2) as executor:
for future in as_completed([executor.submit(run, job) for job in jobs]):
records.append(future.result())
(out/'manifest.json').write_text(json.dumps(dict(pixelsPerMM=25, runs=records), indent=2)+'\n')
assert len(records) == 16 and all(r['reportedShorts'] is not None for r in records)
assert all(r['exitCode'] == 0 and r['reportedShorts'] == 0 for r in records)