Skip to content

fix: avoid net-label connector traces crossing other nets (#674)#703

Closed
DPS0340 wants to merge 2 commits into
tscircuit:mainfrom
DPS0340:fix/connector-trace-crossings
Closed

fix: avoid net-label connector traces crossing other nets (#674)#703
DPS0340 wants to merge 2 commits into
tscircuit:mainfrom
DPS0340:fix/connector-trace-crossings

Conversation

@DPS0340

@DPS0340 DPS0340 commented Jul 24, 2026

Copy link
Copy Markdown

Progress on #674.

Problem

AvailableNetOrientationSolver generates a connector trace from a label's original anchor to its corrected position, but never checks whether that connector crosses an existing trace from a different net. Every such crossing renders as a false junction on the schematic.

On the #674 board (_board#665 input), 3 crossings appear:

JP1.1-SJ3.1 (net8)  x  available-net-orientation-3-V3_3   at (-7.1,-6.1)
U1.1-U1.3 (V3_3)    x  available-net-orientation-5-GND    at (-1.8,0.2)
available-net-orientation-4-V3_3  x  available-net-orientation-9-GND  at (-2.8,-5.5)

example45 and bug-report-20260708T055430Z each had one more (visible in their snapshots as a GND connector slicing through a same-column V3_3 trace).

Fix

getCandidateStatus now computes the candidate's connector trace and rejects the candidate (trace-collision) when the connector would cross another net's trace. A fallback pass in processLabel re-runs the search allowing crossings when no crossing-free candidate exists — so the orientation constraint still wins over crossing avoidance (this preserves repro51's pinned "orientation over purity" behavior; that test still passes unchanged).

Results

  • example45: crossings 2 → 1 (snapshot updated; the GND connector now attaches from the clear side)
  • bug-report-20260708T055430Z: crossings 2 → 1 (snapshot updated)
  • #674 board: the shifted-anchor candidates for the remaining 3 are all walled in by another net's trace along the entire shift axis — fixing those requires routing the connector around the blocking trace, which is a bigger change. Pinned with a test.failing regression (board input included) so the remaining work is tracked by CI and this PR stays reviewable.

Verification

  • bun test — 141 pass, 0 fail (1 new intentional test.failing)
  • bunx tsc --noEmit / biome check — clean

Happy to follow up with the connector-rerouting pass for the walled-in cases if this direction looks right.

@vercel

vercel Bot commented Jul 24, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
schematic-trace-solver Ready Ready Preview, Comment Jul 25, 2026 7:13am

Request Review

@DPS0340

DPS0340 commented Jul 24, 2026

Copy link
Copy Markdown
Author

Following the repo's repro-first workflow: opened #706 as the standalone reproduction PR for #674 (pins the three false-junction crossings with a visual snapshot). This PR is the corresponding fix — happy to rebase once the repro lands.

@DPS0340 DPS0340 mentioned this pull request Jul 24, 2026
Progress on tscircuit#674.

AvailableNetOrientationSolver generated connector traces (from a label's
original anchor to its corrected position) without checking whether the
connector crosses an existing trace from a different net. Each crossing
renders as a false junction. On the tscircuit#674 board this produced 3 crossings,
e.g. the V3_3 connector slicing through the JP1.1-SJ3.1 trace; example45
and bug-report-20260708T055430Z each had one more.

Candidate evaluation now rejects candidates whose connector would cross
another net's trace, with a fallback pass that permits crossings when no
crossing-free candidate exists (so orientation constraints still win over
crossing avoidance, matching repro51's pinned behavior).

Crossings drop 2->1 on example45 and bug-report-20260708T055430Z
(snapshots updated). The tscircuit#674 board's remaining 3 crossings need
connector rerouting around blocking traces — pinned with a test.failing
for follow-up.
@DPS0340

DPS0340 commented Jul 25, 2026

Copy link
Copy Markdown
Author

Rebased onto current main (through #714), no conflicts. Full suite passes (145 pass / 0 fail) and CI is green, so this is ready whenever you get to it.

@DPS0340

DPS0340 commented Jul 25, 2026

Copy link
Copy Markdown
Author

@mohan-bee thanks again for #700 — if you're up for one more, this is the next real fix in the same area (5 files).

I re-verified the numbers against current main just now, so they're not stale:

board main this branch
example45 2 crossings 1
bug-report-20260708T055430Z 2 crossings 1
#674 board 3 crossings 3 (unchanged — see below)

To be upfront about the limitation: the three crossings on the #674 board itself are not fixed here. Their shifted-anchor candidates are walled in by another net's trace along the whole shift axis, so resolving them needs the connector routed around the blocking trace rather than the anchor shifted. That's a bigger change, so I pinned them with a test.failing (board input included) to keep this PR reviewable and keep the remaining work visible in CI.

Full suite: 145 pass / 0 fail. Rebased onto current main, mergeable, CI green.

Happy to do the connector-rerouting pass as a follow-up if this direction looks right to you.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why no snapshots for this ?

@mohan-bee mohan-bee left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see comments

@DPS0340

DPS0340 commented Jul 25, 2026

Copy link
Copy Markdown
Author

@mohan-bee good catch — fixed in c18cc86.

The reason there was no snapshot: the existing assertion is test.failing, so the board never actually got rendered and no snapshot was written. I've added a passing render test alongside it, so the board is now pinned:

tests/repros/__snapshots__/repro-connector-trace-crossing-674.snap.svg

That makes the three remaining crossings visually reviewable instead of just being a number in an assertion, and it'll catch any visual regression while the connector-rerouting follow-up is still outstanding.

Full suite: 146 pass / 0 fail.

DPS0340 added a commit to DPS0340/schematic-trace-solver that referenced this pull request Jul 25, 2026
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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i still don't see anything .. for this input.json

@DPS0340

DPS0340 commented Jul 25, 2026

Copy link
Copy Markdown
Author

@mohan-bee you were right, and I misread your first comment — sorry for the round trip.

I thought you were asking me to add a snapshot, so I added one. The actual problem was that the input.json shouldn't have existed at all: the #674 issue already has a bot-imported bug report at tests/bug-reports/bug-report-20260717T022934Z/ (the directory name comes from the issue's created_at, generated by .github/scripts/import-json-bug-report.ts). I'd hand-created a second directory containing a byte-identical copy of that same board — I diffed them to confirm.

Fixed in 5c8a733:

  • deleted tests/bug-reports/bug-report-20260717-connector-crossing-674/
  • repro now imports bug-report-20260717T022934Z.json
  • dropped the snapshot I'd added, since that bug report already has its own

So no hand-made bug reports and no duplicated board. Full suite 145 pass / 0 fail.


Separately, e3cb03c actually fixes part of what this PR was leaving behind. The remaining crossings had a root cause I'd missed: labels are processed one at a time, so a connector is only validated against traces that exist at that moment. On this board orientation-4 is routed at index 14 but collides with orientation-9, which isn't created until index 17 — the earlier connector never had a chance to see it.

Added a post-pass that runs once every connector exists and swaps in the mirrored L-route where that clears a crossing:

board before after
#674 board 3 2
bug-report-20260706T213649Z 11 9
bug-report-20260706T220324Z 6 5
bug-report-20260721T221026Z 5 4
bug-report-20260717T022934Z 3 2
example43 1 0

The last 2 on the #674 board are still walled in — the mirrored route crosses something too, so those need the connector routed around the blocker. Still pinned by the existing test.failing.

Happy to split that post-pass into its own PR if you'd rather keep this one to the original scope.

DPS0340 added a commit to DPS0340/schematic-trace-solver that referenced this pull request Jul 25, 2026
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.
@mohan-bee was right that the hand-made bug report was wrong. The tscircuit#674
issue already has a bot-imported report at
tests/bug-reports/bug-report-20260717T022934Z (directory name derived from
the issue's created_at by .github/scripts/import-json-bug-report.ts), and
I had hand-created a second directory holding a byte-identical copy.

Removes the hand-made directory and points the repro at the existing bug
report, which already carries its own snapshot test.

Full suite 145 pass / 0 fail.
@DPS0340

DPS0340 commented Jul 25, 2026

Copy link
Copy Markdown
Author

Cleaned this PR back to its original scope (a8b95d9). It's now just two commits:

  1. the connector-crossing avoidance itself
  2. the fix for your review — the hand-made bug report is gone, the repro imports bug-report-20260717T022934Z instead

The post-pass work I mentioned has been split out into #716 as you'd expect, so this PR stays reviewable on its own. #716 is stacked on this branch, so this one goes first.

Worth mentioning what #716 turned up, since it changes the story here: I said the remaining crossings needed "routing around the blocking trace", and that turned out to be exactly right — for the last two, the blocker sits between the endpoints on both axes, so no L-shape avoids it. With detours added, the #674 board goes to 0 crossings and the repro's assertion is no longer test.failing.

This PR on its own: full suite 145 pass / 0 fail, CI green.

DPS0340 added a commit to DPS0340/schematic-trace-solver that referenced this pull request Jul 25, 2026
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.
DPS0340 added a commit to DPS0340/schematic-trace-solver that referenced this pull request Jul 25, 2026
Same issue @mohan-bee 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#670 was opened at 2026-07-16T14:48:56Z and its bot-imported report
already exists as bug-report-20260716T144856Z. The hand-made
bug-report-20260716-long-trace-670/input.json was a byte-identical copy.

Removes the duplicate and points the repro at the existing bug report.

Full suite 145 pass / 0 fail.
@DPS0340

DPS0340 commented Jul 25, 2026

Copy link
Copy Markdown
Author

@MustafaMulla29 @ShiboSoftwareDev — adding you two; you're the top two mergers here (19 and 10 of the last ~60) and I'd only tagged @mohan-bee.

Small: 4 files, but only 2 are sourceAvailableNetOrientationSolver.ts (+58/-1) and the repro test (+62). The other two are snapshot refreshes.

Progress on #674. Net-label connector traces were being routed across other nets' traces. The connector is validated only against traces that exist at the moment it's routed, so a connector created early can't see one created later — concretely, orientation-4 is routed at index 14 but collides with orientation-9, created at index 17.

This picks the mirrored L-route when the default one crosses. Measured different-net crossings vs origin/main:

example45                       2 → 1
bug-report-20260708T055430Z     2 → 1

The #674 board's own 3 crossings are unchanged here — those need the detour routing, which is split into #716 (stacked on this one) to keep this PR reviewable. #716 takes that board 3 → 0.

Full suite green, MERGEABLE / CLEAN.

@DPS0340

DPS0340 commented Jul 25, 2026

Copy link
Copy Markdown
Author

Closing this in favour of #719, which fixes the same root cause more effectively. I should have caught the duplication before opening both — apologies for the extra review surface.

Both PRs add the same missing check to AvailableNetOrientationSolver: a net-label's connector trace is validated against chips and other labels, but never against existing traces. They differ only in the fallback when no crossing-free candidate exists.

I measured both against origin/main on all 19 imported bug reports, counting different-net crossings in the final trace geometry:

origin/main   TOTAL 40
#719          TOTAL 19
#703 (this)   TOTAL 39

Per board, this PR is worse on six of them:

board #719 #703
bug-report-20260706T213649Z 4 11
bug-report-20260706T220324Z 4 6
bug-report-20260707T134549Z 2 3
bug-report-20260716T144856Z 0 4
bug-report-20260717T022934Z 0 3
bug-report-20260721T221026Z 2 5

The reason is that the fallback fires on nearly every label, so this PR degrades to the original behaviour and removes one crossing out of forty. The retry was meant to guarantee a label still gets placed, but in practice it just disables the fix.

They are also not stackable — merging both would leave the disabled-check path as dead code alongside a redundant scan.

So: #719 is the one worth reviewing, and it is best read after #718, which adds the counter both were measured with.

On @mohan-bee's review here — the snapshots and the bot-imported bug report were addressed in the commits above, and that work carries over to #719, so nothing is lost by closing this.

@DPS0340 DPS0340 closed this Jul 25, 2026
DPS0340 added a commit to DPS0340/schematic-trace-solver that referenced this pull request Jul 26, 2026
Same issue @mohan-bee 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#670 was opened at 2026-07-16T14:48:56Z and its bot-imported report
already exists as bug-report-20260716T144856Z. The hand-made
bug-report-20260716-long-trace-670/input.json was a byte-identical copy.

Removes the duplicate and points the repro at the existing bug report.

Full suite 145 pass / 0 fail.
DPS0340 added a commit to DPS0340/schematic-trace-solver that referenced this pull request Jul 26, 2026
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.
DPS0340 added a commit to DPS0340/schematic-trace-solver that referenced this pull request Jul 26, 2026
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.
DPS0340 added a commit to DPS0340/schematic-trace-solver that referenced this pull request Jul 26, 2026
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.
DPS0340 added a commit to DPS0340/schematic-trace-solver that referenced this pull request Jul 26, 2026
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.
DPS0340 added a commit to DPS0340/schematic-trace-solver that referenced this pull request Jul 26, 2026
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.
DPS0340 added a commit to DPS0340/schematic-trace-solver that referenced this pull request Jul 26, 2026
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants