Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,3 +241,12 @@ Use an honest label such as "unnamed component" when no name is available; NEVER
fall back to an ID or append one in parentheses/brackets. Keep IDs in structured
diagnostic reference fields only. Do not forward raw dependency error messages
that contain IDs; format their typed reason using readable circuit names.

## Routing benchmark evidence

Every PR that changes routing behavior must report its effect on the relevant
benchmark or fixed regression fixture set: base/head revisions, identical inputs,
budgets, pass counts, failures and elapsed time. Report pre-existing failures
explicitly; do not present a single successful sample as a clean suite or claim a
speedup from one run. Include an inspected, successfully routed visual snapshot.
Do not merge routing changes without this analysis in the PR description.
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@ import type {
AutoroutingPhaseProps,
BreakoutProps,
} from "@tscircuit/props"
import type { z } from "zod"
import { getSavedAutoroutingPhaseTraces } from "./get-saved-autorouting-phase-traces"
import { getPresetAutoroutingConfig } from "lib/utils/autorouting/getPresetAutoroutingConfig"
import type { z } from "zod"
import type { AutoroutingPhase } from "../AutoroutingPhase"
import { getSavedFanoutTraces } from "../Breakout/get-saved-fanout-traces"
import type { Breakout } from "../Breakout/Breakout"
import { getSavedFanoutTraces } from "../Breakout/get-saved-fanout-traces"
import { BreakoutPoint } from "../BreakoutPoint"
import type { Bus } from "../Bus"
import type { Net } from "../Net"
Expand All @@ -20,6 +19,7 @@ import type {
RoutingPhaseDrcTolerances,
RoutingPhasePlan,
} from "./GroupRoutingPhasePlan"
import { getSavedAutoroutingPhaseTraces } from "./get-saved-autorouting-phase-traces"

type GroupFanoutProps = Pick<
BreakoutProps,
Expand Down Expand Up @@ -138,6 +138,15 @@ function traceHasEndpointMatchingConnectionSelector(
trace: Trace,
connectionSelector: string,
): boolean {
if (connectionSelector.startsWith("net.")) {
const selectedNet = trace
.getSubcircuit()
.selectOne<Net>(connectionSelector, { type: "net" })
return (
selectedNet !== null &&
trace._findConnectedNets().nets.includes(selectedNet)
)
}
const connectionSelectorEndpointKey =
convertPortSelectorToEndpointKey(connectionSelector)
if (
Expand Down Expand Up @@ -392,6 +401,25 @@ export function Group_getRoutingPhasePlans(
const plan = getOrCreateRoutingPhasePlan(plansByPhaseIndex, phaseIndex)
plan.connectionSelectors = connectionSelectors

// A named net owns the joined routing task as well as its port-to-net traces.
// Moving only the traces leaves the actual task in the original phase.
for (const connectionSelector of connectionSelectors) {
if (!connectionSelector.trim().startsWith("net.")) continue
const selectedNet = group.selectOne<Net>(connectionSelector.trim(), {
type: "net",
})
if (!selectedNet || breakoutByNet.has(selectedNet)) continue
if (!phaseProps.reroute) {
for (const existingPlan of plansByPhaseIndex.values()) {
if (existingPlan === plan) continue
existingPlan.nets = existingPlan.nets.filter(
(net) => net !== selectedNet,
)
}
}
if (!plan.nets.includes(selectedNet)) plan.nets.push(selectedNet)
}

for (const trace of traces) {
if (breakoutByTrace.has(trace)) continue
if (selectedTracesByPhaseIndex.get(phaseIndex)!.has(trace)) {
Expand Down
15 changes: 15 additions & 0 deletions repros/named-net-phase/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,18 @@ bun test tests/features/autoroutingphase-named-net-control.test.tsx tests/featur
Baseline: 1 pass / 1 fail. The declaration-only control successfully routes; the selector reproduction throws before routing. The inspected PCB snapshot is explicitly that successful control, not an unresolved board.

Benchmark effect: this reproduction changes no production code or solver dependency. Control completes in about 0.27 s of test time locally; the failing selector completes no routing. These single-run numbers establish behavior, not a performance claim. The stacked fix will compare the same fixtures and the existing phase-selection suite. Bus-lanes solver and its 11-sample benchmark are unchanged by this Core-only phase-selection reproduction.


## Stacked fix results

The selector now enrolls the Net routing task and its connected branches.
Without `reroute`, it moves the net from the old phase; with `reroute`, it adds
an early pass and preserves the later net phase. Input props remain immutable.

- New fixtures: **3/3 pass**, 9 assertions, 2.33 s total process time. The early-pass fixture emits no copper itself; the normal later autorouter produces the inspected successful PCB.
- Existing phase fixtures plus the successful control: identical **25 pass / 3 fail** on base and fix, 287 assertions each, 27 files / 28 tests. Process times: base **24.54 s**, fix **23.80 s**, one run each; no speedup claim.
- The same three existing visual failures occur in both runs: emitted-paths parity (0.39%), emitted-paths cache (0.02%), event-index (0.02%). Their snapshots were not updated.
- Production solver dependencies unchanged. This fixes which task reaches the solver; it does not change the bus-lanes search or its 11-sample benchmark.
- Full typecheck could not be established with the reused older local dependency tree: errors include missing CircuitJSON `footprint_origin`/`pcb_stackup`/`PcbSpiceChannel` and missing type resolution in the isolated JLCPCB source dependency. No errors reference the changed phase planner or the new fixtures. CI uses a clean dependency install.

The fix's PCB snapshots were rendered with Node/resvg and inspected: both show the named net physically routed between R1 and R2.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading