12 — Decisions and risks¶
Part of the TraceMaker plan. Start at
../PLAN.md.
Decisions¶
Every decision has its own record in decisions/: what was decided, the alternatives, the reason and,
where it was replaced, the decision that replaced it. The records are the source; the table below is generated from
them. To add one, run scripts/decisions.py new "Short title" --docs 05 and fill in the file it prints (D134).
Records D1–D131 were converted from the rows of this table on 2026-10-21; their text is unchanged.
| # | Decision | Status |
|---|---|---|
| D1 | Engine in C++20 and CUDA, viewer in TypeScript | accepted |
| D2 | Placement in scope with four optimality levels | accepted |
| D3 | Analytic placement, then annealing, then exact windows | accepted |
| D4 | Octilinear lattice routing first, gridless later | accepted |
| D5 | GPU never makes the final legality decision | accepted |
| D6 | Four-tier failure memory | accepted |
| D7 | Native .kicad_pcb I/O, DSN for benchmarks only |
accepted |
| D8 | KiCad DRC is the benchmark judge | accepted |
| D9 | Integer fixed-point costs | accepted |
| D10 | Browser viewer served by the engine | accepted |
| D11 | Own CUDA kernels, no PyTorch or DREAMPlace runtime | accepted |
| D12 | FLUTE for Steiner trees | accepted |
| D13 | Courtyard gap fallbacks in full placement | accepted |
| D14 | SimPL spreading instead of electrostatic density | accepted |
| D15 | New placement kept only if it routes as well | accepted |
| D16 | Double-pitch portfolio variants on large boards | accepted |
| D17 | CLI, Python module and plugin share one route function | accepted |
| D18 | Position-independent build when bindings are on | accepted |
| D19 | PCM package without a bundled engine by default | superseded by D121 |
| D20 | Annealed replica exchange for parallel tempering | accepted |
| D21 | RUDY overflow and pin density as routability term | accepted |
| D22 | Router as a callback in router-in-the-loop placement | accepted |
| D23 | Exact windows by own branch and bound, not CP-SAT | accepted |
| D24 | --route-check restores a rejected placement by copying the input |
accepted |
| D25 | Decoupling capacitor affinity pseudo-nets | accepted |
| D26 | Component-rule catalogue in YAML, embedded as generated JSON | accepted |
| D27 | lib_id detectors match the footprint name only |
accepted |
| D28 | Component proximity rules reuse affinity pseudo-nets | accepted |
| D29 | Generated keep-outs for crystals and switching inductors | accepted |
| D30 | Per-net coupled routing for detected USB pairs | accepted |
| D31 | --component-rules off by default for placement and routing |
superseded by D52 |
| D32 | Escape planning v1 as reserved corridors | accepted |
| D33 | Escape planning in two of eight portfolio variants | accepted |
| D34 | Escalation rung necks vias down to board minimum | accepted |
| D35 | Escape feasibility reported beside the clean pass | accepted |
| D36 | Impedance rules computed and reported only | superseded by D58 |
| D37 | Closed-form impedance models from the papers | accepted |
| D38 | Adjacent copper layer as the assumed reference plane | accepted |
| D39 | Differential pairs solved for width at the class gap | accepted |
| D40 | User rule override file in strictly checked JSON | accepted |
| D41 | ETH-05 magnetics keep-out like XTAL-04 | accepted |
| D42 | Opt-in connector edge attraction by axis anchor | accepted |
| D43 | Two-stage component-rule pulls in full placement | accepted |
| D44 | Flood-fill reachability pre-check before strict searches | accepted |
| D45 | Replay logs as zstd-compressed JSON lines | accepted |
| D46 | Evidence code D for rules with TraceMaker default values | accepted |
| D47 | Portfolio variant set independent of thread count | accepted |
| D48 | Opt-in side assignment by annealer flip moves | accepted |
| D49 | Opt-in min-cost-flow escape planning v2 | accepted |
| D50 | Differential pairs searched as one object | accepted |
| D51 | DRC follows KiCad 10 connectivity on broken boards | accepted |
| D52 | tracemaker-place defaults to --component-rules soft |
accepted |
| D53 | Global congestion map off, global router v2 deferred | superseded by D56 |
| D54 | Connection planning by copper gap, group re-route removed | accepted |
| D55 | DRC zone-fill edge index instead of GPU broad-phase | accepted |
| D56 | Global router v2 kept off and M6 closed | accepted |
| D57 | M8 closed with its gate not met | accepted |
| D58 | Impedance and width rules as synthetic net classes | accepted |
| D59 | Restart-based successive halving stays off | accepted |
| D60 | Plugin refills zones only on request or after moves | accepted |
| D61 | JSON protocol kept, FlatBuffers dropped | accepted |
| D62 | M9 closed with two items unbuilt | accepted |
| D63 | Half-pitch variant for small boards, no gridless arm | accepted |
| D64 | Coupled pairs may twist at layer changes | accepted |
| D65 | Rule areas block tracks and vias by own flags | accepted |
| D66 | Opt-in soft zone fills as via targets | accepted |
| D67 | Vias kept off SMD pads narrower than 2 mm | accepted |
| D68 | Via in pad at the board minimum via, opt-in | accepted |
| D69 | --first-nets routes named nets first and protects them |
accepted |
| D70 | Native macOS with an optional Metal backend | accepted |
| D71 | Metal cost-to-go field by segmented prefix-min scan | accepted |
| D72 | Router enforces net- and layer-only custom disallow rules | accepted |
| D73 | Router hot-path optimisations | accepted |
| D74 | Footprints clear of the outline are unplaced parts | accepted |
| D75 | Opt-in minimal repair of illegal input placements | accepted |
| D76 | Opt-in layer limits: --no-tracks-on and --layer-cost |
accepted |
| D77 | Coupled-pair work counts every leg check | accepted |
| D78 | Router zone-fill probes through the DRC edge index | accepted |
| D79 | Plane targets exclude teardrops and unreachable fills | accepted |
| D80 | Custom-rule conditions follow observed KiCad item sets | accepted |
| D81 | Named regression board sets with work budgets | accepted |
| D82 | Router applies positional disallow rules | accepted |
| D83 | tracemaker escape analyses outstanding pins under router rules |
accepted |
| D84 | Board-prep and route guidance as agent skills | accepted |
| D85 | In-engine exact zone refill for judging | accepted |
| D86 | Reported route time covers the whole job | accepted |
| D87 (reserved) | reserved by PR #21 (probe sealed BGA targets first), not merged | |
| D88 | Per-phase work counters and route CPU time | accepted |
| D89 | Terminal options screen and options file | accepted |
| D90 | Simple Route JSON supported at the edge only | accepted |
| D91 | Bus routing inside the existing search | accepted |
| D92 | After-route passes: widen power, stitch vias, style metric | accepted |
| D93 | Options screen with global, project and file scopes | accepted |
| D94 | Higher rip and pass limits, extra seeded variants | accepted |
| D95 | Unhelpful options kept as hidden flags | accepted |
| D96 | SRJ fan-out import options for fanout31 |
accepted |
| D97 | M14 plan as measured outcomes, not a build order | accepted |
| D98 | Automatic preferred directions on breakout boards | accepted |
| D99 | Negotiation as transactions with annealing acceptance | accepted |
| D100 | Breakout profile reach-check and field caching | accepted |
| D101 | Breakout portfolio with warm-started rounds | accepted |
| D102 | Portfolio search state saved and resumable | accepted |
| D103 | Clearance continuation ramp with warm starts | accepted |
| D104 | Relax, route, legalise | accepted |
| D105 | Layerless legacy fills inherit the zone's sole layer | accepted |
| D106 | Benchmark gates compare violation multisets | accepted |
| D107 | Fixture preparation by native conversion and ID repair | accepted |
| D108 | KiCad 10 defaults and legacy migration precedence for rules | accepted |
| D109 | Engine never talks to a model; advice files | accepted |
| D110 | Advised attempts as extra portfolio variants | accepted |
| D111 | Advice regions as in-memory rule areas and rules | accepted |
| D112 | Stuck report as part of the route | accepted |
| D113 | failure event explains what rejected the path |
accepted |
| D114 | Read-only reference-return audit | accepted |
| D115 | Footprint check against trusted datasheet references | accepted |
| D116 | Viewer binds loopback by default, token elsewhere | accepted |
| D117 | JLCPCB routing rules as opt-in options | accepted |
| D118 | Milestones M17 to M21 follow the owner's answers | accepted |
| D119 | Agent board session over MCP and JSON lines | accepted |
| D120 | Per-shape zero edge clearance as in KiCad 10.0.6 | accepted |
| D121 | Release as Linux tarball and KiCad plugin package | accepted |
| D122 | PCBWorld D3 run as PCBench boards with Freerouting rerun | accepted |
| D123 | One project brand, the trace logo | accepted |
| D124 | Rule relaxation spent on signals, not power nets | accepted |
| D125 | Legalisation may subdivide long tracks | accepted |
| D126 | Four opt-in escape features from the EtherCAT review | accepted |
| D127 | Soft mask and copper graphics, fine-lattice finish | accepted |
| D128 | --first-nets-ordered routes first nets in list order |
accepted |
| D129 | --bundle-escape river escapes on dense packages |
accepted |
| D130 | --supply-first routes dense-package supply nets first |
accepted |
| D131 | --package-tunnels under dense packages |
accepted |
| D132 | KiCad-measured shapes and net-less arcs in the judge | accepted |
| D133 | Viewer framing for named pages (--view-embed) | accepted |
| D134 | Documentation site: MkDocs, Diátaxis, decision records, Doxygen | accepted |
| D135 | macOS 15: floating-point parsing without std::from_chars | accepted |
Risks¶
| Risk | Likelihood | Mitigation |
|---|---|---|
nvcc 12.4 does not accept GCC 15 as host compiler |
Confirmed | Use -ccbin g++-12 (installed; builds for sm_60/sm_70; ran on the P100). Stay on CUDA 12.x because CUDA 13 drops Pascal and Volta |
| GPUs are shared with other workloads (llama-server held almost all GPU memory on 2026-10-02) | Confirmed | Memory admission control, batch shrinking, CPU fallback with identical results (doc 07 §4) |
| DRC parity with KiCad drifts across KiCad versions | Medium | Pin a KiCad version per release; parity tests in CI |
| Lattice routing misses tight gaps | Medium | Pin-access points, half-pitch last-gasp windows, gridless cleanup, tile-plane arm |
| Placement quality judged subjectively by users (mechanical, thermal intent not in netlist) | High | refine/eco modes by default for placed boards; rule areas and locks honoured; full mode opt-in |
| Negotiation oscillates | Medium | History decay, α scaling, reroute caps, best-board keeping |
| Learned components overfit the benchmark | Medium | Held-out board sets; learned arms only via bandit, never mandatory |
| Viewer slows the engine | Low | Lock-free rings, coalescing, drop-frontier policy |
| Scope (placement + routing + GPU + viewer) is very large | High | Milestones each deliver a usable tool; GPU and learning are additive to working CPU paths |