TraceOverlapShiftSolver treats its A -> B -> A oscillation guard as a reason to stop the entire solve. The first net pair that oscillates aborts the whole pass, so every other cross-net overlap still queued at that moment is silently left in the output, even though those pairs are independent and would have been corrected in the next few iterations.
Sub-solver
lib/solvers/TraceOverlapShiftSolver/TraceOverlapShiftSolver.ts, in _step():
if (this.returnsToPreviousTraceState(nextTraceState)) {
this.activeSubSolver = null
this.solved = true // <- ends the whole solver, not just this net pair
return
}
Reproduction
Minimized from tests/repros/assets/board-1273-trace-overlap-cycle.input.json (74 chips -> 5 chips, 14 pins). Two cross-net collinear overlaps survive the shift solver: GND/VBUS and RTS/DTR. Only the GND/VBUS pair actually oscillates.
{
"chips": [
{
"chipId": "schematic_component_23",
"center": {
"x": 11.084375,
"y": -5.325
},
"width": 2.3000000000000007,
"height": 3.2000000000000006,
"pins": [
{
"pinId": "schematic_port_75",
"x": 9.934375,
"y": -4.325
},
{
"pinId": "schematic_port_79",
"x": 9.934375,
"y": -5.125
},
{
"pinId": "schematic_port_80",
"x": 9.934375,
"y": -5.325
},
{
"pinId": "schematic_port_96",
"x": 12.234375,
"y": -5.025
},
{
"pinId": "schematic_port_100",
"x": 12.234375,
"y": -4.2250000000000005
},
{
"pinId": "schematic_port_101",
"x": 12.234375,
"y": -4.025
}
],
"sectionId": "USB to UART"
},
{
"chipId": "schematic_component_26",
"center": {
"x": 7.629375,
"y": -3.9250000000000007
},
"width": 0.7800000000000002,
"height": 0.7600000000000011,
"pins": [
{
"pinId": "schematic_port_106",
"x": 7.564375,
"y": -4.3050000000000015,
"_facingDirection": "y-"
}
],
"sectionId": "USB to UART"
},
{
"chipId": "schematic_component_27",
"center": {
"x": 9.221875,
"y": -5.55
},
"width": 1.205,
"height": 0.5999999999999996,
"pins": [
{
"pinId": "schematic_port_108",
"x": 8.944374999999999,
"y": -5.25,
"_facingDirection": "y+"
},
{
"pinId": "schematic_port_109",
"x": 8.944374999999999,
"y": -5.85,
"_facingDirection": "y-"
}
],
"sectionId": "USB to UART"
},
{
"chipId": "schematic_component_28",
"center": {
"x": 9.221875,
"y": -4.23
},
"width": 1.205,
"height": 0.6000000000000014,
"pins": [
{
"pinId": "schematic_port_111",
"x": 8.944374999999999,
"y": -3.9299999999999997
}
],
"sectionId": "USB to UART"
},
{
"chipId": "schematic_component_32",
"center": {
"x": 15.769374999999998,
"y": -4.724999999999999
},
"width": 2,
"height": 0.8000000000000007,
"pins": [
{
"pinId": "schematic_port_118",
"x": 14.769374999999998,
"y": -4.524999999999999
},
{
"pinId": "schematic_port_119",
"x": 14.769374999999998,
"y": -4.724999999999999
},
{
"pinId": "schematic_port_121",
"x": 16.769374999999997,
"y": -4.924999999999999
},
{
"pinId": "schematic_port_122",
"x": 16.769374999999997,
"y": -4.724999999999999
}
],
"sectionId": "USB to UART"
}
],
"directConnections": [
{
"netId": ".R5 > .pin1 to .U6 > .VBUS",
"pinIds": [
"schematic_port_108",
"schematic_port_80"
]
}
],
"netConnections": [
{
"netId": "GND",
"isGround": true,
"netLabelWidth": 0.42,
"netLabelHeight": 0.48,
"pinIds": [
"schematic_port_75",
"schematic_port_101",
"schematic_port_106",
"schematic_port_109"
]
},
{
"netId": "VBUS",
"netLabelWidth": 0.42,
"netLabelHeight": 0.6,
"pinIds": [
"schematic_port_79",
"schematic_port_111"
]
},
{
"netId": "RTS",
"netLabelWidth": 0.48,
"pinIds": [
"schematic_port_96",
"schematic_port_118",
"schematic_port_122"
]
},
{
"netId": "DTR",
"netLabelWidth": 0.48,
"pinIds": [
"schematic_port_100",
"schematic_port_119",
"schematic_port_121"
]
}
],
"textBoxes": [],
"availableNetLabelOrientations": {
"GND": [
"y-"
],
"VBUS": [
"y+"
],
"RTS": [
"x-",
"x+"
],
"DTR": [
"x-",
"x+"
]
},
"maxMspPairDistance": 8,
"_hideRatsNet": false
}
const solver = new SchematicTracePipelineSolver(inputProblem)
solver.solve()
// inspect solver.traceOverlapShiftSolver.correctedTraceMap for
// cross-net segments that are collinear and overlapping
Observed
The solver stops at iteration 9 with solved === true, and two distinct cross-net pairs still overlap collinearly:
connectivity_net0 ~ connectivity_net1 (GND / VBUS, the oscillating pair)
connectivity_net3 ~ connectivity_net4 (RTS / DTR, independent)
The RTS/DTR traces share an exact coordinate over a positive-length span, so they render as one wire.
On the full board-1273 fixture the same abort leaves 6 unresolved cross-net pairs after 27 iterations.
Expected
Oscillation between two nets should suspend only that net pair. Independent overlaps should keep being corrected until no correctable overlap remains. For this input only connectivity_net0 ~ connectivity_net1 should remain; RTS/DTR should be separated.
On board-1273 this takes the unresolved pairs from 6 down to 1 (the single genuinely oscillating pair), with the same 135 traces routed and no trace added or dropped.
TraceOverlapShiftSolvertreats its A -> B -> A oscillation guard as a reason to stop the entire solve. The first net pair that oscillates aborts the whole pass, so every other cross-net overlap still queued at that moment is silently left in the output, even though those pairs are independent and would have been corrected in the next few iterations.Sub-solver
lib/solvers/TraceOverlapShiftSolver/TraceOverlapShiftSolver.ts, in_step():Reproduction
Minimized from
tests/repros/assets/board-1273-trace-overlap-cycle.input.json(74 chips -> 5 chips, 14 pins). Two cross-net collinear overlaps survive the shift solver:GND/VBUSandRTS/DTR. Only theGND/VBUSpair actually oscillates.{ "chips": [ { "chipId": "schematic_component_23", "center": { "x": 11.084375, "y": -5.325 }, "width": 2.3000000000000007, "height": 3.2000000000000006, "pins": [ { "pinId": "schematic_port_75", "x": 9.934375, "y": -4.325 }, { "pinId": "schematic_port_79", "x": 9.934375, "y": -5.125 }, { "pinId": "schematic_port_80", "x": 9.934375, "y": -5.325 }, { "pinId": "schematic_port_96", "x": 12.234375, "y": -5.025 }, { "pinId": "schematic_port_100", "x": 12.234375, "y": -4.2250000000000005 }, { "pinId": "schematic_port_101", "x": 12.234375, "y": -4.025 } ], "sectionId": "USB to UART" }, { "chipId": "schematic_component_26", "center": { "x": 7.629375, "y": -3.9250000000000007 }, "width": 0.7800000000000002, "height": 0.7600000000000011, "pins": [ { "pinId": "schematic_port_106", "x": 7.564375, "y": -4.3050000000000015, "_facingDirection": "y-" } ], "sectionId": "USB to UART" }, { "chipId": "schematic_component_27", "center": { "x": 9.221875, "y": -5.55 }, "width": 1.205, "height": 0.5999999999999996, "pins": [ { "pinId": "schematic_port_108", "x": 8.944374999999999, "y": -5.25, "_facingDirection": "y+" }, { "pinId": "schematic_port_109", "x": 8.944374999999999, "y": -5.85, "_facingDirection": "y-" } ], "sectionId": "USB to UART" }, { "chipId": "schematic_component_28", "center": { "x": 9.221875, "y": -4.23 }, "width": 1.205, "height": 0.6000000000000014, "pins": [ { "pinId": "schematic_port_111", "x": 8.944374999999999, "y": -3.9299999999999997 } ], "sectionId": "USB to UART" }, { "chipId": "schematic_component_32", "center": { "x": 15.769374999999998, "y": -4.724999999999999 }, "width": 2, "height": 0.8000000000000007, "pins": [ { "pinId": "schematic_port_118", "x": 14.769374999999998, "y": -4.524999999999999 }, { "pinId": "schematic_port_119", "x": 14.769374999999998, "y": -4.724999999999999 }, { "pinId": "schematic_port_121", "x": 16.769374999999997, "y": -4.924999999999999 }, { "pinId": "schematic_port_122", "x": 16.769374999999997, "y": -4.724999999999999 } ], "sectionId": "USB to UART" } ], "directConnections": [ { "netId": ".R5 > .pin1 to .U6 > .VBUS", "pinIds": [ "schematic_port_108", "schematic_port_80" ] } ], "netConnections": [ { "netId": "GND", "isGround": true, "netLabelWidth": 0.42, "netLabelHeight": 0.48, "pinIds": [ "schematic_port_75", "schematic_port_101", "schematic_port_106", "schematic_port_109" ] }, { "netId": "VBUS", "netLabelWidth": 0.42, "netLabelHeight": 0.6, "pinIds": [ "schematic_port_79", "schematic_port_111" ] }, { "netId": "RTS", "netLabelWidth": 0.48, "pinIds": [ "schematic_port_96", "schematic_port_118", "schematic_port_122" ] }, { "netId": "DTR", "netLabelWidth": 0.48, "pinIds": [ "schematic_port_100", "schematic_port_119", "schematic_port_121" ] } ], "textBoxes": [], "availableNetLabelOrientations": { "GND": [ "y-" ], "VBUS": [ "y+" ], "RTS": [ "x-", "x+" ], "DTR": [ "x-", "x+" ] }, "maxMspPairDistance": 8, "_hideRatsNet": false }Observed
The solver stops at iteration 9 with
solved === true, and two distinct cross-net pairs still overlap collinearly:The
RTS/DTRtraces share an exact coordinate over a positive-length span, so they render as one wire.On the full
board-1273fixture the same abort leaves 6 unresolved cross-net pairs after 27 iterations.Expected
Oscillation between two nets should suspend only that net pair. Independent overlaps should keep being corrected until no correctable overlap remains. For this input only
connectivity_net0 ~ connectivity_net1should remain;RTS/DTRshould be separated.On
board-1273this takes the unresolved pairs from 6 down to 1 (the single genuinely oscillating pair), with the same 135 traces routed and no trace added or dropped.