Add autonomous DoE-packing loop (planner + packer) - #5
Conversation
A two-agent example that designs and floor-plans a photonic Design-of-Experiments test chip on a fixed MPW die, free and local (no cloud simulations): - plan.py (planner) designs the sweep and writes blackboard/doe_plan.json - optimize.py (packer) fills the die in a build/verify/score/journal loop: ramp replicates to capacity, then void-fill to the packable plateau - tools/ verification harness: KLayout DRC, geometric collisions, LVS-style connectivity, an orientation gate (wafer-prober rule), and a largest-empty-rectangle void finder, rolled into a gated figure of merit - generalized device ingestion: PhotonForge PCells or user GDS via tools/library.py - frame capture / GIF is optional (Playwright), so the loop runs headless Replaces the single-device design.py/simulate.py framework on this branch with the packing project; see README.md for setup and run instructions. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 5 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit b7d8f39. Configure here.
| sys.path.insert(0, str(ROOT)) | ||
| from run import build_chip | ||
| import design | ||
| chip, _, _ = build_chip(design) |
There was a problem hiding this comment.
Hierarchy CLI imports deleted modules
High Severity
Running python -m tools.hierarchy still imports run.build_chip and design, but this PR removes design.py and there is no run.py, so the CLI fails before any hierarchy or validation runs.
Reviewed by Cursor Bugbot for commit b7d8f39. Configure here.
| if step is not None: | ||
| gds = exp_dir / f"{int(step):04d}" / "chip.gds" | ||
| else: | ||
| gds = sorted(glob.glob(str(exp_dir / "*" / "chip.gds")))[-1] |
There was a problem hiding this comment.
view_last crashes without experiments
Medium Severity
When no output/experiments/*/chip.gds exists, view_last.py indexes an empty glob list and raises IndexError instead of exiting with a clear message.
Reviewed by Cursor Bugbot for commit b7d8f39. Configure here.
| @@ -0,0 +1,40 @@ | |||
| # die.yaml — the fixed constraints for the v1 DoE-packing campaign. | |||
| # Read by the planner (plan.py) and the loop (optimize.py); the human-editable "blackboard". | |||
There was a problem hiding this comment.
die.yaml never loaded by code
Medium Severity
blackboard/die.yaml states it is read by plan.py and optimize.py, but neither file loads YAML; die size and margins are hardcoded elsewhere, so edits to die.yaml have no effect.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit b7d8f39. Configure here.
| print(f"\nvoid-fill plateau: no remaining void can hold the smallest " | ||
| f"{min_w:.0f}x{min_h:.0f}um site — every packable gap is used. done.", | ||
| flush=True) | ||
| break |
There was a problem hiding this comment.
Void-fill stops on empty pack
Medium Severity
Phase 2 treats an empty void-fill pack as “no packable voids left” and exits, even when fits_smallest_dut still suggests space and the heterogeneous pool simply did not fit that LER bin.
Reviewed by Cursor Bugbot for commit b7d8f39. Configure here.
| AREA_BUDGET = 25.0 | ||
| MIN_DIM = 2000.0 | ||
| ALLOW_ROTATION = False # LOCKED: same prober direction for every site | ||
| GAP = 8.0 # pack gap (bbox-to-bbox; real geometry is further apart) |
There was a problem hiding this comment.
Optimizer ignores plan pack gap
Low Severity
plan.py writes pack.GAP (20 µm) into doe_plan.json, but optimize.py always packs with hardcoded GAP = 8.0, so planner capacity estimates and the packer disagree.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit b7d8f39. Configure here.


A new self-contained example branch: an autonomous agent that designs and floor-plans a photonic Design-of-Experiments (DoE) test chip on a fixed MPW die. It runs entirely free and local (no cloud simulations).
What it does
Two agents share only a file:
plan.py) designs the sweep (which device parameters, ranges, points) and writesblackboard/doe_plan.json.optimize.py) reads the plan and tiles the die in abuild -> verify -> score -> journalloop: ramp replicates to capacity, then void-fill the leftover gaps with real structures until no remaining gap can hold the smallest device.The point beyond rectangle packing is that every site must be measurable: grating couplers at the fiber-array pitch, bond pads at the probe pitch, and a single shared orientation so a wafer prober lands identically at each site (no rotation). A layout can be DRC-clean and still unmeasurable; the loop checks both.
Verification harness (
tools/)KLayout SiEPIC DRC, exact boolean geometric-collision check, LVS-style connectivity, an orientation gate, and a largest-empty-rectangle void finder, rolled into a single gated figure of merit (maximize structures placed, score zero if any hard check fails).
Notes
tools/library.py.design.py/simulate.pyframework with the packing project. SeeREADME.mdfor setup and run instructions.🤖 Generated with Claude Code
Note
Medium Risk
Large architectural swap and new packing/validation logic;
tools/hierarchy.pyCLI still imports removedrun/designmodules, so that entry point may be broken until updated.Overview
Replaces the single-device Tidy3D auto-design loop (
design.py,simulate.py,drc.py,orchestrate.py) with a local DoE chip packing workflow: a planner (plan.py+program_planner.md) writesblackboard/doe_plan.json, and a packer (optimize.py+program.md) fills a fixed 8×3 mm die via replicate ramp plus void-fill until no gap fits the smallest site.Adds the
tools/harness (PhotonForge PCells/GDS library, measurable test sites with GCs and pads,floorplan.pack_into_die, gated FOM incriteria.py, collisions/DRC/orientation/LER invalidation.py+toolbox.py),blackboard/die.yaml, viewer helpers, and optional LiveViewer frame capture /make_gif_from_frames.py. README and.gitignoreare rewritten for the new flow; generatedoutput/and plan artifacts are ignored.Reviewed by Cursor Bugbot for commit b7d8f39. Bugbot is set up for automated code reviews on this repo. Configure here.