TraceRoute.port1_index / port2_index map each trace back to the caller's ports1 / ports2 lists; traces are ordered by lateral bundle slot, not input order, so use these indices to correlate results
doroutes.util.segments_length_um / doroutes.util.cell_length_um — route lengths are the sum of placed cells' info["length"]; cells lacking it raise ValueError
Composite bundle pcells (pcells.straights / pcells.bends) record info["wire_lengths"] (per-wire sums of their inner cells' info["length"]) and info["length"] (exact total over all wires)
Route objects: routing functions return a doroutes.Route (pydantic model, field-compatible with kfactory's ManhattanRoute for future backend integration, generalized for sbends and coordinate endpoints). It carries the wire's placed instances port-to-port (start→end), start_port/end_port, dbu backbone, n_bend90/bend90_radius/length_straights, and length (µm) via a pluggable length_function defaulting to the exact cell-info sum. corners, path_length, iteration and len() remain as backward-compatible properties; TraceRoute is a deprecated alias
FanLeg.instances / FanLeg.n_bend90 — each fan leg carries its placed cells in start→end order
Breaking:add_fan_in now returns (stops, legs) instead of just the stops array — legs is the per-wire FanLeg detail (polyline, exact length, original input index, placed instances). Existing callers should unpack: stops, _ = add_fan_in(...)
GDS hierarchy is unchanged from 1.1.0: bundle bodies stay composite straights_*/bends_* segment cells and fan legs stay flat. Per-wire identity lives in the returned Route objects (instances lists the leg cells plus the shared composite segments); bundle traces use a sliced length_function that reads the wire's own wire_lengths entry per composite segment — still exact sums of cells, no geometry
Old-style TraceRoute(corners=..., path_length=...) construction now raises a pydantic.ValidationError (the fields became read-only properties of Route)
add_route_astar and add_route_manual now return TraceRoute instead of a bare list of corner points; iteration (for pt in result) and len() keep working, but isinstance(result, list) checks and list concatenation do not — use result.corners for those
TraceRoute.path_length, bundle per-trace lengths, and FanLeg.length_um are now the exact sum of the placed cells' info["length"] (correct for euler bends; previously approximated geometrically from the corner polyline)
Bundle traces (BundleResult.traces) now span port-to-port including the fan-in/fan-out legs, with exact lengths for the manhattan, sbend, and lbend fan strategies
Breaking: standardized public API — routing and bundle functions use micron parameters, always return corners, and follow consistent naming (#115, #119)
FanStrategy TypedDict replaces loose keyword arguments for fan-in/fan-out configuration (#115)
Deprecation wrappers added for all renamed/removed parameters — old call sites emit warnings instead of breaking (#115)