fix: relocate net labels placed inside chip bodies#699
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Additional verification: ran the full board from #687 (
So this PR resolves both #655 and the #687 pile-up on the original board. |
|
Ran a label-inside-chip scan across all 21 bug-report boards in the repo:
So beyond the #655 repro board, this fix also clears the hidden labels on four other real bug-report boards. |
Fixes tscircuit#655. NetLabelNetLabelCollisionSolver only relocated a label when it overlapped another label. A label sitting inside a chip body without a label-label collision was never checked against chips, so it rendered behind the component and was illegible. Two changes: - After all label-label collisions are resolved, find labels whose area is >=50% covered by a chip body and run the same candidate search to relocate them. - Port-only labels previously only tried 4 orientations anchored exactly on their pin. When the pin is covered by a chip body (overlapping chips) every orientation collides, so the anchor now slides progressively outward until the label escapes. Orientation constraints from availableNetLabelOrientations are respected. The anchor-sliding escape also resolves tscircuit#687: the V1V1 label that was left stacked on the QD3/QCLK port labels now finds a collision-free position, so the repro's buggy-behavior assertions are flipped to assert the fix.
…ySolver The bug-report-20260707T092615Z snapshot conflicted with tscircuit#712, which landed while this branch was open. Regenerated against current main; the repro-net-label-inside-chip-655 regression test still fails on main and passes here, so the fix this PR makes is unchanged.
57d0acd to
d760e88
Compare
|
Rebased onto current The fix itself is unchanged. To confirm that after the rebase, the regression test in this PR still fails on Full suite passes (145 pass / 0 fail), and CI is green. |
|
Re-verified against current On the #655 board (
So four labels are currently rendered buried inside chip bodies, and none are after this change — with the label count unchanged, i.e. nothing was dropped to achieve it. The regression test also fails on Full suite 145 pass / 0 fail, rebased onto current |
Following @mohan-bee's snapshot feedback on tscircuit#703/tscircuit#707, applying the same here pre-emptively: the assertion only checked which labels overlapped a chip body, so the board was never rendered. Now the relocated labels are visually reviewable.
Applying @mohan-bee's feedback from tscircuit#703/tscircuit#707 here too. The tscircuit#655 board is already a bot-imported bug report (bug-report-20260707T230831Z) with its own snapshot test, so the snapshot I added to this repro duplicated it. The repro keeps only the assertion specific to tscircuit#655 — which labels overlap a chip body. That assertion still fails on main and passes here. Full suite 145 pass / 0 fail.
|
Applied @mohan-bee's feedback from #703/#707 here too (11304a8) — the snapshot I'd added was a duplicate. The #655 board is already a bot-imported bug report ( The repro now keeps only the assertion specific to #655 (which labels overlap a chip body), which still fails on |
|
Extra validation beyond the #655 repro: I ran this branch against the unlabelled JSON bug reports in this repo (the ones filed with an empty Notes section) and measured
So this fixes two previously-unexplained reports outright (#636, #628) and improves a third — none of which were part of the original #655 case. Worth calling out: #636 also had two The cases that remain (#626, one in #630) are all below the Happy to fold any of those JSONs in as regression fixtures if you'd like the coverage pinned. |
|
Pinned the #636 board as a second regression fixture ( Two assertions, both of which fail on The second assertion is the interesting one — it locks in that the orientation constraint stops being violated. On Guarding it explicitly means a future regression in the relocation logic will surface as a constraint violation too, not just as a visual overlap. Verification on this branch: |
The previous commit added tests/bug-reports/bug-report-636/, which repeats the mistake @mohan-bee already flagged on tscircuit#703/tscircuit#707: bug report directories are generated by .github/scripts/import-json-bug-report.ts and named from the issue's created_at, so they must not be hand-created. Issue tscircuit#636 was opened at 2026-07-07T23:08:31Z, and the bot-imported report for it already exists as bug-report-20260707T230831Z. The hand-made bug-report-636.json was a byte-identical copy of it — so tscircuit#636 is not a second board as its comment claimed, it is the same board tscircuit#655 already covers. Removes the duplicate directory and the duplicate test file, keeping the one assertion tscircuit#636 added that tscircuit#655 did not have: labels must stay on an orientation the input allows. Both assertions fail on main and pass here. Full suite 146 pass / 0 fail.
|
Cleaned up a duplicate here as well (0330cfd). A Removed the duplicate directory and the duplicate test file. I kept the one assertion #636 contributed that #655 didn't have — that labels stay on an orientation the input allows — folded into this repro. Both assertions fail on Full suite 146 pass / 0 fail. |
|
Correcting my own comment above, and the commit that followed it. I claimed #636 was a second, independent board that this PR also fixes. It isn't — #636 and #655 are two reports of the same board. The bot-imported fixture What survives is the one assertion #636 genuinely added that #655 didn't have — that labels stay on an orientation the input allows — now folded into the existing #655 repro rather than a duplicate test file: Both assertions fail on So please read the earlier table as covering fewer distinct boards than I implied. The fix itself and its measured effect are unchanged; only my claim about how many separate reports it closes was wrong. |
|
@MustafaMulla29 adding you — you've merged 19 of the last ~60 here, more than anyone, and I'd only tagged @mohan-bee. Whoever has a moment. One note on size, since the diff stat is misleading: GitHub shows 13 files / +811, but the only source change is one file — Fixes #655 (and #636, which turned out to be the same board). Measured on that board: The orientation violations were collateral — once a label is stuck inside a chip, no allowed orientation fits, so the any-orientation fallback fires. Both are asserted in the repro; both fail on Relocation is deliberately gated at Full suite 146 pass / 0 fail, CI green, |
|
Adding a whole-corpus measurement, since this PR's description only cites the one board from #655 and that undersells it. I scanned every imported bug report for two defects: net labels whose bounding box falls inside a chip body, and labels overlapping each other. Comparing
−47% and −43%, with no board regressing on either metric. Per board, where anything changed: The #655 board goes to zero, which is what the PR claims — but it also fixes labels on five other boards that nobody had reported, and clears two label-label overlaps on What it does not fix: 9 in-chip labels remain, concentrated in Method: read Related: #718 does the same kind of pinning for trace crossings, if a standing metric for this class would be useful too. Happy to add one for label placement on the same pattern. |
|
Correcting my measurement above — it understated this PR. I counted a label as "inside a chip" on any interior overlap. That was wrong: Re-measured against the constant the implementation actually uses:
Every genuinely-inside-a-chip label in the corpus is gone, not just the #655 board. My earlier "17 → 9, some remain" was an artifact of the wrong threshold — the 9 "remaining" were 1–6% grazes that were never defects. The label-overlap figure (7 → 4) is unchanged from before, since that check doesn't involve the threshold. Sorry for the noise. The corrected number is the one worth reviewing against, and it's a stronger result than what I first posted. I've opened #720 to pin both metrics as a standing guard, using the same 0.5 constant so the test can't drift from the implementation. |
Fixes #655. Also resolves the pile-up in #687.
Problem
NetLabelNetLabelCollisionSolveronly relocated a label when it overlapped another label (findNextCollidingPairlooks for label-label overlaps only). A label sitting inside a chip body without a label-label collision was never checked against chips, so it rendered behind the component and was illegible. Inbug-report-20260707T230831Z, theVIN,VOUT,PGandU1.FB to R2.pin1labels ended up 100% inside chip bodies.Fix
Two changes in
NetLabelNetLabelCollisionSolver:ChipObstacleSpatialIndexand run through the same candidate search/relocation loop. The 50% threshold avoids relocating labels with small incidental overlaps, which other solvers already tolerate.schematic_component_0/6etc.), so a pin can be covered by another chip's body and every orientation collides. The anchor now slides progressively outward (up to 3mm in 0.1mm steps) until the label escapes. Orientation constraints fromavailableNetLabelOrientationsare respected during the search.The anchor-sliding escape also gives the
V1V1label in the #687 repro a collision-free position, so that repro's "assert the buggy behavior" assertions are flipped to assert the fix.Before / After (bug-report-20260707T230831Z, stage16)
Before: VIN/PG hidden inside U1's body, VOUT inside R3, FB inside R1.
After: all four labels sit outside chip bodies at the nearest legal position.
Verification
bun test— 141 pass, 0 fail (was 2 pre-existing pinned-bug failures + this issue's failing repro)tests/repros/repro-net-label-inside-chip-655.test.ts(matches the repro in Add a repro test for net labels placed inside chip bodies #656 by @abdalraof-albarbar)bunx tsc --noEmit— cleanbunx biome check— clean