@deltarobotics/uhd-viewer 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -0
- package/dist/app/assets/index-CEJyT8hF.css +2 -0
- package/dist/app/assets/{index-CkpIRYgM.js → index-DWZ-48wc.js} +35 -35
- package/dist/app/index.html +2 -2
- package/dist/components/components.css +320 -56
- package/dist/components/index.js +1166 -605
- package/dist/components/index.js.map +1 -1
- package/dist/components/types/uhd-viewer/src/cad/ModelView.d.ts +3 -1
- package/dist/components/types/uhd-viewer/src/canvas/Canvas.d.ts +5 -1
- package/dist/components/types/uhd-viewer/src/canvas/interaction.d.ts +2 -2
- package/dist/components/types/uhd-viewer/src/canvas/reveal.d.ts +18 -0
- package/dist/components/types/uhd-viewer/src/chrome/Chrome.d.ts +12 -2
- package/dist/components/types/uhd-viewer/src/chrome/InterfaceCards.d.ts +11 -1
- package/dist/components/types/uhd-viewer/src/chrome/Sections.d.ts +22 -1
- package/dist/components/types/uhd-viewer/src/components.d.ts +4 -4
- package/dist/components/types/uhd-viewer/src/host/targets.d.ts +16 -0
- package/dist/components/types/uhd-viewer/src/model/classification.d.ts +3 -0
- package/dist/components/types/uhd-viewer/src/model/from-uhd.d.ts +3 -2
- package/dist/components/types/uhd-viewer/src/model/hierarchy.d.ts +10 -6
- package/dist/components/types/uhd-viewer/src/model/level.d.ts +7 -0
- package/dist/components/types/uhd-viewer/src/model/slots.d.ts +2 -0
- package/dist/components/types/uhd-viewer/src/ui/Legend.d.ts +23 -4
- package/dist/components/types/uhd-viewer/src/ui/legendFit.d.ts +26 -13
- package/dist/components/types/uhd-viewer/src/viewer/controller.d.ts +1 -0
- package/dist/components/types/uhd-viewer/src/viewer/hierarchy.d.ts +34 -12
- package/dist/components/types/uhd-viewer/src/viewer/views.d.ts +49 -18
- package/dist/headless/index.js.map +1 -1
- package/dist/lib/uhd-viewer.css +1 -1
- package/dist/lib/uhd-viewer.js +11291 -10973
- package/package.json +1 -1
- package/dist/app/assets/index-Boi2erhd.css +0 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["overlaps","trait","speaks","rolesOf","range","diag","speaks","rolesOf","trait","range","fmt","fmtR","diag","isGround","RANK","worst","natural","snapUp","snapTo","natural"],"sources":["../../../uhd/src/system/bundle.ts","../../../uhd/src/types/bundle.ts","../../../uhd/src/matching/roles.ts","../../../uhd/src/matching/protocol-match.ts","../../../uhd/src/drc/region-tree.ts","../../../uhd/src/parameters/range.ts","../../../uhd/src/drc/param-check.ts","../../../uhd/src/protocols/mechanical.ts","../../../uhd/src/drc/joint-check.ts","../../../uhd/src/drc/link-check.ts","../../../uhd/src/drc/drive-check.ts","../../../uhd/src/drc/signal-check.ts","../../../uhd/src/drc/types.ts","../../../uhd/src/drc/validate-pair.ts","../../../uhd/src/system/connectors.ts","../../../uhd/src/protocols/connector.ts","../../../uhd/src/protocols/net.ts","../../../uhd/src/system/nets.ts","../../../uhd/src/system/index.ts","../../src/source/tolerant.ts","../../src/source/source.ts","../../../uhd/src/system/derive.ts","../../src/model/nets.ts","../../src/model/from-uhd.ts","../../src/canvas/routing.ts","../../src/layout/router.ts","../../src/layout/board-layout.ts","../../src/layout/taps.ts","../../src/layout/card-body.ts","../../src/canvas/geometry.ts","../../src/layout/module-layout.ts","../../src/layout/layout.ts","../../src/layout/metrics.ts","../../src/headless.ts"],"sourcesContent":["/**\n * Reading a UHD bundle: the root and a lookup, optionally for a scenario.\n */\nimport type { UhdBundle } from \"../types/bundle.js\";\nimport type { ModuleDef } from \"../types/module.js\";\nimport type { ModuleLookup } from \"./index.js\";\n\nexport function bundleSystem(bundle: UhdBundle, scenarioId?: string): { root: ModuleDef; lookup: ModuleLookup } {\n const byId = new Map(bundle.definitions.map((d) => [d.id, d]));\n const scenario = scenarioId ? bundle.scenarios?.find((s) => s.id === scenarioId) : undefined;\n for (const d of scenario?.definitions ?? []) byId.set(d.id, d);\n const root = scenario?.root ?? byId.get(bundle.root);\n if (!root) throw new Error(`bundle root \"${bundle.root}\" is not among its definitions`);\n return { root, lookup: (id) => byId.get(id) };\n}\n\n/** Definitions reachable from a root (children and harness children, recursively). */\nexport function reachableDefinitions(root: ModuleDef, lookup: ModuleLookup): ModuleDef[] {\n const out = new Map<string, ModuleDef>([[root.id, root]]);\n const walk = (d: ModuleDef) => {\n for (const c of d.children ?? []) {\n const child = lookup(c.moduleDefId);\n if (child && !out.has(child.id)) {\n out.set(child.id, child);\n walk(child);\n }\n }\n };\n walk(root);\n return [...out.values()];\n}\n","/**\n * UHD bundle: the neutral, self-contained form of a system for tools that\n * only read UHD (the UHD viewer first). A root, every definition it\n * references, optional named variants, and per-definition artifact bases.\n * Producers (a build tool, a library script, a hand-written file)\n * resolve origins before writing it; consumers need nothing else.\n */\nimport type { ModuleDef } from \"./module.js\";\n\nexport const UHD_BUNDLE_SCHEMA = \"uhd.bundle/v0\";\n\nexport interface UhdBundleScenario {\n id: string;\n label: string;\n description?: string;\n /** A variant root definition (replaces the bundle root for this scenario). */\n root?: ModuleDef;\n /** Definitions that replace (by id) or add to the bundle's for this scenario. */\n definitions?: ModuleDef[];\n}\n\nexport interface UhdBundleDiagnostic {\n code: string;\n severity: \"error\" | \"warning\" | \"info\";\n message: string;\n /** What it is about: an instance path, link id, definition id… */\n entity?: { kind: string; id: string };\n source?: { file: string; line?: number };\n /** Who produced it (e.g. \"my-tool/fit-check\", \"uhd/checkSystem\"). */\n validator?: string;\n}\n\nexport interface UhdBundle {\n schema: typeof UHD_BUNDLE_SCHEMA;\n /** Id of the root definition. */\n root: string;\n /** The root and every definition it references (children, harness children). */\n definitions: ModuleDef[];\n /**\n * Base that each definition's relative artifact paths resolve against:\n * definition id → absolute path or URL prefix. Missing: relative to the\n * bundle's own location.\n */\n artifactBases?: Record<string, string>;\n scenarios?: UhdBundleScenario[];\n /** Findings from the producer (a consumer may add its own UHD checks). */\n diagnostics?: UhdBundleDiagnostic[];\n /**\n * Presentation hints keyed by instance path (layout, labels, placement\n * hints, appearance). Opaque to UHD: never topology.\n */\n display?: Record<string, unknown>;\n meta?: { name?: string; producer?: string; producerVersion?: string };\n}\n","/**\n * Protocol role pair compatibility table.\n *\n * Generic pairs apply to any protocol type unless overridden\n * by protocol-specific entries.\n */\n\nconst GENERIC_ROLE_PAIRS: Record<string, string[]> = {\n input: [\"output\"],\n output: [\"input\"],\n bidirectional: [\"input\", \"output\", \"bidirectional\"],\n master: [\"slave\"],\n slave: [\"master\"],\n host: [\"device\", \"peripheral\"],\n device: [\"host\", \"controller\"],\n peripheral: [\"host\", \"controller\"],\n controller: [\"device\", \"peripheral\"],\n source: [\"sink\"],\n sink: [\"source\"],\n transmitter: [\"receiver\"],\n receiver: [\"transmitter\"],\n transceiver: [\"transmitter\", \"receiver\", \"transceiver\"],\n peer: [\"peer\"],\n primary: [\"secondary\"],\n secondary: [\"primary\"],\n target: [\"controller\", \"source\", \"master\", \"host\"],\n};\n\n/**\n * Protocol-specific role pair overrides.\n * Only needed when the generic pairs are wrong or insufficient.\n */\n/** MIPI CSI-2 / DSI sub-roles: transmitter → receiver, clock and data lanes. */\nfunction MIPI_ROLES(): Record<string, string[]> {\n return {\n transmitter: [\"receiver\"],\n receiver: [\"transmitter\"],\n clock_tx_p: [\"clock_rx_p\"],\n clock_tx_n: [\"clock_rx_n\"],\n clock_rx_p: [\"clock_tx_p\"],\n clock_rx_n: [\"clock_tx_n\"],\n data_tx_p: [\"data_rx_p\"],\n data_tx_n: [\"data_rx_n\"],\n data_rx_p: [\"data_tx_p\"],\n data_rx_n: [\"data_tx_n\"],\n };\n}\n\nconst PROTOCOL_ROLE_PAIRS: Record<string, Record<string, string[]>> = {\n i2c: {\n master: [\"slave\"],\n slave: [\"master\"],\n // Sub-roles for slot matching within composed interfaces\n data: [\"data\"],\n clock: [\"clock\"],\n },\n spi: {\n master: [\"slave\"],\n slave: [\"master\"],\n data_out: [\"data_in\"],\n data_in: [\"data_out\"],\n clock: [\"clock\"],\n select: [\"select\"],\n },\n uart: {\n host: [\"device\"],\n device: [\"host\"],\n transmitter: [\"receiver\"],\n receiver: [\"transmitter\"],\n transceiver: [\"transmitter\", \"receiver\", \"transceiver\"],\n },\n power: {\n input: [\"output\"],\n output: [\"input\"],\n ground: [\"ground\"],\n },\n bolt_pattern: {\n structure: [\"component\"],\n component: [\"structure\"],\n },\n // a passive terminal joined to another by a conductor (an LED's anode soldered to a\n // board pad): on a board net, terminals still pair with nothing (system/derive.ts)\n passive: {\n terminal: [\"terminal\"],\n },\n motor_control: {\n controller: [\"target\"],\n target: [\"controller\"],\n source: [\"target\"],\n },\n // Stepper windings (StepperPhases). Older parts used driver/motor; they\n // pair with the output/input roles the builder emits.\n bipolar_stepper_phases: {\n output: [\"input\", \"motor\"],\n input: [\"output\", \"driver\"],\n driver: [\"motor\", \"input\"],\n motor: [\"driver\", \"output\"],\n },\n // CAN bus side (CAN): every node on the bus pairs with every other. Older\n // parts declared the bus as \"transceiver\" or \"peer\"; they are the same family.\n can: {\n node: [\"node\", \"transceiver\", \"peer\"],\n transceiver: [\"node\", \"transceiver\", \"peer\"],\n peer: [\"node\", \"transceiver\", \"peer\"],\n },\n can_signal: {\n node: [\"node\"],\n },\n // CAN logic side (CANLogic): a CAN controller's TX/RX to a transceiver's TXD/RXD.\n can_logic: {\n controller: [\"transceiver\"],\n transceiver: [\"controller\"],\n },\n // Fluid ports (FluidPort): flow goes from a source to a sink; fittings,\n // tubing and passthrough ports are bidirectional; a gauge or transducer\n // senses pressure where it is plumbed in.\n pneumatic: {\n source: [\"sink\", \"bidirectional\", \"sensing\"],\n sink: [\"source\", \"bidirectional\"],\n bidirectional: [\"source\", \"sink\", \"bidirectional\", \"sensing\"],\n sensing: [\"source\", \"bidirectional\"],\n },\n hydraulic: {\n source: [\"sink\", \"bidirectional\", \"sensing\"],\n sink: [\"source\", \"bidirectional\"],\n bidirectional: [\"source\", \"sink\", \"bidirectional\", \"sensing\"],\n sensing: [\"source\", \"bidirectional\"],\n }, // ---- Links. Each composite's slots carry a sub-role per conductor,\n // so ports pair conductor by conductor and nothing else.\n // PCIe: a root (root port, switch downstream port, host side of a slot) with\n // an endpoint (card, SSD, switch upstream port). Lanes TX→RX, clock, sideband.\n pcie: {\n root: [\"endpoint\"],\n endpoint: [\"root\"],\n tx_p: [\"rx_p\"],\n tx_n: [\"rx_n\"],\n rx_p: [\"tx_p\"],\n rx_n: [\"tx_n\"],\n refclk_out_p: [\"refclk_in_p\"],\n refclk_out_n: [\"refclk_in_n\"],\n refclk_in_p: [\"refclk_out_p\"],\n refclk_in_n: [\"refclk_out_n\"],\n perst_out: [\"perst_in\"],\n perst_in: [\"perst_out\"],\n clkreq_out: [\"clkreq_in\"],\n clkreq_in: [\"clkreq_out\"],\n wake_out: [\"wake_in\"],\n wake_in: [\"wake_out\"],\n },\n pcie_lane: {\n transmitter: [\"receiver\"],\n receiver: [\"transmitter\"],\n },\n // M.2: a socket takes a card.\n m2: {\n socket: [\"card\"],\n card: [\"socket\"],\n },\n // MIPI CSI-2 and DSI: transmitter → receiver, clock to clock, data lane to data lane.\n mipi_csi2: MIPI_ROLES(),\n mipi_dsi: MIPI_ROLES(),\n mipi_dphy: {\n transmitter: [\"receiver\"],\n receiver: [\"transmitter\"],\n },\n // Ethernet: any two ports link (auto MDI-X or the cable crosses the pairs).\n ethernet: {\n port: [\"port\"],\n mdi_p: [\"mdi_p\"],\n mdi_n: [\"mdi_n\"],\n },\n ethernet_mdi: {\n bidirectional: [\"bidirectional\"],\n },\n sfp: {\n cage: [\"module\"],\n module: [\"cage\"],\n },\n // I2S / PCM: the clock controller with a clock target (older parts said\n // master / slave); BCLK and WS out to in (or a port that can be either);\n // data out to data in; MCLK out to in.\n i2s: {\n controller: [\"target\", \"slave\"],\n target: [\"controller\", \"master\"],\n master: [\"slave\", \"target\"],\n slave: [\"master\", \"controller\"],\n bclk_out: [\"bclk_in\", \"bclk_io\"],\n bclk_in: [\"bclk_out\", \"bclk_io\"],\n bclk_io: [\"bclk_out\", \"bclk_in\", \"bclk_io\"],\n ws_out: [\"ws_in\", \"ws_io\"],\n ws_in: [\"ws_out\", \"ws_io\"],\n ws_io: [\"ws_out\", \"ws_in\", \"ws_io\"],\n dout_out: [\"din_in\"],\n din_in: [\"dout_out\"],\n mclk_out: [\"mclk_in\"],\n mclk_in: [\"mclk_out\"],\n },\n // DVP parallel camera bus: the camera drives data, PCLK, VSYNC and HREF; the host may drive XCLK.\n dvp: {\n camera: [\"host\"],\n host: [\"camera\"],\n data_out: [\"data_in\"],\n data_in: [\"data_out\"],\n pclk_out: [\"pclk_in\"],\n pclk_in: [\"pclk_out\"],\n vsync_out: [\"vsync_in\"],\n vsync_in: [\"vsync_out\"],\n href_out: [\"href_in\"],\n href_in: [\"href_out\"],\n xclk_out: [\"xclk_in\"],\n xclk_in: [\"xclk_out\"],\n },\n // SD: the host (slot, SDMMC peripheral) clocks the card.\n sd_card: {\n host: [\"card\"],\n card: [\"host\"],\n clk_out: [\"clk_in\"],\n clk_in: [\"clk_out\"],\n cmd: [\"cmd\"],\n dat: [\"dat\"],\n },\n // LED drive: a sinking driver channel to an LED's cathode, a sourcing one to its anode.\n led_drive: {\n sink: [\"cathode\"],\n cathode: [\"sink\"],\n source: [\"anode\"],\n anode: [\"source\"],\n },\n // USB: host with device; a dual-role port with either. Older parts used\n // \"bidirectional\" for a port that can be either.\n usb: {\n host: [\"device\", \"dual_role\", \"bidirectional\"],\n device: [\"host\", \"dual_role\", \"bidirectional\"],\n dual_role: [\"host\", \"device\", \"dual_role\", \"bidirectional\"],\n bidirectional: [\"host\", \"device\", \"dual_role\", \"bidirectional\"],\n d_p: [\"d_p\"],\n d_n: [\"d_n\"],\n sstx_p: [\"ssrx_p\"],\n sstx_n: [\"ssrx_n\"],\n ssrx_p: [\"sstx_p\"],\n ssrx_n: [\"sstx_n\"],\n cc: [\"cc\"],\n },\n usb_signal: {\n transmitter: [\"receiver\"],\n receiver: [\"transmitter\"],\n bidirectional: [\"bidirectional\"],\n },\n // Wireless (network domain).\n wifi: {\n client: [\"access_point\"],\n access_point: [\"client\"],\n peer: [\"peer\"],\n },\n bluetooth: {\n central: [\"peripheral\", \"peer\"],\n peripheral: [\"central\", \"peer\"],\n peer: [\"peer\", \"central\", \"peripheral\"],\n broadcaster: [\"observer\"],\n observer: [\"broadcaster\"],\n },\n ieee802154: {\n node: [\"node\"],\n },\n // ---- Mechanical: drive train, bearings, threads, tracks, wheels.\n gear_mesh: {\n mesh: [\"mesh\"],\n },\n bearing_fit: {\n bearing: [\"seat\"],\n seat: [\"bearing\"],\n },\n thread: {\n external: [\"internal\"],\n internal: [\"external\"],\n },\n t_slot: {\n track: [\"insert\"],\n insert: [\"track\"],\n },\n axial_stop: {\n face: [\"face\"],\n },\n rolling_contact: {\n wheel: [\"surface\"],\n surface: [\"wheel\"],\n },\n // ---- Serial links, IR, mains and coils.\n // RS-485: every node on the bus; half duplex A to A and B to B, full\n // duplex one side's driver pair (Y/Z) to the other's receiver pair (A/B).\n rs485: {\n node: [\"node\"],\n a: [\"a\"],\n b: [\"b\"],\n tx_p: [\"rx_p\"],\n tx_n: [\"rx_n\"],\n rx_p: [\"tx_p\"],\n rx_n: [\"tx_n\"],\n ground: [\"ground\"],\n },\n rs485_signal: {\n line: [],\n },\n // RS-232: DTE with DCE straight through; two DTEs (or two DCEs) through a\n // null modem, which crosses TXD/RXD, RTS/CTS and DTR/DSR (rs232_null_modem warns).\n rs232: {\n dte: [\"dce\", \"dte\"],\n dce: [\"dte\", \"dce\"],\n txd_out: [\"txd_in\", \"rxd_in\"],\n txd_in: [\"txd_out\", \"rxd_out\"],\n rxd_out: [\"rxd_in\", \"txd_in\"],\n rxd_in: [\"rxd_out\", \"txd_out\"],\n rts_out: [\"rts_in\", \"cts_in\"],\n rts_in: [\"rts_out\", \"cts_out\"],\n cts_out: [\"cts_in\", \"rts_in\"],\n cts_in: [\"cts_out\", \"rts_out\"],\n dtr_out: [\"dtr_in\", \"dsr_in\"],\n dtr_in: [\"dtr_out\", \"dsr_out\"],\n dsr_out: [\"dsr_in\", \"dtr_in\"],\n dsr_in: [\"dsr_out\", \"dtr_out\"],\n dcd_out: [\"dcd_in\"],\n dcd_in: [\"dcd_out\"],\n ri_out: [\"ri_in\"],\n ri_in: [\"ri_out\"],\n ground: [\"ground\"],\n },\n // SWD: a probe debugs a target. Older parts gave the target leaves role\n // \"target\", which the generic table pairs with host and controller.\n swd: {\n probe: [\"target\"],\n target: [\"probe\"],\n swdio: [\"swdio\"],\n swclk_out: [\"swclk_in\"],\n swclk_in: [\"swclk_out\"],\n swo_out: [\"swo_in\"],\n swo_in: [\"swo_out\"],\n nreset_out: [\"nreset_in\"],\n nreset_in: [\"nreset_out\"],\n vtref_out: [\"vtref_in\"],\n vtref_in: [\"vtref_out\"],\n ground: [\"ground\"],\n },\n ppm: {\n output: [\"input\"],\n input: [\"output\"],\n signal_out: [\"signal_in\"],\n signal_in: [\"signal_out\"],\n },\n ir_remote: {\n transmitter: [\"receiver\"],\n receiver: [\"transmitter\"],\n },\n ac_power: {\n input: [\"output\"],\n output: [\"input\"],\n line: [\"line\"],\n neutral: [\"neutral\"],\n earth: [\"earth\"],\n },\n ac_terminal: {\n terminal: [],\n },\n inductive_load: {\n driver: [\"load\"],\n load: [\"driver\"],\n drive_plus: [\"coil_plus\"],\n coil_plus: [\"drive_plus\"],\n drive_minus: [\"coil_minus\"],\n coil_minus: [\"drive_minus\"],\n },\n inductive_terminal: {\n terminal: [],\n },\n // Piezo loads (PiezoLoad, PiezoDrive): a driver output with the element it\n // drives, terminal by terminal; outputs and elements pair in order.\n piezo_drive: {\n driver: [\"load\"],\n load: [\"driver\"],\n drive_plus: [\"element_plus\"],\n element_plus: [\"drive_plus\"],\n drive_minus: [\"element_minus\"],\n element_minus: [\"drive_minus\"],\n },\n piezo_terminal: {\n terminal: [],\n },\n // Battery charge ports (ChargePort): a charger's battery terminals with\n // the battery it charges. Separate from `power`, where two outputs never pair.\n battery_charge: {\n charger: [\"battery\"],\n battery: [\"charger\"],\n charge_plus: [\"battery_plus\"],\n battery_plus: [\"charge_plus\"],\n charge_minus: [\"battery_minus\"],\n battery_minus: [\"charge_minus\"],\n },\n};\n\n/**\n * Protocols whose role table is complete: the generic pairs do not apply.\n * (Without this, two CAN transceivers' logic sides would pair through the\n * generic transceiver ↔ transceiver entry.)\n */\nconst NO_GENERIC_FALLBACK = new Set([\n \"can_logic\",\n \"pneumatic\",\n \"hydraulic\",\n \"pcie\",\n \"pcie_lane\",\n \"m2\",\n \"mipi_csi2\",\n \"mipi_dsi\",\n \"mipi_dphy\",\n \"ethernet\",\n \"ethernet_mdi\",\n \"sfp\",\n \"i2s\",\n \"dvp\",\n \"sd_card\",\n \"led_drive\",\n \"wifi\",\n \"bluetooth\",\n \"ieee802154\",\n \"gear_mesh\",\n \"bearing_fit\",\n \"thread\",\n \"t_slot\",\n \"axial_stop\",\n \"rolling_contact\",\n \"rs485\",\n \"rs485_signal\",\n \"rs232\",\n \"ppm\",\n \"ir_remote\",\n \"ac_power\",\n \"ac_terminal\",\n \"inductive_load\",\n \"inductive_terminal\",\n \"piezo_drive\",\n \"piezo_terminal\",\n \"battery_charge\",\n]);\n\n/**\n * Check whether two roles are compatible for a given protocol type.\n * Uses protocol-specific pairs first, falls back to generic pairs.\n */\nexport function areRolesCompatible(\n protocolType: string,\n roleA: string,\n roleB: string,\n): boolean {\n const normalA = roleA.toLowerCase();\n const normalB = roleB.toLowerCase();\n\n if (normalA === normalB && normalA === \"peer\") return true;\n if (normalA === normalB && normalA === \"bidirectional\") return true;\n\n // Check protocol-specific pairs\n const protocolPairs = PROTOCOL_ROLE_PAIRS[protocolType.toLowerCase()];\n if (protocolPairs) {\n const compatA = protocolPairs[normalA];\n if (compatA?.includes(normalB)) return true;\n\n const compatB = protocolPairs[normalB];\n if (compatB?.includes(normalA)) return true;\n }\n\n if (NO_GENERIC_FALLBACK.has(protocolType.toLowerCase())) return false;\n\n // Fall back to generic pairs\n const genericA = GENERIC_ROLE_PAIRS[normalA];\n if (genericA?.includes(normalB)) return true;\n\n const genericB = GENERIC_ROLE_PAIRS[normalB];\n if (genericB?.includes(normalA)) return true;\n\n return false;\n}\n\n/**\n * Return all roles compatible with the given role under a protocol type.\n */\nexport function getCompatibleRoles(\n protocolType: string,\n role: string,\n): string[] {\n const normal = role.toLowerCase();\n const result = new Set<string>();\n\n const protocolPairs = PROTOCOL_ROLE_PAIRS[protocolType.toLowerCase()];\n if (protocolPairs?.[normal]) {\n for (const r of protocolPairs[normal]) result.add(r);\n }\n\n if (GENERIC_ROLE_PAIRS[normal] && !NO_GENERIC_FALLBACK.has(protocolType.toLowerCase())) {\n for (const r of GENERIC_ROLE_PAIRS[normal]) result.add(r);\n }\n\n return [...result];\n}\n","import type { InterfaceDef, ProtocolDef } from \"../types/interface.js\";\nimport { areRolesCompatible } from \"./roles.js\";\n\nexport interface ProtocolMatchResult {\n compatible: boolean;\n confidence: number; // 1.0 = explicit match, 0.0 = no match\n matchedProtocol?: string;\n roleA?: string;\n roleB?: string;\n}\n\n/**\n * Try to match two protocol definitions.\n * Returns the best match if any role pair is compatible.\n */\nfunction matchProtocolDefs(a: ProtocolDef, b: ProtocolDef): ProtocolMatchResult {\n if (a.type.toLowerCase() !== b.type.toLowerCase()) {\n return { compatible: false, confidence: 0 };\n }\n\n // Try all role combinations\n for (const roleA of a.roles) {\n for (const roleB of b.roles) {\n if (areRolesCompatible(a.type, roleA, roleB)) {\n return {\n compatible: true,\n confidence: 1.0,\n matchedProtocol: a.type,\n roleA,\n roleB,\n };\n }\n }\n }\n\n return { compatible: false, confidence: 0 };\n}\n\n/**\n * Match two interfaces by finding the best protocol match.\n * Tries all protocol combinations between the two interfaces.\n */\nexport function matchProtocols(\n interfaceA: InterfaceDef,\n interfaceB: InterfaceDef,\n): ProtocolMatchResult {\n let best: ProtocolMatchResult = { compatible: false, confidence: 0 };\n\n for (const protoA of interfaceA.protocols) {\n for (const protoB of interfaceB.protocols) {\n const result = matchProtocolDefs(protoA, protoB);\n if (result.compatible && result.confidence > best.confidence) {\n best = result;\n }\n }\n }\n\n return best;\n}\n","import type { ModuleDef } from \"../types/module.js\";\nimport type { InterfaceDef, InterfaceProfile } from \"../types/interface.js\";\nimport type { RegionPath } from \"./types.js\";\n\n/**\n * A module's interfaces as a region tree (visualizer-spec §2.2). An interface\n * bound into another interface's active profile is a child region of it; every\n * other exposed interface is a root region.\n */\nexport interface RegionNode {\n iface: InterfaceDef;\n path: RegionPath;\n depth: number;\n parent?: RegionNode;\n children: RegionNode[];\n /** slot the parent's profile binds this region to (undefined at roots) */\n slotId?: string;\n}\n\n/** The profile whose bindings define the region tree: first default-active, else first. */\nexport function pickProfile(iface: InterfaceDef): InterfaceProfile | undefined {\n const profiles = iface.profiles ?? [];\n return profiles.find((p) => p.default_active !== false) ?? profiles[0];\n}\n\nfunction bindingTargets(profile: InterfaceProfile): { slotId: string; interfaceId: string }[] {\n const out: { slotId: string; interfaceId: string }[] = [];\n for (const [slotId, value] of Object.entries(profile.bindings)) {\n for (const interfaceId of Array.isArray(value) ? value : [value]) {\n out.push({ slotId, interfaceId });\n }\n }\n return out;\n}\n\nexport function buildRegionTree(module: ModuleDef): RegionNode[] {\n const byId = new Map(module.interfaces.map((i) => [i.id, i]));\n\n const boundIds = new Set<string>();\n for (const iface of module.interfaces) {\n const profile = pickProfile(iface);\n if (!profile) continue;\n for (const { interfaceId } of bindingTargets(profile)) boundIds.add(interfaceId);\n }\n\n const build = (\n iface: InterfaceDef,\n parent: RegionNode | undefined,\n slotId: string | undefined,\n visited: Set<string>,\n ): RegionNode => {\n const node: RegionNode = {\n iface,\n path: [...(parent?.path ?? []), iface.id],\n depth: parent ? parent.depth + 1 : 0,\n parent,\n children: [],\n slotId,\n };\n const profile = pickProfile(iface);\n if (profile) {\n for (const target of bindingTargets(profile)) {\n if (visited.has(target.interfaceId)) continue; // guard against binding cycles\n const child = byId.get(target.interfaceId);\n if (!child) continue;\n node.children.push(\n build(child, node, target.slotId, new Set([...visited, target.interfaceId])),\n );\n }\n }\n return node;\n };\n\n return module.interfaces\n .filter((i) => i.exposed && !boundIds.has(i.id))\n .map((i) => build(i, undefined, undefined, new Set([i.id])));\n}\n\nexport function flattenTree(roots: RegionNode[]): RegionNode[] {\n const out: RegionNode[] = [];\n const walk = (node: RegionNode) => {\n out.push(node);\n node.children.forEach(walk);\n };\n roots.forEach(walk);\n return out;\n}\n\nexport function descendants(node: RegionNode): RegionNode[] {\n const out: RegionNode[] = [];\n const walk = (n: RegionNode) => {\n for (const child of n.children) {\n out.push(child);\n walk(child);\n }\n };\n walk(node);\n return out;\n}\n\nexport function ancestors(node: RegionNode): RegionNode[] {\n const out: RegionNode[] = [];\n let current = node.parent;\n while (current) {\n out.push(current);\n current = current.parent;\n }\n return out;\n}\n","import type { Parameter } from \"../types/parameter.js\";\n\n/**\n * Get the effective range of a parameter, considering value, range, and tolerance.\n * Returns [min, max] or null if no range can be determined.\n */\nexport function getEffectiveRange(param: Parameter): [number, number] | null {\n if (param.range) {\n return param.range;\n }\n\n if (param.value !== undefined) {\n if (param.tolerance === undefined) {\n // Exact value, no tolerance — treat as point range\n return [param.value, param.value];\n }\n\n if (typeof param.tolerance === \"number\") {\n // Absolute tolerance\n return [param.value - param.tolerance, param.value + param.tolerance];\n }\n\n if (param.tolerance.type === \"absolute\") {\n return [\n param.value - param.tolerance.value,\n param.value + param.tolerance.value,\n ];\n }\n\n if (param.tolerance.type === \"percent\") {\n const delta = param.value * (param.tolerance.value / 100);\n return [param.value - delta, param.value + delta];\n }\n }\n\n return null;\n}\n\n/**\n * Check if two numeric ranges overlap.\n */\nexport function rangesOverlap(\n a: [number, number],\n b: [number, number],\n): boolean {\n return a[0] <= b[1] && b[0] <= a[1];\n}\n\nexport interface ParameterCompatibilityResult {\n compatible: boolean;\n reason?: string;\n rangeA?: [number, number];\n rangeB?: [number, number];\n}\n\n/**\n * Check if two parameters are compatible (their ranges overlap).\n * Parameters must have the same unit for comparison to be meaningful.\n */\nexport function parameterCompatible(\n paramA: Parameter,\n paramB: Parameter,\n): ParameterCompatibilityResult {\n if (paramA.unit !== paramB.unit) {\n return {\n compatible: false,\n reason: `Unit mismatch: \"${paramA.unit}\" vs \"${paramB.unit}\"`,\n };\n }\n\n const rangeA = getEffectiveRange(paramA);\n const rangeB = getEffectiveRange(paramB);\n\n if (!rangeA || !rangeB) {\n // Can't determine range for one or both — assume compatible\n return { compatible: true };\n }\n\n const overlap = rangesOverlap(rangeA, rangeB);\n\n return {\n compatible: overlap,\n rangeA,\n rangeB,\n reason: overlap\n ? undefined\n : `Range [${rangeA[0]}, ${rangeA[1]}] does not overlap [${rangeB[0]}, ${rangeB[1]}] ${paramA.unit}`,\n };\n}\n\n/**\n * Check parameter compatibility between two interfaces by matching parameter IDs.\n */\nexport function checkParameterCompatibility(\n paramsA: Parameter[],\n paramsB: Parameter[],\n): ParameterCompatibilityResult[] {\n const results: ParameterCompatibilityResult[] = [];\n\n for (const pA of paramsA) {\n const pB = paramsB.find((p) => p.id === pA.id);\n if (!pB) continue; // No matching parameter — skip\n\n results.push(parameterCompatible(pA, pB));\n }\n\n return results;\n}\n","import type { Parameter } from \"../types/parameter.js\";\nimport { getEffectiveRange, rangesOverlap } from \"../parameters/range.js\";\nimport type { Diagnostic } from \"./types.js\";\n\n/**\n * Parameters whose semantics are aggregation (sum of draws vs. a limit), not\n * range overlap — comparing a supply's max_current to a sink's draw as ranges\n * produces false errors. These are evaluated by the capacity engine (Phase 6,\n * scoped rule packs) or by a directional pair check in joint-check.ts\n * (`supply_current_rating`, `linear_motion_capacity`), so the pairwise\n * overlap check skips them.\n */\nexport const CAPACITY_PARAM_IDS = new Set([\n \"max_current\",\n \"burst_current\",\n \"drive_current\",\n \"current_draw\",\n \"min_supply_power\",\n \"min_supply_current\",\n \"stroke\",\n \"force\",\n \"linear_speed\",\n \"max_flow\",\n \"flow_rate\",\n \"load_rating\",\n \"coil_current\",\n]);\n\n/** SI-prefix normalization so 40 mA and 0.04 A compare in the same base unit. */\nconst UNIT_SCALE: Record<string, { base: string; scale: number }> = {\n mA: { base: \"A\", scale: 1e-3 },\n µA: { base: \"A\", scale: 1e-6 },\n uA: { base: \"A\", scale: 1e-6 },\n mV: { base: \"V\", scale: 1e-3 },\n kV: { base: \"V\", scale: 1e3 },\n kHz: { base: \"Hz\", scale: 1e3 },\n MHz: { base: \"Hz\", scale: 1e6 },\n GHz: { base: \"Hz\", scale: 1e9 },\n ms: { base: \"s\", scale: 1e-3 },\n µs: { base: \"s\", scale: 1e-6 },\n us: { base: \"s\", scale: 1e-6 },\n mm: { base: \"m\", scale: 1e-3 },\n kΩ: { base: \"Ω\", scale: 1e3 },\n MΩ: { base: \"Ω\", scale: 1e6 },\n kPa: { base: \"Pa\", scale: 1e3 },\n bar: { base: \"Pa\", scale: 1e5 },\n mW: { base: \"W\", scale: 1e-3 },\n kW: { base: \"W\", scale: 1e3 },\n};\n\nfunction normalized(param: Parameter): { base: string; range: [number, number] | null } {\n const scale = UNIT_SCALE[param.unit as string];\n const range = getEffectiveRange(param);\n if (!scale) return { base: param.unit as string, range };\n return {\n base: scale.base,\n range: range ? [range[0] * scale.scale, range[1] * scale.scale] : null,\n };\n}\n\n/**\n * Pairwise parameter check between two matched regions: for every parameter id\n * present on both sides (excluding capacity-semantics params), the effective\n * ranges must overlap in a common base unit.\n */\nexport function checkPairParameters(\n paramsA: Parameter[] | undefined,\n paramsB: Parameter[] | undefined,\n): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n\n for (const pA of paramsA ?? []) {\n if (CAPACITY_PARAM_IDS.has(pA.id)) continue;\n const pB = (paramsB ?? []).find((p) => p.id === pA.id);\n if (!pB) continue;\n\n const nA = normalized(pA);\n const nB = normalized(pB);\n\n if (nA.base !== nB.base) {\n diagnostics.push({\n severity: \"error\",\n code: \"param_unit_mismatch\",\n message: `${pA.id}: unit \"${pA.unit}\" is not comparable with \"${pB.unit}\"`,\n refs: [pA.id],\n });\n continue;\n }\n if (!nA.range || !nB.range) continue; // no determinable range — not checkable\n\n if (!rangesOverlap(nA.range, nB.range)) {\n diagnostics.push({\n severity: \"error\",\n code: \"param_range_disjoint\",\n message: `${pA.id}: ${fmtParam(pA)} vs ${fmtParam(pB)} (ranges do not overlap)`,\n refs: [pA.id],\n });\n }\n }\n\n return diagnostics;\n}\n\n/** A parameter in its own unit, e.g. \"30.5 mm\" or \"18–25.2 V\". */\nfunction fmtParam(param: Parameter): string {\n const range = getEffectiveRange(param);\n const unit = param.unit === \"dimensionless\" ? \"\" : ` ${param.unit}`;\n if (!range) return `?${unit}`;\n return range[0] === range[1] ? `${range[0]}${unit}` : `${range[0]}–${range[1]}${unit}`;\n}\n","import type { InterfaceDef } from \"../types/interface.js\";\nimport type { Parameter } from \"../types/parameter.js\";\nimport {\n angularPitchDeg,\n fastenerDiameterMm,\n forceN,\n holeCount,\n holePitchMm,\n holeSpacingMm,\n keyWidthMm,\n leadMm,\n linearSpeedMmS,\n shaftDiameterMm,\n slotLengthMm,\n strokeMm,\n threadPitchMm,\n} from \"./params.js\";\n\n/**\n * Mechanical interface builders: bolt patterns, rotating shafts and bores,\n * and linear motion.\n *\n * Mating features pair by role and their parameters must overlap:\n * a 30.5 mm stack pattern does not accept a 20 mm board, and an M3 pattern\n * does not accept M2 fasteners. The pair checks in `drc/joint-check.ts`\n * compare what parameters cannot: bolt pattern shapes, shaft profiles and\n * genders, and linear travel and force (docs/mechanical-interfaces.md).\n */\n\n/** \"structure\" = frame / plate providing the holes; \"component\" = part mounted to it. */\nexport type BoltPatternRole = \"structure\" | \"component\";\n\nexport interface BoltPatternConfig {\n id: string;\n name?: string;\n role: BoltPatternRole;\n /**\n * \"cross\": four holes on two perpendicular diagonals of different\n * lengths, as on motor bases (\"16 × 19\"): one pair `spacingMm` apart on x,\n * the other `spacingYmm` apart on y. A cross mates another cross; one\n * with equal diagonals d also mates a 4-hole circle of diameter d or a\n * square of side d/√2, which have the same holes.\n *\n * \"row\": `holeCount` holes in a straight line, `pitchMm` apart (a\n * bracket leg or a channel on a hole grid). hole_spacing is the span from\n * the first hole to the last. A row mates a row whose holes land on its\n * own (same pitch or a whole multiple of it, no longer than it), or a\n * slot at least as long as the row.\n *\n * \"slot\": a straight slot that takes fasteners anywhere along\n * `slotLengthMm` (an extrusion's T-slot, a slotted bracket). It mates a\n * row, a two-hole rectangle on a line (spacingYmm 0) that fits its length,\n * or another slot when one of them is a through slot. A slot has no fixed\n * holes. For holes slotted so their spacing can vary, keep the shape and\n * give spacingMm a range instead.\n *\n * \"grid\": holes on every point of a lattice (a plate, a channel or a gear\n * web drilled on a hole grid). `lattice` \"rectangular\" (rows `pitchYmm`\n * apart, columns `pitchMm` apart) or \"triangular\" (every hole six\n * neighbours `pitchMm` away: rows pitch × √3/2 apart, every other row\n * offset by half a pitch; one grid line along x). The extent is `rows` ×\n * `columns`, centred on the frame, or a disc: every lattice point within\n * `withinDiameterMm` of the frame origin (a lattice point) and outside\n * `minDiameterMm` (a hub or bore). The hole count is derived; give\n * `holeCount` to have the builder confirm it. A grid mates any pattern\n * whose holes all land on its points (`bolt_pattern_holes`): a row along a\n * grid line, a square on the grid, a six-hole circle of diameter 2 ×\n * pitch on a triangular grid. Fasteners through one line of a grid fit a\n * slot.\n *\n * \"arc\": a partial bolt circle: `holeCount` holes on a circle of diameter\n * `spacingMm`, `angularPitchDeg` apart, the first at `startAngleDeg` from\n * the frame's x axis (counter-clockwise about the normal): five of six\n * positions drilled (start −30°, pitch 60°) or four (0°, 60°, 120°,\n * 180°). An arc mates a full circle whose holes include its own, an arc\n * or grid that has its holes, or a pattern whose holes are among its own.\n */\n shape: \"square\" | \"rectangle\" | \"circle\" | \"cross\" | \"row\" | \"slot\" | \"grid\" | \"arc\";\n /**\n * Square side, rectangle X spacing, bolt-circle diameter, or the cross's\n * x diagonal, in mm. Required for those shapes; a row derives it (the\n * span, pitch × (holes − 1)) and a slot has none.\n * A [min, max] range models slotted holes accepting any spacing within it.\n */\n spacingMm?: number | [number, number];\n /** Rectangle Y spacing, or the cross's y diagonal, in mm. */\n spacingYmm?: number | [number, number];\n /** Row: hole-to-hole pitch in mm. Grid: the pitch along x (rectangular), or between neighbours (triangular). */\n pitchMm?: number;\n /** Rectangular grid: the pitch along y (between rows), when it is not `pitchMm`. */\n pitchYmm?: number;\n /** Grid: the lattice (default \"rectangular\"). */\n lattice?: \"rectangular\" | \"triangular\";\n /** Grid: number of rows (along y) and columns (along x), centred on the frame. */\n rows?: number;\n columns?: number;\n /** Grid: a disc extent instead of rows × columns: lattice points within this diameter of the origin. */\n withinDiameterMm?: number;\n /** Grid with a disc extent: leave out the points closer to the origin than half this (a hub). */\n minDiameterMm?: number;\n /** Arc: the angle between neighbouring holes, in degrees. */\n angularPitchDeg?: number;\n /** Arc: the first hole's angle from the frame's x axis, counter-clockwise, in degrees (default 0). */\n startAngleDeg?: number;\n /** Slot: the length along which fasteners can sit, in mm. */\n slotLengthMm?: number;\n /**\n * Slot: \"t_slot\" holds a nut or a screw head captive in a channel (an\n * extrusion); \"through\" is an open slot a fastener passes through (a\n * slotted bracket or plate).\n */\n slotKind?: \"t_slot\" | \"through\";\n /** Number of holes. Required except on a slot (any number of fasteners). */\n holeCount?: number;\n /** Fastener designation, e.g. \"M3\". */\n fastener: string;\n /** Nominal fastener diameter in mm (M3 → 3). A range for holes that take several sizes. */\n fastenerDiameterMm: number | [number, number];\n /** Holes are threaded (true) or clearance/through holes (false). */\n threaded?: boolean;\n /** Anything else the source states (grommets, countersink, slot length). */\n note?: string;\n maxInstances?: number;\n exposed?: boolean;\n defaultActive?: boolean;\n}\n\nexport function BoltPattern(config: BoltPatternConfig): InterfaceDef {\n const fail = (why: string): never => {\n throw new Error(`BoltPattern ${config.id}: ${why}`);\n };\n const gridFields = [\"pitchYmm\", \"lattice\", \"rows\", \"columns\", \"withinDiameterMm\", \"minDiameterMm\"] as const;\n if (config.shape !== \"grid\" && gridFields.some((k) => config[k] !== undefined)) fail(`${gridFields.filter((k) => config[k] !== undefined).join(\", \")}: for a grid`);\n if (config.shape !== \"arc\" && (config.angularPitchDeg !== undefined || config.startAngleDeg !== undefined)) fail(\"angularPitchDeg and startAngleDeg are for an arc\");\n if (config.shape === \"grid\" || config.shape === \"arc\") return holePatternInterface(config, fail);\n if (config.shape === \"cross\" && (config.spacingYmm === undefined || config.holeCount !== 4)) {\n fail(\"a cross pattern has four holes and needs spacingYmm (the second diagonal)\");\n }\n if (config.shape !== \"row\" && config.pitchMm !== undefined) fail(\"pitchMm is for a row or a grid\");\n if (config.shape !== \"slot\" && (config.slotLengthMm !== undefined || config.slotKind !== undefined)) fail(\"slotLengthMm and slotKind are for a slot\");\n\n const parameters: Parameter[] = [];\n if (config.shape === \"row\") {\n if (config.pitchMm === undefined || !(config.pitchMm > 0)) fail(\"a row needs pitchMm\");\n if (config.holeCount === undefined || config.holeCount < 2) fail(\"a row has two or more holes\");\n if (config.spacingMm !== undefined || config.spacingYmm !== undefined) fail(\"a row's span comes from pitchMm and holeCount; leave spacingMm and spacingYmm out\");\n const span = Number((config.pitchMm! * (config.holeCount! - 1)).toFixed(6));\n parameters.push(holeSpacingMm(span), holeCount(config.holeCount!), holePitchMm(config.pitchMm!));\n } else if (config.shape === \"slot\") {\n if (config.slotLengthMm === undefined || !(config.slotLengthMm > 0)) fail(\"a slot needs slotLengthMm\");\n if (config.spacingMm !== undefined || config.spacingYmm !== undefined) fail(\"a slot has no hole spacing; give slotLengthMm\");\n parameters.push(slotLengthMm(config.slotLengthMm!));\n if (config.holeCount !== undefined) parameters.push(holeCount(config.holeCount));\n } else {\n if (config.spacingMm === undefined) fail(`a ${config.shape} pattern needs spacingMm`);\n if (config.holeCount === undefined) fail(`a ${config.shape} pattern needs holeCount`);\n parameters.push(holeSpacingMm(config.spacingMm!), holeCount(config.holeCount!));\n }\n parameters.push(fastenerDiameterMm(config.fastenerDiameterMm));\n if (config.spacingYmm !== undefined) parameters.push(holeSpacingMm(config.spacingYmm, \"y\"));\n\n return {\n id: config.id,\n name: config.name,\n domain: \"mechanical\",\n exposed: config.exposed ?? true,\n default_active: config.defaultActive ?? true,\n protocols: [{ type: \"bolt_pattern\", roles: [config.role] }],\n capabilities: [\"bolt_pattern\"],\n parameters,\n ...(config.maxInstances !== undefined ? { max_instances: config.maxInstances } : {}),\n traits: [\n {\n type: \"bolt_pattern\",\n params: {\n shape: config.shape,\n fastener: config.fastener,\n ...(config.slotKind !== undefined ? { slot_kind: config.slotKind } : {}),\n ...(config.threaded !== undefined ? { threaded: config.threaded } : {}),\n ...(config.note !== undefined ? { note: config.note } : {}),\n },\n },\n ],\n };\n}\n\n/** Lattice description a grid's `bolt_pattern` trait carries; `latticeHoles` places its holes. */\nexport interface GridSpec {\n lattice: \"rectangular\" | \"triangular\";\n pitch: number;\n pitchY?: number;\n rows?: number;\n columns?: number;\n withinDiameter?: number;\n minDiameter?: number;\n}\n\nconst r6 = (v: number) => Number(v.toFixed(6)) + 0;\n\n/**\n * The holes of a grid in its frame's x/y, in mm: rows × columns centred on\n * the origin, or every lattice point (the origin is one) within the disc.\n * Rows run along x; a triangular lattice offsets every other row by half a\n * pitch, rows pitch × √3/2 apart.\n */\nexport function latticeHoles(g: GridSpec): [number, number][] {\n const tri = g.lattice === \"triangular\";\n const dy = tri ? (g.pitch * Math.sqrt(3)) / 2 : (g.pitchY ?? g.pitch);\n const out: [number, number][] = [];\n if (g.withinDiameter !== undefined) {\n const rMax = g.withinDiameter / 2 + 1e-6;\n const rMin = (g.minDiameter ?? 0) / 2 - 1e-6;\n const nj = Math.ceil(rMax / dy) + 1;\n const ni = Math.ceil(rMax / g.pitch) + 2;\n for (let j = -nj; j <= nj; j++) {\n for (let i = -ni - Math.abs(j); i <= ni + Math.abs(j); i++) {\n const x = g.pitch * i + (tri ? (g.pitch / 2) * j : 0);\n const y = dy * j;\n const r = Math.hypot(x, y);\n if (r <= rMax && r >= rMin) out.push([r6(x), r6(y)]);\n }\n }\n return out.sort((p, q) => p[1] - q[1] || p[0] - q[0]);\n }\n const rows = g.rows ?? 1;\n const cols = g.columns ?? 1;\n const shift = tri && rows > 1 ? g.pitch / 4 : 0; // centre the offset rows\n for (let j = 0; j < rows; j++) {\n for (let i = 0; i < cols; i++) {\n const off = tri && j % 2 === 1 ? g.pitch / 2 : 0;\n out.push([r6(-((cols - 1) * g.pitch) / 2 + i * g.pitch + off - shift), r6(-((rows - 1) * dy) / 2 + j * dy)]);\n }\n }\n return out;\n}\n\n/** The holes of a partial bolt circle in its frame's x/y, in mm. */\nexport function arcHoles(diameter: number, count: number, pitchDeg: number, startDeg = 0): [number, number][] {\n return Array.from({ length: count }, (_, k) => {\n const a = ((startDeg + k * pitchDeg) * Math.PI) / 180;\n return [r6((Math.cos(a) * diameter) / 2), r6((Math.sin(a) * diameter) / 2)] as [number, number];\n });\n}\n\nfunction holePatternInterface(config: BoltPatternConfig, fail: (why: string) => never): InterfaceDef {\n const parameters: Parameter[] = [];\n const params: Record<string, unknown> = { shape: config.shape, fastener: config.fastener };\n if (config.slotLengthMm !== undefined || config.slotKind !== undefined) fail(\"slotLengthMm and slotKind are for a slot\");\n if (config.spacingYmm !== undefined) fail(`a ${config.shape} has no spacingYmm`);\n if (config.shape === \"grid\") {\n const lattice = config.lattice ?? \"rectangular\";\n if (config.pitchMm === undefined || !(config.pitchMm > 0)) fail(\"a grid needs pitchMm\");\n if (config.spacingMm !== undefined) fail(\"a grid has no spacingMm; give pitchMm and the extent\");\n if (lattice === \"triangular\" && config.pitchYmm !== undefined) fail(\"a triangular grid has one pitch; leave pitchYmm out\");\n const disc = config.withinDiameterMm !== undefined;\n if (disc && (config.rows !== undefined || config.columns !== undefined)) fail(\"give rows and columns, or withinDiameterMm, not both\");\n if (!disc && (config.rows === undefined || config.columns === undefined)) fail(\"a grid needs rows and columns, or withinDiameterMm\");\n if (config.minDiameterMm !== undefined && !disc) fail(\"minDiameterMm is for a disc extent\");\n if (!disc && (config.rows! < 1 || config.columns! < 1 || !Number.isInteger(config.rows) || !Number.isInteger(config.columns))) fail(\"rows and columns are whole numbers from 1\");\n if (!disc && (config.rows === 1 || config.columns === 1)) fail(\"a grid of one row or one column is a row: use shape \\\"row\\\"\");\n const spec: GridSpec = {\n lattice,\n pitch: config.pitchMm!,\n ...(config.pitchYmm !== undefined ? { pitchY: config.pitchYmm } : {}),\n ...(disc ? { withinDiameter: config.withinDiameterMm! } : { rows: config.rows!, columns: config.columns! }),\n ...(config.minDiameterMm !== undefined ? { minDiameter: config.minDiameterMm } : {}),\n };\n const count = latticeHoles(spec).length;\n if (count < 2) fail(\"the extent holds fewer than two lattice points\");\n if (config.holeCount !== undefined && config.holeCount !== count) fail(`the lattice and extent give ${count} holes, not ${config.holeCount}`);\n parameters.push(holeCount(count), holePitchMm(config.pitchMm!));\n if (lattice === \"rectangular\") parameters.push(holePitchMm(config.pitchYmm ?? config.pitchMm!, \"y\"));\n params.lattice = lattice;\n if (disc) {\n params.within_diameter_mm = config.withinDiameterMm;\n if (config.minDiameterMm !== undefined) params.min_diameter_mm = config.minDiameterMm;\n } else {\n params.rows = config.rows;\n params.columns = config.columns;\n }\n } else {\n if (config.spacingMm === undefined || Array.isArray(config.spacingMm) || !(config.spacingMm > 0)) fail(\"an arc needs spacingMm, the circle's diameter\");\n if (config.holeCount === undefined || config.holeCount < 2) fail(\"an arc has two or more holes\");\n if (config.angularPitchDeg === undefined || !(config.angularPitchDeg > 0)) fail(\"an arc needs angularPitchDeg\");\n if (config.pitchMm !== undefined) fail(\"pitchMm is for a row or a grid\");\n if (config.angularPitchDeg! * config.holeCount! >= 360 - 1e-9) fail(\"the holes go round the whole circle (or overlap): use shape \\\"circle\\\"\");\n parameters.push(holeSpacingMm(config.spacingMm as number), holeCount(config.holeCount!), angularPitchDeg(config.angularPitchDeg!));\n params.start_angle_deg = config.startAngleDeg ?? 0;\n }\n parameters.push(fastenerDiameterMm(config.fastenerDiameterMm));\n if (config.threaded !== undefined) params.threaded = config.threaded;\n if (config.note !== undefined) params.note = config.note;\n return {\n id: config.id,\n name: config.name,\n domain: \"mechanical\",\n exposed: config.exposed ?? true,\n default_active: config.defaultActive ?? true,\n protocols: [{ type: \"bolt_pattern\", roles: [config.role] }],\n capabilities: [\"bolt_pattern\"],\n parameters,\n ...(config.maxInstances !== undefined ? { max_instances: config.maxInstances } : {}),\n traits: [{ type: \"bolt_pattern\", params }],\n };\n}\n\n/**\n * Cross-section of a shaft and of the bore it fits. shaft_diameter is the\n * across-flats size for hex, rounded hex and square; the nominal diameter\n * for round, D-cut, double-D and keyed; the major diameter for a spline.\n *\n * - round: plain cylinder (torque by set screw, clamp or press fit).\n * - hex: hexagon with sharp corners (REV and FTC 5 mm hex, 1/2 in hex).\n * - rounded_hex: hexagon with turned corners (REV UltraHex); fits a hex\n * bore of the same across-flats size.\n * - d_cut: one flat; double_d: two opposite flats.\n * - keyed: round with a keyway and key (`keyWidthMm`).\n * - spline: teeth (`spline` names the standard, e.g. \"25T\" servo spline).\n * - square: square section (across flats).\n */\nexport type ShaftProfile = \"round\" | \"hex\" | \"rounded_hex\" | \"d_cut\" | \"double_d\" | \"keyed\" | \"spline\" | \"square\";\n\n/** \"shaft\" = the male part (a motor shaft, a hex shaft); \"bore\" = the female part (a hub, a gear's bore, a hollow output). */\nexport type ShaftGender = \"shaft\" | \"bore\";\n\nexport interface ShaftConfig {\n id: string;\n name?: string;\n /**\n * Which way torque flows: \"output\" drives (a motor's shaft or hollow\n * output), \"input\" is driven (a propeller hub, a pulley, a gearbox\n * input), \"bidirectional\" carries torque from a driver to a load (a loose\n * shaft, a spacer, a coupler). Independent of `gender`: a motor with a\n * hollow hex output is an output bore.\n */\n role: \"output\" | \"input\" | \"bidirectional\";\n /** Shaft diameter, or bore diameter, in mm (across flats for hex, rounded hex and square). */\n diameterMm: number;\n /** Cross-section. Stated profiles are checked against the mating side's. */\n profile?: ShaftProfile;\n /** Male shaft or female bore. Two shafts or two bores do not mate. */\n gender?: ShaftGender;\n /** Keyed: key (shaft) or keyway (bore) width in mm. */\n keyWidthMm?: number;\n /** Spline: the standard or tooth count as the source states it (\"25T\", \"MAXSpline\"). */\n spline?: string;\n /** Thread designation if threaded, e.g. \"M5\". */\n thread?: string;\n /**\n * A round bore made to go over a shaft of another profile and clamp on it\n * (an adapter: a shaft collar's Ø6 bore on a 5 mm hex shaft, held by a set\n * screw on a flat). The pair check fits it to a shaft of that profile and\n * size instead of comparing the diameters; `by` says what holds it.\n * Only on a round bore, which must clear the shaft's corners.\n */\n clampsOn?: { profile: ShaftProfile; diameterMm: number; by: \"set_screw\" | \"clamp_screw\" | \"press\" | \"adhesive\" };\n /** Anything else the source states (shaft length, hub type, rotation). */\n note?: string;\n exposed?: boolean;\n defaultActive?: boolean;\n}\n\nexport function Shaft(config: ShaftConfig): InterfaceDef {\n if (config.keyWidthMm !== undefined && config.profile !== \"keyed\") {\n throw new Error(`Shaft ${config.id}: keyWidthMm is for a keyed profile`);\n }\n if (config.spline !== undefined && config.profile !== \"spline\") {\n throw new Error(`Shaft ${config.id}: spline is for a spline profile`);\n }\n if (config.clampsOn !== undefined) {\n if (config.gender !== \"bore\" || (config.profile ?? \"round\") !== \"round\") throw new Error(`Shaft ${config.id}: clampsOn is for a round bore`);\n const c = config.clampsOn;\n const corners = c.profile === \"hex\" ? (c.diameterMm * 2) / Math.sqrt(3) : c.profile === \"square\" ? c.diameterMm * Math.SQRT2 : c.diameterMm;\n if (config.diameterMm + 1e-9 < corners - 0.05) {\n throw new Error(`Shaft ${config.id}: a Ø${config.diameterMm} mm bore does not clear a ${c.diameterMm} mm ${c.profile} shaft (${+corners.toFixed(3)} mm across corners)`);\n }\n }\n const parameters: Parameter[] = [shaftDiameterMm(config.diameterMm)];\n if (config.keyWidthMm !== undefined) parameters.push(keyWidthMm(config.keyWidthMm));\n const params: Record<string, unknown> = {\n ...(config.clampsOn !== undefined ? { clamps_on: { profile: config.clampsOn.profile, diameter_mm: config.clampsOn.diameterMm, by: config.clampsOn.by } } : {}),\n ...(config.profile !== undefined ? { profile: config.profile } : {}),\n ...(config.gender !== undefined ? { gender: config.gender } : {}),\n ...(config.spline !== undefined ? { spline: config.spline } : {}),\n ...(config.thread !== undefined ? { thread: config.thread } : {}),\n ...(config.note !== undefined ? { note: config.note } : {}),\n };\n return {\n id: config.id,\n name: config.name,\n domain: \"mechanical\",\n exposed: config.exposed ?? true,\n default_active: config.defaultActive ?? true,\n protocols: [{ type: \"shaft\", roles: [config.role] }],\n capabilities: [\"shaft\"],\n parameters,\n max_instances: 1,\n ...(Object.keys(params).length > 0 ? { traits: [{ type: \"shaft\", params }] } : {}),\n };\n}\n\n/** How a linear output is produced, as the source describes it. */\nexport type LinearMechanism = \"lead_screw\" | \"ball_screw\" | \"belt\" | \"rack_and_pinion\" | \"pneumatic\" | \"hydraulic\" | \"solenoid\" | \"linear_motor\" | \"other\";\n\nexport interface LinearMotionConfig {\n id: string;\n name?: string;\n /**\n * \"output\": the moving member that pushes or pulls (an actuator's rod or\n * inner tube, a lead screw nut's carriage); \"input\": a load or slide\n * driven by one. A load may state the stroke and force it needs.\n */\n role: \"output\" | \"input\";\n /** Travel in mm: given (output) or needed (input). */\n strokeMm?: number;\n /** Travel per input revolution in mm (pitch × starts). */\n leadMm?: number;\n /** Screw thread pitch in mm. */\n threadPitchMm?: number;\n /** Thread starts (lead = pitch × starts). */\n starts?: number;\n /** Rated axial force in N (output), or the force the load needs (input). Say in `note` whether it is dynamic, static or peak. */\n forceN?: number;\n /** Rated linear speed in mm/s. */\n speedMmS?: number;\n mechanism?: LinearMechanism;\n /** True when a load on the output can turn the input (an unpowered actuator does not hold). */\n backdrivable?: boolean;\n /** Anything else the source states (end stops, rod end, side-load limits). */\n note?: string;\n exposed?: boolean;\n defaultActive?: boolean;\n}\n\n/**\n * A linear motion interface: the moving output of a linear actuator, lead\n * screw or slide (role output), or the load it drives (role input). Stroke\n * and force are capacities: the pair check requires the output's stroke and\n * force to cover what the load states (`linear_motion_capacity`). Lead and\n * thread pitch must agree when both sides state them (a screw and its nut).\n */\nexport function LinearMotion(config: LinearMotionConfig): InterfaceDef {\n if (config.starts !== undefined && config.leadMm !== undefined && config.threadPitchMm !== undefined) {\n const lead = config.threadPitchMm * config.starts;\n if (Math.abs(lead - config.leadMm) > 1e-6 * Math.max(1, lead)) {\n throw new Error(`LinearMotion ${config.id}: lead ${config.leadMm} mm is not pitch ${config.threadPitchMm} mm × ${config.starts} starts`);\n }\n }\n const parameters: Parameter[] = [];\n if (config.strokeMm !== undefined) parameters.push(strokeMm(config.strokeMm));\n if (config.leadMm !== undefined) parameters.push(leadMm(config.leadMm));\n if (config.threadPitchMm !== undefined) parameters.push(threadPitchMm(config.threadPitchMm));\n if (config.forceN !== undefined) parameters.push(forceN(config.forceN));\n if (config.speedMmS !== undefined) parameters.push(linearSpeedMmS(config.speedMmS));\n const params: Record<string, unknown> = {\n ...(config.mechanism !== undefined ? { mechanism: config.mechanism } : {}),\n ...(config.starts !== undefined ? { starts: config.starts } : {}),\n ...(config.backdrivable !== undefined ? { backdrivable: config.backdrivable } : {}),\n ...(config.note !== undefined ? { note: config.note } : {}),\n };\n return {\n id: config.id,\n name: config.name,\n domain: \"mechanical\",\n exposed: config.exposed ?? true,\n default_active: config.defaultActive ?? true,\n protocols: [{ type: \"linear_motion\", roles: [config.role] }],\n capabilities: [\"linear_motion\"],\n ...(parameters.length > 0 ? { parameters } : {}),\n max_instances: 1,\n ...(Object.keys(params).length > 0 ? { traits: [{ type: \"linear_motion\", params }] } : {}),\n };\n}\n","import type { InterfaceDef } from \"../types/interface.js\";\nimport type { Diagnostic } from \"./types.js\";\nimport { getEffectiveRange } from \"../parameters/range.js\";\nimport { arcHoles, latticeHoles, type GridSpec } from \"../protocols/mechanical.js\";\n\n/**\n * Pair checks on how two matched interfaces physically join, beyond their\n * protocols and parameters:\n *\n * - `fluid_joint_mismatch`: two fluid ports (FluidPort's `fluid_joint`\n * trait) whose joints do not mate. Threads need the same standard (NPT and\n * NPTF count as one) and size and opposite genders; a push-to-connect\n * fitting or a hose barb takes a tube; quick couplers need the same style\n * and opposite genders. Thread sizes compare without inch marks, spaces\n * or case, and a BSPP or BSPT size may carry ISO 228's \"G\" or ISO 7's\n * \"R\"/\"Rc\"/\"Rp\" prefix (\"G1/4\" is \"1/4\"). Tube diameters are checked as\n * parameters.\n * - `bolt_pattern_shape`: a cross bolt pattern (two diagonals, BoltPattern\n * shape \"cross\") against a pattern of another shape whose holes differ. A\n * cross with equal diagonals d has the holes of a 4-hole circle of\n * diameter d and of a square of side d/√2, so those pairs are compared by\n * that diagonal instead (see boltPatternsShareHoles). Square, rectangle and\n * circle patterns are compared by their parameters only.\n * - `bolt_pattern_line`: a row (BoltPattern shape \"row\") or a slot (shape\n * \"slot\") against a pattern whose holes do not land on it. A row mates a\n * row whose holes fall on its own: the shorter row's pitch is the\n * longer's or a whole multiple of it, and it is no longer. A rectangle\n * with hole_spacing_y 0 counts as a two-hole row (or, when its spacing is\n * a range from 0, as a slot: the older way to write one). A row fits a\n * slot no shorter than the row. Two T-slots do not mate (neither has a\n * hole for the fastener); a through slot mates any slot. A row or slot\n * never mates a pattern whose holes are not on one line (square, circle,\n * cross, a rectangle with a y spacing). The check compares the spans,\n * pitches and lengths itself (see pairCheckedParams).\n * - `bolt_pattern_holes`: a grid (BoltPattern shape \"grid\") or a partial\n * circle (shape \"arc\") against another pattern: the pattern with fewer\n * holes must land on the other's holes under some rotation and shift (or\n * their mirror image), within 0.05 mm. A grid fits a slot (fasteners\n * through one line of the grid); an arc does not.\n * - `shaft_fit`: a shaft and a bore (Shaft `gender`, `profile`) that do not\n * fit: two shafts or two bores; or profiles that do not fit (a hex shaft\n * in a round bore, two different splines). A round shaft in a keyed bore,\n * or a keyed shaft in a round one, fits without its key carrying torque\n * (warning). Diameters and key widths are compared as parameters.\n * - `linear_motion_capacity`: a linear output whose stroke or force is less\n * than the load it drives states it needs.\n * - `supply_current_rating`: a source (a power output, a controller\n * channel) rated for less continuous current than the input it feeds says\n * its source must be rated for (`min_supply_current`); info when the\n * source states no rating.\n */\nexport function checkPairJoints(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n return [...fluidJoint(a, b), ...boltHoles(a, b), ...boltShape(a, b), ...boltLine(a, b), ...shaftFit(a, b), ...linearCapacity(a, b), ...supplyCurrent(a, b)];\n}\n\n/**\n * Pairings whose protocols and roles match but which never mate as they\n * are: two shafts or two bores (a gear's hex bore and another gear's).\n * `validatePair` does not auto-connect them; it lists them as potentials,\n * and an explicit link reports `shaft_fit`.\n */\nexport function neverMates(a: InterfaceDef, b: InterfaceDef): boolean {\n if (!a.protocols.some((p) => p.type === \"shaft\") || !b.protocols.some((p) => p.type === \"shaft\")) return false;\n const [ga, gb] = [traitParams(a, \"shaft\")?.gender, traitParams(b, \"shaft\")?.gender];\n return ga !== undefined && ga === gb;\n}\n\n/**\n * Parameters the joint check compares itself for this pair, which the\n * pairwise overlap check must skip: hole spacings of bolt patterns that share\n * holes in another shape (a cross and a circle), and the spans, counts,\n * pitches and lengths of row and slot patterns.\n */\nexport function pairCheckedParams(a: InterfaceDef, b: InterfaceDef): Set<string> {\n if (holeRule(a, b)) return new Set([\"hole_spacing\", \"hole_spacing_y\", \"hole_count\", \"hole_pitch\", \"hole_pitch_y\", \"angular_pitch\", \"slot_length\"]);\n if (clampFit(a, b)) return new Set([\"shaft_diameter\"]);\n if (lineRule(a, b)) return new Set([\"hole_spacing\", \"hole_spacing_y\", \"hole_count\", \"hole_pitch\", \"slot_length\"]);\n if (boltPatternsShareHoles(a, b)) return new Set([\"hole_spacing\", \"hole_spacing_y\"]);\n return new Set();\n}\n\nconst traitParams = (iface: InterfaceDef, type: string): Record<string, unknown> | undefined =>\n iface.traits?.find((t) => t.type === type)?.params as Record<string, unknown> | undefined;\n\nconst THREAD_FAMILY: Record<string, string> = { npt: \"npt\", nptf: \"npt\" };\nconst threadFamily = (s: unknown) => {\n const k = String(s ?? \"\").toLowerCase();\n return THREAD_FAMILY[k] ?? k;\n};\n/** BSP threads: ISO 228 parallel sizes are written \"G1/4\", ISO 7 taper sizes \"R1/4\", \"Rc1/4\" or \"Rp1/4\". */\nconst BSP_PREFIX = /^(g|rc|rp|r)(?=\\d)/;\nconst normSize = (s: unknown, standard?: unknown) => {\n const size = String(s ?? \"\").replace(/[\"″\\s]/g, \"\").toLowerCase();\n return /^bsp/.test(String(standard ?? \"\").toLowerCase()) ? size.replace(BSP_PREFIX, \"\") : size;\n};\n\n/** Joint kinds that mate with each other (unordered). */\nconst MATES: Record<string, string[]> = {\n thread: [\"thread\"],\n push_to_connect: [\"tube\"],\n tube: [\"push_to_connect\", \"barb\"],\n barb: [\"tube\"],\n quick_coupler: [\"quick_coupler\"],\n};\n\nfunction describe(j: Record<string, unknown>): string {\n if (j.kind === \"thread\") return `${j.standard} ${j.size} ${j.gender} thread`;\n if (j.kind === \"quick_coupler\") return `${j.style} ${j.gender} quick coupler`;\n return String(j.kind).replace(/_/g, \"-\");\n}\n\nfunction fluidJoint(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n const ja = traitParams(a, \"fluid_joint\");\n const jb = traitParams(b, \"fluid_joint\");\n if (!ja || !jb) return [];\n const problem = (why: string): Diagnostic[] => [\n { severity: \"error\", code: \"fluid_joint_mismatch\", message: `${describe(ja)} does not mate with ${describe(jb)}: ${why}`, refs: [a.id, b.id] },\n ];\n if (!(MATES[String(ja.kind)] ?? []).includes(String(jb.kind))) return problem(\"these joint kinds do not connect without a fitting\");\n if (ja.kind === \"thread\") {\n if (threadFamily(ja.standard) !== threadFamily(jb.standard)) return problem(\"different thread standards\");\n if (normSize(ja.size, ja.standard) !== normSize(jb.size, jb.standard)) return problem(\"different thread sizes\");\n }\n if (ja.kind === \"quick_coupler\" && String(ja.style).toLowerCase() !== String(jb.style).toLowerCase()) return problem(\"different coupler styles\");\n if ((ja.kind === \"thread\" || ja.kind === \"quick_coupler\") && ja.gender === jb.gender) return problem(`both are ${ja.gender}`);\n if ((ja.kind === \"barb\" || jb.kind === \"barb\") && ![a, b].every((x) => x.parameters?.some((p) => p.id === \"tube_id\"))) {\n return [{ severity: \"warning\", code: \"fluid_joint_mismatch\", message: \"a hose barb's fit cannot be checked: the tube states no inside diameter\", refs: [a.id, b.id] }];\n }\n return [];\n}\n\n/** How close two hole positions must be to count as the same hole, in mm. */\nconst HOLE_TOLERANCE_MM = 0.05;\n\nconst paramRange = (iface: InterfaceDef, id: string): [number, number] | undefined => {\n const p = iface.parameters?.find((x) => x.id === id);\n return (p && getEffectiveRange(p)) ?? undefined;\n};\n\n/**\n * The diagonal of a 4-hole pattern whose holes lie on a square (equal\n * diagonals), as a range in mm, or undefined for any other pattern: a 4-hole\n * circle's diameter, a square's side × √2, or a cross whose two diagonals can\n * be equal (their ranges overlap).\n */\nfunction squareDiagonal(iface: InterfaceDef): [number, number] | undefined {\n const shape = traitParams(iface, \"bolt_pattern\")?.shape;\n const count = paramRange(iface, \"hole_count\");\n if (count && (count[0] !== 4 || count[1] !== 4)) return undefined;\n const x = paramRange(iface, \"hole_spacing\");\n if (!x) return undefined;\n if (shape === \"circle\") return x;\n if (shape === \"square\") return [x[0] * Math.SQRT2, x[1] * Math.SQRT2];\n if (shape === \"cross\") {\n const y = paramRange(iface, \"hole_spacing_y\") ?? x;\n const lo = Math.max(x[0], y[0]);\n const hi = Math.min(x[1], y[1]);\n return lo <= hi + HOLE_TOLERANCE_MM ? [Math.min(lo, hi), Math.max(lo, hi)] : undefined;\n }\n return undefined;\n}\n\nconst overlaps = (a: [number, number], b: [number, number]) => a[0] <= b[1] + HOLE_TOLERANCE_MM && b[0] <= a[1] + HOLE_TOLERANCE_MM;\n\n/**\n * Two bolt patterns of different shapes, one a cross, that have the same\n * holes: a cross with equal diagonals against a 4-hole circle or a square of\n * the same diagonal. Their hole_spacing parameters mean different lengths\n * (a square's side, a cross's diagonal), so the pair check compares the\n * diagonal here and does not compare those parameters.\n */\nexport function boltPatternsShareHoles(a: InterfaceDef, b: InterfaceDef): boolean {\n const sa = traitParams(a, \"bolt_pattern\")?.shape;\n const sb = traitParams(b, \"bolt_pattern\")?.shape;\n if (sa === undefined || sb === undefined || sa === sb || (sa !== \"cross\" && sb !== \"cross\")) return false;\n const da = squareDiagonal(a);\n const db = squareDiagonal(b);\n return !!da && !!db && overlaps(da, db);\n}\n\nconst fmtRange = (r: [number, number]) => (Math.abs(r[1] - r[0]) <= HOLE_TOLERANCE_MM ? `${+r[0].toFixed(2)}` : `${+r[0].toFixed(2)}–${+r[1].toFixed(2)}`);\n\nfunction boltShape(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n const sa = traitParams(a, \"bolt_pattern\")?.shape;\n const sb = traitParams(b, \"bolt_pattern\")?.shape;\n if (sa === undefined || sb === undefined || sa === sb) return [];\n if (lineRule(a, b) || holeRule(a, b)) return [];\n if (sa !== \"cross\" && sb !== \"cross\") return [];\n if (boltPatternsShareHoles(a, b)) return [];\n const [da, db] = [squareDiagonal(a), squareDiagonal(b)];\n const why =\n da && db\n ? `both have four holes on a square, but the diagonals differ (${fmtRange(da)} mm and ${fmtRange(db)} mm)`\n : \"their holes are not in the same places\";\n return [\n {\n severity: \"error\",\n code: \"bolt_pattern_shape\",\n message: `a ${sa} bolt pattern does not line up with a ${sb} one: ${why}`,\n refs: [a.id, b.id],\n },\n ];\n}\n\n// ---------------------------------------------------------------------------\n// Rows and slots\n// ---------------------------------------------------------------------------\n\n/** A pattern's holes as a line: a row (pitch, possibly a range for slotted holes, and count), a slot, or not on a line. */\ntype Line =\n | { kind: \"row\"; pitch: [number, number]; count: number }\n | { kind: \"slot\"; length: number; slotKind?: string }\n | { kind: \"plane\"; shape: string };\n\nconst isLineShape = (iface: InterfaceDef) => {\n const shape = traitParams(iface, \"bolt_pattern\")?.shape;\n return shape === \"row\" || shape === \"slot\";\n};\n\n/** The line rule applies when both sides are bolt patterns, at least one is a row or a slot, and neither is a grid or an arc (the hole rule). */\nconst lineRule = (a: InterfaceDef, b: InterfaceDef) =>\n traitParams(a, \"bolt_pattern\") !== undefined && traitParams(b, \"bolt_pattern\") !== undefined && (isLineShape(a) || isLineShape(b)) && !holeRule(a, b);\n\n// ---------------------------------------------------------------------------\n// Grids and arcs: compare the holes themselves\n// ---------------------------------------------------------------------------\n\nconst isHoleShape = (iface: InterfaceDef) => {\n const shape = traitParams(iface, \"bolt_pattern\")?.shape;\n return shape === \"grid\" || shape === \"arc\";\n};\n\n/** The hole rule applies when both sides are bolt patterns and at least one is a grid or an arc. */\nconst holeRule = (a: InterfaceDef, b: InterfaceDef) =>\n traitParams(a, \"bolt_pattern\") !== undefined && traitParams(b, \"bolt_pattern\") !== undefined && (isHoleShape(a) || isHoleShape(b));\n\nconst paramNum = (iface: InterfaceDef, id: string) => paramRange(iface, id)?.[0];\n\n/**\n * The holes of any bolt pattern in its frame's x/y (mm), from its\n * parameters and trait; undefined for a slot (no fixed holes) or a pattern\n * whose spacing is a range (slotted holes).\n */\nexport function patternHoles(iface: InterfaceDef): [number, number][] | undefined {\n const t = traitParams(iface, \"bolt_pattern\");\n if (!t) return undefined;\n const shape = String(t.shape);\n if (shape === \"slot\") return undefined;\n if (shape === \"grid\") {\n const spec: GridSpec = {\n lattice: t.lattice === \"triangular\" ? \"triangular\" : \"rectangular\",\n pitch: paramNum(iface, \"hole_pitch\") ?? 0,\n ...(paramNum(iface, \"hole_pitch_y\") !== undefined ? { pitchY: paramNum(iface, \"hole_pitch_y\") } : {}),\n ...(t.within_diameter_mm !== undefined ? { withinDiameter: Number(t.within_diameter_mm) } : { rows: Number(t.rows), columns: Number(t.columns) }),\n ...(t.min_diameter_mm !== undefined ? { minDiameter: Number(t.min_diameter_mm) } : {}),\n };\n return latticeHoles(spec);\n }\n const x = paramRange(iface, \"hole_spacing\");\n if (!x || x[1] - x[0] > HOLE_TOLERANCE_MM) return undefined;\n const count = paramNum(iface, \"hole_count\") ?? 4;\n const d = x[0];\n if (shape === \"arc\") return arcHoles(d, count, paramNum(iface, \"angular_pitch\") ?? 0, Number(t.start_angle_deg ?? 0));\n if (shape === \"row\") {\n const pitch = paramNum(iface, \"hole_pitch\") ?? (count > 1 ? d / (count - 1) : 0);\n return Array.from({ length: count }, (_, k) => [-d / 2 + k * pitch, 0] as [number, number]);\n }\n if (shape === \"circle\") return arcHoles(d, count, 360 / count, 0);\n const yr = paramRange(iface, \"hole_spacing_y\");\n if (yr && yr[1] - yr[0] > HOLE_TOLERANCE_MM) return undefined;\n const y = yr?.[0] ?? d;\n if (shape === \"cross\") return [[-d / 2, 0], [d / 2, 0], [0, -y / 2], [0, y / 2]];\n if (shape === \"rectangle\" && y <= HOLE_TOLERANCE_MM) return count <= 2 ? [[-d / 2, 0], [d / 2, 0]] : undefined;\n return [[-d / 2, -y / 2], [d / 2, -y / 2], [d / 2, y / 2], [-d / 2, y / 2]];\n}\n\n/**\n * Whether every hole of `small` lands on a hole of `large` under one rigid\n * motion of the plane (a rotation and a shift, or their mirror image),\n * within `tol`. Two holes of `small` fix the motion: its first hole and the\n * one farthest from it go onto every pair of `large` holes as far apart.\n */\nexport function holesFitOn(small: [number, number][], large: [number, number][], tol = HOLE_TOLERANCE_MM): boolean {\n if (small.length === 0) return true;\n if (small.length > large.length) return false;\n if (small.length === 1) return large.length > 0;\n const cell = Math.max(tol * 4, 0.5);\n const key = (x: number, y: number) => `${Math.round(x / cell)},${Math.round(y / cell)}`;\n const index = new Map<string, [number, number][]>();\n for (const p of large) {\n const k = key(p[0], p[1]);\n index.set(k, [...(index.get(k) ?? []), p]);\n }\n const has = (x: number, y: number) => {\n const [i, j] = [Math.round(x / cell), Math.round(y / cell)];\n for (let di = -1; di <= 1; di++)\n for (let dj = -1; dj <= 1; dj++) for (const p of index.get(`${i + di},${j + dj}`) ?? []) if (Math.hypot(p[0] - x, p[1] - y) <= tol) return true;\n return false;\n };\n const s0 = small[0];\n let s1 = small[1];\n for (const p of small) if (Math.hypot(p[0] - s0[0], p[1] - s0[1]) > Math.hypot(s1[0] - s0[0], s1[1] - s0[1])) s1 = p;\n const d = Math.hypot(s1[0] - s0[0], s1[1] - s0[1]);\n for (const mirror of [false, true]) {\n const pts = small.map(([x, y]) => [x - s0[0], mirror ? -(y - s0[1]) : y - s0[1]] as [number, number]);\n const v = [s1[0] - s0[0], mirror ? -(s1[1] - s0[1]) : s1[1] - s0[1]];\n const aS = Math.atan2(v[1], v[0]);\n for (const li of large) {\n for (const lj of large) {\n if (li === lj || Math.abs(Math.hypot(lj[0] - li[0], lj[1] - li[1]) - d) > tol) continue;\n const rot = Math.atan2(lj[1] - li[1], lj[0] - li[0]) - aS;\n const [c, s] = [Math.cos(rot), Math.sin(rot)];\n if (pts.every(([x, y]) => has(li[0] + c * x - s * y, li[1] + s * x + c * y))) return true;\n }\n }\n }\n return false;\n}\n\nconst describeHoles = (iface: InterfaceDef) => {\n const t = traitParams(iface, \"bolt_pattern\") ?? {};\n const n = paramNum(iface, \"hole_count\");\n if (t.shape === \"grid\") return `a ${t.lattice} grid of ${n} holes (pitch ${fmtRange(paramRange(iface, \"hole_pitch\") ?? [0, 0])} mm)`;\n if (t.shape === \"arc\") return `a partial circle of ${n} holes on Ø${fmtRange(paramRange(iface, \"hole_spacing\") ?? [0, 0])} mm`;\n return `a ${t.shape} pattern`;\n};\n\nfunction boltHoles(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!holeRule(a, b)) return [];\n const problem = (why: string): Diagnostic[] => [{ severity: \"error\", code: \"bolt_pattern_holes\", message: `${describeHoles(a)} does not line up with ${describeHoles(b)}: ${why}`, refs: [a.id, b.id] }];\n const slotSide = [a, b].find((x) => traitParams(x, \"bolt_pattern\")?.shape === \"slot\");\n if (slotSide) {\n const other = slotSide === a ? b : a;\n if (traitParams(other, \"bolt_pattern\")?.shape === \"grid\") {\n return [{ severity: \"info\", code: \"bolt_pattern_holes\", message: \"fasteners go into the slot through one line of the grid's holes\", refs: [a.id, b.id] }];\n }\n return problem(\"a partial circle's holes are not on one line\");\n }\n const [ha, hb] = [patternHoles(a), patternHoles(b)];\n if (!ha || !hb) return [];\n const [small, large] = ha.length <= hb.length ? [ha, hb] : [hb, ha];\n if (holesFitOn(small, large)) return [];\n return problem(`the ${small.length} holes of one do not all land on the other's ${large.length}`);\n}\n\nfunction lineOf(iface: InterfaceDef): Line {\n const t = traitParams(iface, \"bolt_pattern\") ?? {};\n const shape = String(t.shape);\n if (shape === \"row\") {\n return { kind: \"row\", pitch: paramRange(iface, \"hole_pitch\") ?? [0, 0], count: paramRange(iface, \"hole_count\")?.[0] ?? 2 };\n }\n if (shape === \"slot\") {\n return { kind: \"slot\", length: paramRange(iface, \"slot_length\")?.[1] ?? 0, ...(t.slot_kind !== undefined ? { slotKind: String(t.slot_kind) } : {}) };\n }\n const y = paramRange(iface, \"hole_spacing_y\");\n const x = paramRange(iface, \"hole_spacing\");\n if (shape === \"rectangle\" && x && y && y[1] <= HOLE_TOLERANCE_MM) {\n // the older encodings: a slot as a spacing range from 0, a row as its two end holes\n if (x[0] <= HOLE_TOLERANCE_MM && x[1] > HOLE_TOLERANCE_MM) return { kind: \"slot\", length: x[1] };\n return { kind: \"row\", pitch: x, count: 2 };\n }\n return { kind: \"plane\", shape };\n}\n\nconst span = (r: { pitch: [number, number]; count: number }) => r.pitch[0] * (r.count - 1);\n\n/** Whether every hole of row s lands on a hole of row l. */\nfunction rowOnRow(s: { pitch: [number, number]; count: number }, l: { pitch: [number, number]; count: number }): boolean {\n const fixed = l.pitch[1] - l.pitch[0] <= HOLE_TOLERANCE_MM;\n if (!fixed) return s.count <= 2 && overlaps(s.pitch, l.pitch); // two holes slotted to any spacing in the range\n const p = l.pitch[0];\n if (s.count <= 1) return true;\n for (let k = 1; (s.count - 1) * k <= l.count - 1; k++) {\n if (overlaps(s.pitch, [k * p, k * p])) return true;\n }\n return false;\n}\n\nconst describeLine = (l: Line) =>\n l.kind === \"row\"\n ? `a ${l.count}-hole row (pitch ${fmtRange(l.pitch)} mm)`\n : l.kind === \"slot\"\n ? `a ${+l.length.toFixed(2)} mm ${l.slotKind === \"t_slot\" ? \"T-slot\" : l.slotKind === \"through\" ? \"through slot\" : \"slot\"}`\n : `a ${l.shape} pattern`;\n\nfunction boltLine(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!lineRule(a, b)) return [];\n const la = lineOf(a);\n const lb = lineOf(b);\n const problem = (why: string): Diagnostic[] => [\n { severity: \"error\", code: \"bolt_pattern_line\", message: `${describeLine(la)} does not line up with ${describeLine(lb)}: ${why}`, refs: [a.id, b.id] },\n ];\n if (la.kind === \"plane\" || lb.kind === \"plane\") return problem(\"a row's or a slot's holes lie on one line and the other pattern's do not\");\n if (la.kind === \"slot\" && lb.kind === \"slot\") {\n return la.slotKind === \"t_slot\" && lb.slotKind === \"t_slot\" ? problem(\"neither T-slot has a hole for the fastener; join them with a bracket\") : [];\n }\n if (la.kind === \"slot\" || lb.kind === \"slot\") {\n const [slot, row] = (la.kind === \"slot\" ? [la, lb] : [lb, la]) as [Extract<Line, { kind: \"slot\" }>, Extract<Line, { kind: \"row\" }>];\n return span(row) <= slot.length + HOLE_TOLERANCE_MM ? [] : problem(`the row spans ${+span(row).toFixed(2)} mm, longer than the slot`);\n }\n const [ra, rb] = [la, lb] as Extract<Line, { kind: \"row\" }>[];\n if (rowOnRow(ra, rb) || rowOnRow(rb, ra)) return [];\n return problem(\"the holes of neither row land on the other's (pitch not a whole multiple, or the row is longer)\");\n}\n\n// ---------------------------------------------------------------------------\n// Shafts and bores\n// ---------------------------------------------------------------------------\n\n/** For a shaft profile, the bore profiles it goes into: \"ok\", or \"warn\" when it fits without the key carrying torque. */\nconst SHAFT_FITS: Record<string, Record<string, \"ok\" | \"warn\">> = {\n round: { round: \"ok\", keyed: \"warn\" },\n hex: { hex: \"ok\" },\n rounded_hex: { hex: \"ok\", rounded_hex: \"ok\" },\n d_cut: { d_cut: \"ok\", round: \"ok\" },\n double_d: { double_d: \"ok\", d_cut: \"ok\", round: \"ok\" },\n keyed: { keyed: \"ok\", round: \"warn\" },\n spline: { spline: \"ok\" },\n square: { square: \"ok\" },\n};\n\nconst normSpline = (s: unknown) => String(s).replace(/[\\s_-]/g, \"\").toLowerCase();\nconst profileName = (p: unknown) => String(p).replace(/_/g, \"-\");\n\n/** A bore that clamps on another profile (Shaft `clampsOn`) against a shaft: [bore, shaft], or undefined. */\nfunction clampFit(a: InterfaceDef, b: InterfaceDef): [InterfaceDef, InterfaceDef] | undefined {\n if (!a.protocols.some((p) => p.type === \"shaft\") || !b.protocols.some((p) => p.type === \"shaft\")) return undefined;\n for (const [bore, shaft] of [[a, b], [b, a]] as const) {\n if (traitParams(bore, \"shaft\")?.clamps_on !== undefined && traitParams(shaft, \"shaft\")?.gender !== \"bore\") return [bore, shaft];\n }\n return undefined;\n}\n\nfunction shaftFit(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n const ta = traitParams(a, \"shaft\");\n const tb = traitParams(b, \"shaft\");\n if (!a.protocols.some((p) => p.type === \"shaft\") || !b.protocols.some((p) => p.type === \"shaft\")) return [];\n const diag = (severity: \"error\" | \"warning\" | \"info\", why: string): Diagnostic[] => [{ severity, code: \"shaft_fit\", message: why, refs: [a.id, b.id] }];\n const clamp = clampFit(a, b);\n if (clamp) {\n const [bore, shaft] = clamp;\n const on = traitParams(bore, \"shaft\")!.clamps_on as { profile: string; diameter_mm: number; by: string };\n const profile = traitParams(shaft, \"shaft\")?.profile;\n const d = paramRange(shaft, \"shaft_diameter\");\n const boreD = paramRange(bore, \"shaft_diameter\");\n const sameProfile = profile === undefined || profile === on.profile || (on.profile === \"hex\" && profile === \"rounded_hex\");\n if (sameProfile && d && overlaps(d, [on.diameter_mm, on.diameter_mm])) {\n return diag(\"info\", `the Ø${boreD ? fmtRange(boreD) : \"?\"} mm round bore goes over the ${on.diameter_mm} mm ${profileName(on.profile)} shaft and is held by ${String(on.by).replace(/_/g, \" \")}`);\n }\n if (profile === \"round\" && d && boreD && overlaps(d, boreD)) return []; // it is still a round bore\n return diag(\"error\", `the bore clamps on a ${on.diameter_mm} mm ${profileName(on.profile)} shaft, not a ${d ? fmtRange(d) : \"?\"} mm ${profileName(profile ?? \"unstated\")} one`);\n }\n const [ga, gb] = [ta?.gender, tb?.gender];\n if (ga !== undefined && ga === gb) return diag(\"error\", ga === \"shaft\" ? \"two shafts do not mate without a coupler\" : \"two bores need a shaft between them\");\n const [pa, pb] = [ta?.profile, tb?.profile];\n if (pa === undefined || pb === undefined) return [];\n if (pa === \"spline\" && pb === \"spline\" && ta?.spline !== undefined && tb?.spline !== undefined && normSpline(ta.spline) !== normSpline(tb.spline)) {\n return diag(\"error\", `different splines (${ta.spline} and ${tb.spline})`);\n }\n // which side is the shaft: from either gender; with neither stated, the better fit of the two readings\n const aIsShaft = ga === \"shaft\" || gb === \"bore\" ? true : gb === \"shaft\" || ga === \"bore\" ? false : undefined;\n const fits = (shaft: unknown, bore: unknown) => SHAFT_FITS[String(shaft)]?.[String(bore)];\n const fit =\n aIsShaft === true ? fits(pa, pb) : aIsShaft === false ? fits(pb, pa) : fits(pa, pb) === \"ok\" || fits(pb, pa) === \"ok\" ? \"ok\" : (fits(pa, pb) ?? fits(pb, pa));\n const [shaftP, boreP] = aIsShaft === false ? [pb, pa] : [pa, pb];\n if (fit === \"ok\") return [];\n if (fit === \"warn\") {\n return diag(\n \"warning\",\n boreP === \"keyed\"\n ? `a round shaft in a keyed bore: the keyway is unused, so torque relies on a set screw or clamp`\n : `a keyed shaft in a round bore: it fits without its key, so torque relies on a set screw or clamp`,\n );\n }\n return diag(\"error\", `a ${profileName(shaftP)} shaft does not fit a ${profileName(boreP)} bore`);\n}\n\n// ---------------------------------------------------------------------------\n// Linear motion and supply current: an output's rating against what the input needs\n// ---------------------------------------------------------------------------\n\nconst hasRoleIn = (iface: InterfaceDef, roles: Set<string>, protocol?: string) =>\n iface.protocols.some((p) => (protocol === undefined || p.type === protocol) && p.roles.some((r) => roles.has(r.toLowerCase())));\n\n/** A parameter's value in its base unit (A for mA), or undefined. \"low\" takes a range's lower end, \"high\" its upper end. */\nfunction amount(iface: InterfaceDef, id: string, end: \"low\" | \"high\"): number | undefined {\n const p = iface.parameters?.find((x) => x.id === id);\n const r = p && getEffectiveRange(p);\n if (!r) return undefined;\n const v = end === \"low\" ? r[0] : r[1];\n return p!.unit === \"mA\" ? v / 1000 : v;\n}\n\nconst fmtNum = (v: number) => `${+v.toFixed(3)}`;\n\nfunction linearCapacity(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n const out: Diagnostic[] = [];\n const OUTPUT = new Set([\"output\"]);\n const INPUT = new Set([\"input\"]);\n for (const [o, load] of [[a, b], [b, a]] as const) {\n if (!hasRoleIn(o, OUTPUT, \"linear_motion\") || !hasRoleIn(load, INPUT, \"linear_motion\")) continue;\n for (const [id, what, unit] of [[\"stroke\", \"stroke\", \"mm\"], [\"force\", \"force\", \"N\"]] as const) {\n const need = amount(load, id, \"low\");\n if (need === undefined) continue;\n const give = amount(o, id, \"high\");\n if (give === undefined) {\n out.push({ severity: \"info\", code: \"linear_motion_capacity\", message: `the load needs ${fmtNum(need)} ${unit} of ${what}; the output states no ${what}, so it cannot be checked`, refs: [o.id, load.id] });\n } else if (give + 1e-9 < need) {\n out.push({ severity: \"error\", code: \"linear_motion_capacity\", message: `the output gives ${fmtNum(give)} ${unit} of ${what}, less than the ${fmtNum(need)} ${unit} the load needs`, refs: [o.id, load.id] });\n }\n }\n }\n return out;\n}\n\nconst SUPPLYING = new Set([\"output\", \"source\"]);\n\nfunction supplyCurrent(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n const out: Diagnostic[] = [];\n for (const [load, source] of [[a, b], [b, a]] as const) {\n const need = amount(load, \"min_supply_current\", \"low\");\n if (need === undefined || !hasRoleIn(source, SUPPLYING)) continue;\n const rating = amount(source, \"max_current\", \"high\");\n if (rating === undefined) {\n out.push({ severity: \"info\", code: \"supply_current_rating\", message: `${load.id} needs a source rated for at least ${fmtNum(need)} A; ${source.id} states no current rating`, refs: [source.id, load.id] });\n } else if (rating + 1e-9 < need) {\n out.push({ severity: \"error\", code: \"supply_current_rating\", message: `${source.id} is rated for ${fmtNum(rating)} A; ${load.id} needs a source rated for at least ${fmtNum(need)} A`, refs: [source.id, load.id] });\n }\n }\n return out;\n}\n","import type { InterfaceDef } from \"../types/interface.js\";\nimport type { Diagnostic } from \"./types.js\";\nimport { getEffectiveRange } from \"../parameters/range.js\";\n\n/**\n * Pair checks on links that negotiate or must agree beyond overlapping\n * parameters: PCIe, M.2, MIPI, Ethernet and PoE, SFP, I2S, DVP,\n * SD, LED drive, and wireless.\n *\n * - `link_width` (info): a PCIe link (or an M.2 socket and card carrying PCIe) trains to the widest width and\n * highest generation both ends support; when that is less than either\n * end has, the check says what it runs at. MIPI states the lane count the\n * two can share.\n * - `lane_rate` (warning): a MIPI transmitter whose highest lane rate is\n * above the receiver's: its faster modes do not work.\n * - `m2_key`, `m2_size`, `m2_interface` (errors): a card whose keys do not\n * include the socket's key; a card length the socket has no standoff\n * for; a socket and card with no interface in common.\n * - `ethernet_speed`: no speed in common (error), or the speed they link\n * at when it is below either end's fastest (info). Ethernet and SFP.\n * - `ethernet_medium` (error): copper against fibre.\n * - `fiber_mismatch` (error): single-mode against multi-mode, a transmit\n * wavelength that is not the other end's receive wavelength, or a duplex\n * module against a BiDi one.\n * - `poe_power`: a powered device that needs more power than the PSE gives\n * (error); passive PoE against an 802.3 end (warning); a device powered\n * only by PoE on a port that gives none (warning).\n * - `sfp_form` (error): an SFP-family module in a QSFP cage, or the reverse.\n * - `audio_format` (error): I2S ports with no frame format in common.\n * - `audio_direction` (error): two ports that both only send, or both only\n * receive.\n * - `dvp_width`: a host narrower than the camera takes its upper bits\n * (warning); a wider host leaves its low bits unused (info).\n * - `sd_form`, `sd_mode`, `sd_capacity` (errors): another card form, no\n * bus mode in common, a card class the host does not read.\n * - `led_drive_current` (warning): a driver that can be set above the\n * LED's maximum current.\n * - `usb_speed`: USB ports with no speed in common (error), or the speed\n * they fall back to when it is below either end's fastest (info).\n * - `wireless_band` (error): radios with no band in common.\n * - `wireless_stack` (error): Bluetooth with no mode in common (Classic\n * against LE), 802.15.4 radios with no stack in common (Zigbee against\n * Thread).\n * - `zigbee_roles` (warning): two Zigbee radios that can only be end\n * devices.\n */\nexport function checkPairLinks(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n return [\n ...linkWidth(a, b),\n ...laneRate(a, b),\n ...m2(a, b),\n ...ethernet(a, b),\n ...poe(a, b),\n ...sfp(a, b),\n ...audio(a, b),\n ...dvp(a, b),\n ...sd(a, b),\n ...ledDrive(a, b),\n ...usb(a, b),\n ...wireless(a, b),\n ];\n}\n\n/** Parameters `checkPairLinks` compares itself, which the pairwise overlap check skips. */\nexport const LINK_CHECKED_PARAMS = new Set([\"link_speed\", \"lane_rate\", \"bus_width\", \"poe_power\", \"wavelength\"]);\n\n/** The link-checked parameters this pair carries (both ends speak a link protocol that `checkPairLinks` covers). */\nexport function linkCheckedParams(a: InterfaceDef, b: InterfaceDef): Set<string> {\n const ids = (x: InterfaceDef) => new Set((x.parameters ?? []).map((p) => p.id));\n const [ia, ib] = [ids(a), ids(b)];\n return new Set([...LINK_CHECKED_PARAMS].filter((id) => ia.has(id) && ib.has(id)));\n}\n\nconst trait = (iface: InterfaceDef, type: string): Record<string, unknown> | undefined =>\n iface.traits?.find((t) => t.type === type)?.params as Record<string, unknown> | undefined;\nconst speaks = (iface: InterfaceDef, type: string) => iface.protocols.some((p) => p.type === type);\nconst rolesOf = (iface: InterfaceDef, type: string) => new Set(iface.protocols.filter((p) => p.type === type).flatMap((p) => p.roles));\nconst range = (iface: InterfaceDef, id: string): [number, number] | undefined => {\n const p = iface.parameters?.find((x) => x.id === id);\n return (p && getEffectiveRange(p)) ?? undefined;\n};\nconst list = (v: unknown): string[] => (Array.isArray(v) ? v.map(String) : v === undefined ? [] : [String(v)]);\nconst common = (x: unknown, y: unknown) => list(x).filter((v) => list(y).includes(v));\nconst diag = (severity: Diagnostic[\"severity\"], code: string, message: string, a: InterfaceDef, b: InterfaceDef): Diagnostic => ({ severity, code, message, refs: [a.id, b.id] });\n\n// ---------------------------------------------------------------------------\n// Lanes\n// ---------------------------------------------------------------------------\n\nfunction linkWidth(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if ((speaks(a, \"pcie\") && speaks(b, \"pcie\")) || (speaks(a, \"m2\") && speaks(b, \"m2\"))) {\n const [la, lb, ga, gb] = [range(a, \"lane_count\"), range(b, \"lane_count\"), range(a, \"pcie_generation\"), range(b, \"pcie_generation\")];\n if (!la || !lb) return [];\n const lanes = Math.min(la[1], lb[1]);\n const gen = ga && gb ? Math.min(ga[1], gb[1]) : undefined;\n const narrower = lanes < Math.max(la[1], lb[1]);\n const slower = ga && gb ? gen! < Math.max(ga[1], gb[1]) : false;\n if (!narrower && !slower) return [];\n return [diag(\"info\", \"link_width\", `the link trains at x${lanes}${gen ? ` Gen ${gen}` : \"\"} (x${la[1]}${ga ? ` Gen ${ga[1]}` : \"\"} against x${lb[1]}${gb ? ` Gen ${gb[1]}` : \"\"})`, a, b)];\n }\n for (const type of [\"mipi_csi2\", \"mipi_dsi\"]) {\n if (!speaks(a, type) || !speaks(b, type)) continue;\n const [la, lb] = [range(a, \"lane_count\"), range(b, \"lane_count\")];\n if (!la || !lb) return [];\n const hi = Math.min(la[1], lb[1]);\n const lo = Math.max(la[0], lb[0]);\n if (lo > hi) return []; // the overlap check reports it\n if (hi < Math.max(la[1], lb[1])) return [diag(\"info\", \"link_width\", `the link runs on at most ${hi} lane${hi === 1 ? \"\" : \"s\"}`, a, b)];\n }\n return [];\n}\n\nfunction laneRate(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n for (const type of [\"mipi_csi2\", \"mipi_dsi\"]) {\n if (!speaks(a, type) || !speaks(b, type)) continue;\n const tx = rolesOf(a, type).has(\"transmitter\") ? a : rolesOf(b, type).has(\"transmitter\") ? b : undefined;\n if (!tx) return [];\n const rx = tx === a ? b : a;\n const [rt, rr] = [range(tx, \"lane_rate\"), range(rx, \"lane_rate\")];\n if (rt && rr && rt[1] > rr[1]) return [diag(\"warning\", \"lane_rate\", `the transmitter runs lanes up to ${rt[1]} Mbit/s, the receiver up to ${rr[1]} Mbit/s: modes above ${rr[1]} Mbit/s per lane do not work`, a, b)];\n }\n return [];\n}\n\n// ---------------------------------------------------------------------------\n// M.2\n// ---------------------------------------------------------------------------\n\nfunction m2(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n const [ta, tb] = [trait(a, \"m2\"), trait(b, \"m2\")];\n if (!ta || !tb) return [];\n const socketSide = rolesOf(a, \"m2\").has(\"socket\") ? a : rolesOf(b, \"m2\").has(\"socket\") ? b : undefined;\n if (!socketSide) return [];\n const [socket, card] = socketSide === a ? [ta, tb] : [tb, ta];\n const out: Diagnostic[] = [];\n const key = list(socket.key)[0];\n if (key && !list(card.key).includes(key)) out.push(diag(\"error\", \"m2_key\", `a ${list(card.key).join(\"+\")}-key card does not fit an ${key}-key socket`, a, b));\n const size = list(card.sizes)[0];\n if (size && list(socket.sizes).length && !list(socket.sizes).includes(size)) out.push(diag(\"error\", \"m2_size\", `the socket holds ${list(socket.sizes).join(\", \")} cards, not ${size}`, a, b));\n if (!common(socket.carries, card.carries).length) out.push(diag(\"error\", \"m2_interface\", `the socket carries ${list(socket.carries).join(\", \")}; the card uses ${list(card.carries).join(\", \")}`, a, b));\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Ethernet, PoE, SFP\n// ---------------------------------------------------------------------------\n\nconst speedsOf = (iface: InterfaceDef) => (trait(iface, \"ethernet\") ?? trait(iface, \"sfp\"))?.speeds_mbps as number[] | undefined;\nconst fmtSpeed = (s: number) => (s >= 1000 ? `${s / 1000} Gbit/s` : `${s} Mbit/s`);\n\nfunction ethernet(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n const both = (speaks(a, \"ethernet\") && speaks(b, \"ethernet\")) || (speaks(a, \"sfp\") && speaks(b, \"sfp\"));\n if (!both) return [];\n const out: Diagnostic[] = [];\n const [sa, sb] = [speedsOf(a), speedsOf(b)];\n if (sa && sb) {\n const shared = sa.filter((s) => sb.includes(s));\n if (!shared.length) out.push(diag(\"error\", \"ethernet_speed\", `no speed in common (${sa.map(fmtSpeed).join(\", \")} against ${sb.map(fmtSpeed).join(\", \")})`, a, b));\n else if (Math.max(...shared) < Math.max(...sa, ...sb)) out.push(diag(\"info\", \"ethernet_speed\", `the link runs at ${fmtSpeed(Math.max(...shared))}`, a, b));\n }\n const [ea, eb] = [trait(a, \"ethernet\"), trait(b, \"ethernet\")];\n if (ea && eb) {\n if (ea.medium !== eb.medium) out.push(diag(\"error\", \"ethernet_medium\", `a ${ea.medium} port does not link to a ${eb.medium} port without a media converter`, a, b));\n const [fa, fb] = [ea.fiber as Record<string, number | string> | undefined, eb.fiber as Record<string, number | string> | undefined];\n if (fa && fb) {\n if (fa.mode !== fb.mode) out.push(diag(\"error\", \"fiber_mismatch\", `${String(fa.mode).replace(\"_\", \"-\")} optics against ${String(fb.mode).replace(\"_\", \"-\")}`, a, b));\n if (fa.strands !== fb.strands) out.push(diag(\"error\", \"fiber_mismatch\", `a ${fa.strands}-strand port against a ${fb.strands}-strand one`, a, b));\n if (fa.tx_nm !== fb.rx_nm || fb.tx_nm !== fa.rx_nm) out.push(diag(\"error\", \"fiber_mismatch\", `wavelengths do not cross over: ${fa.tx_nm}/${fa.rx_nm} nm (tx/rx) against ${fb.tx_nm}/${fb.rx_nm} nm`, a, b));\n }\n }\n return out;\n}\n\nfunction poe(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"ethernet\") || !speaks(b, \"ethernet\")) return [];\n const [pa, pb] = [trait(a, \"poe\"), trait(b, \"poe\")];\n const out: Diagnostic[] = [];\n for (const [pd, pdIf, other, otherIf] of [[pa, a, pb, b], [pb, b, pa, a]] as const) {\n if (pd?.role !== \"pd\") continue;\n if (other?.role !== \"pse\") {\n if (pd.required) out.push(diag(\"warning\", \"poe_power\", `${pdIf.id} is powered only over Ethernet; ${otherIf.id} gives no PoE, so it needs an injector`, a, b));\n continue;\n }\n if ((pd.standard === \"passive\") !== (other.standard === \"passive\")) {\n out.push(diag(\"warning\", \"poe_power\", `${other.standard === \"passive\" ? \"passive PoE\" : `${other.standard} PoE`} feeding ${pd.standard === \"passive\" ? \"a passive PoE device\" : `an ${pd.standard} device`}: one side does no 802.3 detection, so the device may not power up, or may be damaged`, a, b));\n }\n const need = range(pdIf, \"poe_power\");\n const give = range(otherIf, \"poe_power\");\n if (need && give && give[1] + 1e-9 < need[1]) out.push(diag(\"error\", \"poe_power\", `${otherIf.id} gives ${give[1]} W; ${pdIf.id} draws up to ${need[1]} W`, a, b));\n }\n return out;\n}\n\nconst SFP_FAMILY: Record<string, string> = { sfp: \"sfp\", \"sfp+\": \"sfp\", sfp28: \"sfp\", \"qsfp+\": \"qsfp\", qsfp28: \"qsfp\" };\n\nfunction sfp(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n const [ta, tb] = [trait(a, \"sfp\"), trait(b, \"sfp\")];\n if (!ta || !tb) return [];\n if (SFP_FAMILY[String(ta.form)] === SFP_FAMILY[String(tb.form)]) return [];\n return [diag(\"error\", \"sfp_form\", `an ${String(ta.form).toUpperCase()} ${[...rolesOf(a, \"sfp\")][0]} does not take an ${String(tb.form).toUpperCase()} ${[...rolesOf(b, \"sfp\")][0]}`, a, b)];\n}\n\n// ---------------------------------------------------------------------------\n// Audio, cameras, SD, LEDs\n// ---------------------------------------------------------------------------\n\nfunction audio(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n const [ta, tb] = [trait(a, \"audio_port\"), trait(b, \"audio_port\")];\n if (!ta || !tb) return [];\n const out: Diagnostic[] = [];\n if (!common(ta.formats, tb.formats).length) out.push(diag(\"error\", \"audio_format\", `no frame format in common (${list(ta.formats).join(\", \")} against ${list(tb.formats).join(\", \")})`, a, b));\n if (ta.direction !== \"duplex\" && ta.direction === tb.direction) out.push(diag(\"error\", \"audio_direction\", `both ports only ${ta.direction === \"out\" ? \"send\" : \"receive\"} audio`, a, b));\n return out;\n}\n\nfunction dvp(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"dvp\") || !speaks(b, \"dvp\")) return [];\n const cam = rolesOf(a, \"dvp\").has(\"camera\") ? a : rolesOf(b, \"dvp\").has(\"camera\") ? b : undefined;\n if (!cam) return [];\n const host = cam === a ? b : a;\n const [wc, wh] = [range(cam, \"bus_width\")?.[1], range(host, \"bus_width\")?.[1]];\n if (wc === undefined || wh === undefined || wc === wh) return [];\n return wh < wc\n ? [diag(\"warning\", \"dvp_width\", `an ${wh}-bit host takes the upper ${wh} of the camera's ${wc} data bits (D${wc - 1}..D${wc - wh})`, a, b)]\n : [diag(\"info\", \"dvp_width\", `the camera's ${wc} data bits land on the host's upper bits; D${wh - wc - 1}..D0 of the host are unused`, a, b)];\n}\n\nfunction sd(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n const [ta, tb] = [trait(a, \"sd_card\"), trait(b, \"sd_card\")];\n if (!ta || !tb) return [];\n const out: Diagnostic[] = [];\n if (ta.form && tb.form && ta.form !== tb.form) out.push(diag(\"error\", \"sd_form\", `a ${ta.form} ${[...rolesOf(a, \"sd_card\")][0]} against a ${tb.form} ${[...rolesOf(b, \"sd_card\")][0]}`, a, b));\n if (!common(ta.modes, tb.modes).length) out.push(diag(\"error\", \"sd_mode\", `no bus mode in common (${list(ta.modes).join(\", \")} against ${list(tb.modes).join(\", \")})`, a, b));\n const hostSide = rolesOf(a, \"sd_card\").has(\"host\") ? ta : rolesOf(b, \"sd_card\").has(\"host\") ? tb : undefined;\n const cardSide = hostSide === ta ? tb : ta;\n if (hostSide?.capacity_classes && cardSide.capacity_classes && !common(hostSide.capacity_classes, cardSide.capacity_classes).length) {\n out.push(diag(\"error\", \"sd_capacity\", `the host reads ${list(hostSide.capacity_classes).join(\", \").toUpperCase()} cards, not ${list(cardSide.capacity_classes).join(\", \").toUpperCase()}`, a, b));\n }\n return out;\n}\n\nfunction ledDrive(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"led_drive\") || !speaks(b, \"led_drive\")) return [];\n const isLed = (x: InterfaceDef) => [...rolesOf(x, \"led_drive\")].some((r) => r === \"anode\" || r === \"cathode\");\n const led = isLed(a) ? a : isLed(b) ? b : undefined;\n if (!led) return [];\n const driver = led === a ? b : a;\n const [max, set] = [range(led, \"led_current\")?.[1], range(driver, \"led_current\")];\n if (max === undefined || !set || set[0] > max) return []; // disjoint: the overlap check reports it\n return set[1] > max ? [diag(\"warning\", \"led_drive_current\", `the driver can be set up to ${set[1]} mA, above the LED's ${max} mA maximum: set it at or below ${max} mA`, a, b)] : [];\n}\n\nconst USB_ORDER = [\"low\", \"full\", \"high\", \"super\", \"super_plus\", \"super_plus_2x2\", \"usb4\"];\n\nfunction usb(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n const [ta, tb] = [trait(a, \"usb\"), trait(b, \"usb\")];\n if (!ta || !tb) return [];\n const shared = common(ta.speeds, tb.speeds).sort((x, y) => USB_ORDER.indexOf(y) - USB_ORDER.indexOf(x));\n if (!shared.length) return [diag(\"error\", \"usb_speed\", `no speed in common (${list(ta.speeds).join(\", \")} against ${list(tb.speeds).join(\", \")})`, a, b)];\n const top = Math.max(...[...list(ta.speeds), ...list(tb.speeds)].map((s) => USB_ORDER.indexOf(s)));\n return USB_ORDER.indexOf(shared[0]!) < top ? [diag(\"info\", \"usb_speed\", `the ports run at ${shared[0]!.replace(/_/g, \" \")} speed`, a, b)] : [];\n}\n\n// ---------------------------------------------------------------------------\n// Wireless\n// ---------------------------------------------------------------------------\n\nfunction wireless(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n const [wa, wb] = [trait(a, \"wireless\"), trait(b, \"wireless\")];\n if (!wa || !wb || wa.standard !== wb.standard) return [];\n const out: Diagnostic[] = [];\n if (!common(wa.bands, wb.bands).length) out.push(diag(\"error\", \"wireless_band\", `no band in common (${list(wa.bands).join(\", \")} against ${list(wb.bands).join(\", \")})`, a, b));\n if ((wa.standard === \"bluetooth\" || wa.standard === \"ieee802154\") && !common(wa.stacks, wb.stacks).length) {\n out.push(diag(\"error\", \"wireless_stack\", `nothing in common to speak (${list(wa.stacks).join(\", \")} against ${list(wb.stacks).join(\", \")})`, a, b));\n }\n if (wa.standard === \"ieee802154\" && common(wa.stacks, wb.stacks).includes(\"zigbee\")) {\n const endOnly = (w: Record<string, unknown>) => list(w.zigbee_roles).length > 0 && list(w.zigbee_roles).every((r) => r === \"end_device\");\n if (endOnly(wa) && endOnly(wb)) out.push(diag(\"warning\", \"zigbee_roles\", \"two Zigbee end devices do not talk directly: the network needs a coordinator (and routers)\", a, b));\n }\n return out;\n}\n","import type { InterfaceDef } from \"../types/interface.js\";\nimport type { Diagnostic } from \"./types.js\";\nimport { getEffectiveRange } from \"../parameters/range.js\";\n\n/**\n * Pair checks for the drive-train and fastening vocabulary\n * (`protocols/drive.ts`):\n *\n * - `gear_mesh`: two gears with a different module or pressure angle\n * (error); kinds that do not go together (two racks, two internal gears,\n * a spur gear against a helical one, a bevel against a spur, a worm\n * without its wheel); helical gears on parallel shafts whose helix angles\n * differ or whose hands are the same; an internal gear against a pinion\n * with as many teeth or more. Otherwise an info with the ratio, the centre\n * distance and the engaged face width.\n * - `bearing_fit`: a bearing whose outside diameter is not the seat's\n * (error, within 0.05 mm); a kind the seat is not made for (warning); a\n * bearing wider than a blind seat is deep (info: it stands proud).\n * - `thread_fit`: threads of a different diameter, pitch or hand (error);\n * otherwise an info with the engaged length when both state a length.\n * - `t_slot_fit`: an insert whose neck does not pass the track's opening,\n * whose head is no wider than the opening (nothing holds it) or wider or\n * taller than the channel (errors); an insert that only slides in from an\n * end on a track that only takes drop-in hardware (error); different named\n * profiles when the dimensions cannot be compared (warning).\n * - `axial_face`: two faces whose annuli do not overlap (one passes inside\n * the other: error), or that turn relative to each other (warning: they rub).\n * - `rolling_contact`: a wheel smaller than the surface is made for (error).\n */\nexport function checkPairDrive(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n return [...gearMesh(a, b), ...bearingFit(a, b), ...threadFit(a, b), ...tSlotFit(a, b), ...axialFace(a, b), ...rollingContact(a, b)];\n}\n\n/** Parameters `checkPairDrive` compares itself, by protocol: the pairwise overlap check skips them for that pair. */\nconst DRIVE_CHECKED: Record<string, string[]> = {\n gear_mesh: [\"gear_module\", \"pressure_angle\", \"tooth_count\", \"face_width\"],\n bearing_fit: [\"bearing_od\", \"bearing_width\", \"bearing_bore\", \"seat_depth\", \"load_rating\"],\n // `length` is a screw's length under the head or an insert's length (what fastener stacks read), not a fit\n thread: [\"fastener_diameter\", \"thread_pitch\", \"thread_length\", \"length\"],\n t_slot: [\"slot_opening\", \"channel_width\", \"channel_depth\", \"slot_length\", \"neck_width\", \"head_width\", \"head_height\"],\n axial_stop: [\"face_od\", \"face_id\", \"axial_length\"],\n rolling_contact: [\"wheel_diameter\", \"tread_width\", \"load_rating\", \"min_wheel_diameter\"],\n};\n\n/** The drive-checked parameters of this pair (both ends speak the same drive protocol). */\nexport function driveCheckedParams(a: InterfaceDef, b: InterfaceDef): Set<string> {\n for (const [protocol, ids] of Object.entries(DRIVE_CHECKED)) if (speaks(a, protocol) && speaks(b, protocol)) return new Set(ids);\n return new Set();\n}\n\nconst TOL_MM = 0.05;\n\nconst speaks = (iface: InterfaceDef, type: string) => iface.protocols.some((p) => p.type === type);\nconst rolesOf = (iface: InterfaceDef, type: string) => new Set(iface.protocols.filter((p) => p.type === type).flatMap((p) => p.roles));\nconst trait = (iface: InterfaceDef, type: string): Record<string, unknown> => (iface.traits?.find((t) => t.type === type)?.params as Record<string, unknown>) ?? {};\nconst range = (iface: InterfaceDef, id: string): [number, number] | undefined => {\n const p = iface.parameters?.find((x) => x.id === id);\n return (p && getEffectiveRange(p)) ?? undefined;\n};\nconst value = (iface: InterfaceDef, id: string): number | undefined => {\n const r = range(iface, id);\n return r ? r[0] : undefined;\n};\nconst fmt = (v: number) => `${+v.toFixed(3)}`;\nconst fmtR = (r: [number, number]) => (Math.abs(r[1] - r[0]) <= 1e-9 ? fmt(r[0]) : `${fmt(r[0])}–${fmt(r[1])}`);\nconst diag = (severity: Diagnostic[\"severity\"], code: string, message: string, a: InterfaceDef, b: InterfaceDef): Diagnostic => ({ severity, code, message, refs: [a.id, b.id] });\nconst overlaps = (x: [number, number], y: [number, number], tol: number) => x[0] <= y[1] + tol && y[0] <= x[1] + tol;\n\n// ---------------------------------------------------------------------------\n// Gears\n// ---------------------------------------------------------------------------\n\n/** Kinds that mesh with each other (unordered). */\nconst GEAR_MATES: Record<string, string[]> = {\n spur: [\"spur\", \"internal\", \"rack\"],\n helical: [\"helical\", \"internal\", \"rack\"],\n internal: [\"spur\", \"helical\"],\n rack: [\"spur\", \"helical\"],\n bevel: [\"bevel\"],\n worm: [\"worm_wheel\"],\n worm_wheel: [\"worm\"],\n};\n\nfunction gearMesh(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"gear_mesh\") || !speaks(b, \"gear_mesh\")) return [];\n const [ta, tb] = [trait(a, \"gear_mesh\"), trait(b, \"gear_mesh\")];\n const [ka, kb] = [String(ta.kind ?? \"spur\"), String(tb.kind ?? \"spur\")];\n const err = (why: string) => [diag(\"error\", \"gear_mesh\", why, a, b)];\n const [ma, mb] = [value(a, \"gear_module\"), value(b, \"gear_module\")];\n if (ma !== undefined && mb !== undefined && Math.abs(ma - mb) > 1e-3 * Math.max(ma, mb)) return err(`module ${fmt(ma)} mm and module ${fmt(mb)} mm teeth do not mesh`);\n const [pa, pb] = [value(a, \"pressure_angle\"), value(b, \"pressure_angle\")];\n if (pa !== undefined && pb !== undefined && Math.abs(pa - pb) > 0.01) return err(`pressure angles ${fmt(pa)}° and ${fmt(pb)}° do not mesh`);\n if (!(GEAR_MATES[ka] ?? []).includes(kb)) return err(`a ${ka.replace(/_/g, \" \")} gear does not mesh with a ${kb.replace(/_/g, \" \")} gear`);\n const [za, zb] = [value(a, \"tooth_count\"), value(b, \"tooth_count\")];\n if (ka === \"helical\" && kb === \"helical\") {\n const [ha, hb] = [Number(ta.helix_angle_deg), Number(tb.helix_angle_deg)];\n if (Math.abs(ha - hb) > 0.01) return err(`helix angles ${fmt(ha)}° and ${fmt(hb)}° differ: helical gears on parallel shafts need the same angle`);\n if (ta.hand !== undefined && ta.hand === tb.hand) return err(`both are ${ta.hand}-hand: helical gears on parallel shafts need opposite hands`);\n }\n if ((ka === \"internal\" || kb === \"internal\") && za !== undefined && zb !== undefined) {\n const [ring, pinion] = ka === \"internal\" ? [za, zb] : [zb, za];\n if (pinion >= ring) return err(`a ${pinion}-tooth pinion does not fit inside a ${ring}-tooth internal gear`);\n }\n if (ma === undefined || za === undefined || zb === undefined) return [];\n const parts: string[] = [];\n if (ka === \"rack\" || kb === \"rack\") {\n const z = ka === \"rack\" ? zb : za;\n parts.push(`the pinion's axis sits ${fmt((ma * z) / 2)} mm from the rack's pitch line; ${fmt(Math.PI * ma * z)} mm of travel per turn`);\n } else if (ka === \"worm\" || kb === \"worm\") {\n const [worm, wheel] = ka === \"worm\" ? [za, zb] : [zb, za];\n parts.push(`ratio ${fmt(wheel / worm)}:1 (${wheel} teeth, ${worm} start${worm === 1 ? \"\" : \"s\"})`);\n } else {\n const internal = ka === \"internal\" || kb === \"internal\";\n const beta = ka === \"helical\" ? (Number(ta.helix_angle_deg) * Math.PI) / 180 : 0;\n const centre = ((internal ? Math.abs(za - zb) : za + zb) * ma) / (2 * Math.cos(beta));\n parts.push(`${za} teeth to ${zb}: ratio ${fmt(Math.max(za, zb) / Math.min(za, zb))}:1; centre distance ${fmt(centre)} mm`);\n }\n const [fa, fb] = [value(a, \"face_width\"), value(b, \"face_width\")];\n if (fa !== undefined && fb !== undefined) parts.push(`engaged face width ${fmt(Math.min(fa, fb))} mm`);\n return [diag(\"info\", \"gear_mesh\", parts.join(\"; \"), a, b)];\n}\n\n// ---------------------------------------------------------------------------\n// Bearings\n// ---------------------------------------------------------------------------\n\nfunction bearingFit(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"bearing_fit\") || !speaks(b, \"bearing_fit\")) return [];\n const [bearing, seat] = rolesOf(a, \"bearing_fit\").has(\"bearing\") ? [a, b] : [b, a];\n if (!rolesOf(seat, \"bearing_fit\").has(\"seat\") || !rolesOf(bearing, \"bearing_fit\").has(\"bearing\")) return [];\n const out: Diagnostic[] = [];\n const [od, seatOd] = [range(bearing, \"bearing_od\"), range(seat, \"bearing_od\")];\n if (od && seatOd && !overlaps(od, seatOd, TOL_MM)) {\n return [diag(\"error\", \"bearing_fit\", `a Ø${fmtR(od)} mm bearing does not fit a Ø${fmtR(seatOd)} mm seat`, bearing, seat)];\n }\n const [tb, ts] = [trait(bearing, \"bearing_fit\"), trait(seat, \"bearing_fit\")];\n const kinds = Array.isArray(ts.kinds) ? ts.kinds.map(String) : [];\n if (kinds.length && tb.kind !== undefined && !kinds.includes(String(tb.kind))) {\n out.push(diag(\"warning\", \"bearing_fit\", `the seat is made for ${kinds.join(\" or \")} bearings, not a ${tb.kind} bearing`, bearing, seat));\n }\n const [w, depth] = [value(bearing, \"bearing_width\"), value(seat, \"seat_depth\")];\n if (w !== undefined && depth !== undefined && !ts.through && w > depth + TOL_MM) {\n const flange = tb.flange_od_mm !== undefined ? \" (its flange outside the seat)\" : \"\";\n out.push(diag(\"info\", \"bearing_fit\", `the ${fmt(w)} mm wide bearing stands ${fmt(w - depth)} mm proud of the ${fmt(depth)} mm deep seat${flange}`, bearing, seat));\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Threads\n// ---------------------------------------------------------------------------\n\nfunction threadFit(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"thread\") || !speaks(b, \"thread\")) return [];\n const [ta, tb] = [trait(a, \"thread\"), trait(b, \"thread\")];\n const name = (t: Record<string, unknown>) => String(t.designation ?? \"thread\");\n const err = (why: string) => [diag(\"error\", \"thread_fit\", `${name(ta)} and ${name(tb)} do not fit: ${why}`, a, b)];\n const [da, db] = [range(a, \"fastener_diameter\"), range(b, \"fastener_diameter\")];\n if (da && db && !overlaps(da, db, TOL_MM)) return err(`diameters ${fmtR(da)} mm and ${fmtR(db)} mm`);\n const [pa, pb] = [range(a, \"thread_pitch\"), range(b, \"thread_pitch\")];\n if (pa && pb && !overlaps(pa, pb, 0.005)) return err(`pitches ${fmtR(pa)} mm and ${fmtR(pb)} mm`);\n if ((ta.hand ?? \"right\") !== (tb.hand ?? \"right\")) return err(`a ${ta.hand ?? \"right\"}-hand and a ${tb.hand ?? \"right\"}-hand thread`);\n const [la, lb] = [value(a, \"thread_length\"), value(b, \"thread_length\")];\n if (la === undefined || lb === undefined) return [];\n const internal = rolesOf(a, \"thread\").has(\"internal\") ? a : b;\n const ti = internal === a ? ta : tb;\n const [li, le] = internal === a ? [la, lb] : [lb, la];\n const engaged = Math.min(li, le);\n return [diag(\"info\", \"thread_fit\", `up to ${fmt(engaged)} mm of thread engaged (${fmt(le)} mm external, ${fmt(li)} mm internal${ti.through ? \", through\" : \"\"})`, a, b)];\n}\n\n// ---------------------------------------------------------------------------\n// T-slots\n// ---------------------------------------------------------------------------\n\nconst normProfile = (s: unknown) => String(s ?? \"\").replace(/[\\s_-]/g, \"\").toLowerCase();\n\nfunction tSlotFit(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"t_slot\") || !speaks(b, \"t_slot\")) return [];\n const [track, insert] = rolesOf(a, \"t_slot\").has(\"track\") ? [a, b] : [b, a];\n if (!rolesOf(track, \"t_slot\").has(\"track\") || !rolesOf(insert, \"t_slot\").has(\"insert\")) return [];\n const [tt, ti] = [trait(track, \"t_slot\"), trait(insert, \"t_slot\")];\n const err = (why: string) => diag(\"error\", \"t_slot_fit\", why, track, insert);\n const out: Diagnostic[] = [];\n const opening = value(track, \"slot_opening\");\n const [neck, head, height] = [value(insert, \"neck_width\"), value(insert, \"head_width\"), value(insert, \"head_height\")];\n const [cw, cd] = [value(track, \"channel_width\"), value(track, \"channel_depth\")];\n let compared = false;\n if (opening !== undefined && neck !== undefined) {\n compared = true;\n if (neck > opening + TOL_MM) out.push(err(`the ${fmt(neck)} mm neck does not pass the ${fmt(opening)} mm opening`));\n }\n if (opening !== undefined && head !== undefined) {\n compared = true;\n if (head <= opening + TOL_MM) out.push(err(`the ${fmt(head)} mm head passes through the ${fmt(opening)} mm opening: the lips do not hold it`));\n }\n if (cw !== undefined && head !== undefined) {\n compared = true;\n if (head > cw + TOL_MM) out.push(err(`the ${fmt(head)} mm head is wider than the ${fmt(cw)} mm channel`));\n }\n if (cd !== undefined && height !== undefined) {\n compared = true;\n if (height > cd + TOL_MM) out.push(err(`the ${fmt(height)} mm head is taller than the ${fmt(cd)} mm channel is deep`));\n }\n const [et, ei] = [Array.isArray(tt.entry) ? tt.entry.map(String) : [], Array.isArray(ti.entry) ? ti.entry.map(String) : []];\n if (et.length && ei.length && !ei.some((e) => et.includes(e))) out.push(err(`the insert goes in ${ei.join(\" or \")}; the track takes ${et.join(\" or \")}`.replace(/drop_in/g, \"drop-in\").replace(/\\bend\\b/g, \"from an end\")));\n if (!compared && tt.profile !== undefined && ti.profile !== undefined && normProfile(tt.profile) !== normProfile(ti.profile)) {\n out.push(diag(\"warning\", \"t_slot_fit\", `the track is a ${tt.profile} slot and the insert is made for ${ti.profile}: no dimensions to compare`, track, insert));\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Axial faces\n// ---------------------------------------------------------------------------\n\nfunction axialFace(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"axial_stop\") || !speaks(b, \"axial_stop\")) return [];\n const [oa, ob, ia, ib] = [value(a, \"face_od\"), value(b, \"face_od\"), value(a, \"face_id\"), value(b, \"face_id\")];\n if (oa === undefined || ob === undefined) return [];\n const contactOd = Math.min(oa, ob);\n const contactId = Math.max(ia ?? 0, ib ?? 0);\n if (contactOd <= contactId + TOL_MM) {\n return [diag(\"error\", \"axial_face\", `the faces do not touch: a Ø${fmt(contactOd)} mm face passes inside the other's Ø${fmt(contactId)} mm bore`, a, b)];\n }\n const [ta, tb] = [trait(a, \"axial_stop\"), trait(b, \"axial_stop\")];\n if (ta.turns_with !== undefined && tb.turns_with !== undefined && ta.turns_with !== tb.turns_with) {\n return [diag(\"warning\", \"axial_face\", `one face turns with the ${ta.turns_with}, the other with the ${tb.turns_with}: they rub (touch only the bearing's inner ring, or use a thrust washer)`, a, b)];\n }\n return [];\n}\n\n// ---------------------------------------------------------------------------\n// Wheels\n// ---------------------------------------------------------------------------\n\nfunction rollingContact(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"rolling_contact\") || !speaks(b, \"rolling_contact\")) return [];\n const [wheel, surface] = rolesOf(a, \"rolling_contact\").has(\"wheel\") ? [a, b] : [b, a];\n const [d, min] = [value(wheel, \"wheel_diameter\"), value(surface, \"min_wheel_diameter\")];\n if (d !== undefined && min !== undefined && d + TOL_MM < min) return [diag(\"error\", \"rolling_contact\", `a Ø${fmt(d)} mm wheel is smaller than the Ø${fmt(min)} mm the surface is made for`, wheel, surface)];\n return [];\n}\n","import type { InterfaceDef } from \"../types/interface.js\";\nimport type { Diagnostic } from \"./types.js\";\nimport { getEffectiveRange } from \"../parameters/range.js\";\n\n/**\n * Pair checks for serial links, IR remotes, AC mains, coils, piezo loads\n * and battery charge ports (`protocols/serial.ts`,\n * `protocols/actuation.ts`, `protocols/battery.ts`):\n *\n * - `rs485_duplex` (error): a half-duplex port against a full-duplex one.\n * - `rs232_null_modem` (warning): two DTEs or two DCEs: the link needs a\n * null-modem (crossover) cable.\n * - `ppm_channels` (warning): an input that decodes fewer channels than the\n * output sends drops the rest. `ppm_polarity` (error): positive pulses\n * into an input that takes only negative ones, or the reverse.\n * - `ir_link`: a carrier outside the receiver's band (a warning within 10 %,\n * where range drops; an error beyond); an emitter wavelength outside the\n * receiver's band (warning); no coding protocol in common (error).\n * - `ac_power`: a plug that does not go into the socket (IEC 60320 and NEMA\n * pairs; error); an input that needs protective earth on an outlet\n * without one (error).\n * - `inductive_load`: a coil that draws more than the channel is rated for\n * (error); nothing that clamps the turn-off spike (warning, or info when\n * the channel does not say); a polarised coil on a channel that reverses\n * (warning).\n * - `piezo_drive`: a driver whose lowest output voltage is above what the\n * element takes (error), or that can be set above it (warning); an element\n * count the driver has too few outputs for (error).\n * - `battery_charge`: no chemistry in common (error); a charge voltage above\n * the battery's (error), one that can be set above it (warning) or one\n * below it (warning: the battery is not filled); a charge current above\n * what the battery accepts (error), or one that can be set above it\n * (warning).\n */\nexport function checkPairSignals(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n return [...rs485(a, b), ...rs232(a, b), ...ppm(a, b), ...irLink(a, b), ...acPower(a, b), ...inductive(a, b), ...piezo(a, b), ...batteryCharge(a, b)];\n}\n\nconst SIGNAL_CHECKED: Record<string, string[]> = {\n ppm: [\"channel_count\"],\n ir_remote: [\"ir_carrier\", \"wavelength\"],\n inductive_load: [\"coil_current\", \"coil_resistance\"],\n piezo_drive: [\"drive_voltage\"],\n battery_charge: [\"charge_voltage\", \"charge_current\"],\n};\n\n/** Parameters `checkPairSignals` compares itself for this pair, which the overlap check skips. */\nexport function signalCheckedParams(a: InterfaceDef, b: InterfaceDef): Set<string> {\n for (const [protocol, ids] of Object.entries(SIGNAL_CHECKED)) if (speaks(a, protocol) && speaks(b, protocol)) return new Set(ids);\n return new Set();\n}\n\nconst speaks = (iface: InterfaceDef, type: string) => iface.protocols.some((p) => p.type === type);\nconst rolesOf = (iface: InterfaceDef, type: string) => new Set(iface.protocols.filter((p) => p.type === type).flatMap((p) => p.roles));\nconst trait = (iface: InterfaceDef, type: string): Record<string, unknown> => (iface.traits?.find((t) => t.type === type)?.params as Record<string, unknown>) ?? {};\nconst range = (iface: InterfaceDef, id: string): [number, number] | undefined => {\n const p = iface.parameters?.find((x) => x.id === id);\n return (p && getEffectiveRange(p)) ?? undefined;\n};\nconst fmt = (v: number) => `${+v.toFixed(3)}`;\nconst fmtR = (r: [number, number]) => (Math.abs(r[1] - r[0]) <= 1e-9 ? fmt(r[0]) : `${fmt(r[0])}–${fmt(r[1])}`);\nconst diag = (severity: Diagnostic[\"severity\"], code: string, message: string, a: InterfaceDef, b: InterfaceDef): Diagnostic => ({ severity, code, message, refs: [a.id, b.id] });\nconst pick = (a: InterfaceDef, b: InterfaceDef, type: string, role: string): [InterfaceDef, InterfaceDef] | undefined =>\n rolesOf(a, type).has(role) ? [a, b] : rolesOf(b, type).has(role) ? [b, a] : undefined;\n\nfunction rs485(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"rs485\") || !speaks(b, \"rs485\")) return [];\n const [da, db] = [trait(a, \"rs485\").duplex ?? \"half\", trait(b, \"rs485\").duplex ?? \"half\"];\n return da === db ? [] : [diag(\"error\", \"rs485_duplex\", `a ${da}-duplex RS-485 port does not link with a ${db}-duplex one without an adapter`, a, b)];\n}\n\nfunction rs232(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"rs232\") || !speaks(b, \"rs232\")) return [];\n const ra = rolesOf(a, \"rs232\");\n const rb = rolesOf(b, \"rs232\");\n const both = (r: string) => ra.has(r) && rb.has(r) && ra.size === 1 && rb.size === 1;\n if (both(\"dte\") || both(\"dce\")) {\n const r = [...ra][0].toUpperCase();\n return [diag(\"warning\", \"rs232_null_modem\", `two ${r}s: the link needs a null-modem cable (TXD to RXD, RTS to CTS, DTR to DSR crossed)`, a, b)];\n }\n return [];\n}\n\nfunction ppm(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"ppm\") || !speaks(b, \"ppm\")) return [];\n const p = pick(a, b, \"ppm\", \"output\");\n if (!p) return [];\n const [out, inp] = p;\n const res: Diagnostic[] = [];\n const [co, ci] = [range(out, \"channel_count\"), range(inp, \"channel_count\")];\n if (co && ci && co[1] > ci[1]) res.push(diag(\"warning\", \"ppm_channels\", `the output sends ${fmt(co[1])} channels; the input decodes ${fmt(ci[1])}, so the last ${fmt(co[1] - ci[1])} are lost`, out, inp));\n const [po, pi] = [trait(out, \"ppm\").polarity, trait(inp, \"ppm\").polarity];\n if (po !== undefined && pi !== undefined && po !== \"either\" && pi !== \"either\" && po !== pi) res.push(diag(\"error\", \"ppm_polarity\", `${po} pulses into an input that takes ${pi} pulses (an inverter between them fixes it)`, out, inp));\n return res;\n}\n\nfunction irLink(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"ir_remote\") || !speaks(b, \"ir_remote\")) return [];\n const p = pick(a, b, \"ir_remote\", \"transmitter\");\n if (!p || !rolesOf(p[1], \"ir_remote\").has(\"receiver\")) return [];\n const [tx, rx] = p;\n const out: Diagnostic[] = [];\n const [ct, cr] = [range(tx, \"ir_carrier\"), range(rx, \"ir_carrier\")];\n if (ct && cr) {\n const f = (ct[0] + ct[1]) / 2;\n const off = f < cr[0] ? (cr[0] - f) / cr[0] : f > cr[1] ? (f - cr[1]) / cr[1] : 0;\n if (off > 0.1) out.push(diag(\"error\", \"ir_link\", `a ${fmtR(ct)} kHz carrier is outside the receiver's ${fmtR(cr)} kHz band`, tx, rx));\n else if (off > 0.005) out.push(diag(\"warning\", \"ir_link\", `a ${fmtR(ct)} kHz carrier is ${fmt(off * 100)} % off the receiver's ${fmtR(cr)} kHz band: it works at a shorter range`, tx, rx));\n }\n const [wt, wr] = [range(tx, \"wavelength\"), range(rx, \"wavelength\")];\n if (wt && wr && wr[1] > wr[0] && (wt[1] < wr[0] || wt[0] > wr[1])) out.push(diag(\"warning\", \"ir_link\", `the ${fmtR(wt)} nm emitter is outside the receiver's ${fmtR(wr)} nm band`, tx, rx));\n const [pt, pr] = [trait(tx, \"ir_remote\").protocols, trait(rx, \"ir_remote\").protocols];\n if (Array.isArray(pt) && Array.isArray(pr) && pt.length && pr.length) {\n const norm = (s: unknown) => String(s).replace(/[\\s_-]/g, \"\").toLowerCase();\n if (!pt.some((x) => pr.map(norm).includes(norm(x)))) out.push(diag(\"error\", \"ir_link\", `the transmitter codes ${pt.join(\", \")}; the receiver decodes ${pr.join(\", \")}`, tx, rx));\n }\n return out;\n}\n\n/** IEC 60320 inlets (male) and the connectors that go into them; NEMA receptacles and the plugs they take. */\nconst SOCKET_TAKES: Record<string, string[]> = {\n c2: [\"c1\"],\n c4: [\"c3\"],\n c6: [\"c5\"],\n c8: [\"c7\"],\n c14: [\"c13\", \"c15\"],\n c16: [\"c15\"],\n c18: [\"c17\"],\n c20: [\"c19\", \"c21\"],\n c22: [\"c21\"],\n \"nema1-15r\": [\"nema1-15p\"],\n \"nema5-15r\": [\"nema1-15p\", \"nema5-15p\"],\n \"nema5-20r\": [\"nema1-15p\", \"nema5-15p\", \"nema5-20p\"],\n \"nema6-15r\": [\"nema6-15p\"],\n \"nema6-20r\": [\"nema6-15p\", \"nema6-20p\"],\n};\nconst normPlug = (s: unknown): string | undefined => {\n const t = String(s ?? \"\").toLowerCase().replace(/\\s+/g, \"\");\n const iec = /(?:^|iec(?:60320)?-?)c(\\d{1,2})(?![\\d])/.exec(t);\n if (iec) return `c${iec[1]}`;\n const nema = /nema(\\d{1,2}-\\d{2}[pr])/.exec(t);\n return nema ? `nema${nema[1]}` : undefined;\n};\nconst isSocket = (k: string) => k in SOCKET_TAKES;\nconst fits = (x: string, y: string) => (SOCKET_TAKES[x] ?? []).includes(y) || (SOCKET_TAKES[y] ?? []).includes(x);\n\nfunction acPower(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"ac_power\") || !speaks(b, \"ac_power\")) return [];\n const out: Diagnostic[] = [];\n const [ta, tb] = [trait(a, \"ac_power\"), trait(b, \"ac_power\")];\n const [pa, pb] = [normPlug(ta.plug), normPlug(tb.plug)];\n // a cord's two ends are compared against what they plug into: both ends known and neither takes the other\n if (pa && pb && (isSocket(pa) || isSocket(pb)) && !fits(pa, pb)) out.push(diag(\"error\", \"ac_power\", `a ${ta.plug} does not mate with a ${tb.plug}`, a, b));\n const p = pick(a, b, \"ac_power\", \"input\");\n if (p) {\n const [inp, src] = p;\n if (trait(inp, \"ac_power\").earth === true && trait(src, \"ac_power\").earth === false) out.push(diag(\"error\", \"ac_power\", \"the input needs protective earth; the outlet has none\", inp, src));\n }\n return out;\n}\n\nfunction inductive(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"inductive_load\") || !speaks(b, \"inductive_load\")) return [];\n const p = pick(a, b, \"inductive_load\", \"driver\");\n if (!p || !rolesOf(p[1], \"inductive_load\").has(\"load\")) return [];\n const [drv, load] = p;\n const out: Diagnostic[] = [];\n const [cur, max] = [range(load, \"coil_current\"), range(drv, \"max_current\")];\n if (cur && max && cur[1] > max[1] + 1e-9) out.push(diag(\"error\", \"inductive_load\", `the coil draws ${fmt(cur[1])} A; the channel is rated for ${fmt(max[1])} A`, drv, load));\n const [td, tl] = [trait(drv, \"inductive_drive\"), trait(load, \"inductive_load\")];\n const loadClamps = tl.suppression !== undefined && tl.suppression !== \"none\";\n if (!loadClamps && tl.suppression === \"none\" && td.flyback === \"none\") out.push(diag(\"warning\", \"inductive_load\", \"neither the coil nor the channel has a flyback diode or clamp: add one across the coil\", drv, load));\n else if (!loadClamps && td.flyback === undefined && td.switching !== \"relay\") out.push(diag(\"info\", \"inductive_load\", \"the channel does not say whether it clamps the coil's turn-off spike\", drv, load));\n if (tl.polarized === true && td.switching === \"h_bridge\") out.push(diag(\"warning\", \"inductive_load\", \"the channel can reverse the coil, whose suppression is polarised: drive it one way only\", drv, load));\n return out;\n}\n\nconst EPS = 1e-9;\n\nfunction piezo(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"piezo_drive\") || !speaks(b, \"piezo_drive\")) return [];\n const p = pick(a, b, \"piezo_drive\", \"driver\");\n if (!p || !rolesOf(p[1], \"piezo_drive\").has(\"load\")) return [];\n const [drv, load] = p;\n const out: Diagnostic[] = [];\n const [vd, vl] = [range(drv, \"drive_voltage\"), range(load, \"drive_voltage\")];\n if (vd && vl) {\n if (vd[0] > vl[1] + EPS) out.push(diag(\"error\", \"piezo_drive\", `the driver puts out ${fmtR(vd)} V peak to peak; the element takes ${fmt(vl[1])}`, drv, load));\n else if (vd[1] > vl[1] + EPS) out.push(diag(\"warning\", \"piezo_drive\", `the driver can put out ${fmt(vd[1])} V peak to peak; the element takes ${fmt(vl[1])}: set the amplitude no higher`, drv, load));\n }\n const [outputs, elements] = [trait(drv, \"piezo_drive\").outputs, trait(load, \"piezo_load\").elements];\n if (typeof outputs === \"number\" && typeof elements === \"number\" && elements > outputs) {\n out.push(diag(\"error\", \"piezo_drive\", `the load has ${elements} elements driven separately; the driver has ${outputs} output${outputs === 1 ? \"\" : \"s\"}`, drv, load));\n }\n return out;\n}\n\nfunction batteryCharge(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"battery_charge\") || !speaks(b, \"battery_charge\")) return [];\n const p = pick(a, b, \"battery_charge\", \"charger\");\n if (!p || !rolesOf(p[1], \"battery_charge\").has(\"battery\")) return [];\n const [chg, bat] = p;\n const out: Diagnostic[] = [];\n const [cc, cb] = [trait(chg, \"battery_charge\").chemistry, trait(bat, \"battery_charge\").chemistry];\n if (Array.isArray(cc) && Array.isArray(cb) && cc.length && cb.length) {\n const norm = (s: unknown) => String(s).replace(/[\\s_-]/g, \"\").toLowerCase();\n if (!cb.some((x) => cc.map(norm).includes(norm(x)))) out.push(diag(\"error\", \"battery_charge\", `the charger charges ${cc.join(\", \")}; the battery is ${cb.join(\", \")}`, chg, bat));\n }\n const [vc, vb] = [range(chg, \"charge_voltage\"), range(bat, \"charge_voltage\")];\n if (vc && vb) {\n if (vc[0] > vb[1] + EPS) out.push(diag(\"error\", \"battery_charge\", `the charger charges to ${fmtR(vc)} V; the battery's charge voltage is ${fmtR(vb)} V`, chg, bat));\n else if (vc[1] > vb[1] + EPS) out.push(diag(\"warning\", \"battery_charge\", `the charger can be set to ${fmt(vc[1])} V; the battery's charge voltage is ${fmtR(vb)} V: set it no higher`, chg, bat));\n else if (vc[1] < vb[0] - EPS) out.push(diag(\"warning\", \"battery_charge\", `the charger charges to ${fmtR(vc)} V; the battery's charge voltage is ${fmtR(vb)} V, so it is not charged fully`, chg, bat));\n }\n const [ic, ib] = [range(chg, \"charge_current\"), range(bat, \"charge_current\")];\n if (ic && ib) {\n if (ic[0] > ib[1] + EPS) out.push(diag(\"error\", \"battery_charge\", `the charger charges at ${fmtR(ic)} A; the battery accepts ${fmt(ib[1])} A`, chg, bat));\n else if (ic[1] > ib[1] + EPS) out.push(diag(\"warning\", \"battery_charge\", `the charger can charge at ${fmt(ic[1])} A; the battery accepts ${fmt(ib[1])} A: set the charge current no higher`, chg, bat));\n }\n return out;\n}\n","import type { SlotMatch } from \"../types/interface.js\";\n\n/**\n * DRC result model — the serializable contract between the engine and every\n * renderer (web PairScene, ASCII, JSON export). See docs/drc-implementation-plan.md\n * Phase 1 and docs/visualizer-spec.md §10.\n *\n * Everything here must survive JSON.parse(JSON.stringify(x)) unchanged.\n */\n\nexport type Tier = \"protocol\" | \"compositional\" | \"inferred\" | \"manual\" | \"none\";\n\nexport const TIER_CONFIDENCE: Record<Tier, number> = {\n protocol: 1.0,\n compositional: 0.8,\n inferred: 0.5,\n manual: 0.3,\n none: 0.0,\n};\n\nexport type ConnectionState =\n | \"valid\"\n | \"valid_inferred\"\n | \"valid_manual\"\n | \"configuration_needed\"\n | \"warning\"\n | \"incompatible\"\n | \"not_configured\";\n\nexport interface Diagnostic {\n severity: \"error\" | \"warning\" | \"info\";\n code: string;\n message: string;\n /** ids of the things this diagnostic is about (param ids, interface ids, slot ids) */\n refs?: string[];\n}\n\n/**\n * Path from a module's surface down to a region: [\"actuator_port_1\", \"uart\"].\n * The attachment altitude of a match is where this path ends — NOT just an\n * interface id (visualizer-spec §4 rule 1).\n */\nexport type RegionPath = string[];\n\nexport interface EndpointRef {\n moduleId: string;\n regionPath: RegionPath;\n}\n\nexport interface EndpointAttachment extends EndpointRef {\n /** role played on the matched protocol (\"master\", \"device\", \"input\", …) */\n role: string;\n /** derived from regionPath.length; sub↔top asymmetry is legal */\n altitude: \"top\" | \"sub\";\n}\n\n/** One end of a conductor: a leaf interface, plus how it was reached. */\nexport interface LeafRef {\n moduleId: string;\n interfaceId: string;\n /** slot on the composed parent this leaf fills (absent for bare leaves) */\n slotId?: string;\n /** physical pin label if known (\"D16\", \"pin 3\") */\n pin?: string;\n}\n\n/** One conductor / wire inside a connection. */\nexport interface SubLinkResult {\n id: string;\n from: LeafRef;\n to: LeafRef;\n method: \"protocol\" | \"manual\" | \"inferred\";\n locked: boolean;\n /** split fulfillment: which module actually supplies this slot */\n provenance?: { moduleId: string };\n /** mirrored-ordering hint: from/to render at the same row index */\n rowPair: number;\n diagnostics: Diagnostic[];\n}\n\nexport interface UnresolvedSlot {\n moduleId: string;\n regionPath: RegionPath;\n slotId: string;\n required: boolean;\n match: SlotMatch;\n}\n\n/** A realized pairing between two regions — one shared region in the B8 view. */\nexport interface ConnectionResult {\n id: string;\n a: EndpointAttachment;\n b: EndpointAttachment;\n topology: \"wire\" | \"bus\" | \"split\" | \"or\";\n /** protocol type the pairing matched on */\n protocol: string;\n tier: Tier;\n confidence: number;\n state: ConnectionState;\n subLinks: SubLinkResult[];\n /** required slots with no counterpart → amber sockets, CONFIGURATION_NEEDED */\n unresolvedSlots: UnresolvedSlot[];\n /** bus multi-drop extras beyond a/b */\n drops?: EndpointAttachment[];\n diagnostics: Diagnostic[];\n}\n\n/** One entry per region node per module — \"everything is shown\" (spec §5.1). */\nexport interface InterfaceCensusEntry {\n moduleId: string;\n regionPath: RegionPath;\n /** protocol summary for rail rendering (\"i2c · master, slave\") */\n label: string;\n status: \"connected\" | \"partial\" | \"compatible\" | \"no_counterpart\" | \"conflict\";\n /** donut data for partially-engaged parents */\n engagement?: { engaged: number; total: number };\n /** human-readable qualifier (\"compatible: d3\", \"∅ range vs power_5v_out\") */\n reason?: string;\n}\n\n/** A compatible-but-unconnected pairing — ◉ ports and dashed potential bands. */\nexport interface PotentialConnection {\n a: EndpointRef;\n b: EndpointRef;\n protocol: string;\n tier: Tier;\n confidence: number;\n /** true when every checked parameter is compatible */\n clean: boolean;\n diagnostics: Diagnostic[];\n}\n\n/**\n * Capacity findings (Phase 6). Shaped for scoped rule packs: `ruleId` names the\n * rule that produced the report and `scope` names where that rule was declared\n * (domain pack, protocol def, interface), so domains with different physics\n * (current vs. flow vs. bandwidth) reuse the same report shape.\n */\nexport interface CapacityReport {\n id: string;\n ruleId: string;\n scope: { level: \"domain\" | \"protocol\" | \"interface\"; id: string };\n resource: string;\n unit: string;\n used: number;\n limit: number;\n contributors: EndpointRef[];\n severity: \"error\" | \"warning\" | \"info\";\n message: string;\n}\n\n/** Explicit user-authored link (Phase 4). Locked links always win over derived. */\nexport interface ManualLinkDef {\n id: string;\n from: LeafRef;\n to: LeafRef;\n locked?: boolean;\n}\n\nexport interface PairVerdict {\n state: ConnectionState;\n counts: {\n connections: number;\n valid: number;\n warnings: number;\n errors: number;\n configurationNeeded: number;\n potentials: number;\n };\n}\n\nexport interface ModuleSummary {\n id: string;\n name: string;\n interfaceCount: number;\n}\n\nexport interface PairValidationResult {\n modules: { a: ModuleSummary; b: ModuleSummary };\n connections: ConnectionResult[];\n census: InterfaceCensusEntry[];\n potentials: PotentialConnection[];\n capacity: CapacityReport[];\n verdict: PairVerdict;\n}\n\nexport interface ValidatePairOptions {\n /** ghost third-party modules for split fulfillment (Phase 3+) */\n context?: import(\"../types/module.js\").ModuleDef[];\n /** user-authored links overlaid on discovery (Phase 4) */\n manualLinks?: ManualLinkDef[];\n /** compute census suggestions / potentials (default true) */\n includePotentials?: boolean;\n /**\n * The pair is a link someone made (a stored or derived system link), not a\n * discovery: pairings that never mate (two shafts, two bores) are accepted\n * as connections so their diagnostics say why. Discovery lists them as\n * potentials only.\n */\n explicit?: boolean;\n}\n","import type { ModuleDef } from \"../types/module.js\";\nimport { matchProtocols, type ProtocolMatchResult } from \"../matching/protocol-match.js\";\nimport { areRolesCompatible } from \"../matching/roles.js\";\nimport {\n buildRegionTree,\n flattenTree,\n descendants,\n pickProfile,\n type RegionNode,\n} from \"./region-tree.js\";\nimport { checkPairParameters } from \"./param-check.js\";\nimport { checkPairJoints, neverMates, pairCheckedParams } from \"./joint-check.js\";\nimport { checkPairLinks, linkCheckedParams } from \"./link-check.js\";\nimport { checkPairDrive, driveCheckedParams } from \"./drive-check.js\";\nimport { checkPairSignals, signalCheckedParams } from \"./signal-check.js\";\nimport type {\n ConnectionResult,\n ConnectionState,\n Diagnostic,\n InterfaceCensusEntry,\n LeafRef,\n PairValidationResult,\n PotentialConnection,\n SubLinkResult,\n UnresolvedSlot,\n ValidatePairOptions,\n} from \"./types.js\";\nimport { TIER_CONFIDENCE } from \"./types.js\";\n\ninterface Candidate {\n a: RegionNode;\n b: RegionNode;\n match: ProtocolMatchResult;\n diagnostics: Diagnostic[];\n clean: boolean;\n /** Never auto-connected (two shafts, two bores): a potential only, unless the pair is explicit. */\n potentialOnly: boolean;\n}\n\n/**\n * Validate a pair of modules: discover connections across both region trees,\n * resolve conductors, run parameter checks, and produce the full serializable\n * result the visualizer renders from (docs/drc-implementation-plan.md Phase 2).\n *\n * v1 scope: protocol-tier matching only. Compositional/inferred discovery\n * (Phase 3a), manual links (Phase 4), bridges (Phase 5), and capacity (Phase 6)\n * layer on top of this pipeline.\n */\nexport function validatePair(\n moduleA: ModuleDef,\n moduleB: ModuleDef,\n opts: ValidatePairOptions = {},\n): PairValidationResult {\n const includePotentials = opts.includePotentials !== false;\n\n const rootsA = buildRegionTree(moduleA);\n const rootsB = buildRegionTree(moduleB);\n const regionsA = flattenTree(rootsA);\n const regionsB = flattenTree(rootsB);\n\n // --- Stage 1: discovery — enumerate every compatible region pairing ---\n const candidates: Candidate[] = [];\n for (const a of regionsA) {\n for (const b of regionsB) {\n if (a.iface.domain !== b.iface.domain) continue;\n const match = matchProtocols(a.iface, b.iface);\n if (!match.compatible) continue;\n // parameters the joint check compares itself (a cross against a circle, a row against a slot)\n // and those the link check compares (speeds, lane rates, bus widths, PoE power)\n // and those the drive and signal checks compare (gear modules, bearing diameters, IR carriers)\n const skip = new Set([\n ...pairCheckedParams(a.iface, b.iface),\n ...linkCheckedParams(a.iface, b.iface),\n ...driveCheckedParams(a.iface, b.iface),\n ...signalCheckedParams(a.iface, b.iface),\n ]);\n const params = checkPairParameters(a.iface.parameters, b.iface.parameters).filter((d) => !d.refs?.some((r) => skip.has(r)));\n const diagnostics = [\n ...params,\n ...checkPairJoints(a.iface, b.iface),\n ...checkPairLinks(a.iface, b.iface),\n ...checkPairDrive(a.iface, b.iface),\n ...checkPairSignals(a.iface, b.iface),\n ];\n candidates.push({\n a,\n b,\n match,\n diagnostics,\n clean: diagnostics.every((d) => d.severity !== \"error\"),\n potentialOnly: !opts.explicit && neverMates(a.iface, b.iface),\n });\n }\n }\n\n // Highest common altitude first, then parametric cleanliness, then stable ids.\n candidates.sort(\n (x, y) =>\n x.a.depth + x.b.depth - (y.a.depth + y.b.depth) ||\n Number(y.clean) - Number(x.clean) ||\n candidateKey(x).localeCompare(candidateKey(y)),\n );\n\n // --- Stage 2: acceptance — auto-connect only unambiguous pairings ---\n // A region (or any of its ancestors/descendants) participates in at most one\n // connection; consumed subtrees drop out of the alive set as we accept.\n const consumedA = new Set<RegionNode>();\n const consumedB = new Set<RegionNode>();\n const accepted: Candidate[] = [];\n\n const blocked = (node: RegionNode, consumed: Set<RegionNode>): boolean =>\n consumed.has(node) ||\n descendants(node).some((d) => consumed.has(d)) ||\n ancestorConsumed(node, consumed);\n\n // A mechanical feature that has interchangeable twins (an extrusion's four identical slots, a\n // bracket's identical legs, a plate's identical bearing seats) is one choice, not several: one\n // connection per pair of twin classes is made, on the first twin of each, and the rest stay potentials.\n const twinClassesDone = new Set<string>();\n const twinPair = (c: Candidate) => {\n const [ka, kb] = [twinKey(c.a), twinKey(c.b)];\n return ka !== undefined && kb !== undefined ? `${ka}\\u0000${kb}` : undefined;\n };\n const alive = (c: Candidate) =>\n !c.potentialOnly && !blocked(c.a, consumedA) && !blocked(c.b, consumedB) && !(twinPair(c) !== undefined && twinClassesDone.has(twinPair(c)!));\n\n let progressed = true;\n while (progressed) {\n progressed = false;\n const aliveCandidates = candidates.filter(alive);\n for (const c of aliveCandidates) {\n if (!alive(c)) continue; // may have been consumed earlier this sweep\n // an endpoint whose clean pairings are taken by a twin's connection waits rather than\n // falling back to a pairing with errors\n const twinHeld = candidates.filter((x) => x.clean && !x.potentialOnly && twinPair(x) !== undefined && twinClassesDone.has(twinPair(x)!));\n if (!c.clean && twinHeld.some((x) => x.a === c.a || x.b === c.b)) continue;\n if (!isUnambiguous(c, aliveCandidates.filter(alive))) continue;\n accepted.push(c);\n const tp = twinPair(c);\n if (tp !== undefined) twinClassesDone.add(tp);\n consumedA.add(c.a);\n for (const d of descendants(c.a)) consumedA.add(d);\n consumedB.add(c.b);\n for (const d of descendants(c.b)) consumedB.add(d);\n progressed = true;\n }\n }\n\n // --- Stage 3: build connection results (sub-links, states) ---\n const connections = accepted.map((c) => buildConnection(c, moduleA.id, moduleB.id));\n\n // --- Stage 4: potentials — compatible pairings that were not auto-connected ---\n const potentials: PotentialConnection[] = includePotentials\n ? candidates\n .filter((c) => !accepted.includes(c))\n .map((c) => ({\n a: { moduleId: moduleA.id, regionPath: c.a.path },\n b: { moduleId: moduleB.id, regionPath: c.b.path },\n protocol: c.match.matchedProtocol ?? \"\",\n tier: \"protocol\" as const,\n confidence: c.match.confidence,\n clean: c.clean,\n diagnostics: c.diagnostics,\n }))\n : [];\n\n // --- Stage 5: census — every region of both modules is represented ---\n const census = [\n ...buildCensus(moduleA.id, regionsA, consumedA, accepted.map((c) => c.a), candidates.map((c) => c.a), candidates, \"a\"),\n ...buildCensus(moduleB.id, regionsB, consumedB, accepted.map((c) => c.b), candidates.map((c) => c.b), candidates, \"b\"),\n ];\n\n // --- Stage 6: verdict rollup ---\n const counts = {\n connections: connections.length,\n valid: connections.filter((c) => c.state === \"valid\" || c.state === \"valid_inferred\" || c.state === \"valid_manual\").length,\n warnings: connections.filter((c) => c.state === \"warning\").length,\n errors: connections.filter((c) => c.state === \"incompatible\").length,\n configurationNeeded: connections.filter((c) => c.state === \"configuration_needed\").length,\n potentials: potentials.length,\n };\n const state: ConnectionState =\n connections.length === 0\n ? \"not_configured\"\n : counts.errors > 0\n ? \"incompatible\"\n : counts.configurationNeeded > 0\n ? \"configuration_needed\"\n : counts.warnings > 0\n ? \"warning\"\n : \"valid\";\n\n return {\n modules: {\n a: { id: moduleA.id, name: moduleA.name, interfaceCount: regionsA.length },\n b: { id: moduleB.id, name: moduleB.name, interfaceCount: regionsB.length },\n },\n connections,\n census,\n potentials,\n capacity: [], // Phase 6\n verdict: { state, counts },\n };\n}\n\nfunction candidateKey(c: Candidate): string {\n return `${c.a.path.join(\".\")}~${c.b.path.join(\".\")}`;\n}\n\nfunction ancestorConsumed(node: RegionNode, consumed: Set<RegionNode>): boolean {\n let current = node.parent;\n while (current) {\n if (consumed.has(current)) return true;\n current = current.parent;\n }\n return false;\n}\n\n/**\n * Auto-connect policy: a candidate is accepted only when it is the sole viable\n * choice for BOTH of its endpoints — the only clean alive candidate, or (when an\n * endpoint has no clean options at all) the only alive candidate. Ambiguous\n * matches (a GPIO that a dozen pins could serve) surface as potentials for the\n * user to click instead. Connections are never auto-locked.\n */\nfunction isUnambiguous(c: Candidate, aliveCandidates: Candidate[]): boolean {\n for (const side of [\"a\", \"b\"] as const) {\n const other = side === \"a\" ? \"b\" : \"a\";\n // a pairing with a region inside c's other end (a power port's own pin, when the ports match) is\n // the same connection at a lower altitude, not a rival to it; and a composite and the leaves it\n // binds are one choice, not several: when a composite pairs with a composite and also with that\n // composite's own leaves, the composite pairing counts (highest altitude first). A composite\n // against a lone leaf stays ambiguous with the leaves inside it.\n const below = new Set(descendants(c[other]));\n const composite = (n: RegionNode) => Boolean(n.iface.slots?.length);\n const forEndpoint = aliveCandidates\n .filter((x) => x[side] === c[side] && !below.has(x[other]))\n .filter((x, _, all) => !all.some((y) => y !== x && composite(y[side]) && composite(y[other]) && isAncestor(y[other], x[other])));\n const clean = forEndpoint.filter((x) => x.clean);\n const pool = clean.length > 0 ? clean : forEndpoint;\n if (pool.length === 1 && pool[0] === c) continue;\n // rivals that differ only by which interchangeable twin they use are the same choice: take the first\n const twin = twinKey(c[other]);\n if (twin === undefined || pool[0] !== c || !pool.every((x) => twinKey(x[other]) === twin)) return false;\n }\n return true;\n}\n\nfunction isAncestor(node: RegionNode, of: RegionNode): boolean {\n let current = of.parent;\n while (current) {\n if (current === node) return true;\n current = current.parent;\n }\n return false;\n}\n\nfunction buildConnection(c: Candidate, moduleIdA: string, moduleIdB: string): ConnectionResult {\n const id = `${moduleIdA}:${c.a.path.join(\".\")}~${moduleIdB}:${c.b.path.join(\".\")}`;\n const { subLinks, unresolvedSlots } = resolveSubLinks(id, c, moduleIdA, moduleIdB);\n\n const allDiagnostics = [...c.diagnostics, ...subLinks.flatMap((l) => l.diagnostics)];\n const hasError = allDiagnostics.some((d) => d.severity === \"error\");\n const hasWarning = allDiagnostics.some((d) => d.severity === \"warning\");\n const state: ConnectionState = hasError\n ? \"incompatible\"\n : unresolvedSlots.some((s) => s.required)\n ? \"configuration_needed\"\n : hasWarning\n ? \"warning\"\n : \"valid\";\n\n return {\n id,\n a: {\n moduleId: moduleIdA,\n regionPath: c.a.path,\n role: c.match.roleA ?? \"\",\n altitude: c.a.depth === 0 ? \"top\" : \"sub\",\n },\n b: {\n moduleId: moduleIdB,\n regionPath: c.b.path,\n role: c.match.roleB ?? \"\",\n altitude: c.b.depth === 0 ? \"top\" : \"sub\",\n },\n topology: \"wire\",\n protocol: c.match.matchedProtocol ?? \"\",\n tier: \"protocol\",\n confidence: TIER_CONFIDENCE.protocol,\n state,\n subLinks,\n unresolvedSlots,\n diagnostics: c.diagnostics,\n };\n}\n\n/**\n * Pair the matched regions' slots into conductors. When both sides declare\n * slots, slots pair by protocol + complementary role and each side's conductor\n * endpoint is the leaf its active profile binds. When either side is a bare\n * leaf, the connection is a single conductor between the regions themselves.\n * rowPair indices carry the mirrored row ordering the layout engine uses.\n */\nfunction resolveSubLinks(\n connectionId: string,\n c: Candidate,\n moduleIdA: string,\n moduleIdB: string,\n): { subLinks: SubLinkResult[]; unresolvedSlots: UnresolvedSlot[] } {\n const slotsA = c.a.iface.slots ?? [];\n const slotsB = c.b.iface.slots ?? [];\n const subLinks: SubLinkResult[] = [];\n const unresolvedSlots: UnresolvedSlot[] = [];\n\n if (slotsA.length === 0 || slotsB.length === 0) {\n subLinks.push({\n id: `${connectionId}#0`,\n from: { moduleId: moduleIdA, interfaceId: c.a.iface.id },\n to: { moduleId: moduleIdB, interfaceId: c.b.iface.id },\n method: \"protocol\",\n locked: false,\n rowPair: 0,\n diagnostics: [],\n });\n return { subLinks, unresolvedSlots };\n }\n\n const profileA = pickProfile(c.a.iface);\n const profileB = pickProfile(c.b.iface);\n const usedB = new Set<string>();\n let row = 0;\n\n for (const slotA of slotsA) {\n const protocol = slotA.match.protocol;\n const partner = slotsB.find(\n (slotB) =>\n !usedB.has(slotB.id) &&\n protocol !== undefined &&\n slotB.match.protocol?.toLowerCase() === protocol.toLowerCase() &&\n (slotA.match.role === undefined ||\n slotB.match.role === undefined ||\n areRolesCompatible(protocol, slotA.match.role, slotB.match.role)),\n );\n\n if (!partner) {\n if (slotA.required) {\n unresolvedSlots.push({\n moduleId: moduleIdA,\n regionPath: c.a.path,\n slotId: slotA.id,\n required: true,\n match: slotA.match,\n });\n }\n continue;\n }\n usedB.add(partner.id);\n\n subLinks.push({\n id: `${connectionId}#${row}`,\n from: leafRef(moduleIdA, c.a.iface.id, slotA.id, profileA?.bindings[slotA.id]),\n to: leafRef(moduleIdB, c.b.iface.id, partner.id, profileB?.bindings[partner.id]),\n method: \"protocol\",\n locked: false,\n rowPair: row,\n diagnostics: [],\n });\n row++;\n }\n\n for (const slotB of slotsB) {\n if (slotB.required && !usedB.has(slotB.id)) {\n unresolvedSlots.push({\n moduleId: moduleIdB,\n regionPath: c.b.path,\n slotId: slotB.id,\n required: true,\n match: slotB.match,\n });\n }\n }\n\n return { subLinks, unresolvedSlots };\n}\n\nfunction leafRef(\n moduleId: string,\n ownerInterfaceId: string,\n slotId: string,\n binding: string | string[] | undefined,\n): LeafRef {\n const bound = Array.isArray(binding) ? binding[0] : binding;\n return { moduleId, interfaceId: bound ?? ownerInterfaceId, slotId };\n}\n\nfunction buildCensus(\n moduleId: string,\n regions: RegionNode[],\n consumed: Set<RegionNode>,\n connectedNodes: RegionNode[],\n candidateNodes: RegionNode[],\n candidates: Candidate[],\n side: \"a\" | \"b\",\n): InterfaceCensusEntry[] {\n const connectedSet = new Set(connectedNodes);\n const candidateSet = new Set(candidateNodes);\n\n return regions.map((node) => {\n const label = node.iface.protocols\n .map((p) => `${p.type} · ${p.roles.join(\", \")}`)\n .join(\" | \");\n const base = { moduleId, regionPath: node.path, label };\n\n if (connectedSet.has(node)) {\n return { ...base, status: \"connected\" as const };\n }\n\n const engagedChildren = node.children.filter(\n (child) => connectedSet.has(child) || descendants(child).some((d) => connectedSet.has(d)),\n );\n if (engagedChildren.length > 0) {\n return {\n ...base,\n status: \"partial\" as const,\n engagement: { engaged: engagedChildren.length, total: node.children.length },\n };\n }\n\n if (consumed.has(node)) {\n // inside a connected parent's shared territory — engaged via the parent\n return { ...base, status: \"connected\" as const, reason: \"via parent\" };\n }\n\n if (candidateSet.has(node)) {\n const counterparts = candidates\n .filter((c) => c[side] === node)\n .map((c) => (side === \"a\" ? c.b : c.a).iface.id);\n return {\n ...base,\n status: \"compatible\" as const,\n reason: `compatible: ${[...new Set(counterparts)].join(\", \")}`,\n };\n }\n\n return { ...base, status: \"no_counterpart\" as const };\n });\n}\n\n/**\n * Interchangeable mechanical features: a mechanical interface without a pin,\n * keyed by everything but its id, name and geometry (protocols,\n * capabilities, parameters, traits, slots). Two interfaces of one module with\n * the same key are twins: bolting a bracket to one face of an extrusion or\n * another is the same connection. Electrical interfaces are never twins\n * (choosing a pin is a wiring decision).\n */\nconst twinKeys = new WeakMap<RegionNode, string | undefined>();\nfunction twinKey(node: RegionNode): string | undefined {\n if (twinKeys.has(node)) return twinKeys.get(node);\n const i = node.iface;\n const key =\n i.domain === \"mechanical\" && i.pin === undefined && node.parent === undefined\n ? JSON.stringify([i.protocols, i.capabilities ?? [], i.parameters ?? [], i.traits ?? [], i.slots ?? []])\n : undefined;\n twinKeys.set(node, key);\n return key;\n}\n","/**\n * Connector links: a link between two connector composites (or a\n * connector and a link-scoped composition) mates positions, not protocols.\n * Checked here: connector type, gender, position count and compose slots.\n * What the positions carry is checked on the links derived from them\n * (derive.ts).\n */\nimport type { InterfaceDef } from \"../types/interface.js\";\nimport type { InterfaceLink } from \"../types/module.js\";\nimport type { Diagnostic } from \"../drc/types.js\";\nimport { isConnector } from \"../protocols/connector.js\";\nimport type { LinkChildResult, LinkResult, ResolvedEndpoint } from \"./index.js\";\n\n\ninterface ConnectorParams {\n connector_type?: string;\n gender?: string;\n positions?: number;\n mates_with?: string[];\n}\n\nfunction connectorParams(iface: InterfaceDef): ConnectorParams[] {\n return (iface.traits ?? []).filter((t) => t.type === \"connector\").map((t) => (t.params ?? {}) as ConnectorParams);\n}\n\n/** Connector type slugs declared on an interface (its `connector` traits). */\nexport function connectorTypes(iface: InterfaceDef): string[] {\n return connectorParams(iface)\n .map((p) => String(p.connector_type ?? \"\"))\n .filter(Boolean);\n}\n\n/** Slot → bound interface id, from the connector's default (first) profile. */\nexport function slotBindings(iface: InterfaceDef): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [slot, v] of Object.entries(iface.profiles?.[0]?.bindings ?? {})) {\n const id = Array.isArray(v) ? v[0] : v;\n if (id) out[slot] = id;\n }\n return out;\n}\n\n/** Slot ids of a connector, in position order. */\nexport function slotIds(iface: InterfaceDef): string[] {\n return (iface.slots ?? []).map((s) => s.id);\n}\n\n/** Position pairs of a connector link: stored child links, else same slot id. */\nexport function positionPairs(link: InterfaceLink, a: ResolvedEndpoint, b: ResolvedEndpoint): { a: string; b: string }[] {\n if (link.childLinks?.length) return link.childLinks.map((c) => ({ a: c.a, b: c.b }));\n const bSlots = new Set(slotIds(b.iface));\n return slotIds(a.iface)\n .filter((s) => bSlots.has(s))\n .map((s) => ({ a: s, b: s }));\n}\n\nconst OPPOSITE_ONLY = new Set([\"plug\", \"receptacle\", \"male\", \"female\", \"socket\", \"header\"]);\n\nfunction mateProblems(link: InterfaceLink, a: ResolvedEndpoint, b: ResolvedEndpoint): Diagnostic[] {\n const out: Diagnostic[] = [];\n const pa = connectorParams(a.iface);\n const pb = connectorParams(b.iface);\n const ta = connectorTypes(a.iface);\n const tb = connectorTypes(b.iface);\n if (ta.length && tb.length) {\n const accepts = (x: ConnectorParams[], y: string[]) => x.some((p) => (p.mates_with ?? []).some((m) => y.includes(m)));\n if (!ta.some((t) => tb.includes(t)) && !accepts(pa, tb) && !accepts(pb, ta)) {\n out.push({ severity: \"error\", code: \"connector_mismatch\", message: `${a.path} is ${ta.join(\"/\")} but ${b.path} is ${tb.join(\"/\")}`, refs: [a.path, b.path] });\n }\n }\n const ga = pa.find((p) => p.gender)?.gender;\n const gb = pb.find((p) => p.gender)?.gender;\n if (ga && gb && ga === gb && OPPOSITE_ONLY.has(ga)) {\n out.push({ severity: \"error\", code: \"connector_gender\", message: `${a.path} and ${b.path} are both ${ga}`, refs: [a.path, b.path] });\n }\n if (!a.composed && !b.composed) {\n const na = slotIds(a.iface).length;\n const nb = slotIds(b.iface).length;\n if (na && nb && na !== nb && !link.childLinks?.length) {\n out.push({ severity: \"error\", code: \"connector_positions\", message: `${a.path} has ${na} positions but ${b.path} has ${nb}`, refs: [a.path, b.path] });\n }\n }\n for (const [composed, other] of [[a, b], [b, a]] as const) {\n if (!composed.composed) continue;\n const known = new Set(slotIds(other.iface));\n for (const slot of Object.keys(composed.composed)) {\n if (!known.has(slot)) {\n out.push({ severity: \"error\", code: \"compose_unknown_slot\", message: `${composed.path} composes ${slot}, which ${other.path} does not have (${[...known].join(\", \")})`, refs: [composed.path, other.path] });\n }\n }\n }\n return out;\n}\n\nfunction leafFor(end: ResolvedEndpoint, slot: string): LinkChildResult[\"a\"] {\n const composed = end.composed?.[slot];\n if (composed) return { slotId: slot, leafId: composed.iface.id, pin: composed.iface.pin === undefined ? undefined : String(composed.iface.pin) };\n const leafId = slotBindings(end.iface)[slot];\n const leaf = leafId ? end.owner.interfaces.find((i) => i.id === leafId) : undefined;\n return { slotId: slot, leafId: leafId ?? slot, pin: leaf?.pin === undefined ? undefined : String(leaf.pin) };\n}\n\n/** Validate a stored link between two connectors: mating only, by position. */\nexport function validateConnectorLink(link: InterfaceLink, a: ResolvedEndpoint, b: ResolvedEndpoint): LinkResult {\n const diagnostics = mateProblems(link, a, b);\n const children: LinkChildResult[] = positionPairs(link, a, b).map((p) => ({\n a: leafFor(a, p.a),\n b: leafFor(b, p.b),\n method: link.childLinks?.length ? \"manual\" : \"protocol\",\n locked: false,\n }));\n return {\n link,\n a,\n b,\n state: diagnostics.some((d) => d.severity === \"error\") ? \"incompatible\" : \"configured\",\n protocol: \"connector\",\n children,\n unresolvedSlots: [],\n diagnostics,\n };\n}\n","import type { TraitDef } from \"../types/trait.js\";\nimport type { InterfaceDef } from \"../types/interface.js\";\nimport type { DomainKind } from \"../types/domain.js\";\n\n/**\n * Physical connector or termination on an interface.\n *\n * Emits the `connector` trait shape the audited parts library already uses\n * (`{ connector_type }`), plus optional detail such as gender, pin count,\n * and the physical pin order.\n */\nexport interface ConnectorDetail {\n /** e.g. \"female\", \"male\", \"receptacle\", \"plug\". */\n gender?: string;\n /** Number of positions on the connector. */\n positions?: number;\n /** Signal names in physical pin order, pin 1 first. */\n pinout?: string[];\n /** Free-form note citing the source for the connector details. */\n note?: string;\n /**\n * On a harness module's end: which end of the links it carries this\n * connector mates with (\"a\" or \"b\"). Checked by the harness_connector rule.\n */\n mates?: \"a\" | \"b\";\n /**\n * How the connector comes with the part: \"fitted\" (the default)\n * when it is attached, \"loose\" when it ships in the bag and is fitted\n * during assembly (a shield's header strips, soldered by the builder).\n */\n supplied?: \"fitted\" | \"loose\";\n}\n\n/**\n * Build a `connector` trait. `connectorType` is a lowercase slug such as\n * \"xt60\", \"jst_sh_8\", \"solder_pad\", \"bare_wire_lead\", or \"mmcx\".\n */\nexport function connectorTrait(connectorType: string, detail: ConnectorDetail = {}): TraitDef {\n return {\n type: \"connector\",\n params: {\n connector_type: connectorType,\n ...(detail.gender !== undefined ? { gender: detail.gender } : {}),\n ...(detail.positions !== undefined ? { positions: detail.positions } : {}),\n ...(detail.pinout !== undefined ? { pinout: detail.pinout } : {}),\n ...(detail.note !== undefined ? { note: detail.note } : {}),\n ...(detail.mates !== undefined ? { mates: detail.mates } : {}),\n ...(detail.supplied !== undefined ? { supplied: detail.supplied } : {}),\n },\n };\n}\n\n/** The interfaces of a part whose connector ships loose, to be fitted during assembly (`supplied: \"loose\"`). */\nexport function looseConnectors(def: { interfaces: InterfaceDef[] }): { iface: InterfaceDef; connectorType: string; note?: string }[] {\n return def.interfaces.flatMap((iface) =>\n (iface.traits ?? [])\n .filter((t) => t.type === \"connector\" && (t.params as { supplied?: string } | undefined)?.supplied === \"loose\")\n .map((t) => {\n const p = t.params as { connector_type?: string; note?: string };\n return { iface, connectorType: String(p.connector_type ?? \"connector\"), ...(p.note ? { note: p.note } : {}) };\n }),\n );\n}\n\n// ---------------------------------------------------------------------------\n// Connector composites\n// ---------------------------------------------------------------------------\n\n\n/** One physical position: its printed label and the interface it carries (none: unused, e.g. VOID). */\nexport type ConnectorPin = string | { label: string; to?: string; note?: string } | [label: string, to?: string];\n\nexport interface ConnectorConfig extends ConnectorDetail {\n id: string;\n name?: string;\n /** Connector type slug, e.g. \"jst_sh_8\", \"dji_6pin\", \"xt60\". */\n connector: string;\n /** Positions in physical order, pin 1 first. Slot ids are `p1`, `p2`, …. */\n pins: ConnectorPin[];\n domain?: DomainKind;\n exposed?: boolean;\n /** Other connector types this one mates with (default: the same type only). */\n matesWith?: string[];\n traits?: TraitDef[];\n}\n\n/** The protocol type every connector composite speaks. */\nexport const CONNECTOR_PROTOCOL = \"connector\";\n\n/** True for a connector composite (or a link-scoped composition). */\nexport function isConnector(iface: InterfaceDef): boolean {\n return iface.protocols.some((p) => p.type === CONNECTOR_PROTOCOL);\n}\n\n/**\n * A physical connector as one interface: one slot per position\n * (`p1…pN`) and a default profile binding each used position to the pad or\n * leaf interface it carries. Links between two connectors are matched by\n * position; the functional links (power, UART, …) are derived by tracing\n * conductors through harnesses (`deriveLinks`).\n *\n * Part-authoring rule: every physical connector on a part is a connector\n * composite. A connector carrying exactly one functional interface (USB-C,\n * an RF jack) may keep the connector trait on that interface instead.\n */\nexport function Connector(config: ConnectorConfig): InterfaceDef {\n const pins = config.pins.map((p) =>\n typeof p === \"string\" ? { label: p } : Array.isArray(p) ? { label: p[0], to: p[1] } : p,\n );\n const bindings: Record<string, string> = {};\n pins.forEach((p, i) => {\n if (p.to) bindings[`p${i + 1}`] = p.to;\n });\n const trait = connectorTrait(config.connector, {\n gender: config.gender,\n positions: pins.length,\n pinout: pins.map((p) => p.label),\n note: config.note,\n mates: config.mates,\n supplied: config.supplied,\n });\n if (config.matesWith?.length) (trait.params as Record<string, unknown>).mates_with = config.matesWith;\n return {\n id: config.id,\n name: config.name,\n domain: config.domain ?? \"electrical\",\n exposed: config.exposed ?? true,\n default_active: true,\n protocols: [{ type: CONNECTOR_PROTOCOL, roles: [\"mate\"] }],\n slots: pins.map((p, i) => ({ id: `p${i + 1}`, label: p.label, required: false, match: {} })),\n profiles: [{ id: `${config.id}_pinout`, label: \"Pinout\", default_active: true, bindings }],\n max_instances: 1,\n traits: [trait, ...(config.traits ?? [])],\n };\n}\n","import type { InterfaceDef } from \"../types/interface.js\";\nimport type { InterfaceLink } from \"../types/module.js\";\nimport type { TraitDef } from \"../types/trait.js\";\nimport { voltageRangeV, voltageV } from \"./params.js\";\n\n/**\n * Nets: the conductors of a board joining two or more pins.\n *\n * A net is an interface on the board module itself (protocol `net`, not\n * exposed). Each pin on the net is joined to it by an ordinary stored link\n * from the pin (`child`) to the net (`self`). The functional links between\n * the pins (supply output to inputs, I2C master to target) are derived from\n * the memberships by `deriveLinks`, so system checks see a board the same way\n * they see a cable. See docs/boards-and-nets.md.\n */\nexport const NET_PROTOCOL = \"net\";\n\nexport interface NetConfig {\n id: string;\n /** Net name as a schematic would print it, e.g. \"3V3\", \"GND\", \"SDA\". */\n name?: string;\n /**\n * Design voltage of the net: what the board intends this rail to be, not\n * what a part allows (a 1.2–5.5 V adjustable regulator set to 3.3 V). Every\n * pin on the net with a `voltage` parameter is checked against it.\n */\n voltageV?: number | [number, number];\n traits?: TraitDef[];\n}\n\n/** True for a net interface. */\nexport function isNet(iface: InterfaceDef): boolean {\n return iface.protocols.some((p) => p.type === NET_PROTOCOL);\n}\n\n/** A net on a board: the node that its pins' membership links join. */\nexport function Net(config: NetConfig): InterfaceDef {\n const v = config.voltageV;\n return {\n id: config.id,\n name: config.name ?? config.id,\n domain: \"electrical\",\n exposed: false,\n default_active: true,\n protocols: [{ type: NET_PROTOCOL, roles: [\"node\"] }],\n ...(v !== undefined ? { parameters: [Array.isArray(v) ? voltageRangeV(v[0], v[1]) : voltageV(v)] } : {}),\n ...(config.traits?.length ? { traits: config.traits } : {}),\n };\n}\n\n/**\n * Membership links joining pins to a net on the linking module. Members are\n * `\"<child>:<interface>\"` (an interface or export of a direct child). Link\n * ids are `<net>.<child>.<interface>`.\n *\n * links: [...netLinks(\"gnd\", [\"u1:pad_gnd\", \"u2:pin_6\", \"u2:pin_7\", \"u3:pgnd\"])]\n */\nexport function netLinks(net: string, members: string[]): InterfaceLink[] {\n return members.map((member) => {\n const [child, interfaceId, extra] = member.split(\":\");\n if (!child || !interfaceId || extra !== undefined || child.includes(\"/\")) {\n throw new Error(`Net \"${net}\": member \"${member}\" is not \"<child>:<interface>\"`);\n }\n return {\n id: `${net}.${child}.${interfaceId}`,\n a: { child, interfaceId },\n b: { self: true, interfaceId: net },\n };\n });\n}\n","/**\n * Boards and nets: a custom PCB is an ordinary module whose\n * children are its components and whose nets are `Net` interfaces on the\n * board itself, each pin joined to its net by a stored membership link\n * (docs/boards-and-nets.md).\n *\n * Here: validation of membership links, the net index of a module, and the\n * board rules that need whole nets rather than pairs of pins:\n *\n * net a net with fewer than two pins; a pin on two nets;\n * several modules driving one supply net; ground joined\n * to a supply; a supply pin whose voltage range\n * excludes the net's design voltage, or a logic pin\n * rated below it\n * (netRule); a passive with every terminal on one net, a\n * part's power input on the net of an output it feeds,\n * a strap on a net that carries another part's signal\n * (partWiringRule)\n * bus_pullup an I2C link over nets with no pull-up resistor to a supply\n * design_envelope a stated body larger than the module's design envelope\n *\n * The functional links between the pins of a net are derived in derive.ts.\n */\nimport type { InterfaceDef } from \"../types/interface.js\";\nimport type { InterfaceLink, ModuleDef } from \"../types/module.js\";\nimport type { Parameter } from \"../types/parameter.js\";\nimport type { DesignEnvelopeTrait, StrapTrait } from \"../types/trait.js\";\nimport type { Diagnostic } from \"../drc/types.js\";\nimport { getEffectiveRange, rangesOverlap } from \"../parameters/range.js\";\nimport { isNet, NET_PROTOCOL } from \"../protocols/net.js\";\nimport { passiveInstance, passiveOf } from \"../protocols/passive.js\";\nimport { isConnector } from \"../protocols/connector.js\";\nimport { slotBindings } from \"./connectors.js\";\nimport { formatPath, netPortOf, validateLinks, type LinkResult, type ModuleLookup, type ResolvedEndpoint } from \"./index.js\";\nimport type { SystemDiagnostic } from \"./checks.js\";\n\n// ---------------------------------------------------------------------------\n// Membership links\n// ---------------------------------------------------------------------------\n\n/**\n * Validate a stored link with a net at one end: it joins one pin to a net\n * declared on the linking module. Nothing is matched; what the pins on a net\n * carry is checked on the links derived from it.\n *\n * A child's net port (a net the child exports) is joined like a pin: to a\n * net of the linking module, or by a pin linked to the port, which puts the\n * pin on the child's net. Two net ports join through a net of the linking\n * module, not to each other.\n */\nexport function validateNetLink(link: InterfaceLink, a: ResolvedEndpoint, b: ResolvedEndpoint): LinkResult {\n const diagnostics: Diagnostic[] = [];\n // a net port is the member of the linking module's own net\n const netIsA = isNet(a.iface) && !(a.netPort && isNet(b.iface) && \"self\" in link.b);\n const [net, member] = netIsA ? [a, b] : [b, a];\n const netTarget = netIsA ? link.a : link.b;\n if (isNet(member.iface)) {\n if (!(member.netPort && \"self\" in netTarget)) {\n const message = member.netPort && net.netPort\n ? `${a.path} and ${b.path} are both net ports; join them through a net of this module`\n : `${a.path} and ${b.path} are both nets; a pin joins a net, and two nets that are one conductor are one net`;\n diagnostics.push({ severity: \"error\", code: \"net_to_net\", message, refs: [a.path, b.path] });\n }\n } else if (member.iface.slots?.length || isConnector(member.iface)) {\n diagnostics.push({ severity: \"error\", code: \"net_member_composite\", message: `${member.path} is a composite interface; a net joins pins, so link its leaves`, refs: [member.path, net.path] });\n }\n if (!(\"self\" in netTarget) && !net.netPort) {\n diagnostics.push({ severity: \"error\", code: \"net_not_own\", message: `${net.path} is a net of a child; nets join pins on the module that declares them, or a child exports the net as a net port`, refs: [net.path] });\n }\n return {\n link,\n a,\n b,\n state: diagnostics.length ? \"incompatible\" : \"configured\",\n protocol: NET_PROTOCOL,\n children: [],\n unresolvedSlots: [],\n diagnostics,\n };\n}\n\n/** True for a link result that is a net membership rather than a functional link. */\nexport function isNetMembership(r: LinkResult): boolean {\n return r.protocol === NET_PROTOCOL;\n}\n\n/**\n * The ends of a valid membership link: the linking module's own net and its\n * member (a pin, or a child's net port), or, for a pin linked straight to a\n * child's net port, that port and the pin.\n */\nexport function membershipEnds(r: LinkResult): { net: ResolvedEndpoint; member: ResolvedEndpoint } | { port: ResolvedEndpoint; member: ResolvedEndpoint } {\n if (isNet(r.a.iface) && \"self\" in r.link.a) return { net: r.a, member: r.b };\n if (isNet(r.b.iface) && \"self\" in r.link.b) return { net: r.b, member: r.a };\n return r.a.netPort ? { port: r.a, member: r.b } : { port: r.b, member: r.a };\n}\n\n/** Canonical path of the module instance and interface an endpoint finally resolves to (`sensor/u1:pin_3`). */\nexport function physicalPath(end: ResolvedEndpoint): string {\n return formatPath(end.ownerPath, end.iface.id);\n}\n\n// ---------------------------------------------------------------------------\n// Net index\n// ---------------------------------------------------------------------------\n\nexport interface NetMember {\n /**\n * Canonical path of the pin, e.g. `u2:pin_8`. A pin reached through a net\n * port has the path of the part below the linking module, `sensor/u1:pin_7`.\n */\n path: string;\n end: ResolvedEndpoint;\n /**\n * The membership link. One stored on a sub-module is prefixed with the\n * sub-module's instance path, `sensor/vdd.u1.pin_7`.\n */\n link: string;\n /**\n * Set on a pin reached through a net port: the nets of sub-modules it was\n * reached through, outermost first (`[\"sensor:vdd\"]`). The last is the net\n * the pin is a member of.\n */\n through?: string[];\n}\n\n/** A net of a sub-module on a conductor, reached through a net port. */\nexport interface NestedNet {\n /** Canonical path of the net below the linking module, `sensor:vdd`. */\n path: string;\n iface: InterfaceDef;\n}\n\nexport interface BoardNet {\n iface: InterfaceDef;\n /**\n * Canonical path of the net on the module, `:<id>`. A conductor with no\n * net of the module (pins linked straight to a child's net port) is named\n * by the port's net, `sensor:vdd`, and so is its `iface.id`.\n */\n path: string;\n /** The pins on the net; with a lookup, also the pins its net ports reach (`through` set). */\n members: NetMember[];\n /** Children's net ports joined to the net. Present only when there are any. */\n ports?: NetMember[];\n /** Sub-module nets on the conductor through those ports, at any depth. Present only with a lookup and ports. */\n nested?: NestedNet[];\n}\n\ntype LinkCache = Map<ModuleDef, LinkResult[]>;\n\nfunction storedLinks(def: ModuleDef, lookup: ModuleLookup, cache: LinkCache): LinkResult[] {\n let links = cache.get(def);\n if (!links) {\n links = validateLinks(def, lookup);\n cache.set(def, links);\n }\n return links;\n}\n\n/**\n * What a child's net port reaches inside the child: the pins on the net, at\n * any depth (through the net ports of the child's own children, and pins\n * the child links straight to them), with canonical paths below the module\n * that links the port; and the nets passed through, outermost first.\n */\nexport function netPortReach(port: ResolvedEndpoint, lookup: ModuleLookup): { members: NetMember[]; nets: NestedNet[] } {\n return reachPort(port, lookup, new Map(), 0);\n}\n\nfunction reachPort(port: ResolvedEndpoint, lookup: ModuleLookup, cache: LinkCache, depth: number): { members: NetMember[]; nets: NestedNet[] } {\n const base = port.ownerPath;\n const netPath = physicalPath(port);\n const out = { members: [] as NetMember[], nets: [{ path: netPath, iface: port.iface }] };\n if (depth >= 16) return out;\n const below = (e: ResolvedEndpoint): ResolvedEndpoint => {\n const ownerPath = [...base, ...e.ownerPath];\n return { ...e, path: formatPath(ownerPath, e.iface.id), ownerPath };\n };\n const linkId = (id: string) => `${base.join(\"/\")}/${id}`;\n const valid = storedLinks(port.owner, lookup, cache).filter((r) => isNetMembership(r) && r.state !== \"incompatible\");\n const inner: ResolvedEndpoint[] = [];\n for (const r of valid) {\n const m = membershipEnds(r);\n if (!(\"net\" in m) || m.net.iface.id !== port.iface.id) continue;\n if (m.member.netPort) inner.push(m.member);\n else out.members.push({ path: physicalPath(below(m.member)), end: below(m.member), link: linkId(r.link.id), through: [netPath] });\n }\n for (const p of inner) {\n const deeper = below(p);\n const innerPath = physicalPath(deeper);\n // pins the child links straight to its own child's port are on that net too\n for (const r of valid) {\n const m = membershipEnds(r);\n if (\"port\" in m && physicalPath(m.port) === physicalPath(p)) {\n out.members.push({ path: physicalPath(below(m.member)), end: below(m.member), link: linkId(r.link.id), through: [netPath, innerPath] });\n }\n }\n const reached = reachPort(deeper, lookup, cache, depth + 1);\n out.members.push(...reached.members.map((x) => ({ ...x, through: [netPath, ...(x.through ?? [])] })));\n out.nets.push(...reached.nets);\n }\n return out;\n}\n\n/**\n * Every net declared on `def`, with the pins its valid membership links\n * join. A child's net port on a net is listed in `ports`; given a lookup,\n * the pins the port reaches inside the child are members too (with\n * `through`), and the child's nets are `nested`. Pins linked straight to a\n * child's net port are members of the net the port is on, or of a net of\n * their own named by the port when it is on none.\n */\nexport function moduleNets(def: ModuleDef, links: LinkResult[], lookup?: ModuleLookup): BoardNet[] {\n const nets = new Map<string, BoardNet>();\n for (const iface of def.interfaces) {\n if (isNet(iface)) nets.set(iface.id, { iface, path: formatPath([], iface.id), members: [] });\n }\n const straight: { port: ResolvedEndpoint; member: NetMember }[] = [];\n for (const r of links) {\n if (!isNetMembership(r) || r.state === \"incompatible\") continue;\n const m = membershipEnds(r);\n const entry: NetMember = { path: m.member.path, end: m.member, link: r.link.id };\n if (\"port\" in m) {\n straight.push({ port: m.port, member: entry });\n continue;\n }\n const net = nets.get(m.net.iface.id);\n if (!net) continue;\n if (m.member.netPort) (net.ports ??= []).push(entry);\n else net.members.push(entry);\n }\n for (const { port, member } of straight) {\n const key = physicalPath(port);\n const host = [...nets.values()].find((n) => n.ports?.some((p) => physicalPath(p.end) === key));\n if (host) {\n host.members.push(member);\n continue;\n }\n const own = nets.get(`port#${key}`) ?? { iface: { ...port.iface, id: key }, path: key, members: [], ports: [{ path: port.path, end: port, link: member.link }] };\n own.members.push(member);\n nets.set(`port#${key}`, own);\n }\n if (lookup) {\n const cache: LinkCache = new Map();\n for (const net of nets.values()) {\n for (const p of net.ports ?? []) {\n const reached = reachPort(p.end, lookup, cache, 0);\n net.members.push(...reached.members);\n (net.nested ??= []).push(...reached.nets);\n }\n }\n }\n return [...nets.values()];\n}\n\n/**\n * Design voltage of a conductor: its own net's, else the shallowest nested\n * net that states one (a sub-module's 3V3 joined by a net that states none).\n */\nexport function conductorVoltageRange(net: BoardNet): [number, number] | undefined {\n const own = netVoltageRange(net.iface);\n if (own) return own;\n const nested = [...(net.nested ?? [])].sort((x, y) => x.path.split(\"/\").length - y.path.split(\"/\").length);\n for (const n of nested) {\n const r = netVoltageRange(n.iface);\n if (r) return r;\n }\n return undefined;\n}\n\n/** True when every one of `members` is a pin reached through the same sub-module net: that module's own check covers it. */\nfunction sameNested(members: NetMember[]): boolean {\n if (!members.length || members.some((m) => !m.through)) return false;\n return new Set(members.map((m) => m.through![m.through!.length - 1])).size === 1;\n}\n\nfunction param(iface: InterfaceDef, id: string): Parameter | undefined {\n return iface.parameters?.find((p) => p.id === id);\n}\n\nconst hasRole = (iface: InterfaceDef, type: string, role: string) =>\n iface.protocols.some((p) => p.type === type && p.roles.includes(role));\n\n/** Design voltage of a net (its `voltage` parameter) as a range, if stated. */\nexport function netVoltageRange(net: InterfaceDef): [number, number] | undefined {\n const p = param(net, \"voltage\");\n return (p && getEffectiveRange(p)) ?? undefined;\n}\n\n/** Nominal design voltage of a net: its value, else the lower end of its range. */\nexport function netVoltage(net: InterfaceDef): number | undefined {\n const p = param(net, \"voltage\");\n return p?.value ?? p?.range?.[0];\n}\n\nconst fmtRange = (r: [number, number]) => (r[0] === r[1] ? `${r[0]} V` : `${r[0]}–${r[1]} V`);\n\n/**\n * Paths a module's boundary supplies from outside: its exported child\n * interfaces, the leaves those exports bind, every pin on a net it exports\n * as a net port, and every pin on a net that carries one of them. A power input here is fed through the board edge, so\n * the unpowered rule does not report it when the board is checked alone.\n */\nexport function edgeFedPaths(def: ModuleDef, lookup: ModuleLookup, nets: BoardNet[]): Set<string> {\n const fed = new Set<string>();\n for (const ex of def.exports ?? []) {\n if (!(\"child\" in ex.from)) {\n // a net port: everything on the net is supplied through it\n const netId = ex.from.interfaceId;\n for (const m of nets.find((n) => n.iface.id === netId)?.members ?? []) fed.add(m.path);\n continue;\n }\n const { child, interfaceId } = ex.from;\n fed.add(`${child}:${interfaceId}`);\n const ref = def.children?.find((c) => c.id === child);\n const iface = ref ? lookup(ref.moduleDefId)?.interfaces.find((i) => i.id === interfaceId) : undefined;\n for (const leaf of iface ? Object.values(slotBindings(iface)) : []) fed.add(`${child}:${leaf}`);\n }\n for (const net of nets) {\n if (net.members.some((m) => fed.has(m.path))) for (const m of net.members) fed.add(m.path);\n }\n return fed;\n}\n\n// ---------------------------------------------------------------------------\n// Rules\n// ---------------------------------------------------------------------------\n\n/**\n * Rules over whole nets. Given a lookup, a net's children's net ports are\n * followed into the children, so a conductor that runs on both sides of a\n * module's edge is checked once here: its supplies, its ground, and every\n * pin on it against one design voltage (`conductorVoltageRange`). What lies\n * wholly inside one sub-module's net is left to that module's own check.\n */\nexport function netRule(def: ModuleDef, links: LinkResult[], lookup?: ModuleLookup): SystemDiagnostic[] {\n const nets = moduleNets(def, links, lookup);\n const out: SystemDiagnostic[] = [];\n const netsOf = new Map<string, string[]>();\n // pins reached through a net port, by where they finally are: net -> the routes (ports, or \"direct\") reaching them\n const physical = new Map<string, Map<string, Set<string>>>();\n\n for (const net of nets) {\n const id = net.iface.id;\n const label = net.iface.name && net.iface.name !== id ? `${id} (${net.iface.name})` : id;\n const refs = [net.path, ...net.members.map((m) => m.path)];\n const direct = net.members.filter((m) => !m.through);\n for (const m of [...direct, ...(net.ports ?? [])]) netsOf.set(m.path, [...(netsOf.get(m.path) ?? []), id]);\n for (const m of net.members) {\n const key = physicalPath(m.end);\n const byNet = physical.get(key) ?? new Map<string, Set<string>>();\n byNet.set(id, (byNet.get(id) ?? new Set()).add(m.through ? m.through[0] : \"direct\"));\n physical.set(key, byNet);\n }\n\n const joined = [...direct, ...(net.ports ?? [])];\n // a net the module exports as a net port has its other end outside\n if (joined.length + (netPortOf(def, id) ? 1 : 0) < 2) {\n out.push({\n id: `net:${id}:members`,\n rule: \"net\",\n severity: \"warning\",\n message: joined.length\n ? `net ${label} joins only ${joined[0].path}; nothing else is on it.`\n : `net ${label} joins no pins.`,\n refs,\n });\n }\n\n // more than one module driving a supply net. A connector or land carries power, it does not make\n // it, and a terminal that both gives and takes it (a cell's +, beside its charger) is storage\n const drivers = new Map<string, string[]>();\n const driving: NetMember[] = [];\n for (const m of net.members) {\n if (!hasRole(m.end.iface, \"power\", \"output\")) continue;\n if (hasRole(m.end.iface, \"power\", \"input\")) continue;\n if ((m.end.owner.categories ?? []).some((c) => c === \"connector\" || c.startsWith(\"connector.\"))) continue;\n const owner = m.end.ownerPath.join(\"/\");\n drivers.set(owner, [...(drivers.get(owner) ?? []), m.path]);\n driving.push(m);\n }\n if (drivers.size > 1 && !sameNested(driving)) {\n const paths = [...drivers.values()].flat();\n out.push({\n id: `net:${id}:drivers`,\n rule: \"net\",\n severity: \"error\",\n message: `net ${label} is driven by ${drivers.size} supplies (${paths.join(\", \")}); outputs in parallel fight each other.`,\n refs: [net.path, ...paths],\n });\n }\n\n // ground joined to a supply rail\n const groundMembers = net.members.filter((m) => hasRole(m.end.iface, \"power\", \"ground\"));\n const railMembers = net.members.filter((m) => hasRole(m.end.iface, \"power\", \"input\") || hasRole(m.end.iface, \"power\", \"output\"));\n const grounds = groundMembers.map((m) => m.path);\n const rails = railMembers.map((m) => m.path);\n if (grounds.length && rails.length && !sameNested([...groundMembers, ...railMembers])) {\n out.push({\n id: `net:${id}:ground`,\n rule: \"net\",\n severity: \"error\",\n message: `net ${label} joins ground (${grounds.join(\", \")}) to supply pins (${rails.join(\", \")}): a short.`,\n refs: [net.path, ...grounds, ...rails],\n });\n }\n\n // each pin with a stated voltage takes the net's design voltage. A supply\n // output's range is what it produces, so it must overlap; a supply input's\n // is what it accepts, so the whole rail must lie within it (a 4.2 V cell\n // rail on a 3.3 V input is a fault even though 3.0-3.3 V overlaps). A logic\n // or analog pin's range is its signal level: tied to a lower rail (a strap\n // to GND) it is driven low, so only a net above its maximum is reported.\n const design = conductorVoltageRange(net);\n const nestedRange = new Map((net.nested ?? []).map((n) => [n.path, netVoltageRange(n.iface)]));\n if (design) {\n // one conductor has one voltage: a sub-module's net joined here must state the same\n for (const n of net.nested ?? []) {\n const r = nestedRange.get(n.path);\n if (!r || rangesOverlap(r, design)) continue;\n out.push({\n id: `net:${id}:port_voltage:${n.path}`,\n rule: \"net\",\n severity: \"error\",\n message: `net ${label} is ${fmtRange(design)}, but ${n.path} (${n.iface.name ?? n.iface.id}), joined to it through a net port, is ${fmtRange(r)}.`,\n refs: [net.path, n.path],\n details: { net: design, nested: r },\n });\n }\n for (const m of net.members) {\n // a pin on a sub-module net that states this voltage is checked by that module\n const local = m.through ? nestedRange.get(m.through[m.through.length - 1]) : undefined;\n if (local && local[0] === design[0] && local[1] === design[1]) continue;\n const p = param(m.end.iface, \"voltage\");\n const range = p && getEffectiveRange(p);\n if (!range) continue;\n const supply = m.end.iface.protocols.some((x) => x.type === \"power\");\n const inputOnly = supply && hasRole(m.end.iface, \"power\", \"input\") && !hasRole(m.end.iface, \"power\", \"output\");\n const eps = 1e-9;\n const ok = inputOnly\n ? range[0] - eps <= design[0] && design[1] <= range[1] + eps\n : supply\n ? rangesOverlap(range, design)\n : design[1] <= range[1] || grounds.length > 0;\n if (ok) continue;\n out.push({\n id: `net:${id}:voltage:${m.path}`,\n rule: \"net\",\n severity: \"error\",\n message: supply\n ? `${m.path} (${m.end.iface.name ?? m.end.iface.id}) is rated ${fmtRange(range)} but net ${label} is ${fmtRange(design)}${inputOnly && rangesOverlap(range, design) ? \", outside its rating at one end\" : \"\"}.`\n : `${m.path} (${m.end.iface.name ?? m.end.iface.id}) is rated to ${range[1]} V but net ${label} reaches ${design[1]} V.`,\n refs: [net.path, m.path, `link:${m.link}`],\n details: { pin: range, net: design },\n });\n }\n }\n }\n\n // a push-pull logic output drives its net up to its own supply. When the\n // driving part has one supply net (a charger's STAT on its VDD), the net\n // reaches that supply's voltage, and a logic or analog input rated below it\n // is overdriven (an MCP73831's STAT at VBUS on a 3 V MCU pin). Open-drain\n // outputs, pins that are also inputs, and parts with several supplies are\n // left alone: their high level is not known from the model.\n const supplyNetsOf = (ownerPath: string): string[] => {\n const ids = new Set<string>();\n for (const net of nets) {\n if (net.members.some((m) => m.end.ownerPath.join(\"/\") === ownerPath && hasRole(m.end.iface, \"power\", \"input\") && !hasRole(m.end.iface, \"power\", \"ground\"))) ids.add(net.iface.id);\n }\n return [...ids];\n };\n for (const net of nets) {\n const label = net.iface.name && net.iface.name !== net.iface.id ? `${net.iface.id} (${net.iface.name})` : net.iface.id;\n for (const d of net.members) {\n const di = d.end.iface;\n if (!di.protocols.some((p) => p.type === \"digital\" && p.roles.includes(\"output\") && !p.roles.includes(\"input\") && !p.roles.includes(\"bidirectional\"))) continue;\n if ((di.capabilities ?? []).includes(\"open_drain\")) continue;\n const owner = d.end.ownerPath.join(\"/\");\n const supplies = supplyNetsOf(owner);\n if (supplies.length !== 1) continue;\n const supply = nets.find((n) => n.iface.id === supplies[0])!;\n const level = conductorVoltageRange(supply)?.[1];\n if (level === undefined) continue;\n for (const m of net.members) {\n if (m === d || m.end.ownerPath.join(\"/\") === owner) continue;\n if (m.end.iface.protocols.some((x) => x.type === \"power\")) continue;\n const p = param(m.end.iface, \"voltage\");\n const range = p && getEffectiveRange(p);\n if (!range || range[1] >= level - 1e-9) continue;\n out.push({\n id: `net:${net.iface.id}:drive:${m.path}`,\n rule: \"net\",\n severity: \"error\",\n message: `${d.path} (${di.name ?? di.id}) drives net ${label} up to its supply ${supply.iface.name ?? supply.iface.id} (${level} V), but ${m.path} (${m.end.iface.name ?? m.end.iface.id}) is rated to ${range[1]} V: divide, clamp or use an open-drain output.`,\n refs: [net.path, d.path, m.path, supply.path],\n details: { driver: d.path, supply: supply.path, level, pin: range },\n });\n }\n }\n }\n\n for (const [path, ids] of netsOf) {\n if (ids.length < 2) continue;\n out.push({\n id: `net:short:${path}`,\n rule: \"net\",\n severity: \"error\",\n message: `${path} is on nets ${ids.join(\", \")}, which joins them into one conductor.`,\n refs: [path, ...ids.map((n) => formatPath([], n))],\n });\n }\n // a pin inside a sub-module reached on two nets by two routes (its net's port on one, an exported pin on the\n // other); one port on two nets is reported above, by the port\n for (const [path, byNet] of physical) {\n const routes = new Set([...byNet.values()].flatMap((r) => [...r]));\n if (byNet.size < 2 || routes.size < 2) continue;\n const ids = [...byNet.keys()];\n out.push({\n id: `net:short:${path}`,\n rule: \"net\",\n severity: \"error\",\n message: `${path} is on nets ${ids.join(\", \")} (through a net port and an export), which joins them into one conductor.`,\n refs: [path, ...ids.map((n) => formatPath([], n))],\n });\n }\n return out;\n}\n\n/**\n * Faults of one part's own pins on the board's nets. Each is stated\n * from the model, not from a part's name:\n *\n * - **A shorted passive.** A two-terminal passive (resistor, capacitor,\n * inductor, ferrite bead) with every terminal on one net is a component\n * that does nothing: a capacitor across nothing, a resistor in series with\n * nothing. Its terminals belong on two nets.\n * - **An output tied back to its own input.** A part's power output (output\n * only) on one net with a power input (input only) of the same part that\n * feeds it short-circuits the converter: VOUT on VIN. Which input feeds\n * which output is the part's `bridgesTo` (a leaf or the composite binding\n * it); a part that states no bridge for its supply pins is taken as a\n * converter whose every power input feeds every power output. A part that\n * states its bridges may supply its own other inputs (an MCU's\n * core-regulator output on its own core supply pins). Connectors and lands carry power, they do\n * not convert it, and are skipped.\n * - **A strap on a signal.** A leaf with a `strap` trait, while its part runs\n * an interface in the strap's `when` (or always, without `when`), must sit\n * at a fixed level: on a supply or ground net, or on a net of its own with\n * a resistor to one (a pull-up or pull-down). On a net that carries\n * another pin's logic signal (a bus line) and no supply or ground pin, its\n * level follows the signal, whatever pull-up the line has: an IMU's\n * address strap moved onto SDA.\n */\nexport function partWiringRule(def: ModuleDef, links: LinkResult[], lookup?: ModuleLookup): SystemDiagnostic[] {\n const nets = moduleNets(def, links, lookup);\n const out: SystemDiagnostic[] = [];\n const ownerKey = (m: NetMember) => m.end.ownerPath.join(\"/\");\n const label = (n: BoardNet) => (n.iface.name && n.iface.name !== n.iface.id ? `${n.iface.id} (${n.iface.name})` : n.iface.id);\n const netsOfPin = new Map<string, BoardNet[]>();\n for (const n of nets) for (const m of n.members) netsOfPin.set(m.path, [...(netsOfPin.get(m.path) ?? []), n]);\n const isPower = (i: InterfaceDef) => i.protocols.some((p) => p.type === \"power\");\n const isPassivePin = (i: InterfaceDef) => i.protocols.length > 0 && i.protocols.every((p) => p.type === \"passive\");\n const isConnectorPart = (d: ModuleDef) => (d.categories ?? []).some((c) => c === \"connector\" || c.startsWith(\"connector.\"));\n\n // 1. passives with every terminal on one net\n const passives = new Map<string, { owner: ModuleDef; ownerPath: string[]; members: NetMember[] }>();\n for (const n of nets) {\n for (const m of n.members) {\n if (!passiveOf(m.end.owner)) continue;\n const k = ownerKey(m);\n const e = passives.get(k) ?? { owner: m.end.owner, ownerPath: m.end.ownerPath, members: [] };\n e.members.push(m);\n passives.set(k, e);\n }\n }\n for (const [path, { owner, ownerPath, members }] of passives) {\n const terminals = owner.interfaces.filter(isPassivePin);\n if (terminals.length < 2 || sameNested(members)) continue;\n const netIds = terminals.map((t) => (netsOfPin.get(formatPath(ownerPath, t.id)) ?? []).map((n) => n.iface.id));\n if (netIds.some((ids) => ids.length !== 1) || new Set(netIds.map((ids) => ids[0])).size !== 1) continue;\n const net = nets.find((n) => n.iface.id === netIds[0][0])!;\n const kind = passiveOf(owner)!.kind.replace(\"_\", \" \");\n out.push({\n id: `net:${net.iface.id}:shorted:${path}`,\n rule: \"net\",\n severity: \"error\",\n message: `${path} (${kind}, ${owner.name ?? owner.id}) has every terminal on net ${label(net)}: it is shorted and does nothing. Its terminals belong on two nets.`,\n refs: [net.path, ...members.map((m) => m.path)],\n details: { part: path, kind, net: net.iface.id },\n });\n }\n\n // 2. a power output on a net with an input of the same part that feeds it\n const outputOnly = (i: InterfaceDef) => hasRole(i, \"power\", \"output\") && !hasRole(i, \"power\", \"input\") && !hasRole(i, \"power\", \"ground\");\n const inputOnly = (i: InterfaceDef) => hasRole(i, \"power\", \"input\") && !hasRole(i, \"power\", \"output\") && !hasRole(i, \"power\", \"ground\");\n /** The ids an interface stands for: itself and every composite binding it. */\n const withComposites = (owner: ModuleDef, id: string) => [id, ...owner.interfaces.filter((c) => Object.values(slotBindings(c)).includes(id)).map((c) => c.id)];\n const bridges = (owner: ModuleDef, inputId: string, outputId: string) => {\n const targets = new Set(withComposites(owner, outputId));\n return withComposites(owner, inputId).some((id) => (owner.interfaces.find((i) => i.id === id)?.bridgesTo ?? []).some((t) => targets.has(t)));\n };\n const statesBridges = (owner: ModuleDef) =>\n owner.interfaces.some((i) => isPower(i) && (i.bridgesTo ?? []).some((t) => { const x = owner.interfaces.find((j) => j.id === t); return !!x && isPower(x); }));\n for (const n of nets) {\n const byOwner = new Map<string, NetMember[]>();\n for (const m of n.members) byOwner.set(ownerKey(m), [...(byOwner.get(ownerKey(m)) ?? []), m]);\n for (const [path, ms] of byOwner) {\n const owner = ms[0].end.owner;\n if (isConnectorPart(owner) || passiveOf(owner)) continue;\n const outs = ms.filter((m) => outputOnly(m.end.iface));\n const ins = ms.filter((m) => inputOnly(m.end.iface));\n if (!outs.length || !ins.length) continue;\n const declared = statesBridges(owner);\n const fed = ins.filter((i) => outs.some((o) => !declared || bridges(owner, i.end.iface.id, o.end.iface.id)));\n if (!fed.length || sameNested([...outs, ...fed])) continue;\n const name = (m: NetMember) => `${m.path} (${m.end.iface.name ?? m.end.iface.id})`;\n out.push({\n id: `net:${n.iface.id}:feedback:${path}`,\n rule: \"net\",\n severity: \"error\",\n message: `net ${label(n)} ties ${path}'s output ${outs.map(name).join(\", \")} to its own input ${fed.map(name).join(\", \")}, which feeds it: the output is shorted to the input.`,\n refs: [n.path, ...outs.map((m) => m.path), ...fed.map((m) => m.path)],\n details: { part: path, outputs: outs.map((m) => m.path), inputs: fed.map((m) => m.path) },\n });\n }\n }\n\n // 3. a strap on a net that carries another pin's signal and nothing that fixes its level\n const inUse = (ownerPath: string, ids: string[]) =>\n links.some((r) => !isNetMembership(r) && [r.a, r.b].some((e) => e.ownerPath.join(\"/\") === ownerPath && ids.includes(e.iface.id)));\n const strapOf = (m: NetMember) => {\n const t = m.end.iface.traits?.find((x) => x.type === \"strap\") as StrapTrait | undefined;\n if (!t) return undefined;\n const when = t.params?.when ?? [];\n return !when.length || inUse(ownerKey(m), when) ? t : undefined;\n };\n for (const n of nets) {\n // a supply or ground pin on the net fixes its level (a strap through a resistor is on a net of its own)\n if (n.members.some((m) => isPower(m.end.iface))) continue;\n for (const s of n.members) {\n const strap = strapOf(s);\n if (!strap) continue;\n const signals = n.members.filter((m) => m !== s && !isPower(m.end.iface) && !isPassivePin(m.end.iface) && !strapOf(m));\n if (!signals.length || sameNested([s, ...signals])) continue;\n out.push({\n id: `net:${n.iface.id}:strap:${s.path}`,\n rule: \"net\",\n severity: \"error\",\n message: `${s.path} (${s.end.iface.name ?? s.end.iface.id}) is a strap (${strap.params.function}) but net ${label(n)} carries ${signals.map((m) => m.path).join(\", \")}: its level follows that signal. Tie it to a supply or ground, directly or through a resistor.`,\n refs: [n.path, s.path, ...signals.map((m) => m.path)],\n details: { strap: s.path, function: strap.params.function, signals: signals.map((m) => m.path) },\n });\n }\n }\n return out;\n}\n\n/**\n * An I2C link derived over nets needs a pull-up on each of its nets: a\n * resistor (a `passive` resistor child) with one terminal on the bus net and\n * the other on a supply net (a net with a power output or a positive design\n * voltage). Parts with internal pull-ups are not modelled, so this warns.\n */\nexport function busPullupRule(def: ModuleDef, links: LinkResult[], lookup: ModuleLookup): SystemDiagnostic[] {\n const nets = moduleNets(def, links, lookup);\n const byId = new Map(nets.map((n) => [n.iface.id, n]));\n const netsOfPath = new Map<string, string[]>();\n for (const n of nets) for (const m of n.members) netsOfPath.set(m.path, [...(netsOfPath.get(m.path) ?? []), n.iface.id]);\n\n const isSupply = (n: BoardNet) =>\n n.members.some((m) => hasRole(m.end.iface, \"power\", \"output\")) || (netVoltage(n.iface) ?? 0) > 0;\n\n // the part a member pin is on: a direct child, or a part inside a sub-module reached through a net port\n const partOf = (m: NetMember): ModuleDef | undefined => {\n if (m.through) return m.end.owner;\n if (m.end.ownerPath.length !== 1) return undefined;\n const ref = def.children?.find((c) => c.id === m.end.ownerPath[0]);\n return ref ? lookup(ref.moduleDefId) : undefined;\n };\n\n const pulledUp = (n: BoardNet) =>\n n.members.some((m) => {\n const child = partOf(m);\n if (!child || passiveOf(child)?.kind !== \"resistor\") return false;\n return child.interfaces\n .filter((t) => t.id !== m.end.iface.id)\n .some((t) => (netsOfPath.get(formatPath(m.end.ownerPath, t.id)) ?? []).some((other) => {\n const on = byId.get(other);\n return on !== undefined && on !== n && isSupply(on);\n }));\n });\n\n const out: SystemDiagnostic[] = [];\n const reported = new Set<string>();\n // a net that carries a device's I2C line (a pad its I2C composite binds) and reaches another part is\n // an I2C bus even when no I2C link is derived (a controller whose bus pins are assigned in firmware)\n for (const n of nets) {\n if (reported.has(n.iface.id) || n.members.length < 2 || pulledUp(n)) continue;\n const owners = new Set(n.members.map((m) => m.end.ownerPath.join(\"/\")));\n if (owners.size < 2) continue;\n const device = n.members.find((m) => {\n const child = partOf(m);\n // a target's (slave's) I2C composite: a controller's composites are pin options, not a bus in use\n return !!child?.interfaces.some((i) => i.protocols.some((p) => p.type === \"i2c\" && p.roles.length > 0 && p.roles.every((r) => r === \"slave\" || r === \"target\")) && i.slots?.length && Object.values(slotBindings(i)).includes(m.end.iface.id));\n });\n if (!device) continue;\n reported.add(n.iface.id);\n out.push({\n id: `bus_pullup:${n.iface.id}`,\n rule: \"bus_pullup\",\n severity: \"warning\",\n message: `net ${n.iface.id} carries I2C (${device.path}) but no resistor pulls it up to a supply.`,\n refs: [n.path, device.path],\n });\n }\n for (const r of links) {\n if (r.protocol !== \"i2c\" || r.state === \"incompatible\" || !r.derived?.nets?.length) continue;\n for (const id of r.derived.nets) {\n const n = byId.get(id);\n if (!n || reported.has(id) || pulledUp(n)) continue;\n reported.add(id);\n out.push({\n id: `bus_pullup:${id}`,\n rule: \"bus_pullup\",\n severity: \"warning\",\n message: `net ${id} carries I2C (${r.a.path} ↔ ${r.b.path}) but no resistor pulls it up to a supply.`,\n refs: [n.path, `link:${r.link.id}`, r.a.path, r.b.path],\n });\n }\n }\n return out;\n}\n\n/**\n * Per-placement passive values (`ChildModuleRef.overrides` on a passive, at\n * any depth): each override must be one the part allows and agree with its\n * series (grades, ranges, ordering code). See `passiveInstance`.\n */\nexport function passiveOverrideRule(system: ModuleDef, lookup: ModuleLookup): SystemDiagnostic[] {\n const out: SystemDiagnostic[] = [];\n const seen = new Set<string>();\n const visit = (d: ModuleDef, prefix: string[]) => {\n if (seen.has(d.id)) return;\n seen.add(d.id);\n for (const c of d.children ?? []) {\n const def = lookup(c.moduleDefId);\n if (!def) continue;\n const path = [...prefix, c.id].join(\"/\");\n if (c.overrides && Object.keys(c.overrides).length) {\n const inst = passiveInstance(def, c.overrides);\n for (const [i, problem] of (inst?.problems ?? []).entries()) {\n out.push({\n id: `passive_override:${path}:${i}`,\n rule: \"passive_override\",\n severity: \"error\",\n message: `${path} (${def.id}): ${problem}`,\n refs: [path],\n details: { overrides: c.overrides },\n });\n }\n }\n visit(def, [...prefix, c.id]);\n }\n };\n visit(system, []);\n return out;\n}\n\n/** A stated body (`dimensions_mm`) larger than the module's `design_envelope`. */\nexport function designEnvelopeRule(def: ModuleDef): SystemDiagnostic[] {\n const env = def.traits?.find((t) => t.type === \"design_envelope\")?.params as DesignEnvelopeTrait[\"params\"] | undefined;\n if (!env) return [];\n const body = def.domains?.find((d) => d.domain === \"mechanical\" && d.dimensions_mm)?.dimensions_mm;\n if (!body) return [];\n const out: SystemDiagnostic[] = [];\n for (const axis of [\"length\", \"width\", \"height\"] as const) {\n const max = env.max_mm[axis];\n const size = body[axis];\n if (max === undefined || size === undefined || size <= max) continue;\n out.push({\n id: `design_envelope:${axis}`,\n rule: \"design_envelope\",\n severity: \"error\",\n message: `${def.id}: ${axis} ${size} mm exceeds the design envelope's ${max} mm${env.reason ? ` (${env.reason})` : \"\"}.`,\n refs: [],\n details: { axis, size, max },\n });\n }\n return out;\n}\n","/**\n * System-level helpers for modules with children: canonical paths, boundary\n * interfaces (own + exported), and validation of stored interface links.\n */\nimport type { InterfaceDef } from \"../types/interface.js\";\nimport type {\n ChildLink,\n EndpointTarget,\n InterfaceExport,\n InterfaceLink,\n ModuleDef,\n} from \"../types/module.js\";\nimport type { ConnectionResult, ConnectionState, Diagnostic, SubLinkResult } from \"../drc/types.js\";\nimport { validatePair } from \"../drc/validate-pair.js\";\nimport { matchProtocols } from \"../matching/protocol-match.js\";\nimport { validateConnectorLink } from \"./connectors.js\";\nimport { isConnector } from \"../protocols/connector.js\";\nimport { isNet } from \"../protocols/net.js\";\nimport { validateNetLink } from \"./nets.js\";\n\n/** Resolves a child's `moduleDefId` to its definition. */\nexport type ModuleLookup = (moduleDefId: string) => ModuleDef | undefined;\n\n// ---------------------------------------------------------------------------\n// Canonical paths\n// ---------------------------------------------------------------------------\n\n/**\n * Canonical path of a module instance or interface below a root module:\n * `child/grandchild` for modules, `child/grandchild:interface` for interfaces,\n * and `...:interface/slot` for a child interface under a composed one.\n */\nexport function formatPath(modules: string[], interfaceId?: string, slotId?: string): string {\n const base = modules.join(\"/\");\n if (interfaceId === undefined) return base;\n return `${base}:${interfaceId}${slotId !== undefined ? `/${slotId}` : \"\"}`;\n}\n\nexport function parsePath(path: string): { modules: string[]; interfaceId?: string; slotId?: string } {\n const [modulePart, interfacePart] = path.split(\":\");\n const modules = modulePart ? modulePart.split(\"/\") : [];\n if (interfacePart === undefined) return { modules };\n const [interfaceId, slotId] = interfacePart.split(\"/\");\n return { modules, interfaceId, ...(slotId !== undefined ? { slotId } : {}) };\n}\n\n// ---------------------------------------------------------------------------\n// Interfaces\n// ---------------------------------------------------------------------------\n\n/**\n * Interfaces that appear on a module's outline: every interface that is not\n * bound as a leaf into another interface's profile (pins behind a UART port\n * are revealed by opening the link, not drawn on the outline). Power and\n * ground leaves stay primary even when a connector binds them, because a\n * supply net is shared by every consumer. Connector composites do\n * not hide what they bind: a pad on a socket is still a pad.\n */\nexport function primaryInterfaces(def: ModuleDef): InterfaceDef[] {\n const bound = new Set<string>();\n for (const iface of def.interfaces) {\n if (isConnector(iface)) continue;\n for (const profile of iface.profiles ?? []) {\n for (const value of Object.values(profile.bindings)) {\n for (const id of Array.isArray(value) ? value : [value]) {\n if (id !== iface.id) bound.add(id);\n }\n }\n }\n }\n const isPower = (iface: InterfaceDef) => iface.protocols.some((p) => p.type === \"power\");\n return def.interfaces.filter((iface) => iface.exposed && (!bound.has(iface.id) || isPower(iface)));\n}\n\n/** Interfaces reachable from `iface` through its profiles (the slice DRC needs). */\nfunction boundClosure(def: ModuleDef, root: InterfaceDef): InterfaceDef[] {\n const byId = new Map(def.interfaces.map((i) => [i.id, i]));\n const seen = new Map<string, InterfaceDef>([[root.id, root]]);\n const queue = [root];\n while (queue.length) {\n const current = queue.shift()!;\n for (const profile of current.profiles ?? []) {\n for (const value of Object.values(profile.bindings)) {\n for (const id of Array.isArray(value) ? value : [value]) {\n const leaf = byId.get(id);\n if (leaf && !seen.has(id)) {\n seen.set(id, leaf);\n queue.push(leaf);\n }\n }\n }\n }\n }\n return [...seen.values()];\n}\n\nexport interface ResolvedExport extends InterfaceExport {\n /** The child module the export comes from (the module itself for a net port). */\n childDef: ModuleDef;\n /** The child interface being exported (the net, for a net port). */\n iface: InterfaceDef;\n /** True when implied by `kind: \"group\"` rather than declared. */\n implicit: boolean;\n}\n\nfunction childDef(def: ModuleDef, childId: string, lookup: ModuleLookup): ModuleDef {\n const ref = def.children?.find((c) => c.id === childId);\n if (!ref) throw new Error(`Module \"${def.id}\" has no child \"${childId}\"`);\n const resolved = lookup(ref.moduleDefId);\n if (!resolved) throw new Error(`Child \"${childId}\" of \"${def.id}\" references unknown module \"${ref.moduleDefId}\"`);\n return resolved;\n}\n\n/** True for an export of the module's own net (`from: { self: true, interfaceId }`). */\nexport function isNetPort(ex: InterfaceExport): ex is InterfaceExport & { from: { self: true; interfaceId: string } } {\n return \"self\" in ex.from && ex.from.self === true;\n}\n\n/** The net port that exports net `netId` of `def`, if the module declares one. */\nexport function netPortOf(def: ModuleDef, netId: string): InterfaceExport | undefined {\n return (def.exports ?? []).find((ex) => isNetPort(ex) && ex.from.interfaceId === netId);\n}\n\n/** True for a module marked as one printed circuit board (`kind: \"board\"`). */\nexport function isBoard(def: ModuleDef): boolean {\n return def.kind === \"board\";\n}\n\n/**\n * Exports of a module: its declared `exports`, plus — for `kind: \"group\"` —\n * every primary interface of every child that no internal link consumes.\n * Implicit export ids are `<child>__<interface>`. A net port resolves to the\n * module's own net, with `childDef` the module itself.\n */\nexport function resolveExports(def: ModuleDef, lookup: ModuleLookup): ResolvedExport[] {\n const out: ResolvedExport[] = [];\n const declared = new Set<string>();\n for (const ex of def.exports ?? []) {\n if (!(\"child\" in ex.from)) {\n const netId = ex.from.interfaceId;\n const net = def.interfaces.find((i) => i.id === netId);\n if (!net || !isNet(net)) throw new Error(`Export \"${ex.id}\" of \"${def.id}\": \"${netId}\" is not a net of the module; only a net is exported from the module itself`);\n out.push({ ...ex, childDef: def, iface: net, implicit: false });\n continue;\n }\n const child = childDef(def, ex.from.child, lookup);\n const iface = boundaryInterfaces(child, lookup).find((i) => i.id === ex.from.interfaceId);\n if (!iface) throw new Error(`Export \"${ex.id}\" of \"${def.id}\": child \"${ex.from.child}\" has no interface \"${ex.from.interfaceId}\"`);\n out.push({ ...ex, childDef: child, iface, implicit: false });\n declared.add(`${ex.from.child}:${ex.from.interfaceId}`);\n }\n if (def.kind !== \"group\") return out;\n\n const linkedInternally = new Set<string>();\n for (const link of def.links ?? []) {\n for (const end of [link.a, link.b]) {\n if (\"child\" in end) linkedInternally.add(`${end.child}:${end.interfaceId}`);\n }\n }\n for (const ref of def.children ?? []) {\n const child = childDef(def, ref.id, lookup);\n for (const iface of boundaryInterfaces(child, lookup)) {\n const key = `${ref.id}:${iface.id}`;\n if (declared.has(key) || linkedInternally.has(key)) continue;\n out.push({\n id: `${ref.id}__${iface.id}`,\n name: `${ref.name ?? child.name} · ${iface.name ?? iface.id}`,\n from: { child: ref.id, interfaceId: iface.id },\n childDef: child,\n iface,\n implicit: true,\n });\n }\n }\n return out;\n}\n\n/** Everything a neighbour can attach to: primary own interfaces plus exports. */\nexport function boundaryInterfaces(def: ModuleDef, lookup: ModuleLookup): InterfaceDef[] {\n const own = primaryInterfaces(def);\n if (!def.exports?.length && def.kind !== \"group\") return own;\n const exported = resolveExports(def, lookup).map((ex) => ({\n ...ex.iface,\n id: ex.id,\n name: ex.name ?? ex.iface.name,\n // a net port is on the edge, though the net it exports is not drawn on the outline\n ...(isNetPort(ex) ? { exposed: true } : {}),\n }));\n return [...own, ...exported];\n}\n\n// ---------------------------------------------------------------------------\n// Link validation\n// ---------------------------------------------------------------------------\n\nexport interface ResolvedEndpoint {\n /** Canonical path of the endpoint interface relative to the linking module. */\n path: string;\n /** The module that finally owns the interface (after following exports). */\n owner: ModuleDef;\n iface: InterfaceDef;\n /** Instance path of `owner` below the linking module (export hops included). */\n ownerPath: string[];\n /** Link-scoped composition: each slot of the ad-hoc connector, resolved. */\n composed?: Record<string, ResolvedEndpoint>;\n /**\n * Set when the endpoint is a child's net reached through the net port the\n * child exports (`iface` is that net, `owner` the module declaring it).\n */\n netPort?: true;\n}\n\n/**\n * Follow an endpoint through exports down to the module that owns the\n * interface. A child's net is reached only through the net port the child\n * exports for it (the port's id, or the net's own id when the port takes\n * it); the result is then marked `netPort`. A child's net without a port\n * resolves too, and the link to it is refused (`net_not_own`).\n */\nexport function resolveEndpoint(def: ModuleDef, end: EndpointTarget, lookup: ModuleLookup): ResolvedEndpoint {\n if (\"child\" in end && end.compose) return resolveComposition(def, end.child, end.interfaceId, end.compose, lookup);\n let owner = \"child\" in end ? childDef(def, end.child, lookup) : def;\n let interfaceId = end.interfaceId;\n const modules = \"child\" in end ? [end.child] : [];\n const ownerPath = [...modules];\n let throughPort = false;\n\n for (let depth = 0; depth < 16; depth++) {\n const own = owner.interfaces.find((i) => i.id === interfaceId);\n if (own) {\n const port = modules.length > 0 && isNet(own) && (throughPort || netPortOf(owner, own.id)?.id === own.id);\n return { path: formatPath(modules, end.interfaceId), owner, iface: own, ownerPath, ...(port ? { netPort: true as const } : {}) };\n }\n const ex = resolveExports(owner, lookup).find((e) => e.id === interfaceId);\n if (!ex) break;\n interfaceId = ex.from.interfaceId;\n if (!(\"child\" in ex.from)) {\n // a net port: the net is on the same module\n throughPort = true;\n continue;\n }\n owner = ex.childDef;\n ownerPath.push(ex.from.child);\n }\n throw new Error(`Link endpoint ${formatPath(modules, end.interfaceId)} not found on \"${owner.id}\"`);\n}\n\n/**\n * Resolve `value` below child `childId`: an interface on the child's boundary\n * (`\"rail_4v5\"`) or a canonical path below it (`\"fc:uart1_tx\"`,\n * `\"arm/motor:phases\"`). Paths are relative to the linking module.\n */\nexport function resolveBelow(def: ModuleDef, childId: string, value: string, lookup: ModuleLookup): ResolvedEndpoint {\n if (!value.includes(\":\")) return resolveEndpoint(def, { child: childId, interfaceId: value }, lookup);\n const { modules, interfaceId } = parsePath(value);\n let current = childDef(def, childId, lookup);\n const prefix = [childId];\n for (const m of modules.slice(0, -1)) {\n current = childDef(current, m, lookup);\n prefix.push(m);\n }\n const inner = resolveEndpoint(current, { child: modules[modules.length - 1], interfaceId: interfaceId! }, lookup);\n return { ...inner, path: formatPath([...prefix, modules[modules.length - 1]], interfaceId), ownerPath: [...prefix, ...inner.ownerPath] };\n}\n\n/**\n * A link-scoped composition: an ad-hoc connector on the child,\n * valid for this link only, whose slots are the other end's positions.\n */\nfunction resolveComposition(def: ModuleDef, childId: string, interfaceId: string, compose: Record<string, string>, lookup: ModuleLookup): ResolvedEndpoint {\n const owner = childDef(def, childId, lookup);\n if (owner.interfaces.some((i) => i.id === interfaceId)) {\n throw new Error(`Link-scoped composition \"${interfaceId}\" on \"${childId}\" shadows an existing interface; give it a new name`);\n }\n const composed: Record<string, ResolvedEndpoint> = {};\n for (const [slot, value] of Object.entries(compose)) composed[slot] = resolveBelow(def, childId, value, lookup);\n const first = Object.values(composed)[0];\n const iface: InterfaceDef = {\n id: interfaceId,\n name: interfaceId,\n domain: first?.iface.domain ?? \"electrical\",\n exposed: true,\n protocols: [{ type: \"connector\", roles: [\"mate\"] }],\n slots: Object.entries(composed).map(([slot, r]) => ({ id: slot, label: r.iface.name ?? r.iface.id, required: false, match: {} })),\n profiles: [{ id: \"link\", label: \"Link-scoped\", bindings: Object.fromEntries(Object.entries(compose).map(([slot, v]) => [slot, v])) }],\n traits: [{ type: \"link_scoped\", params: { note: \"Composed on the link: the module has no interface grouping these.\" } }],\n };\n return { path: formatPath([childId], interfaceId), owner, iface, ownerPath: [childId], composed };\n}\n\nexport type LinkState = \"configured\" | \"partial\" | \"incompatible\" | \"unconfigured\";\n\nexport interface LinkChildResult {\n a: { slotId?: string; leafId: string; pin?: string };\n b: { slotId?: string; leafId: string; pin?: string };\n /** protocol: derived by DRC; manual: stored child links; wired: traced through a harness. */\n method: \"protocol\" | \"manual\" | \"wired\";\n locked: boolean;\n}\n\nexport interface LinkResult {\n link: InterfaceLink;\n a: ResolvedEndpoint;\n b: ResolvedEndpoint;\n state: LinkState;\n /** Protocol type the pairing matched on (or the a-side's first type if none matched). */\n protocol: string;\n children: LinkChildResult[];\n unresolvedSlots: string[];\n diagnostics: Diagnostic[];\n /**\n * Set on links derived from conductors: the stored connector links\n * and harness children the conductors run through, and the board nets\n * they join through, when any.\n */\n derived?: { via: string[]; harnesses: string[]; nets?: string[] };\n}\n\nconst STATE_MAP: Record<ConnectionState, LinkState> = {\n valid: \"configured\",\n valid_inferred: \"configured\",\n valid_manual: \"configured\",\n configuration_needed: \"partial\",\n warning: \"partial\",\n incompatible: \"incompatible\",\n not_configured: \"unconfigured\",\n};\n\nfunction slice(owner: ModuleDef, iface: InterfaceDef): ModuleDef {\n return { ...owner, interfaces: boundClosure(owner, iface), interfaceGroups: [] };\n}\n\nfunction leafPin(owner: ModuleDef, leafId: string): string | undefined {\n const pin = owner.interfaces.find((i) => i.id === leafId)?.pin;\n return pin === undefined ? undefined : String(pin);\n}\n\nfunction childFromSubLink(sub: SubLinkResult, aOwner: ModuleDef, bOwner: ModuleDef): LinkChildResult {\n return {\n a: { slotId: sub.from.slotId, leafId: sub.from.interfaceId, pin: leafPin(aOwner, sub.from.interfaceId) },\n b: { slotId: sub.to.slotId, leafId: sub.to.interfaceId, pin: leafPin(bOwner, sub.to.interfaceId) },\n method: \"protocol\",\n locked: false,\n };\n}\n\nfunction storedChildren(stored: ChildLink[], a: ResolvedEndpoint, b: ResolvedEndpoint): LinkChildResult[] {\n const leafFor = (end: ResolvedEndpoint, slotOrLeaf: string) => {\n const binding = end.iface.profiles?.[0]?.bindings[slotOrLeaf];\n const leafId = typeof binding === \"string\" ? binding : slotOrLeaf;\n return { slotId: binding !== undefined ? slotOrLeaf : undefined, leafId, pin: leafPin(end.owner, leafId) };\n };\n return stored.map((c) => ({\n a: leafFor(a, c.a),\n b: leafFor(b, c.b),\n method: \"manual\",\n locked: c.locked ?? false,\n }));\n}\n\n/**\n * Validate one stored interface link: DRC runs on slices of the two owning\n * modules containing just the linked interfaces and the leaves they bind, so\n * the result describes exactly this connection (auto-discovery ambiguity\n * elsewhere on a module does not matter).\n */\nexport function validateLink(def: ModuleDef, link: InterfaceLink, lookup: ModuleLookup): LinkResult {\n const a = resolveEndpoint(def, link.a, lookup);\n const b = resolveEndpoint(def, link.b, lookup);\n if (isNet(a.iface) || isNet(b.iface)) return validateNetLink(link, a, b);\n if (isConnector(a.iface) && isConnector(b.iface)) return validateConnectorLink(link, a, b);\n return validateResolved(link, a, b);\n}\n\n/** Validate a link whose ends are already resolved (stored or derived). */\nexport function validateResolved(link: InterfaceLink, a: ResolvedEndpoint, b: ResolvedEndpoint): LinkResult {\n const pair = validatePair(slice(a.owner, a.iface), slice(b.owner, b.iface), { includePotentials: false, explicit: true });\n const connection: ConnectionResult | undefined = pair.connections.find(\n (c) => c.a.regionPath[0] === a.iface.id && c.b.regionPath[0] === b.iface.id,\n );\n\n if (!connection) {\n const match = matchProtocols(a.iface, b.iface);\n const reason = a.iface.domain !== b.iface.domain\n ? `domains differ (${a.iface.domain} vs ${b.iface.domain})`\n : match.compatible\n ? \"interfaces match by protocol but parameters conflict\"\n : `no compatible protocol/role between ${a.path} and ${b.path}`;\n const paramDiagnostics = pair.connections.flatMap((c) => c.diagnostics);\n return {\n link,\n a,\n b,\n state: \"incompatible\",\n protocol: a.iface.protocols[0]?.type ?? \"custom\",\n children: link.childLinks ? storedChildren(link.childLinks, a, b) : [],\n unresolvedSlots: [],\n diagnostics: [{ severity: \"error\", code: \"link_incompatible\", message: reason, refs: [] }, ...paramDiagnostics],\n };\n }\n\n const storedProblems = link.childLinks ? childLinkProblems(link.childLinks) : [];\n const children = link.childLinks\n ? storedChildren(link.childLinks, a, b)\n : connection.subLinks\n .filter((s) => s.from.interfaceId !== a.iface.id || s.to.interfaceId !== b.iface.id)\n .map((s) => childFromSubLink(s, a.owner, b.owner));\n\n const state: LinkState = storedProblems.length\n ? \"incompatible\"\n : link.childLinks && STATE_MAP[connection.state] === \"partial\"\n ? \"configured\"\n : STATE_MAP[connection.state];\n return {\n link,\n a,\n b,\n state,\n protocol: connection.protocol,\n children,\n unresolvedSlots: connection.unresolvedSlots.map((u) => `${u.moduleId}:${u.slotId}`),\n diagnostics: [...storedProblems, ...connection.diagnostics],\n };\n}\n\n/** Stored child links must use each slot at most once on each side. */\nfunction childLinkProblems(stored: ChildLink[]): Diagnostic[] {\n const problems: Diagnostic[] = [];\n for (const side of [\"a\", \"b\"] as const) {\n const seen = new Map<string, number>();\n for (const c of stored) seen.set(c[side], (seen.get(c[side]) ?? 0) + 1);\n for (const [slot, n] of seen) {\n if (n > 1) {\n problems.push({\n severity: \"error\",\n code: \"child_link_duplicate\",\n message: `stored child links map ${side}-side ${slot} ${n} times; each conductor must land on a distinct slot`,\n refs: [slot],\n });\n }\n }\n }\n return problems;\n}\n\n/** Validate every stored link on a module. */\nexport function validateLinks(def: ModuleDef, lookup: ModuleLookup): LinkResult[] {\n return (def.links ?? []).map((link) => validateLink(def, link, lookup));\n}\n","/**\n * A bundle that does not hold everything it names still draws.\n *\n * UHD's resolvers throw on a child whose definition is not in the bundle, and\n * on a link or an export that names an interface nobody has. A producer that\n * could not fetch some definitions (a library that was unreachable) writes\n * exactly such a bundle, and the viewer drew nothing at all for it.\n *\n * `tolerantSystem` gives the viewer a system the resolvers accept: a missing\n * definition is stood in for by a placeholder that has the interfaces its\n * parents' links and exports name, and a link or an export that still cannot\n * be resolved is left out. What was stood in for and what was left out is\n * returned, so the views can say so.\n */\nimport type { InterfaceDef, ModuleDef } from \"@uhd/types/index.js\";\nimport type { EndpointTarget } from \"@uhd/types/module.js\";\nimport { boundaryInterfaces, resolveEndpoint, type ModuleLookup } from \"@uhd/system/index.js\";\nimport { isNet } from \"@uhd/protocols/net.js\";\n\n/** A definition the bundle names and does not hold. */\nexport interface MissingDefinition {\n /** The definition id the children name. */\n id: string;\n /** Where it is used: the parent definition and the child's id and label there. */\n usedBy: { parent: string; child: string; name?: string }[];\n}\n\n/** A link or an export left out because it could not be resolved. */\nexport interface LeftOut {\n kind: \"link\" | \"export\";\n /** The definition it was on. */\n on: string;\n id: string;\n /** The resolver's message. */\n why: string;\n}\n\nexport interface TolerantSystem {\n root: ModuleDef;\n lookup: ModuleLookup;\n missing: MissingDefinition[];\n leftOut: LeftOut[];\n}\n\nconst PLACEHOLDERS = new WeakSet<ModuleDef>();\n\n/** Whether a definition is a placeholder for one the bundle does not hold. */\nexport function isPlaceholder(def: ModuleDef | undefined): boolean {\n return !!def && PLACEHOLDERS.has(def);\n}\n\n/** The interface ids one end of a link names on `child`'s boundary. */\nfunction namedOn(end: EndpointTarget, child: string): string[] {\n if (!(\"child\" in end) || end.child !== child) return [];\n if (!end.compose) return [end.interfaceId];\n // a composition's values are boundary interfaces, or paths below the child (which a placeholder cannot have)\n return Object.values(end.compose).filter((v) => !v.includes(\":\"));\n}\n\nexport function tolerantSystem(root: ModuleDef, lookup: ModuleLookup): TolerantSystem {\n const missing = new Map<string, MissingDefinition>();\n const wanted = new Map<string, Map<string, InterfaceDef>>();\n\n // 1. what is missing, and the interfaces its parents name on it\n const seen = new Set<ModuleDef>();\n const walk = (def: ModuleDef) => {\n if (seen.has(def)) return;\n seen.add(def);\n for (const ref of def.children ?? []) {\n const child = lookup(ref.moduleDefId);\n if (child) {\n walk(child);\n continue;\n }\n const m = missing.get(ref.moduleDefId) ?? { id: ref.moduleDefId, usedBy: [] };\n m.usedBy.push({ parent: def.id, child: ref.id, ...(ref.name ? { name: ref.name } : {}) });\n missing.set(ref.moduleDefId, m);\n const ifaces = wanted.get(ref.moduleDefId) ?? new Map<string, InterfaceDef>();\n wanted.set(ref.moduleDefId, ifaces);\n const want = (id: string, like?: InterfaceDef) => {\n if (ifaces.has(id) && !like) return;\n // the other end's domain, so the line is drawn in its colour; no protocol is claimed\n ifaces.set(id, { id, name: id, domain: like?.domain ?? ifaces.get(id)?.domain ?? \"electrical\", exposed: true, protocols: [{ type: \"custom\", roles: [] }] });\n };\n for (const link of def.links ?? []) {\n for (const [end, other] of [[link.a, link.b], [link.b, link.a]] as const) {\n const ids = namedOn(end, ref.id);\n if (!ids.length) continue;\n let like: InterfaceDef | undefined;\n try {\n like = resolveEndpoint(def, other, lookup).iface;\n } catch {\n like = undefined;\n }\n for (const id of ids) want(id, \"child\" in end && end.compose ? undefined : like);\n }\n }\n for (const ex of def.exports ?? []) if (\"child\" in ex.from && ex.from.child === ref.id) want(ex.from.interfaceId);\n for (const u of ref.unconnected ?? []) want(u.interfaceId);\n }\n };\n walk(root);\n\n const placeholders = new Map<string, ModuleDef>();\n for (const [id, m] of missing) {\n const def: ModuleDef = {\n id,\n name: m.usedBy[0]?.name ?? id,\n description: `The definition \"${id}\" is not in this bundle. This is a placeholder with the interfaces its links name.`,\n interfaces: [...(wanted.get(id)?.values() ?? [])],\n };\n PLACEHOLDERS.add(def);\n placeholders.set(id, def);\n }\n const withPlaceholders: ModuleLookup = (id) => lookup(id) ?? placeholders.get(id);\n\n // 2. leave out what still cannot be resolved, children before their parents\n const leftOut: LeftOut[] = [];\n const cleaned = new Map<ModuleDef, ModuleDef>();\n const cleanLookup: ModuleLookup = (id) => {\n const d = withPlaceholders(id);\n return d && clean(d);\n };\n function clean(def: ModuleDef): ModuleDef {\n const done = cleaned.get(def);\n if (done) return done;\n cleaned.set(def, def); // a definition that holds itself is not followed twice\n for (const ref of def.children ?? []) cleanLookup(ref.moduleDefId);\n\n const why = (e: unknown) => (e instanceof Error ? e.message : String(e));\n const children = (def.children ?? []).filter((ref) => withPlaceholders(ref.moduleDefId));\n const exports = (def.exports ?? []).filter((ex) => {\n try {\n const from = ex.from;\n if (!(\"child\" in from)) {\n // a net port (UHD 0.3.0): the module exports one of its own nets\n if (!def.interfaces.some((i) => i.id === from.interfaceId && isNet(i))) throw new Error(`\"${from.interfaceId}\" is not a net of \"${def.id}\"`);\n return true;\n }\n const ref = children.find((c) => c.id === from.child);\n const child = ref && cleanLookup(ref.moduleDefId);\n if (!child) throw new Error(`\"${def.id}\" has no child \"${from.child}\"`);\n if (!boundaryInterfaces(child, cleanLookup).some((i) => i.id === from.interfaceId)) throw new Error(`child \"${from.child}\" has no interface \"${from.interfaceId}\"`);\n return true;\n } catch (e) {\n leftOut.push({ kind: \"export\", on: def.id, id: ex.id, why: why(e) });\n return false;\n }\n });\n const base: ModuleDef = exports.length === (def.exports?.length ?? 0) ? def : { ...def, exports };\n const links = (def.links ?? []).filter((link) => {\n try {\n resolveEndpoint(base, link.a, cleanLookup);\n resolveEndpoint(base, link.b, cleanLookup);\n return true;\n } catch (e) {\n leftOut.push({ kind: \"link\", on: def.id, id: link.id, why: why(e) });\n return false;\n }\n });\n const out = links.length === (def.links?.length ?? 0) ? base : { ...base, links };\n if (PLACEHOLDERS.has(def) && out !== def) PLACEHOLDERS.add(out);\n cleaned.set(def, out);\n return out;\n }\n const cleanRoot = clean(root);\n return { root: cleanRoot, lookup: cleanLookup, missing: [...missing.values()], leftOut };\n}\n","/**\n * Viewer input (docs: protoboard-cli/docs/specs/uhd-boundary.md, \"The viewer\n * contract\"). The viewer shows whatever a UHD bundle describes: a root, its\n * definitions, scenarios, artifact bases, producer diagnostics and display\n * hints. It knows nothing about any particular project.\n */\nimport { bundleSystem } from \"@uhd/system/bundle.js\";\nimport { UHD_BUNDLE_SCHEMA, type UhdBundle, type UhdBundleDiagnostic } from \"@uhd/types/bundle.js\";\nimport type { ModuleDef } from \"@uhd/types/index.js\";\nimport type { ModuleLookup } from \"@uhd/system/index.js\";\nimport type { LevelLayout } from \"../layout/layout\";\nimport type { ArtifactResolver, ViewerOptions } from \"../api\";\nimport { tolerantSystem, type LeftOut, type MissingDefinition } from \"./tolerant\";\n\nexport interface ViewerScenario {\n id: string;\n label: string;\n description: string;\n system: ModuleDef;\n lookup: ModuleLookup;\n /** Definitions the bundle names and does not hold: drawn as placeholders (source/tolerant.ts). */\n missing: MissingDefinition[];\n /** Links and exports that could not be resolved, and are not drawn. */\n leftOut: LeftOut[];\n}\n\n/** Surface appearance for a definition (and optionally named sub-bodies of its CAD). */\nexport interface Appearance {\n color?: string;\n metalness?: number;\n roughness?: number;\n opacity?: number;\n parts?: Record<string, Omit<Appearance, \"parts\">>;\n}\n\nexport interface LabelHint {\n title?: string;\n sub?: string;\n hide?: boolean;\n}\n\n/** Presentation hints keyed by instance path. Never topology. */\nexport interface DisplayConfig {\n diagram?: {\n /** Hand layouts per drill level (\"\" = top). */\n layouts?: Record<string, LevelLayout>;\n /** Instance paths drawn expanded in place by default. */\n expanded?: string[];\n /** Links opened (conductors shown) by default. */\n openLinks?: string[];\n };\n spatial?: {\n /** Instance path the assembly is placed from (default: the best-connected structure). */\n root?: string;\n /** Explicit placements for modules no mate reaches (row-major 4×4, root coordinates). */\n placements?: Record<string, { matrix: number[]; note?: string }>;\n labels?: {\n modules?: Record<string, LabelHint>;\n /** Fastener harnesses and routed wire harnesses, by instance path. */\n harnesses?: Record<string, LabelHint>;\n };\n /** By definition id. */\n appearance?: Record<string, Appearance>;\n /** How the 3D view opens (PB-873). */\n view?: SpatialView;\n };\n}\n\n/**\n * The 3D view's opening camera, in the root's coordinates. Presentation only:\n * a watch modelled display-down (its case's frame has the display at −z)\n * says `up: [0, 0, -1]` and opens display-up, without changing the model.\n */\nexport interface SpatialView {\n /** The direction drawn up (default [0, 0, 1]): the camera's up, the orbit axis and the ground grid follow it. */\n up?: [number, number, number];\n /** A saved camera: azimuth and elevation (degrees, about `up`), distance (mm) and target. Without a distance the model is fitted. */\n camera?: { azimuth?: number; elevation?: number; distance?: number; target?: [number, number, number] };\n}\n\nexport interface LoadedSource {\n name: string;\n bundleUrl: string;\n scenarios: ViewerScenario[];\n /** URL for a definition's artifact file path, or undefined if it cannot be resolved. */\n resolveArtifact: ArtifactResolver;\n /** Findings from the bundle's producer (e.g. Protoboard's aggregated check). */\n hostDiagnostics: UhdBundleDiagnostic[];\n display: DisplayConfig;\n /** The bundle as loaded (for host views that read more of it than the viewer draws). */\n bundle: UhdBundle;\n}\n\nexport interface SourceOptions {\n /** Development only: absolute filesystem bases are served through Vite's /@fs route. */\n fsRoute?: boolean;\n /** A host's resolver; it receives the default one as `fallback`. */\n resolveArtifact?: ViewerOptions[\"resolveArtifact\"];\n}\n\n/**\n * The bundle URL for the standalone app: `?bundle=<url>`, then the URL a\n * server injected into the page, then the development default (none in a\n * production build).\n */\nexport function pickBundleUrl(search: string, injected?: string | null, fallback?: string | null): string | undefined {\n return new URLSearchParams(search).get(\"bundle\") ?? injected ?? fallback ?? undefined;\n}\n\n/**\n * URL prefix for an artifact base (`UhdBundle.artifactBases`: an absolute\n * path or a URL prefix), or undefined when it cannot be fetched over HTTP.\n * Absolute filesystem paths only resolve in development, through /@fs.\n */\nexport function baseToUrl(base: string, options: Pick<SourceOptions, \"fsRoute\"> = {}): string | undefined {\n if (!base.startsWith(\"/\")) return base.replace(/\\/$/, \"\");\n // compiled out of production builds\n if (import.meta.env.DEV && options.fsRoute) return (base.startsWith(\"/@fs/\") ? base : `/@fs${base}`).replace(/\\/$/, \"\");\n return undefined;\n}\n\n/** The default resolver: a definition's artifact base, or the bundle's own location. */\nexport function bundleResolver(bundle: UhdBundle, bundleUrl: string, options: Pick<SourceOptions, \"fsRoute\"> = {}): ArtifactResolver {\n const here = bundleUrl.replace(/[^/]*$/, \"\").replace(/\\/$/, \"\");\n const warned = new Set<string>();\n return (definitionId, filePath) => {\n if (/^https?:\\/\\//.test(filePath)) return filePath;\n const base = bundle.artifactBases?.[definitionId];\n const prefix = base ? baseToUrl(base, options) : here;\n if (prefix !== undefined) return `${prefix}/${filePath}`;\n if (base && !warned.has(base)) {\n warned.add(base);\n console.warn(`uhd-viewer: artifact base ${base} is a filesystem path; serve the bundle with \\`uhd-viewer serve\\` or give the viewer a resolver`);\n }\n return undefined;\n };\n}\n\nexport async function loadBundle(url: string, options: SourceOptions = {}): Promise<LoadedSource> {\n const res = await fetch(url);\n if (!res.ok) throw new Error(`could not load UHD bundle ${url} (${res.status})`);\n return sourceFromBundle((await res.json()) as UhdBundle, url, options);\n}\n\nexport function sourceFromBundle(bundle: UhdBundle, url: string, options: SourceOptions = {}): LoadedSource {\n if (bundle.schema !== UHD_BUNDLE_SCHEMA) throw new Error(`${url} is not a UHD bundle (schema ${String(bundle.schema)})`);\n const scenarios: ViewerScenario[] = [\n { id: \"nominal\", label: \"Nominal\", description: \"\", ...sys(bundle) },\n ...(bundle.scenarios ?? []).filter((s) => s.id !== \"nominal\").map((s) => ({ id: s.id, label: s.label, description: s.description ?? \"\", ...sys(bundle, s.id) })),\n ];\n const nominal = bundle.scenarios?.find((s) => s.id === \"nominal\");\n if (nominal) scenarios[0].label = nominal.label;\n const fallback = bundleResolver(bundle, url, options);\n const host = options.resolveArtifact;\n return {\n name: bundle.meta?.name ?? bundle.root,\n bundleUrl: url,\n scenarios,\n resolveArtifact: host ? (definitionId, filePath) => host(definitionId, filePath, fallback) : fallback,\n hostDiagnostics: bundle.diagnostics ?? [],\n display: (bundle.display ?? {}) as DisplayConfig,\n bundle,\n };\n}\n\nfunction sys(bundle: UhdBundle, scenario?: string): Pick<ViewerScenario, \"system\" | \"lookup\" | \"missing\" | \"leftOut\"> {\n const raw = bundleSystem(bundle, scenario);\n // a bundle that names what it does not hold still draws, and says what it lacks\n const { root, lookup, missing, leftOut } = tolerantSystem(raw.root, raw.lookup);\n return { system: root, lookup, missing, leftOut };\n}\n","/**\n * Derived links: the functional connections a physical wiring makes.\n *\n * Stored links between connectors mate positions; harness modules carry\n * conductors between their own ends (internal `self` ↔ `self` links whose\n * child links are the wires, straight through by default). Walking those\n * conductors from a pad on one part to a pad on another gives leaf pairs.\n * Each pad is lifted back to the functional interface it belongs to — the\n * composite (UART, I2C, FC/ESC port…) whose bound pads all travel to the same\n * module, else the pad itself — and each lifted pair becomes an ordinary link\n * result, validated like a stored link and tagged `derived`.\n *\n * System checks run on stored and derived links together, so supply budgets,\n * interface reuse, unpowered inputs and bus addresses see through cables.\n * The walk also checks the wiring: conductor pairs inside a composite must\n * match the pairing the protocol expects (TX to RX).\n *\n * Board nets join the same walk: each net is a node that its\n * member pins' membership links reach, so every pin on a net reaches every\n * other. On a net, a pair of pads is a link only when the interfaces they\n * lift to pair by protocol (a supply output with an input, an I2C master\n * with a target); pads that do not pair (two loads, two targets) share the\n * net without a link between them. A rail (a net with a supply or ground pin\n * on it, or a design voltage) carries power only: a logic or analog pin tied\n * to it is a strap and pairs with nothing, and ground pins on one net share\n * it without a link per pair. The net rule checks what pairs cannot (nets.ts).\n *\n * A supply output on a rail that states its design voltage (a `Net` with a\n * `voltage`) is validated at that voltage: the board sets the rail (an\n * adjustable regulator by its feedback divider, a charger by its cell), so\n * the output's full adjustable or charge range is not what its loads see.\n * The net rule still checks every pin against the rail's voltage.\n *\n * A composite lifts when every pad it binds reaches the other module. Each\n * pairing its protocol expects must then be wired inside it: a pad wired to\n * the wrong counterpart is `harness_wiring`, a required one wired elsewhere\n * or not at all is `bus_incomplete`.\n *\n * Net ports: a child's net that the child exports as a net port, joined\n * here to a net (or to a pin), is followed into the child, and through its\n * own children's net ports at any depth. Every pin on the child's net is\n * then on the conductor, so a supply or bus whose ends sit on both sides of\n * the child's edge is derived once, here: a regulator on this module with\n * the loads inside the child, a controller here with a sensor inside it. A\n * pair whose conductor stays inside one child (two of its pins on its own\n * net) is the child's own and is derived when the child is checked. Without\n * net ports, derivation stops at each module's edge as before.\n *\n * Scope: harnesses that are children of the linking module, and connector\n * links and nets stored on it, and the nets of children behind net ports.\n * Parts may be nested (a pad on stack/fc).\n */\nimport type { InterfaceDef } from \"../types/interface.js\";\nimport type { InterfaceLink, ModuleDef } from \"../types/module.js\";\nimport type { Diagnostic } from \"../drc/types.js\";\nimport {\n formatPath,\n resolveEndpoint,\n resolveExports,\n validateLinks,\n validateResolved,\n type LinkChildResult,\n type LinkResult,\n type ModuleLookup,\n type ResolvedEndpoint,\n} from \"./index.js\";\nimport { positionPairs, slotBindings } from \"./connectors.js\";\nimport { isConnector } from \"../protocols/connector.js\";\nimport { isNet, NET_PROTOCOL } from \"../protocols/net.js\";\nimport { membershipEnds, netPortReach, physicalPath } from \"./nets.js\";\nimport { matchProtocols } from \"../matching/protocol-match.js\";\nimport { getEffectiveRange } from \"../parameters/range.js\";\n\ninterface Terminal {\n key: string;\n owner: ModuleDef;\n ownerPath: string[];\n leaf: InterfaceDef;\n}\n\ninterface Edge {\n to: string;\n link?: string;\n harness?: string;\n net?: string;\n /** A membership stored inside a child, reached through its net port. */\n inner?: true;\n}\n\nconst pathKey = (p: string[]) => p.join(\"/\");\n\n/** The conductor node for one position of a resolved connector end. */\nfunction nodeFor(end: ResolvedEndpoint, slot: string, lookup: ModuleLookup): { key: string; terminal?: Terminal; harness?: string } | undefined {\n const composed = end.composed?.[slot];\n if (composed) {\n const key = `${pathKey(composed.ownerPath)}#${composed.iface.id}`;\n if (composed.owner.kind === \"harness\") return { key, harness: composed.ownerPath[0] };\n return { key, terminal: { key, owner: composed.owner, ownerPath: composed.ownerPath, leaf: composed.iface } };\n }\n if (end.owner.kind === \"harness\") return { key: `${pathKey(end.ownerPath)}#${end.iface.id}/${slot}`, harness: end.ownerPath[0] };\n const leafId = slotBindings(end.iface)[slot];\n if (!leafId) return undefined; // unused position (VOID)\n const leaf = end.owner.interfaces.find((i) => i.id === leafId);\n if (!leaf) return undefined;\n const key = `${pathKey(end.ownerPath)}#${leafId}`;\n return { key, terminal: { key, owner: end.owner, ownerPath: end.ownerPath, leaf } };\n}\n\n/** Composite interfaces (not connectors) that bind `leafId` in their default profile. */\nfunction compositesBinding(owner: ModuleDef, leafId: string): { iface: InterfaceDef; leaves: string[] }[] {\n const out: { iface: InterfaceDef; leaves: string[] }[] = [];\n for (const iface of owner.interfaces) {\n if (isConnector(iface) || !iface.profiles?.length) continue;\n const leaves = Object.values(slotBindings(iface));\n if (leaves.includes(leafId)) out.push({ iface, leaves });\n }\n return out;\n}\n\ninterface Candidate {\n iface: InterfaceDef;\n /** Pads it binds (1 for the pad itself). */\n size: number;\n /** The pads that are not ground (the pad's own id for a pad). */\n live: string[];\n}\n\n/**\n * What a pad can lift to, largest first: each composite binding it whose\n * bound pads all travel to the same module, then the pad itself.\n */\nfunction liftCandidates(owner: ModuleDef, leaf: InterfaceDef, carried: Set<string>): Candidate[] {\n const eligible = compositesBinding(owner, leaf.id)\n .filter((c) => c.leaves.every((l) => carried.has(l)))\n .sort((x, y) => y.leaves.length - x.leaves.length)\n .map((c) => ({ iface: c.iface, size: c.leaves.length, live: c.leaves.filter((l) => !isGround(owner.interfaces.find((i) => i.id === l) ?? leaf)) }));\n return [...eligible, { iface: leaf, size: 1, live: [leaf.id] }];\n}\n\nconst isComposite = (iface: InterfaceDef) => Boolean(iface.slots?.length);\n\n/**\n * The functional interfaces a pad pair lifts to: the largest pair that pairs\n * by protocol, composite with composite or pad with pad (a composite port is\n * not validated against a lone pad). With none, a conductor still links the\n * largest candidates of one kind (two composites, else the two pads it joins)\n * and the link reports the mismatch; on a net the pads only share the net.\n * A composite is never validated against the lone pad a wire lands on: that\n * finds the composite's own matching pad and passes the wire that is wrong\n * (a cell's + lead on the board's BAT- pad). Two ground pads on a net share it without a link; as\n * conductors of two composites they still pair.\n */\nfunction lift(a: Candidate[], b: Candidate[], onNet: boolean, joined: (la: string, lb: string) => boolean = () => true): { fa: InterfaceDef; fb: InterfaceDef } | undefined {\n let best: { fa: InterfaceDef; fb: InterfaceDef } | undefined;\n let bestSize = 0;\n for (const x of a) {\n for (const y of b) {\n if (x.size + y.size <= bestSize || isComposite(x.iface) !== isComposite(y.iface)) continue;\n // two composites pair only when a conductor other than ground joins them: on a board, a part's\n // LED supply and a regulator's output may both reach the other part, but only their grounds meet\n if (isComposite(x.iface) && !x.live.some((la) => y.live.some((lb) => joined(la, lb)))) continue;\n if (onNet && !isComposite(x.iface) && isGround(x.iface) && isGround(y.iface)) continue;\n // passive terminals (a resistor's, a capacitor's) on a net only share it: they pair only through an explicit conductor\n if (onNet && isPassive(x.iface) && isPassive(y.iface)) continue;\n if (!matchProtocols(x.iface, y.iface).compatible) continue;\n best = { fa: x.iface, fb: y.iface };\n bestSize = x.size + y.size;\n }\n }\n if (best || onNet) return best;\n if (isComposite(a[0].iface) === isComposite(b[0].iface)) return { fa: a[0].iface, fb: b[0].iface };\n return { fa: a[a.length - 1].iface, fb: b[b.length - 1].iface };\n}\n\n/** Root-relative endpoint for an interface owned at `ownerPath`: through an export when one exists. */\nfunction endpointFor(def: ModuleDef, ownerPath: string[], owner: ModuleDef, iface: InterfaceDef, lookup: ModuleLookup): ResolvedEndpoint {\n if (ownerPath.length > 1) {\n const top = def.children?.find((c) => c.id === ownerPath[0]);\n const topDef = top ? lookup(top.moduleDefId) : undefined;\n for (const ex of topDef ? resolveExports(topDef, lookup) : []) {\n try {\n const r = resolveEndpoint(def, { child: ownerPath[0], interfaceId: ex.id }, lookup);\n if (r.owner === owner && r.iface.id === iface.id && pathKey(r.ownerPath) === pathKey(ownerPath)) return r;\n } catch {\n /* unresolvable export: skip */\n }\n }\n }\n return { path: formatPath(ownerPath, iface.id), owner, iface, ownerPath };\n}\n\nconst targetFor = (end: ResolvedEndpoint) => {\n const [child] = end.ownerPath;\n const interfaceId = end.path.slice(end.path.indexOf(\":\") + 1);\n const below = end.ownerPath.length > 1 && !end.path.startsWith(`${child}:`) ? `${end.ownerPath.slice(1).join(\"/\")}:${end.iface.id}` : interfaceId;\n return { child, interfaceId: below };\n};\n\n/**\n * Functional links derived from the connector links and harnesses of `def`.\n * Pass `stored` to reuse results from validateLinks.\n */\nexport function deriveLinks(def: ModuleDef, lookup: ModuleLookup, stored: LinkResult[] = validateLinks(def, lookup)): LinkResult[] {\n const edges = new Map<string, Edge[]>();\n const terminals = new Map<string, Terminal>();\n const order: string[] = [];\n const addEdge = (x: string, y: string, e: Omit<Edge, \"to\">) => {\n edges.set(x, [...(edges.get(x) ?? []), { to: y, ...e }]);\n edges.set(y, [...(edges.get(y) ?? []), { to: x, ...e }]);\n };\n\n // 1. mated positions of stored connector links\n for (const r of stored) {\n if (r.protocol !== \"connector\" || r.state === \"incompatible\") continue;\n for (const p of positionPairs(r.link, r.a, r.b)) {\n const na = nodeFor(r.a, p.a, lookup);\n const nb = nodeFor(r.b, p.b, lookup);\n if (!na || !nb) continue;\n for (const n of [na, nb]) {\n if (n.terminal && !terminals.has(n.key)) {\n terminals.set(n.key, n.terminal);\n order.push(n.key);\n }\n }\n addEdge(na.key, nb.key, { link: r.link.id });\n }\n }\n\n // 1b. net memberships: each pin is joined to its net's node\n const rails = new Set<string>();\n const hasVoltage = (iface: InterfaceDef) => Boolean(iface.parameters?.some((p) => p.id === \"voltage\"));\n const terminalFor = (end: ResolvedEndpoint) => {\n const key = `${pathKey(end.ownerPath)}#${end.iface.id}`;\n if (!terminals.has(key)) {\n terminals.set(key, { key, owner: end.owner, ownerPath: end.ownerPath, leaf: end.iface });\n order.push(key);\n }\n return key;\n };\n // a child's net behind its net port: one node, joined to every pin the port reaches inside the child\n const nestedNets = new Map<string, InterfaceDef>();\n // port nodes whose nested net is a rail (a design voltage or a supply or ground pin inside)\n const railPorts = new Set<string>();\n const portNode = (port: ResolvedEndpoint) => {\n const node = `net#${physicalPath(port)}`;\n if (edges.has(node)) return node;\n edges.set(node, []);\n const reached = netPortReach(port, lookup);\n for (const n of reached.nets) nestedNets.set(n.path, n.iface);\n if (reached.nets.some((n) => hasVoltage(n.iface)) || reached.members.some((m) => isPower(m.end.iface))) {\n railPorts.add(node);\n for (const n of reached.nets) rails.add(n.path);\n }\n for (const m of reached.members) addEdge(node, terminalFor(m.end), { link: m.link, net: m.through![m.through!.length - 1], inner: true });\n return node;\n };\n for (const r of stored) {\n if (r.protocol !== NET_PROTOCOL || r.state === \"incompatible\") continue;\n const ends = membershipEnds(r);\n if (\"port\" in ends) {\n // a pin linked straight to a child's net port\n const node = portNode(ends.port);\n if (isPower(ends.member.iface)) rails.add(physicalPath(ends.port));\n addEdge(terminalFor(ends.member), node, { link: r.link.id, net: physicalPath(ends.port) });\n continue;\n }\n const { net, member } = ends;\n if (member.netPort) {\n // the parent's net and the child's net behind the port are one conductor: a rail on either side is a rail on both\n const node = portNode(member);\n if (hasVoltage(net.iface) || railPorts.has(node)) rails.add(net.iface.id);\n addEdge(`net#${net.iface.id}`, node, { link: r.link.id, net: net.iface.id });\n continue;\n }\n if (isPower(member.iface) || hasVoltage(net.iface)) rails.add(net.iface.id);\n addEdge(terminalFor(member), `net#${net.iface.id}`, { link: r.link.id, net: net.iface.id });\n }\n\n // 2. conductors inside harness children\n for (const ref of def.children ?? []) {\n const h = lookup(ref.moduleDefId);\n if (h?.kind !== \"harness\") continue;\n for (const link of h.links ?? []) {\n if (!(\"self\" in link.a) || !(\"self\" in link.b)) continue;\n const ia = h.interfaces.find((i) => i.id === link.a.interfaceId);\n const ib = h.interfaces.find((i) => i.id === link.b.interfaceId);\n if (!ia || !ib) continue;\n const ra: ResolvedEndpoint = { path: formatPath([ref.id], ia.id), owner: h, iface: ia, ownerPath: [ref.id] };\n const rb: ResolvedEndpoint = { path: formatPath([ref.id], ib.id), owner: h, iface: ib, ownerPath: [ref.id] };\n for (const p of positionPairs(link, ra, rb)) {\n addEdge(`${ref.id}#${ia.id}/${p.a}`, `${ref.id}#${ib.id}/${p.b}`, { harness: ref.id });\n }\n }\n }\n\n // 3. walk from each terminal through non-terminal nodes to the terminals it reaches\n interface Pair {\n a: Terminal;\n b: Terminal;\n links: Set<string>;\n harnesses: Set<string>;\n nets: Set<string>;\n }\n const pairs = new Map<string, Pair>();\n for (const start of order) {\n // `outside`: the conductor so far runs through something of this module, not only a child's own net\n const walk = (node: string, seen: Set<string>, links: Set<string>, harnesses: Set<string>, nets: Set<string>, outside: boolean) => {\n for (const e of edges.get(node) ?? []) {\n if (seen.has(e.to)) continue;\n const nextLinks = e.link ? new Set([...links, e.link]) : links;\n const nextHarnesses = e.harness ? new Set([...harnesses, e.harness]) : harnesses;\n const nextNets = e.net ? new Set([...nets, e.net]) : nets;\n const nextOutside = outside || !e.inner;\n const t = terminals.get(e.to);\n if (t) {\n // two pins on a child's own net pair in the child's check, not here\n if (!nextOutside) continue;\n let a = terminals.get(start)!;\n let b = t;\n if (pathKey(a.ownerPath) === pathKey(b.ownerPath)) {\n // the walk never pairs a part with itself, except a part supplying\n // itself through a board net (an on-chip regulator's output to its core)\n if (!nextNets.size || !selfSupply(a.leaf, b.leaf)) continue;\n if (!isPowerOutput(a.leaf)) [a, b] = [b, a];\n }\n // over a rail only power pins pair; a logic pin tied to it is a strap\n if ([...nextNets].some((n) => rails.has(n)) && !(isPower(a.leaf) && isPower(b.leaf))) continue;\n const key = [start, e.to].sort().join(\"|\");\n if (!pairs.has(key)) pairs.set(key, { a, b, links: nextLinks, harnesses: nextHarnesses, nets: nextNets });\n continue;\n }\n walk(e.to, new Set([...seen, e.to]), nextLinks, nextHarnesses, nextNets, nextOutside);\n }\n };\n walk(start, new Set([start]), new Set(), new Set(), new Set(), false);\n }\n\n // 4. group by module pair, lift pads to functional interfaces, validate\n const byModules = new Map<string, Pair[]>();\n for (const p of pairs.values()) {\n const fwd = `${pathKey(p.a.ownerPath)}|${pathKey(p.b.ownerPath)}`;\n const rev = `${pathKey(p.b.ownerPath)}|${pathKey(p.a.ownerPath)}`;\n if (fwd !== rev && byModules.has(rev)) byModules.get(rev)!.push({ ...p, a: p.b, b: p.a });\n else byModules.set(fwd, [...(byModules.get(fwd) ?? []), p]);\n }\n\n const out: LinkResult[] = [];\n for (const group of byModules.values()) {\n const carriedA = new Set(group.map((p) => p.a.leaf.id));\n const carriedB = new Set(group.map((p) => p.b.leaf.id));\n const functional = new Map<string, { fa: InterfaceDef; fb: InterfaceDef; pairs: Pair[] }>();\n const wires = new Set(group.map((p) => `${p.a.leaf.id}|${p.b.leaf.id}`));\n const joined = (la: string, lb: string) => wires.has(`${la}|${lb}`);\n for (const p of group) {\n const lifted = lift(liftCandidates(p.a.owner, p.a.leaf, carriedA), liftCandidates(p.b.owner, p.b.leaf, carriedB), p.nets.size > 0, joined);\n if (!lifted) continue;\n const { fa, fb } = lifted;\n const k = `${fa.id}|${fb.id}`;\n const entry = functional.get(k) ?? { fa, fb, pairs: [] };\n entry.pairs.push(p);\n functional.set(k, entry);\n }\n for (const { fa, fb, pairs: wires } of functional.values()) {\n const { a: ta, b: tb } = wires[0];\n const a = endpointFor(def, ta.ownerPath, ta.owner, fa, lookup);\n const b = endpointFor(def, tb.ownerPath, tb.owner, fb, lookup);\n const via = [...new Set(wires.flatMap((w) => [...w.links]))].sort();\n const harnesses = [...new Set(wires.flatMap((w) => [...w.harnesses]))].sort();\n const nets = [...new Set(wires.flatMap((w) => [...w.nets]))].sort();\n const link: InterfaceLink = {\n id: `${via.join(\"+\")}~${fa.id}~${fb.id}`,\n name: `${fa.name ?? fa.id} ↔ ${fb.name ?? fb.id}`,\n a: targetFor(a),\n b: targetFor(b),\n ...(harnesses.length ? { harness: harnesses[0] } : {}),\n };\n const result = { ...validateResolved(link, atRail(def, nets, a, nestedNets), atRail(def, nets, b, nestedNets)), a, b };\n const wired: LinkChildResult[] = wires\n .filter((w) => w.a.leaf.id !== fa.id || w.b.leaf.id !== fb.id)\n .map((w) => ({\n a: { slotId: slotOf(fa, w.a.leaf.id), leafId: w.a.leaf.id, pin: pinOf(w.a.leaf) },\n b: { slotId: slotOf(fb, w.b.leaf.id), leafId: w.b.leaf.id, pin: pinOf(w.b.leaf) },\n method: \"wired\",\n locked: false,\n }));\n const problems = [...wiringProblems(result, wired), ...(isComposite(fa) ? missingConductors(result, fa, fb, wired) : [])];\n // slots the 1:1 slot pairing leaves open (a second VLED pin, an exposed pad beside GND, VIN and\n // VINA on one rail against one VBAT slot) are complete when a conductor (a wire or a board net)\n // joins every pad of the slot to the other side of the link\n const unresolved = result.unresolvedSlots.filter((u) => !reachedByConductor(u, fa, fb, a, b, wired));\n const state = problems.length ? \"incompatible\" : result.state === \"partial\" && !unresolved.length && !result.diagnostics.some((d) => d.severity !== \"info\") ? \"configured\" : result.state;\n out.push({\n ...result,\n unresolvedSlots: unresolved,\n state,\n children: wired.length ? wired : result.children,\n diagnostics: [...problems, ...result.diagnostics],\n derived: { via, harnesses, ...(nets.length ? { nets } : {}) },\n });\n }\n }\n return out;\n}\n\nconst isPower = (i: InterfaceDef) => i.protocols.some((p) => p.type === \"power\");\nconst isPassive = (i: InterfaceDef) => i.protocols.length > 0 && i.protocols.every((p) => p.type === \"passive\");\n\n/**\n * A supply output on a rail whose net states a design voltage, as the board\n * runs it: its voltage narrowed to the rail's when the rail lies inside the\n * output's own range (outside it, the output keeps its range and the link\n * fails as it should). Used for validation only.\n */\nfunction atRail(def: ModuleDef, nets: string[], end: ResolvedEndpoint, nested: Map<string, InterfaceDef> = new Map()): ResolvedEndpoint {\n if (!isPowerOutput(end.iface)) return end;\n const own = end.iface.parameters?.find((p) => p.id === \"voltage\");\n const ownRange = own && getEffectiveRange(own);\n if (!own || !ownRange) return end;\n // this module's own nets first, then the children's nets behind net ports\n const ordered = [...nets.filter((id) => !nested.has(id)), ...nets.filter((id) => nested.has(id))];\n for (const id of ordered) {\n const net = def.interfaces.find((i) => i.id === id && isNet(i)) ?? nested.get(id);\n const v = net?.parameters?.find((p) => p.id === \"voltage\");\n const rail = v && getEffectiveRange(v);\n if (!rail || rail[0] < ownRange[0] || rail[1] > ownRange[1]) continue;\n // the composite and the output leaves it binds, all at the rail's voltage (validation slices the owner by id)\n const bound = new Set([end.iface.id, ...(end.iface.profiles ?? []).flatMap((pr) => Object.values(pr.bindings).flat().filter((x): x is string => typeof x === \"string\"))]);\n const narrow = (i: InterfaceDef): InterfaceDef =>\n bound.has(i.id) && isPowerOutput(i) && i.parameters?.some((p) => p.id === \"voltage\")\n ? { ...i, parameters: i.parameters.map((p) => (p.id === \"voltage\" ? { ...p, value: v!.value ?? (rail[0] + rail[1]) / 2, range: rail as [number, number] } : p)) }\n : i;\n const owner = { ...end.owner, interfaces: end.owner.interfaces.map(narrow) };\n return { ...end, owner, iface: owner.interfaces.find((i) => i.id === end.iface.id)! };\n }\n return end;\n}\nconst isGround = (i: InterfaceDef) => i.protocols.some((p) => p.type === \"power\" && p.roles.includes(\"ground\"));\nconst isPowerOutput = (i: InterfaceDef) => i.protocols.some((p) => p.type === \"power\" && p.roles.includes(\"output\"));\nconst isPowerInput = (i: InterfaceDef) => i.protocols.some((p) => p.type === \"power\" && p.roles.includes(\"input\"));\nconst selfSupply = (x: InterfaceDef, y: InterfaceDef) => (isPowerOutput(x) && isPowerInput(y)) || (isPowerOutput(y) && isPowerInput(x));\n\nconst pinOf = (leaf: InterfaceDef) => (leaf.pin === undefined ? undefined : String(leaf.pin));\n\nfunction slotOf(composite: InterfaceDef, leafId: string): string | undefined {\n return Object.entries(slotBindings(composite)).find(([, id]) => id === leafId)?.[0];\n}\n\n/** A `module:slot` the slot pairing left open, all of whose pads reach the other end of the link over a conductor. */\nfunction reachedByConductor(slot: string, fa: InterfaceDef, fb: InterfaceDef, a: ResolvedEndpoint, b: ResolvedEndpoint, wired: LinkChildResult[]): boolean {\n const [moduleId, slotId] = [slot.slice(0, slot.lastIndexOf(\":\")), slot.slice(slot.lastIndexOf(\":\") + 1)];\n const sides = [\n { owner: a.owner, iface: fa, reached: new Set(wired.map((w) => w.a.leafId)) },\n { owner: b.owner, iface: fb, reached: new Set(wired.map((w) => w.b.leafId)) },\n ].filter((x) => x.owner.id === moduleId);\n return sides.some(({ iface, reached }) => {\n const bound = iface.profiles?.[0]?.bindings[slotId];\n const leaves = (Array.isArray(bound) ? bound : bound ? [bound] : []).filter((l): l is string => typeof l === \"string\");\n return leaves.length > 0 && leaves.every((l) => reached.has(l));\n });\n}\n\n/** Conductors inside a composite must land where the protocol pairing expects. */\nfunction wiringProblems(result: LinkResult, wired: LinkChildResult[]): Diagnostic[] {\n if (result.state === \"incompatible\") return [];\n const expected = new Map(result.children.filter((c) => c.method === \"protocol\").map((c) => [c.a.leafId, c.b.leafId]));\n // what each pad reaches: one counterpart through a conductor, every pad of a net through the net\n // (two supply pins on one net are one conductor, so either is the pairing the protocol expects)\n const reaches = new Map<string, Set<string>>();\n for (const w of wired) reaches.set(w.a.leafId, (reaches.get(w.a.leafId) ?? new Set()).add(w.b.leafId));\n const out: Diagnostic[] = [];\n for (const w of wired) {\n const want = expected.get(w.a.leafId);\n if (want && want !== w.b.leafId && !reaches.get(w.a.leafId)!.has(want)) {\n out.push({\n severity: \"error\",\n code: \"harness_wiring\",\n message: `${w.a.leafId} is wired to ${w.b.leafId}, but ${result.protocol} pairs it with ${want}`,\n refs: [result.a.path, result.b.path],\n });\n }\n }\n return out;\n}\n\n/**\n * A composite lifted over conductors needs one for each required pairing its\n * protocol expects. A required pad that reaches the other module only outside\n * the counterpart composite (SDA landed on an interrupt pin) leaves the bus\n * incomplete.\n */\nfunction missingConductors(result: LinkResult, fa: InterfaceDef, fb: InterfaceDef, wired: LinkChildResult[]): Diagnostic[] {\n if (result.state === \"incompatible\") return [];\n const wiredA = new Set(wired.map((w) => w.a.leafId));\n const wiredB = new Set(wired.map((w) => w.b.leafId));\n const required = (iface: InterfaceDef, slot?: string) => iface.slots?.find((s) => s.id === slot)?.required ?? false;\n const out: Diagnostic[] = [];\n for (const c of result.children) {\n if (c.method !== \"protocol\" || (wiredA.has(c.a.leafId) && wiredB.has(c.b.leafId))) continue;\n if (!required(fa, c.a.slotId) && !required(fb, c.b.slotId)) continue;\n const slot = c.a.slotId ?? c.b.slotId ?? c.a.leafId;\n out.push({\n severity: \"error\",\n code: \"bus_incomplete\",\n message: `${result.protocol} ${slot}: ${result.a.path} ${c.a.leafId} and ${result.b.path} ${c.b.leafId} are not wired to each other`,\n refs: [result.a.path, result.b.path],\n });\n }\n return out;\n}\n\n/** Stored links plus the links derived from them. */\nexport function systemLinks(def: ModuleDef, lookup: ModuleLookup): LinkResult[] {\n const stored = validateLinks(def, lookup);\n return [...stored, ...deriveLinks(def, lookup, stored)];\n}\n","/**\n * Board nets in the view model (PB-823; UHD docs/boards-and-nets.md).\n *\n * A net is a `Net` interface on the board itself (protocol `net`, not\n * exposed), joined to each pin on it by a stored membership link. Drawing a\n * line per membership would draw a star of N lines per net, most of them to\n * the same component; drawing every pair would be worse. Instead:\n *\n * - each net is a junction node (`:<net>`; `board:<net>` when the board is\n * expanded in place);\n * - each component on the net gets one port for it, named for the net, and\n * one grouped line to the junction whose children are its pins on the net;\n * - a ground net (a ground pin on it and no supply pin) is drawn as ground\n * symbols at its members, like any ground link, unless GND wires are on;\n * - the functional links UHD derives over the nets (an I2C bus, a supply to\n * its loads) are listed by name, and their state is carried by the grouped\n * lines they run over, so a `bus_incomplete` or `harness_wiring` finding\n * on one turns those lines red, as it does for a cable's lanes.\n */\nimport type { InterfaceDef, ModuleDef } from \"@uhd/types/index.js\";\nimport type { LinkResult, ModuleLookup } from \"@uhd/system/index.js\";\nimport { isNet } from \"@uhd/protocols/net.js\";\nimport { isNetMembership, netVoltageRange } from \"@uhd/system/nets.js\";\nimport { slotBindings } from \"@uhd/system/connectors.js\";\nimport type { LinkState, ViewChildPort, ViewDerived, ViewLink, ViewNode, ViewPort } from \"./types\";\n\nconst RANK: Record<LinkState, number> = { incompatible: 3, partial: 2, unconfigured: 1, configured: 0 };\nconst worst = (states: LinkState[]): LinkState => states.reduce<LinkState>((w, s) => (RANK[s] > RANK[w] ? s : w), \"configured\");\n\nconst hasPower = (i: InterfaceDef, role?: string) => i.protocols.some((p) => p.type === \"power\" && (!role || p.roles.includes(role)));\nconst isGroundPin = (i: InterfaceDef) => hasPower(i, \"ground\");\nconst isSupplyPin = (i: InterfaceDef) => hasPower(i, \"input\") || hasPower(i, \"output\");\n\n/** Node id of a net: the canonical path of the net interface (`:<net>`, or `board:<net>` inside an expanded board). */\nexport const netNodeId = (prefix: string, net: string) => `${prefix.replace(/\\/$/, \"\")}:${net}`;\n\n/** Port id on a component for its connection to a net. */\nexport const netPortId = (net: string) => `net:${net}`;\n\nconst fmtV = (r: [number, number]) => (r[0] === r[1] ? `${r[0]} V` : `${r[0]}–${r[1]} V`);\n\n/**\n * Label of a grouped membership line: the pin's name, or the distinct names\n * of several (\"VDD/VDDIO\"), or the first and how many others (\"IOVDD +3\").\n */\nexport function pinsLabel(names: string[]): string {\n const counts = new Map<string, number>();\n for (const n of names) counts.set(n, (counts.get(n) ?? 0) + 1);\n const distinct = [...counts.keys()];\n if (distinct.length === 1) return distinct[0];\n if (distinct.length === 2) return distinct.join(\"/\");\n return `${distinct[0]} +${distinct.length - 1}`;\n}\n\nexport interface LevelNets {\n /** Junction nodes (ground nets left out unless `grounds`). */\n nodes: ViewNode[];\n /** One grouped line per component and net. */\n links: ViewLink[];\n /** Ports to add to the component nodes, by node id. */\n ports: Map<string, ViewPort[]>;\n derived: ViewDerived[];\n /** Membership link id (prefixed) → grouped line id. */\n owners: Map<string, string>;\n /** Derived link id (prefixed) → grouped line ids it runs over. */\n derivedOwners: Map<string, string[]>;\n}\n\n/**\n * The nets of `def` drawn at a level (`prefix` \"\" for the level module itself,\n * `<child>/` for a board expanded in place). `results` are the module's stored\n * link results, `derived` the links UHD derives from them.\n */\nexport function levelNets(\n def: ModuleDef,\n results: LinkResult[],\n derived: LinkResult[],\n lookup: ModuleLookup,\n prefix: string,\n opts: { grounds: boolean; parent?: string },\n): LevelNets {\n const out: LevelNets = { nodes: [], links: [], ports: new Map(), derived: [], owners: new Map(), derivedOwners: new Map() };\n const nets = def.interfaces.filter(isNet);\n if (!nets.length) return out;\n const memberships = results.filter(isNetMembership);\n const childName = (id: string) => {\n const ref = def.children?.find((c) => c.id === id);\n return (ref?.name ?? (ref ? lookup(ref.moduleDefId)?.name : undefined) ?? id).toUpperCase();\n };\n\n for (const net of nets) {\n const mine = memberships.filter((r) => [r.a, r.b].some((e) => e.iface === net && e.ownerPath.length === 0));\n const members = mine.map((r) => {\n const pinEnd = r.a.iface === net ? r.link.b : r.link.a;\n const pin = r.a.iface === net ? r.b : r.a;\n return { r, child: \"child\" in pinEnd ? pinEnd.child : \"\", pin: pin.iface };\n });\n const pins = members.map((m) => m.pin);\n const ground = pins.some(isGroundPin) && !pins.some(isSupplyPin);\n const rail = pins.some((p) => hasPower(p)) || Boolean(net.parameters?.some((p) => p.id === \"voltage\"));\n const over = derived.filter((d) => d.derived?.nets?.includes(net.id));\n const leaf = pins.map((p) => p.protocols[0]?.type).find((t) => t && t !== \"passive\" && t !== \"custom\");\n const signal = ground ? \"ground\" : rail ? \"power\" : (over.find((d) => d.protocol !== \"power\")?.protocol ?? leaf ?? \"custom\");\n const range = netVoltageRange(net);\n const nodeId = netNodeId(prefix, net.id);\n const children = [...new Set(members.map((m) => m.child))];\n\n if (!ground || opts.grounds) {\n out.nodes.push({\n id: nodeId,\n label: (net.name ?? net.id).toUpperCase(),\n icon: ground ? \"arrow-down-to-line\" : \"git-commit-horizontal\",\n kind: \"net\",\n ...(opts.parent ? { parent: opts.parent } : {}),\n ports: children.map((c) => ({ id: c, name: childName(c), domain: \"electrical\", protocol: signal, roles: [], children: [] })),\n shape: \"pill\",\n status: \"configured\",\n childCount: 0,\n description: `Net ${net.name ?? net.id}: ${pins.length} pin${pins.length === 1 ? \"\" : \"s\"}${range ? `, ${fmtV(range)}` : \"\"}`,\n net: { id: net.id, name: net.name ?? net.id, signal, ...(range ? { voltage: fmtV(range) } : {}), ground, pins: pins.length },\n });\n }\n\n for (const child of children) {\n const group = members.filter((m) => m.child === child);\n const nodeOfChild = prefix + child;\n const portId = netPortId(net.id);\n const pinPorts: ViewChildPort[] = group.map((m) => ({\n slotId: m.pin.id,\n name: m.pin.name ?? m.pin.id,\n leafId: m.pin.id,\n ...(m.pin.pin !== undefined ? { pin: String(m.pin.pin) } : {}),\n }));\n const list = out.ports.get(nodeOfChild) ?? [];\n list.push({ id: portId, name: net.name ?? net.id, domain: \"electrical\", protocol: signal, roles: [], children: pinPorts });\n out.ports.set(nodeOfChild, list);\n\n const id = `${prefix}${net.id}.${child}`;\n const memberIds = group.map((m) => prefix + m.r.link.id);\n const state = worst(group.map((m) => m.r.state as LinkState));\n out.links.push({\n id,\n linkId: id,\n alsoIds: memberIds,\n source: { node: nodeOfChild, port: portId },\n target: { node: nodeId, port: child },\n name: pinsLabel(group.map((m) => m.pin.name ?? m.pin.id)),\n domain: \"electrical\",\n protocol: signal,\n state,\n children: group.map((m) => ({\n id: prefix + m.r.link.id,\n label: m.pin.name ?? m.pin.id,\n a: m.pin.id,\n b: net.name ?? net.id,\n ...(m.pin.pin !== undefined ? { aPin: String(m.pin.pin) } : {}),\n state: m.r.state as LinkState,\n })),\n ...(group.length > 1\n ? {\n lanes: group.map((m, i) => ({\n id: `${id}#${i}`,\n name: (m.pin.name ?? m.pin.id).toUpperCase(),\n domain: \"electrical\",\n protocol: signal,\n state: m.r.state as LinkState,\n children: [],\n conductors: [`${id}#c${i}`],\n })),\n conductors: group.map((m, i) => ({\n id: `${id}#c${i}`,\n label: String(m.pin.pin ?? m.pin.name ?? m.pin.id).toUpperCase(),\n protocol: signal,\n domain: \"electrical\",\n state: m.r.state as LinkState,\n })),\n }\n : {}),\n ...(ground ? { ground: true } : {}),\n net: { id: net.id, name: net.name ?? net.id },\n diagnostics: group.flatMap((m) => m.r.diagnostics.map((d) => d.message)),\n });\n for (const m of memberIds) out.owners.set(m, id);\n }\n }\n\n // functional links over the nets, by name, carried by the grouped lines they run over\n for (const d of derived) {\n if (!d.derived?.nets?.length) continue;\n // the lines it runs over, and every line carrying a pin of either end: a bus whose SDA landed on\n // another net shows that line too, where a line of its own would be missing\n const pinsOf = (e: LinkResult[\"a\"]) => new Set([e.iface.id, ...Object.values(slotBindings(e.iface))]);\n const carrying = [d.a, d.b].flatMap((e) => {\n const pins = pinsOf(e);\n return out.links.filter((l) => l.source.node === prefix + (e.ownerPath[0] ?? \"\") && l.children.some((c) => pins.has(c.a))).map((l) => l.id);\n });\n const via = [...new Set([...d.derived.via.map((v) => out.owners.get(prefix + v)).filter((x): x is string => Boolean(x)), ...carrying])];\n const id = prefix + d.link.id;\n out.derivedOwners.set(id, via);\n const end = (e: LinkResult[\"a\"]) => ({ node: prefix + (e.ownerPath[0] ?? \"\"), iface: e.path.slice(e.path.indexOf(\":\") + 1) });\n out.derived.push({\n id,\n name: d.link.name ?? d.link.id,\n protocol: d.protocol,\n state: d.state as LinkState,\n a: end(d.a),\n b: end(d.b),\n nets: d.derived.nets.map((n) => netNodeId(prefix, n)),\n via,\n children: d.children.map((c) => ({ a: c.a.slotId ?? c.a.leafId, aPin: c.a.pin, b: c.b.slotId ?? c.b.leafId, bPin: c.b.pin })),\n diagnostics: d.diagnostics.map((x) => x.message),\n });\n // the lines it runs over carry its state, as a cable's lanes carry the links derived through it\n for (const line of out.links.filter((l) => via.includes(l.id))) {\n if (RANK[d.state as LinkState] > RANK[line.state]) line.state = d.state as LinkState;\n for (const x of d.diagnostics) if (!line.diagnostics.includes(x.message)) line.diagnostics.push(x.message);\n }\n }\n return out;\n}\n","/**\n * Adapter: UHD system ModuleDef → neutral view model.\n *\n * A level shows the children of one module. Children that have children of\n * their own are drawn expanded in place when listed in `expanded` (their\n * boundary ports are exports, joined to the inner ports by pass-through\n * lines); otherwise they are drawn as a single card with boundary ports.\n * Harness children (kind \"harness\") become harness nodes, and every link\n * they carry is drawn in two segments through them. System diagnostics\n * (checkSystem) are overlaid onto link state for DRC colouring.\n */\nimport type { ChildLink, InterfaceDef, InterfaceLink, ModuleDef } from \"@uhd/types/index.js\";\nimport {\n boundaryInterfaces,\n resolveExports,\n validateLinks,\n type LinkResult,\n type ModuleLookup,\n type ResolvedEndpoint,\n} from \"@uhd/system/index.js\";\nimport { deriveLinks } from \"@uhd/system/derive.js\";\nimport type { SystemDiagnostic } from \"@uhd/system/checks.js\";\nimport { isConnector } from \"@uhd/protocols/connector.js\";\nimport { isNetMembership } from \"@uhd/system/nets.js\";\nimport { levelNets, type LevelNets } from \"./nets\";\nimport { isPlaceholder } from \"../source/tolerant\";\nimport type {\n LinkState,\n ViewChildPort,\n ViewConductor,\n ViewLane,\n ViewLink,\n ViewModel,\n ViewNode,\n ViewPort,\n} from \"./types\";\n\n/**\n * UHD taxonomy paths (UHD docs/taxonomy.md) and their icons, matched by whole\n * segments in the definition's category order, before the words below:\n * `actuator.motor_controller` (an ESC) is not under `actuator.motor`.\n */\nconst TAXONOMY_ICONS: [string, string][] = [\n [\"actuator.motor_controller\", \"zap\"],\n [\"actuator.motor\", \"rotate-cw\"],\n [\"mechanical.propeller\", \"fan\"],\n [\"microcontroller.flight_controller\", \"cpu\"],\n [\"power.battery\", \"battery-full\"],\n [\"connectivity.wireless.video\", \"video\"],\n [\"sensor.gnss\", \"satellite\"],\n [\"mechanical.structure\", \"hexagon\"],\n [\"component.passive.capacitor\", \"battery-medium\"],\n];\n\nconst underPath = (path: string, root: string) => path === root || path.startsWith(`${root}.`);\n\n/** Words in categories and tags (strap before battery: a battery strap is a strap). */\nconst CATEGORY_ICONS: Record<string, string> = {\n \"flight-controller\": \"cpu\",\n esc: \"zap\",\n motor: \"rotate-cw\",\n propeller: \"fan\",\n strap: \"link\",\n battery: \"battery-full\",\n receiver: \"radio\",\n video: \"video\",\n gnss: \"satellite\",\n structure: \"hexagon\",\n capacitor: \"battery-medium\",\n};\n\nfunction iconFor(def: ModuleDef): string {\n if (def.display?.icon) return def.display.icon;\n for (const path of def.categories ?? []) for (const [root, icon] of TAXONOMY_ICONS) if (underPath(path, root)) return icon;\n const words = [...(def.categories ?? []), ...(def.tags ?? [])].map((w) => w.toLowerCase());\n for (const word of words) {\n for (const [key, icon] of Object.entries(CATEGORY_ICONS)) {\n if (word.includes(key)) return icon;\n }\n }\n if (/esc/i.test(def.name)) return \"zap\";\n if (/battery strap|strap/i.test(def.name)) return \"link\";\n if (/battery|lipo/i.test(def.name)) return \"battery-full\";\n if (/capacitor/i.test(def.name)) return \"battery-medium\";\n if (/receiver|elrs/i.test(def.name)) return \"radio\";\n if (/gnss|gps/i.test(def.name)) return \"satellite\";\n if (/motor/i.test(def.name)) return \"rotate-cw\";\n if (/prop/i.test(def.name)) return \"fan\";\n if (/air unit|camera|video/i.test(def.name)) return \"video\";\n if (/flight controller/i.test(def.name)) return \"cpu\";\n return \"box\";\n}\n\nfunction shapeFor(def: ModuleDef): ViewNode[\"shape\"] {\n if (def.kind === \"harness\") return \"pill\";\n if (def.display?.shape === \"circle\") return \"circle\";\n // a motor controller (taxonomy actuator.motor_controller) is not a motor\n const categories = (def.categories ?? []).filter((c) => !underPath(c, \"actuator.motor_controller\"));\n return /motor|propeller|\\bprop\\b/i.test(`${def.name} ${categories.join(\" \")} ${(def.tags ?? []).join(\" \")}`) &&\n !def.children?.length\n ? \"circle\"\n : \"rect\";\n}\n\nfunction childPorts(owner: ModuleDef | undefined, iface: InterfaceDef): ViewChildPort[] {\n if (!iface.slots?.length) return [];\n const profile = iface.profiles?.[0];\n return iface.slots.map((slot) => {\n const bound = profile?.bindings[slot.id];\n const leafId = typeof bound === \"string\" ? bound : Array.isArray(bound) ? bound[0] : undefined;\n const leaf = leafId ? owner?.interfaces.find((i) => i.id === leafId) : undefined;\n return {\n slotId: slot.id,\n name: leaf?.name ?? slot.id.toUpperCase(),\n leafId,\n pin: leaf?.pin !== undefined ? String(leaf.pin) : undefined,\n };\n });\n}\n\nfunction toPort(iface: InterfaceDef, owner: ModuleDef, exported?: ViewPort[\"exported\"]): ViewPort {\n return {\n id: iface.id,\n name: iface.name ?? iface.id,\n domain: iface.domain,\n protocol: iface.protocols[0]?.type ?? \"custom\",\n roles: iface.protocols[0]?.roles ?? [],\n children: childPorts(owner, iface),\n ...(exported ? { exported } : {}),\n };\n}\n\nfunction portsOf(def: ModuleDef, lookup: ModuleLookup): ViewPort[] {\n const own = boundaryInterfaces(def, lookup);\n const exports = new Map(\n (def.exports?.length || def.kind === \"group\" ? resolveExports(def, lookup) : []).map((e) => [e.id, e]),\n );\n return own.map((iface) => {\n const ex = exports.get(iface.id);\n if (!ex) return toPort(iface, def);\n // a net port (UHD 0.3.0) exports the module's own net: no child behind it to draw a pass-through to\n return \"child\" in ex.from ? toPort(iface, ex.childDef, { child: ex.from.child, interfaceId: ex.from.interfaceId }) : toPort(iface, def);\n });\n}\n\nconst isGround = (r: LinkResult) =>\n [r.a.iface, r.b.iface].every((i) => i.protocols.some((p) => p.type === \"power\" && p.roles.includes(\"ground\")));\n\nconst RANK: Record<LinkState, number> = { incompatible: 3, partial: 2, unconfigured: 1, configured: 0 };\n\nfunction worst(states: LinkState[]): LinkState {\n return states.reduce<LinkState>((w, s) => (RANK[s] > RANK[w] ? s : w), \"configured\");\n}\n\n/** Link ids whose child links are stored overrides. */\ntype Overrides = Record<string, ChildLink[]>;\n\nfunction toLinks(r: LinkResult, prefix: string, harnessNode: string | undefined, manual: boolean): ViewLink[] {\n const endpoint = (end: typeof r.link.a) =>\n \"child\" in end\n ? { node: prefix + end.child, port: end.interfaceId }\n : { node: prefix.replace(/\\/$/, \"\"), port: end.interfaceId };\n const linkId = prefix + r.link.id;\n const base: Omit<ViewLink, \"id\" | \"source\" | \"target\"> = {\n linkId,\n name: r.link.name ?? r.link.id,\n domain: r.a.iface.domain,\n protocol: r.protocol,\n state: r.state,\n children: r.children.map((c, i) => ({\n id: `${linkId}#${i}`,\n label: (c.a.slotId ?? c.a.leafId).toUpperCase(),\n a: c.a.slotId ?? c.a.leafId,\n b: c.b.slotId ?? c.b.leafId,\n aPin: c.a.pin,\n bPin: c.b.pin,\n state: r.state,\n })),\n ...(isGround(r) ? { ground: true } : {}),\n ...(manual ? { manual: true } : {}),\n diagnostics: [...r.diagnostics.map((d) => d.message), ...r.unresolvedSlots.map((s) => `unresolved slot ${s}`)],\n };\n const source = endpoint(r.link.a);\n const target = endpoint(r.link.b);\n // ground returns stay ground symbols at their ports rather than routing through the harness\n if (!harnessNode || isGround(r)) return [{ ...base, id: linkId, source, target }];\n return [\n { ...base, id: linkId, source, target: { node: harnessNode, port: `${r.link.id}:a` }, harness: harnessNode, segment: \"a\" },\n { ...base, id: `${linkId}~b`, source: { node: harnessNode, port: `${r.link.id}:b` }, target, harness: harnessNode, segment: \"b\" },\n ];\n}\n\n/** \"UART5 (DJI)\" → \"UART5\", \"10V/12V BEC\" → \"10V/12V\": a lane label short enough for the canvas. */\nconst shortName = (name: string) => name.split(/\\s[(—-]|\\s(?=[A-Z][a-z])/)[0].trim();\n\nfunction leafProtocol(iface: InterfaceDef | undefined): string {\n const p = iface?.protocols[0];\n if (!p) return \"custom\";\n if (p.type === \"power\" && p.roles.includes(\"ground\")) return \"ground\";\n return p.type;\n}\n\n/**\n * Signal type of a lane or conductor (signal classification): what the link it\n * belongs to carries (I2C, UART, power…), except that a ground is a ground.\n * Leaves alone are not enough: I2C's SCL and SDA are declared as digital lines.\n */\nfunction signalOf(linkProtocol: string, leaf?: InterfaceDef): string {\n return leafProtocol(leaf) === \"ground\" ? \"ground\" : linkProtocol;\n}\n\n/** The leaf interface behind one position of a resolved connector end. */\nfunction positionLeaf(end: ResolvedEndpoint, slot: string): InterfaceDef | undefined {\n const composed = end.composed?.[slot];\n if (composed) return composed.iface;\n const bound = end.iface.profiles?.[0]?.bindings[slot];\n const id = Array.isArray(bound) ? bound[0] : bound;\n return id ? end.owner.interfaces.find((i) => i.id === id) : undefined;\n}\n\nfunction laneOf(r: LinkResult): ViewLane {\n const names = [r.a.iface.name ?? r.a.iface.id, r.b.iface.name ?? r.b.iface.id].map(shortName);\n // a bundle is named for what it is (\"UART\", \"I2C\"), not which instance (\"UART1\"): it opens to show its signals\n const shortest = names.sort((x, y) => x.length - y.length)[0].toUpperCase();\n const name = r.children.length > 1 ? shortest.replace(/(?<=[A-Z])\\d+$/, \"\") : shortest;\n const leafOf = (id?: string) => r.a.owner.interfaces.find((x) => x.id === id);\n return {\n id: r.link.id,\n name,\n domain: r.a.iface.domain,\n protocol: signalOf(r.protocol, r.a.iface),\n state: STATE_OF(r),\n children:\n r.children.length > 1\n ? r.children.map((c, i) => ({\n id: `${r.link.id}#${i}`,\n name: (c.a.slotId ?? c.a.leafId).replace(/^.*_/, \"\").toUpperCase(),\n domain: r.a.iface.domain,\n protocol: signalOf(r.protocol, leafOf(c.a.leafId)),\n state: STATE_OF(r),\n children: [],\n }))\n : [],\n };\n}\n\nconst STATE_OF = (r: LinkResult): LinkState => r.state as LinkState;\n\nexport interface LevelLinks {\n links: ViewLink[];\n /** Harness children drawn as regions on links, not as nodes. */\n regionHarnesses: Set<string>;\n /** Stored or derived link id → the view link that draws it (for diagnostics). */\n owners: Map<string, string>;\n /** Every link UHD derives at this level (through cables and over nets). */\n derived: LinkResult[];\n}\n\n/**\n * The links of one level (PB-803/805). A harness with exactly two connector\n * ends becomes one link from part to part with the harness as a region along\n * it; its lanes are the links derived through its conductors and its\n * conductors are the mated positions. Logical links that name a harness get\n * the same region. Anything else keeps its own line.\n */\nexport function levelLinks(\n def: ModuleDef,\n results: LinkResult[],\n lookup: ModuleLookup,\n prefix: string,\n overrides: Overrides | undefined,\n): LevelLinks {\n const derived = deriveLinks(def, lookup, results);\n const links: ViewLink[] = [];\n const consumed = new Set<string>();\n const regionHarnesses = new Set<string>();\n const owners = new Map<string, string>();\n const tabbed = new Set<string>();\n\n for (const ref of def.children ?? []) {\n const h = lookup(ref.moduleDefId);\n if (h?.kind !== \"harness\") continue;\n const ends = results.filter((r) => r.protocol === \"connector\" && [r.a, r.b].some((e) => e.owner === h && e.ownerPath[0] === ref.id));\n if (ends.length !== 2) continue;\n const part = (r: LinkResult) => (r.a.owner === h && r.a.ownerPath[0] === ref.id ? { end: r.link.b, res: r.b, first: false } : { end: r.link.a, res: r.a, first: true });\n const [r1, r2] = ends;\n const p1 = part(r1);\n const p2 = part(r2);\n const via = new Set([r1.link.id, r2.link.id]);\n const carried = derived.filter((d) => d.derived!.via.some((v) => via.has(v)));\n const lanes = carried.map(laneOf);\n const conductors: ViewConductor[] = r1.children.map((c, i) => {\n const slot = p1.first ? c.a.slotId : c.b.slotId;\n const leaf = slot ? positionLeaf(p1.res, slot) : undefined;\n const label = p1.res.iface.slots?.find((x) => x.id === slot)?.label ?? leaf?.name ?? slot ?? String(i + 1);\n // the derived link this conductor belongs to decides its DRC state\n const owner = leaf\n ? carried.find((d) => [d.a.iface.id, d.b.iface.id].includes(leaf.id) || d.children.some((ch) => ch.a.leafId === leaf.id || ch.b.leafId === leaf.id))\n : undefined;\n const id = `${r1.link.id}#${slot ?? i}`;\n if (owner && leaf) {\n // group the conductor under its lane, and under the lane's child when it carries one\n const lane = lanes.find((l) => l.id === owner.link.id)!;\n (lane.conductors ??= []).push(id);\n const k = owner.children.findIndex((ch) => ch.a.leafId === leaf.id || ch.b.leafId === leaf.id);\n if (k >= 0 && lane.children[k]) (lane.children[k].conductors ??= []).push(id);\n }\n return {\n id,\n label: label.toUpperCase(),\n protocol: owner ? signalOf(owner.protocol, leaf) : leafProtocol(leaf),\n domain: leaf?.domain ?? r1.a.iface.domain,\n state: owner ? STATE_OF(owner) : STATE_OF(r1),\n };\n });\n const states = [r1, r2, ...carried].map(STATE_OF);\n const state = states.reduce<LinkState>((w, x) => (RANK[x] > RANK[w] ? x : w), \"configured\");\n const protocols = [...new Set(lanes.map((l) => l.protocol))];\n const endpoint = (end: InterfaceLink[\"a\"]) => (\"child\" in end ? { node: prefix + end.child, port: end.interfaceId } : { node: prefix.replace(/\\/$/, \"\"), port: end.interfaceId });\n const id = prefix + r1.link.id;\n links.push({\n id,\n linkId: id,\n alsoIds: [prefix + r2.link.id],\n source: endpoint(p1.end),\n target: endpoint(p2.end),\n name: `${lanes.length} LINK${lanes.length === 1 ? \"\" : \"S\"}`,\n domain: r1.a.iface.domain,\n // the cable reads as the signal it carries (UART, I2C…), or as power when it only carries supply and return\n protocol: protocols.find((p) => p !== \"power\" && p !== \"ground\") ?? (protocols.includes(\"power\") || protocols.includes(\"ground\") ? \"power\" : protocols[0] ?? \"custom\"),\n state,\n children: lanes.map((l) => ({ id: l.id, label: l.name, a: l.name, b: l.name, state: l.state })),\n lanes,\n conductors,\n run: { id: prefix + ref.id, defId: h.id, name: (ref.name ?? h.name).toUpperCase(), icon: h.display?.icon ?? \"cable\", physical: true, tab: true },\n diagnostics: [...r1.diagnostics, ...r2.diagnostics, ...carried.flatMap((d) => d.diagnostics)].map((d) => d.message),\n });\n consumed.add(r1.link.id).add(r2.link.id);\n regionHarnesses.add(ref.id);\n for (const x of [r1, r2, ...carried]) owners.set(prefix + x.link.id, id);\n }\n\n for (const r of results) {\n // net memberships are drawn grouped, per component and net (./nets.ts)\n if (consumed.has(r.link.id) || isNetMembership(r)) continue;\n const harnessRef = r.link.harness ? def.children?.find((c) => c.id === r.link.harness) : undefined;\n const harnessDef = harnessRef ? lookup(harnessRef.moduleDefId) : undefined;\n const [view] = toLinks(r, prefix, undefined, Boolean(prefix === \"\" && overrides?.[r.link.id]));\n if (r.children.length > 1) {\n const leafOf = (id?: string) => r.a.owner.interfaces.find((x) => x.id === id);\n view.lanes = r.children.map((c, i) => ({\n id: `${view.id}#${i}`,\n name: (c.a.slotId ?? c.a.leafId).replace(/^.*_/, \"\").toUpperCase(),\n domain: r.a.iface.domain,\n protocol: signalOf(r.protocol, leafOf(c.a.leafId)),\n state: STATE_OF(r),\n children: [],\n conductors: [`${view.id}#c${i}`],\n }));\n view.conductors = r.children.map((c, i) => ({\n id: `${view.id}#c${i}`,\n label: (c.a.pin ?? c.a.slotId ?? c.a.leafId).toUpperCase(),\n protocol: signalOf(r.protocol, leafOf(c.a.leafId)),\n domain: r.a.iface.domain,\n state: STATE_OF(r),\n }));\n }\n if (harnessRef && harnessDef?.kind === \"harness\") {\n view.run = {\n id: prefix + harnessRef.id,\n defId: harnessDef.id,\n name: (harnessRef.name ?? harnessDef.name).toUpperCase(),\n icon: harnessDef.display?.icon ?? \"cable\",\n physical: false,\n tab: !tabbed.has(harnessRef.id),\n };\n tabbed.add(harnessRef.id);\n regionHarnesses.add(harnessRef.id);\n }\n owners.set(prefix + r.link.id, view.id);\n links.push(view);\n }\n return { links, regionHarnesses, owners, derived };\n}\n\n/**\n * Carry a check result on a link down to what is drawn inside it, so expanded\n * lanes and ribbon conductors follow the DRC classification too: a finding on\n * the link itself applies to all of them, one on a link derived through a\n * cable only to that lane (and its conductors).\n */\nfunction overlayChildren(link: ViewLink, refId: string, state: LinkState) {\n const bump = (x: { state: LinkState }) => {\n if (RANK[state] > RANK[x.state]) x.state = state;\n };\n const all = (ls: ViewLane[]): ViewLane[] => ls.flatMap((l) => [l, ...all(l.children)]);\n const direct = link.linkId === refId || link.alsoIds?.includes(refId) || !link.run?.physical;\n const hit = direct ? all(link.lanes ?? []) : all((link.lanes ?? []).filter((l) => l.id === refId));\n hit.forEach(bump);\n const conductorIds = new Set(hit.flatMap((l) => l.conductors ?? []));\n for (const c of link.conductors ?? []) if (direct || conductorIds.has(c.id)) bump(c);\n}\n\nexport interface BuildOptions {\n /** Child ids (at this level) drawn expanded in place. */\n expanded: Set<string>;\n /** Stored child-link overrides keyed by link id (top level). */\n overrides?: Overrides;\n /**\n * System diagnostics to overlay on link state. Refs are relative to the\n * root; findings of a board checked on its own (see App) carry its path\n * (`link:board/<id>`), so they overlay when that board is drilled into.\n */\n diagnostics?: SystemDiagnostic[];\n /** Draw ground nets as junctions with wires (GND wires on) rather than as ground symbols. */\n grounds?: boolean;\n}\n\n/** Apply child-link overrides to a module's stored links. */\nexport function withOverrides(def: ModuleDef, overrides: Overrides | undefined): ModuleDef {\n if (!overrides || !Object.keys(overrides).length) return def;\n return {\n ...def,\n links: (def.links ?? []).map((l: InterfaceLink) => (overrides[l.id] ? { ...l, childLinks: overrides[l.id] } : l)),\n };\n}\n\n/** Descend `drill` child ids from the root to find the module shown at this level. */\nexport function levelModule(root: ModuleDef, drill: string[], lookup: ModuleLookup): { def: ModuleDef; path: ViewModel[\"path\"] } {\n let def = root;\n const path: ViewModel[\"path\"] = [{ id: \"\", label: root.name }];\n for (const childId of drill) {\n const ref = def.children?.find((c) => c.id === childId);\n const next = ref ? lookup(ref.moduleDefId) : undefined;\n if (!ref || !next) break;\n path.push({ id: path.length > 1 ? `${path[path.length - 1].id}/${childId}` : childId, label: ref.name ?? next.name });\n def = next;\n }\n return { def, path };\n}\n\nexport function buildView(root: ModuleDef, lookup: ModuleLookup, drill: string[], opts: BuildOptions): ViewModel {\n const { def: rawLevel, path } = levelModule(root, drill, lookup);\n const level = drill.length === 0 ? withOverrides(rawLevel, opts.overrides) : rawLevel;\n const nodes: ViewNode[] = [];\n const links: ViewLink[] = [];\n\n const nodeFor = (id: string, name: string | undefined, def: ModuleDef, parent?: string, expanded = false): ViewNode => ({\n id,\n label: (name ?? def.name).toUpperCase(),\n icon: iconFor(def),\n kind: def.kind ?? \"module\",\n ...(parent ? { parent } : {}),\n ...(expanded ? { expanded } : {}),\n // a harness shows its connector ends (PB-805); carried logical links add their own pairs\n ports: def.kind === \"harness\" ? def.interfaces.filter(isConnector).map((i) => toPort(i, def)) : portsOf(def, lookup),\n shape: expanded ? \"rect\" : shapeFor(def),\n status: \"configured\",\n defId: def.id,\n manufacturer: def.manufacturer,\n partNumber: def.part_number,\n description: def.description,\n category: def.categories?.[0],\n childCount: def.kind === \"harness\" ? 0 : (def.children?.length ?? 0),\n ...(isPlaceholder(def) ? { missing: true } : {}),\n });\n\n /** Harness ports: one in/out pair per carried link. */\n const addHarnessPorts = (node: ViewNode, results: LinkResult[]) => {\n for (const r of results) {\n if (r.link.harness !== node.id.split(\"/\").pop() || isGround(r)) continue;\n for (const side of [\"a\", \"b\"] as const) {\n node.ports.push({\n id: `${r.link.id}:${side}`,\n name: r.link.name ?? r.link.id,\n domain: r.a.iface.domain,\n protocol: r.protocol,\n roles: [],\n children: [],\n });\n }\n }\n };\n\n // Sheet ports: the level module's own boundary, drawn at the canvas edges.\n if (drill.length > 0) {\n for (const port of portsOf(level, lookup)) {\n nodes.push({\n id: `@${port.id}`,\n label: port.name.toUpperCase(),\n icon: \"arrow-right-left\",\n kind: \"module\",\n ports: [{ ...port }],\n shape: \"rect\",\n status: \"configured\",\n childCount: 0,\n sheetPort: true,\n });\n if (port.exported) {\n links.push({\n id: `@${port.id}->${port.exported.child}`,\n linkId: `@${port.id}`,\n source: { node: `@${port.id}`, port: port.id },\n target: { node: port.exported.child, port: port.exported.interfaceId },\n name: port.name,\n domain: port.domain,\n protocol: port.protocol,\n state: \"configured\",\n children: [],\n passThrough: true,\n diagnostics: [],\n });\n }\n }\n }\n\n const levelResults = validateLinks(level, lookup);\n const top = levelLinks(level, levelResults, lookup, \"\", opts.overrides);\n const owners = new Map(top.owners);\n const grounds = opts.grounds ?? false;\n // board nets: junction nodes and grouped membership lines (./nets.ts)\n const netLevels: LevelNets[] = [levelNets(level, levelResults, top.derived, lookup, \"\", { grounds })];\n /** Link-scoped compositions (PB-805) are ports on their child for as long as the link exists. */\n const addComposedPorts = (results: LinkResult[], prefix: string) => {\n for (const r of results) {\n for (const [end, resolved] of [[r.link.a, r.a], [r.link.b, r.b]] as const) {\n if (!(\"child\" in end) || !end.compose) continue;\n const node = nodes.find((n) => n.id === prefix + end.child);\n if (!node || node.ports.some((p) => p.id === end.interfaceId)) continue;\n node.ports.push({\n ...toPort(resolved.iface, resolved.owner),\n name: resolved.iface.name ?? end.interfaceId,\n children: Object.entries(resolved.composed ?? {}).map(([slotId, c]) => ({\n slotId,\n name: c.iface.name ?? c.iface.id,\n leafId: c.iface.id,\n pin: c.iface.pin !== undefined ? String(c.iface.pin) : undefined,\n })),\n });\n }\n }\n };\n\n for (const ref of level.children ?? []) {\n const def = lookup(ref.moduleDefId);\n if (!def) continue;\n const expanded = opts.expanded.has(ref.id) && (def.children?.length ?? 0) > 0 && def.kind !== \"harness\";\n if (def.kind === \"harness\" && top.regionHarnesses.has(ref.id)) continue;\n const node = nodeFor(ref.id, ref.name, def, undefined, expanded);\n if (def.kind === \"harness\") addHarnessPorts(node, levelResults);\n nodes.push(node);\n if (!expanded) continue;\n\n const innerResults = validateLinks(def, lookup);\n const innerLinks = levelLinks(def, innerResults, lookup, `${ref.id}/`, undefined);\n for (const [k, v] of innerLinks.owners) owners.set(k, v);\n netLevels.push(levelNets(def, innerResults, innerLinks.derived, lookup, `${ref.id}/`, { grounds, parent: ref.id }));\n for (const inner of def.children ?? []) {\n const innerDef = lookup(inner.moduleDefId);\n if (!innerDef) continue;\n if (innerDef.kind === \"harness\" && innerLinks.regionHarnesses.has(inner.id)) continue;\n const innerNode = nodeFor(`${ref.id}/${inner.id}`, inner.name, innerDef, ref.id);\n if (innerDef.kind === \"harness\") addHarnessPorts(innerNode, innerResults);\n nodes.push(innerNode);\n }\n addComposedPorts(innerResults, `${ref.id}/`);\n links.push(...innerLinks.links);\n\n // pass-through lines from each boundary export to the child port it exposes\n const exports = def.exports?.length || def.kind === \"group\" ? resolveExports(def, lookup) : [];\n for (const ex of exports) {\n // a net port's net is drawn as the sub-module's own junction, joined by its memberships\n if (!(\"child\" in ex.from)) continue;\n links.push({\n id: `${ref.id}:${ex.id}`,\n linkId: `${ref.id}:${ex.id}`,\n source: { node: ref.id, port: ex.id },\n target: { node: `${ref.id}/${ex.from.child}`, port: ex.from.interfaceId },\n name: ex.name ?? ex.id,\n domain: ex.iface.domain,\n protocol: ex.iface.protocols[0]?.type ?? \"custom\",\n state: \"configured\",\n children: [],\n passThrough: true,\n diagnostics: [],\n });\n }\n }\n\n addComposedPorts(levelResults, \"\");\n links.push(...top.links);\n\n const derived: ViewModel[\"derived\"] = [];\n const derivedOwners = new Map<string, string[]>();\n for (const n of netLevels) {\n nodes.push(...n.nodes);\n links.push(...n.links);\n derived.push(...n.derived);\n for (const [k, v] of n.owners) owners.set(k, v);\n for (const [k, v] of n.derivedOwners) derivedOwners.set(k, v);\n for (const [nodeId, ports] of n.ports) {\n const node = nodes.find((x) => x.id === nodeId);\n if (node) node.ports.push(...ports.filter((p) => !node.ports.some((q) => q.id === p.id)));\n }\n }\n\n // overlay system diagnostics on the links of this level: errors → incompatible, warnings → partial\n const levelPrefix = drill.length ? `${drill.join(\"/\")}/` : \"\";\n for (const d of opts.diagnostics ?? []) {\n if (d.severity === \"info\") continue;\n const state: LinkState = d.severity === \"error\" ? \"incompatible\" : \"partial\";\n for (const ref of d.refs) {\n if (!ref.startsWith(\"link:\") || !ref.startsWith(`link:${levelPrefix}`)) continue;\n const id = ref.slice(5 + levelPrefix.length);\n for (const x of derived.filter((x) => x.id === id)) {\n if (RANK[state] > RANK[x.state]) x.state = state;\n if (!x.diagnostics.includes(d.message)) x.diagnostics.push(d.message);\n }\n const targets = derivedOwners.get(id) ?? [owners.get(id) ?? id];\n for (const link of links.filter((l) => targets.includes(l.linkId))) {\n if (RANK[state] > RANK[link.state]) link.state = state;\n if (!link.diagnostics.includes(d.message)) link.diagnostics.push(d.message);\n overlayChildren(link, id, state);\n }\n }\n }\n\n // node status = worst state of the links touching it\n for (const node of nodes) {\n const touching = links.filter(\n (l) => !l.passThrough && (l.source.node === node.id || l.target.node === node.id || l.source.node.startsWith(`${node.id}/`) || l.target.node.startsWith(`${node.id}/`)),\n );\n node.status = touching.length ? worst(touching.map((l) => l.state)) : \"unconfigured\";\n }\n\n return { path, nodes, links, derived };\n}\n","/**\n * Orthogonal link routing with filleted corners (design decision D3).\n * Pure geometry: no React.\n */\n\nexport type Side = \"left\" | \"right\" | \"top\" | \"bottom\";\nexport type Pt = [number, number];\n\nconst STUB = 18;\n\nconst DIR: Record<Side, Pt> = {\n left: [-1, 0],\n right: [1, 0],\n top: [0, -1],\n bottom: [0, 1],\n};\n\nfunction stub([x, y]: Pt, side: Side, len = STUB): Pt {\n const [dx, dy] = DIR[side];\n return [x + dx * len, y + dy * len];\n}\n\nconst horizontal = (s: Side) => s === \"left\" || s === \"right\";\n\n/** Remove duplicate and collinear points. */\nexport function simplify(points: Pt[]): Pt[] {\n const out: Pt[] = [];\n for (const p of points) {\n const last = out[out.length - 1];\n if (last && Math.abs(last[0] - p[0]) < 0.5 && Math.abs(last[1] - p[1]) < 0.5) continue;\n out.push(p);\n while (out.length >= 3) {\n const [a, b, c] = out.slice(-3);\n const collinear =\n (Math.abs(a[0] - b[0]) < 0.5 && Math.abs(b[0] - c[0]) < 0.5) ||\n (Math.abs(a[1] - b[1]) < 0.5 && Math.abs(b[1] - c[1]) < 0.5);\n if (!collinear) break;\n out.splice(out.length - 2, 1);\n }\n }\n return out;\n}\n\n/** Insert elbows so every segment between consecutive points is axis-aligned. */\nfunction orthogonalize(points: Pt[], startHorizontal: boolean): Pt[] {\n const out: Pt[] = [points[0]];\n let wasHorizontal = startHorizontal;\n for (let i = 1; i < points.length; i++) {\n const [px, py] = out[out.length - 1];\n const [x, y] = points[i];\n if (Math.abs(px - x) > 0.5 && Math.abs(py - y) > 0.5) {\n // continue in the current direction first, then turn\n out.push(wasHorizontal ? [x, py] : [px, y]);\n }\n out.push([x, y]);\n const [ax, ay] = out[out.length - 2];\n wasHorizontal = Math.abs(ay - y) < 0.5 && Math.abs(ax - x) > 0.5;\n }\n return out;\n}\n\n/**\n * Route from a port on `sourceSide` to a port on `targetSide`. Waypoints, when\n * given, are visited in order; otherwise a 1–2 elbow Manhattan route is used.\n */\nexport function route(\n source: Pt,\n sourceSide: Side,\n target: Pt,\n targetSide: Side,\n waypoints: Pt[] = [],\n): Pt[] {\n const s1 = stub(source, sourceSide);\n const t1 = stub(target, targetSide);\n let middle: Pt[];\n\n if (waypoints.length > 0) {\n middle = waypoints;\n } else if (horizontal(sourceSide) && horizontal(targetSide)) {\n const mx = (s1[0] + t1[0]) / 2;\n middle = [[mx, s1[1]], [mx, t1[1]]];\n } else if (!horizontal(sourceSide) && !horizontal(targetSide)) {\n const my = (s1[1] + t1[1]) / 2;\n middle = [[s1[0], my], [t1[0], my]];\n } else if (horizontal(sourceSide)) {\n middle = [[t1[0], s1[1]]];\n } else {\n middle = [[s1[0], t1[1]]];\n }\n\n const pts = orthogonalize([source, s1, ...middle, t1], horizontal(sourceSide));\n // final approach must arrive along the target side's axis\n const last = pts[pts.length - 1];\n const [tx, ty] = target;\n if (horizontal(targetSide) && Math.abs(last[1] - ty) > 0.5) pts.push([last[0], ty]);\n if (!horizontal(targetSide) && Math.abs(last[0] - tx) > 0.5) pts.push([tx, last[1]]);\n pts.push(target);\n return simplify(pts);\n}\n\n/** SVG path through `points` with quadratic fillets of radius `r` (or per-corner radii). */\nexport function filletPath(points: Pt[], r: number | number[]): string {\n if (points.length < 2) return \"\";\n let d = `M${points[0][0]},${points[0][1]}`;\n for (let i = 1; i < points.length - 1; i++) {\n const [ax, ay] = points[i - 1];\n const [bx, by] = points[i];\n const [cx, cy] = points[i + 1];\n const l1 = Math.hypot(bx - ax, by - ay);\n const l2 = Math.hypot(cx - bx, cy - by);\n const radius = Math.max(0, Math.min(Array.isArray(r) ? r[i - 1] : r, l1 / 2, l2 / 2));\n const p1x = bx - ((bx - ax) / l1) * radius;\n const p1y = by - ((by - ay) / l1) * radius;\n const p2x = bx + ((cx - bx) / l2) * radius;\n const p2y = by + ((cy - by) / l2) * radius;\n d += ` L${p1x},${p1y} Q${bx},${by} ${p2x},${p2y}`;\n }\n const [ex, ey] = points[points.length - 1];\n return `${d} L${ex},${ey}`;\n}\n\nexport function length(points: Pt[]): number {\n let total = 0;\n for (let i = 1; i < points.length; i++) {\n total += Math.hypot(points[i][0] - points[i - 1][0], points[i][1] - points[i - 1][1]);\n }\n return total;\n}\n\n/** Point at fraction `t` (0..1) along the polyline. */\nexport function pointAt(points: Pt[], t: number): Pt {\n const target = length(points) * Math.min(1, Math.max(0, t));\n let walked = 0;\n for (let i = 1; i < points.length; i++) {\n const [ax, ay] = points[i - 1];\n const [bx, by] = points[i];\n const seg = Math.hypot(bx - ax, by - ay);\n if (walked + seg >= target && seg > 0) {\n const f = (target - walked) / seg;\n return [ax + (bx - ax) * f, ay + (by - ay) * f];\n }\n walked += seg;\n }\n return points[points.length - 1];\n}\n\n/** Fraction along the path of the middle of its longest segment (default label spot). */\nexport function longestSegmentMid(points: Pt[]): number {\n const total = length(points) || 1;\n let best = 0;\n let bestMid = 0.5;\n let walked = 0;\n for (let i = 1; i < points.length; i++) {\n const seg = Math.hypot(points[i][0] - points[i - 1][0], points[i][1] - points[i - 1][1]);\n if (seg > best) {\n best = seg;\n bestMid = (walked + seg / 2) / total;\n }\n walked += seg;\n }\n return bestMid;\n}\n\n/**\n * Offset an orthogonal polyline sideways by `d` (positive = left of travel\n * direction in screen space). Returns the points and concentric fillet radii.\n */\nexport function offsetPolyline(points: Pt[], d: number, r: number): { points: Pt[]; radii: number[] } {\n const pts = simplify(points);\n if (pts.length < 2 || d === 0) return { points: pts, radii: pts.map(() => r) };\n const normals: Pt[] = [];\n for (let i = 1; i < pts.length; i++) {\n const dx = pts[i][0] - pts[i - 1][0];\n const dy = pts[i][1] - pts[i - 1][1];\n const len = Math.hypot(dx, dy) || 1;\n normals.push([dy / len, -dx / len]);\n }\n const out: Pt[] = [];\n const radii: number[] = [];\n out.push([pts[0][0] + normals[0][0] * d, pts[0][1] + normals[0][1] * d]);\n for (let i = 1; i < pts.length - 1; i++) {\n const n1 = normals[i - 1];\n const n2 = normals[i];\n // mitred corner: exact for any turn angle (orthogonal corners reduce to n1 + n2)\n const k = d / (1 + n1[0] * n2[0] + n1[1] * n2[1]);\n out.push([pts[i][0] + (n1[0] + n2[0]) * k, pts[i][1] + (n1[1] + n2[1]) * k]);\n // turn direction: cross of incoming and outgoing direction vectors\n const din: Pt = [pts[i][0] - pts[i - 1][0], pts[i][1] - pts[i - 1][1]];\n const dout: Pt = [pts[i + 1][0] - pts[i][0], pts[i + 1][1] - pts[i][1]];\n const cross = Math.sign(din[0] * dout[1] - din[1] * dout[0]);\n // left-of-travel offsets sit on the outside of a right (clockwise) turn; the\n // fillet is a tangent length, so it scales with tan(half the turn) to stay concentric\n const cos = (din[0] * dout[0] + din[1] * dout[1]) / ((Math.hypot(...din) * Math.hypot(...dout)) || 1);\n const half = Math.tan(Math.acos(Math.max(-1, Math.min(1, cos))) / 2);\n radii.push(Math.max(2, r + cross * d * half));\n }\n const n = normals[normals.length - 1];\n const last = pts[pts.length - 1];\n out.push([last[0] + n[0] * d, last[1] + n[1] * d]);\n return { points: out, radii };\n}\n","/**\n * Grid router (PB-803, design D12): orthogonal routes on the 16 px grid.\n *\n * A* over grid cells with a direction in the state. It avoids module cards,\n * penalises bends and crossings, and keeps parallel runs one grid step apart\n * by charging for cells another route already runs along. Pinned waypoints\n * (dragged by the user, saved in the display file) are visited in order; the\n * bends it chooses itself are the automatic waypoints.\n */\nimport type { Pt, Side } from \"../canvas/routing\";\nimport { simplify } from \"../canvas/routing\";\n\nexport const GRID = 16;\n\nexport interface Rect {\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\nconst DIRS: Pt[] = [[1, 0], [0, 1], [-1, 0], [0, -1]];\nconst SIDE_DIR: Record<Side, number> = { right: 0, bottom: 1, left: 2, top: 3 };\n\nconst COST = { step: 1, bend: 4, parallel: 12, cross: 3 };\n\nexport const snap = (v: number) => Math.round(v / GRID) * GRID;\n\nclass Heap {\n private a: { k: number; v: number }[] = [];\n push(k: number, v: number) {\n const a = this.a;\n a.push({ k, v });\n let i = a.length - 1;\n while (i > 0) {\n const p = (i - 1) >> 1;\n if (a[p].k <= a[i].k) break;\n [a[p], a[i]] = [a[i], a[p]];\n i = p;\n }\n }\n pop(): number | undefined {\n const a = this.a;\n if (!a.length) return undefined;\n const top = a[0].v;\n const last = a.pop()!;\n if (a.length) {\n a[0] = last;\n let i = 0;\n for (;;) {\n const l = 2 * i + 1;\n const r = l + 1;\n let m = i;\n if (l < a.length && a[l].k < a[m].k) m = l;\n if (r < a.length && a[r].k < a[m].k) m = r;\n if (m === i) break;\n [a[m], a[i]] = [a[i], a[m]];\n i = m;\n }\n }\n return top;\n }\n get size() {\n return this.a.length;\n }\n}\n\nexport class GridRouter {\n private x0: number;\n private y0: number;\n private W: number;\n private H: number;\n private blocked: Uint8Array;\n /** Cells used by earlier routes: bit 1 horizontal run, bit 2 vertical run. */\n private used: Uint8Array;\n /** Search state, allocated once and reused: a state is valid when its stamp is the current search's. */\n private g: Float64Array;\n private prev: Int32Array;\n private stamp: Uint32Array;\n private gen = 0;\n private thorough: boolean;\n\n /**\n * `thorough`: a search that runs out of its budget is retried over the whole grid (off while\n * dragging, where a frame cannot wait for it).\n */\n constructor(obstacles: Rect[], extra: Pt[] = [], margin = 12, thorough = true) {\n this.thorough = thorough;\n // a level with nothing on it (a new system with no modules yet) still has a grid: one cell at the origin\n const xs = [...obstacles.flatMap((b) => [b.x, b.x + b.w]), ...extra.map((p) => p[0]), ...(obstacles.length || extra.length ? [] : [0])];\n const ys = [...obstacles.flatMap((b) => [b.y, b.y + b.h]), ...extra.map((p) => p[1]), ...(obstacles.length || extra.length ? [] : [0])];\n this.x0 = Math.floor(Math.min(...xs) / GRID) - margin;\n this.y0 = Math.floor(Math.min(...ys) / GRID) - margin;\n this.W = Math.ceil(Math.max(...xs) / GRID) + margin - this.x0 + 1;\n this.H = Math.ceil(Math.max(...ys) / GRID) + margin - this.y0 + 1;\n this.blocked = new Uint8Array(this.W * this.H);\n this.used = new Uint8Array(this.W * this.H);\n this.g = new Float64Array(this.W * this.H * 4);\n this.prev = new Int32Array(this.W * this.H * 4);\n this.stamp = new Uint32Array(this.W * this.H * 4);\n for (const b of obstacles) {\n // a cell is blocked when its point lies inside the card (edges included, so routes keep off outlines)\n for (let gx = Math.ceil(b.x / GRID); gx <= Math.floor((b.x + b.w) / GRID); gx++) {\n for (let gy = Math.ceil(b.y / GRID); gy <= Math.floor((b.y + b.h) / GRID); gy++) {\n const i = this.idx(gx, gy);\n if (i >= 0) this.blocked[i] = 1;\n }\n }\n }\n }\n\n private idx(gx: number, gy: number): number {\n const x = gx - this.x0;\n const y = gy - this.y0;\n return x < 0 || y < 0 || x >= this.W || y >= this.H ? -1 : y * this.W + x;\n }\n\n /**\n * Route from a port (on `fromSide` of its card) to another port, through\n * `pins` in order. Returns the polyline in canvas coordinates. With\n * `within`, the route stays inside that rectangle (a link between two\n * modules of a container expanded in place never leaves the container);\n * where no such route exists it is routed without the limit.\n */\n route(from: Pt, fromSide: Side, to: Pt, toSide: Side, pins: Pt[] = [], within?: Rect): Pt[] {\n if (within) {\n const region = { x0: Math.ceil(within.x / GRID), y0: Math.ceil(within.y / GRID), x1: Math.floor((within.x + within.w) / GRID), y1: Math.floor((within.y + within.h) / GRID) };\n this.region = region;\n try {\n const inside = this.routeOnce(from, fromSide, to, toSide, pins, true);\n if (inside) return inside;\n } finally {\n this.region = undefined;\n }\n }\n return this.routeOnce(from, fromSide, to, toSide, pins, false)!;\n }\n\n /** The cells a search may use, in grid coordinates (a container's inside), when a route is kept within one. */\n private region: { x0: number; y0: number; x1: number; y1: number } | undefined;\n\n /** One routing attempt; `strict` gives up (undefined, nothing marked) where a leg finds no way instead of jogging straight. */\n private routeOnce(from: Pt, fromSide: Side, to: Pt, toSide: Side, pins: Pt[], strict: boolean): Pt[] | undefined {\n const d0 = SIDE_DIR[fromSide];\n const dEnd = SIDE_DIR[toSide];\n const s: Pt = [snap(from[0]) / GRID + DIRS[d0][0], snap(from[1]) / GRID + DIRS[d0][1]];\n const t: Pt = [snap(to[0]) / GRID + DIRS[dEnd][0], snap(to[1]) / GRID + DIRS[dEnd][1]];\n const stops: Pt[] = [...pins.map((p) => [snap(p[0]) / GRID, snap(p[1]) / GRID] as Pt), t];\n let cells: Pt[] = [s];\n let dir = d0;\n for (let k = 0; k < stops.length; k++) {\n const last = k === stops.length - 1;\n // arrive at the end cell heading into the target port\n const arrive = last ? (dEnd + 2) % 4 : -1;\n // a bounded search first (keeps drags at frame rate); unless mid-drag, one that gives up gets the\n // whole grid, then may arrive from any side, before the route falls back to a straight jog\n const from = cells[cells.length - 1];\n const leg =\n this.search(from, dir, stops[k], arrive) ??\n (this.thorough ? this.search(from, dir, stops[k], arrive, Infinity) ?? (arrive >= 0 ? this.search(from, dir, stops[k], -1, Infinity) : undefined) : undefined);\n if (!leg) {\n if (strict) return undefined;\n cells.push(stops[k]);\n continue;\n }\n cells = cells.concat(leg.cells.slice(1));\n dir = leg.dir;\n }\n this.mark(cells);\n const pts: Pt[] = [from, ...cells.map(([gx, gy]) => [gx * GRID, gy * GRID] as Pt), to];\n return orthogonal(simplify(pts));\n }\n\n private search(start: Pt, startDir: number, goal: Pt, arriveDir: number, budget?: number): { cells: Pt[]; dir: number } | undefined {\n const { g, prev, stamp, region } = this;\n const gen = ++this.gen;\n const cost = (st: number) => (stamp[st] === gen ? g[st] : Infinity);\n const si = this.idx(start[0], start[1]);\n const gi = this.idx(goal[0], goal[1]);\n if (si < 0 || gi < 0) return undefined;\n const heap = new Heap();\n const h = (i: number) => Math.abs((i % this.W) - (gi % this.W)) + Math.abs(Math.floor(i / this.W) - Math.floor(gi / this.W));\n const s0 = si * 4 + startDir;\n g[s0] = 0;\n prev[s0] = -1;\n stamp[s0] = gen;\n heap.push(h(si), s0);\n let found = -1;\n let expanded = 0;\n // a search that has to wander this far is blocked (e.g. mid-drag, a card over a port): give up and jog\n const limit = budget ?? 6000 + 80 * (Math.abs(start[0] - goal[0]) + Math.abs(start[1] - goal[1]));\n while (heap.size && expanded < limit) {\n const st = heap.pop()!;\n expanded++;\n const cell = st >> 2;\n const dir = st & 3;\n if (cell === gi && (arriveDir < 0 || dir === arriveDir)) {\n found = st;\n break;\n }\n const cx = cell % this.W;\n const cy = Math.floor(cell / this.W);\n for (let nd = 0; nd < 4; nd++) {\n if (nd === (dir + 2) % 4) continue;\n const nx = cx + DIRS[nd][0];\n const ny = cy + DIRS[nd][1];\n if (nx < 0 || ny < 0 || nx >= this.W || ny >= this.H) continue;\n if (region && (nx + this.x0 < region.x0 || nx + this.x0 > region.x1 || ny + this.y0 < region.y0 || ny + this.y0 > region.y1)) continue;\n const ni = ny * this.W + nx;\n if (this.blocked[ni] && ni !== gi) continue;\n const horizontal = nd % 2 === 0;\n const u = this.used[ni];\n let c = COST.step + (nd !== dir ? COST.bend : 0);\n if (u) c += (horizontal ? u & 1 : u & 2) ? COST.parallel : COST.cross;\n const ns = ni * 4 + nd;\n const ng = g[st] + c;\n if (ng < cost(ns)) {\n g[ns] = ng;\n prev[ns] = st;\n stamp[ns] = gen;\n heap.push(ng + h(ni), ns);\n }\n }\n }\n if (found < 0) return undefined;\n const cells: Pt[] = [];\n for (let st = found; st >= 0; st = prev[st]) {\n const cell = st >> 2;\n cells.push([(cell % this.W) + this.x0, Math.floor(cell / this.W) + this.y0]);\n }\n cells.reverse();\n return { cells, dir: found & 3 };\n }\n\n /** Treat an existing route (canvas coordinates, axis-aligned) as occupied, as if it had just been routed. */\n occupy(points: Pt[]) {\n const cells = points.map(([x, y]) => [Math.round(x / GRID), Math.round(y / GRID)] as Pt);\n this.mark(cells.filter((c, i) => i === 0 || c[0] !== cells[i - 1][0] || c[1] !== cells[i - 1][1]));\n }\n\n private mark(cells: Pt[]) {\n for (let i = 1; i < cells.length; i++) {\n const [a, b] = [cells[i - 1], cells[i]];\n const horizontal = a[1] === b[1];\n const n = Math.max(Math.abs(b[0] - a[0]), Math.abs(b[1] - a[1]));\n for (let k = 0; k <= n; k++) {\n const x = a[0] + Math.sign(b[0] - a[0]) * k;\n const y = a[1] + Math.sign(b[1] - a[1]) * k;\n const idx = this.idx(x, y);\n if (idx >= 0) this.used[idx] |= horizontal ? 1 : 2;\n }\n }\n }\n}\n\n/** Make every segment axis-aligned (ports that sit off the grid get a short jog). */\nfunction orthogonal(points: Pt[]): Pt[] {\n const out: Pt[] = [points[0]];\n for (let i = 1; i < points.length; i++) {\n const [px, py] = out[out.length - 1];\n const [x, y] = points[i];\n if (Math.abs(px - x) > 0.5 && Math.abs(py - y) > 0.5) out.push([px, y]);\n out.push([x, y]);\n }\n return simplify(out);\n}\n","/**\n * Board-level layout (PB-873): a level with nets — a board's components and\n * the junctions of its nets — laid out the way a schematic sheet reads, as\n * layers with channels between them.\n *\n * - Components are clustered: a passive or discrete part (a decoupling\n * capacitor, a pull-up, a crystal) sits under the part it serves, named in\n * its label (\"U7 input\") or else the part it shares the most specific net\n * with; a connector or switch that serves one part only sits with it too.\n * - Clusters go in columns by function, from the taxonomy category:\n * connectors, power, the processor, then sensors and outputs. A part driven\n * only by another peripheral (the LEDs of an LED driver) goes one column\n * further out. A column too tall for a landscape sheet wraps.\n * - Within a column, clusters are ordered by barycentre sweeps and set at\n * the height of what they connect to, as close as the gaps allow, so lines\n * between columns run level and cross less.\n * - Junctions go in the channels between columns, each in the channel\n * between the parts it joins, level with them; a channel holds one or more\n * lanes of junctions and is as wide as its lines need.\n *\n * Same input, same output; nothing overlaps.\n */\nimport { GRID } from \"./router\";\n\nexport interface BoardNode {\n id: string;\n w: number;\n h: number;\n /** A net junction (placed after the components). */\n net?: boolean;\n /** Taxonomy category (\"power.regulator\", \"component.passive.capacitor\"). */\n category?: string;\n label?: string;\n /** A junction that is one tap of a rail drawn in several places: the rail's id (taps.ts). */\n tapOf?: string;\n /** A card's height once one side holds this many ports (cards grow to fit their ports). */\n heightFor?: (perSide: number) => number;\n /** Ports on lines that do not go to a junction (a sheet port's, a direct link's): either side. */\n otherPorts?: number;\n}\n\nexport interface Rect {\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\nexport type FunctionGroup = \"io\" | \"power\" | \"mcu\" | \"sensor\" | \"output\" | \"other\";\nconst GROUP_ORDER: FunctionGroup[] = [\"io\", \"power\", \"mcu\", \"sensor\", \"output\", \"other\"];\n/** Column of each group: sensors and outputs share the column after the processor. */\nconst GROUP_COLUMN: Record<FunctionGroup, number> = { io: 0, power: 1, mcu: 2, sensor: 3, output: 3, other: 3 };\n\n/** Card spacing inside a cluster, and between clusters in a column. */\nconst GAP_IN_X = 96;\nconst GAP_IN_Y = 64;\nconst GAP_CLUSTER = 112;\n/** Junction lanes: the gap between junctions in a lane, and between lanes. */\nconst HUB_GAP_Y = 32;\nconst LANE_GAP = 96;\n/** How far a junction may be pushed down its lane before the channel opens another. */\nconst LANE_PUSH = 480;\n/** Room between a column and the junction lanes beside it: a base, and a grid track per few lines. */\nconst CHANNEL_PAD = 80;\nconst STEP = GRID;\n/** A column shorter than this never wraps. */\nconst WRAP_MIN = 1600;\n\n/** A passive or discrete part: placed with the part it serves rather than in a group of its own. */\nexport function isSatellite(category?: string): boolean {\n return !!category && /^component\\.(passive|discrete)\\b/.test(category);\n}\n\n/** The function group of a component, from its category. */\nexport function functionGroup(category?: string): FunctionGroup {\n const c = category ?? \"\";\n if (/^(connector|interconnect)\\b|^component\\.(switch|protection|button)\\b|^mechanical\\.connector/.test(c)) return \"io\";\n if (/^power\\b|^energy\\b|^battery\\b/.test(c)) return \"power\";\n if (/^(microcontroller|processor|compute|fpga|soc)\\b|^component\\.(mcu|processor)\\b/.test(c)) return \"mcu\";\n if (/^sensor\\b/.test(c)) return \"sensor\";\n if (/^(actuator|display|lighting|audio|communication|radio|motor)\\b|^component\\.(display|led|ic|driver|audio)\\b/.test(c)) return \"output\";\n return \"other\";\n}\n\nconst natural = (a: string, b: string) => a.localeCompare(b, undefined, { numeric: true });\nconst snapUp = (v: number) => Math.ceil(v / STEP) * STEP;\nconst snapTo = (v: number) => Math.round(v / STEP) * STEP;\n\nconst words = (s: string) =>\n s\n .toUpperCase()\n .split(/[^A-Z0-9+-]+/)\n .filter((w) => w.length >= 3 && !GENERIC.has(w));\n/** Words too common in part names to say which part a passive serves. */\nconst GENERIC = new Set([\"THE\", \"AND\", \"FOR\", \"PULL-UP\", \"PULL-DOWN\", \"PULL\", \"BULK\", \"BYPASS\", \"INPUT\", \"OUTPUT\", \"SERIES\", \"UPPER\", \"LOWER\", \"TOP\", \"BOTTOM\", \"PAD\", \"PADS\", \"LOAD\", \"SENSE\", \"DIVIDER\", \"MODULE\"]);\n\n/** Whether `boxes` overlap once each is grown by its own padding. */\nexport function hits(a: Rect, b: Rect, padA = 0, padB = 0): boolean {\n return a.x - padA < b.x + b.w + padB && b.x - padB < a.x + a.w + padA && a.y - padA < b.y + b.h + padB && b.y - padB < a.y + a.h + padA;\n}\n\n/** Search offsets, cheapest first: a vertical move costs less than a sideways one. */\nlet OFFSETS: [number, number][] | undefined;\nfunction offsets(): [number, number][] {\n if (OFFSETS) return OFFSETS;\n const out: [number, number, number][] = [];\n const R = 90;\n for (let i = -R; i <= R; i++) for (let j = -R; j <= R; j++) out.push([i * STEP, j * STEP, Math.abs(i) * 1.25 + Math.abs(j) + (i < 0 ? 0.01 : 0) + (j < 0 ? 0.005 : 0)]);\n out.sort((a, b) => a[2] - b[2]);\n OFFSETS = out.map(([x, y]) => [x, y]);\n return OFFSETS;\n}\n\n/**\n * The free top-left position nearest `ideal` (a centre) for a box of size w×h,\n * clear of every obstacle by the paddings. Falls back to below everything.\n */\nexport function freeSpot(ideal: [number, number], w: number, h: number, obstacles: Rect[], pad: { x: number; y: number } = { x: 36, y: 18 }): { x: number; y: number } {\n const x0 = Math.round((ideal[0] - w / 2) / STEP) * STEP;\n const y0 = Math.round((ideal[1] - h / 2) / STEP) * STEP;\n const clear = (x: number, y: number) =>\n obstacles.every((o) => !(x - pad.x < o.x + o.w && o.x < x + w + pad.x && y - pad.y < o.y + o.h && o.y < y + h + pad.y));\n for (const [dx, dy] of offsets()) if (clear(x0 + dx, y0 + dy)) return { x: x0 + dx, y: y0 + dy };\n const bottom = Math.max(0, ...obstacles.map((o) => o.y + o.h));\n return { x: x0, y: bottom + 2 * pad.y };\n}\n\n/**\n * Isotonic placement: tops for boxes in a fixed order, each at least `gap`\n * below the one before, as close to its ideal top as that allows (least\n * squares, pool-adjacent-violators).\n */\nexport function pack(ideal: number[], heights: number[], gap: number): number[] {\n // z_i = y_i − (the room the boxes above take); z must not decrease\n const offset: number[] = [];\n let acc = 0;\n for (let i = 0; i < ideal.length; i++) {\n offset.push(acc);\n acc += heights[i] + gap;\n }\n const blocks: { sum: number; n: number }[] = [];\n for (let i = 0; i < ideal.length; i++) {\n blocks.push({ sum: ideal[i] - offset[i], n: 1 });\n while (blocks.length > 1 && blocks[blocks.length - 2].sum / blocks[blocks.length - 2].n > blocks[blocks.length - 1].sum / blocks[blocks.length - 1].n) {\n const b = blocks.pop()!;\n blocks[blocks.length - 1].sum += b.sum;\n blocks[blocks.length - 1].n += b.n;\n }\n }\n const out: number[] = [];\n for (const b of blocks) for (let k = 0; k < b.n; k++) out.push(snapTo(b.sum / b.n + offset[out.length]));\n // snapping can close a gap by a step: open it again\n for (let i = 1; i < out.length; i++) out[i] = Math.max(out[i], out[i - 1] + snapUp(heights[i - 1]) + gap);\n return out;\n}\n\n/** What the layout and the rail taps share: the clusters of a board level. */\nexport interface BoardClusters {\n /** Cluster (its anchor's id) of each component. */\n clusterOf: Map<string, string>;\n /** Members of each cluster: the anchor first, then its satellites in reading order. */\n clusters: Map<string, string[]>;\n /** Function group of each cluster. */\n group: Map<string, FunctionGroup>;\n /** Component members of each junction. */\n members: Map<string, string[]>;\n /** Component ↔ component lines (two-member nets of their own). */\n direct: [string, string][];\n}\n\n/** Cluster a board level's components: each passive with the part it serves, a dedicated connector with its part. */\nexport function boardClusters(nodes: BoardNode[], edges: [string, string][]): BoardClusters {\n const byId = new Map(nodes.map((n) => [n.id, n]));\n const comps = nodes.filter((n) => !n.net).sort((a, b) => natural(a.id, b.id));\n\n // nets as member sets; component ↔ component lines count as two-member nets\n const memberSets = new Map<string, Set<string>>();\n const direct: [string, string][] = [];\n for (const [a, b] of edges) {\n const na = byId.get(a);\n const nb = byId.get(b);\n if (!na || !nb || a === b) continue;\n if (na.net && !nb.net) memberSets.set(a, (memberSets.get(a) ?? new Set()).add(b));\n else if (nb.net && !na.net) memberSets.set(b, (memberSets.get(b) ?? new Set()).add(a));\n else if (!na.net && !nb.net) direct.push([a, b]);\n }\n const members = new Map([...memberSets].map(([k, s]) => [k, [...s].sort(natural)]));\n const nets: string[][] = [...members.values(), ...direct];\n const affinity = affinities(nets);\n\n const satellite = (n: BoardNode) => isSatellite(n.category);\n const anchors = comps.filter((n) => !satellite(n));\n const group = new Map<string, FunctionGroup>(anchors.map((n) => [n.id, functionGroup(n.category)]));\n const rank = (id: string) => GROUP_ORDER.indexOf(group.get(id) ?? \"other\");\n const parentOf = new Map<string, string>();\n for (const s of comps.filter(satellite)) {\n const label = (s.label ?? \"\").toUpperCase();\n // 1. a designator named in the label (\"U7 INPUT\", \"Y1 LOAD XL1\")\n const named = comps.filter((o) => o !== s && new RegExp(`(^|[^A-Z0-9])${o.id.toUpperCase().replace(/[^A-Z0-9]/g, \"\")}([^A-Z0-9]|$)`).test(label));\n // 2. an anchor whose name shares a distinctive word (\"LED DRIVER VCC\" → \"LED DRIVER\")\n const own = new Set(words(label));\n const worded = anchors\n .map((o) => ({ o, n: words(o.label ?? \"\").filter((w) => own.has(w)).length }))\n .filter((x) => x.n > 0)\n .sort((a, b) => b.n - a.n || rank(a.o.id) - rank(b.o.id) || natural(a.o.id, b.o.id));\n // 3. the component sharing the most specific nets (ties: the processor first)\n const aff = [...(affinity.get(s.id) ?? new Map<string, number>())].sort((a, b) => b[1] - a[1] || (group.has(a[0]) ? rank(a[0]) : 9) - (group.has(b[0]) ? rank(b[0]) : 9) || natural(a[0], b[0]));\n const pick = named[0]?.id ?? worded[0]?.o.id ?? aff[0]?.[0];\n if (pick) parentOf.set(s.id, pick);\n }\n // follow satellite → satellite chains to an anchor; a satellite with none becomes an anchor of its own\n const anchorOf = (id: string): string => {\n const seen = new Set<string>();\n let cur = id;\n while (parentOf.has(cur) && !seen.has(cur)) {\n seen.add(cur);\n cur = parentOf.get(cur)!;\n }\n return seen.has(cur) || !group.has(cur) ? id : cur;\n };\n // a connector or switch dedicated to one part (an LRA's pads, the SWD pads, a button) sits with\n // that part: every specific net it is on (three members or fewer) goes to the same cluster\n for (const n of anchors) {\n if (group.get(n.id) !== \"io\") continue;\n const targets = new Set<string>();\n for (const set of nets) if (set.includes(n.id) && set.length <= 3) for (const o of set) if (o !== n.id) targets.add(anchorOf(o));\n targets.delete(n.id);\n const [only] = targets;\n if (targets.size === 1 && group.has(only) && group.get(only) !== \"io\") {\n parentOf.set(n.id, only);\n group.delete(n.id);\n }\n }\n const sats = new Map<string, string[]>();\n for (const n of comps) {\n const a = satellite(n) || !group.has(n.id) ? anchorOf(n.id) : n.id;\n if (!group.has(a)) group.set(a, \"other\");\n if (a !== n.id) sats.set(a, [...(sats.get(a) ?? []), n.id]);\n else if (!sats.has(a)) sats.set(a, []);\n }\n const clusters = new Map<string, string[]>();\n const clusterOf = new Map<string, string>();\n for (const [a, list] of sats) {\n // satellites listed by what they hang from (Y1's load caps beside Y1), then by id\n const chain = (id: string): string[] => (parentOf.has(id) && parentOf.get(id) !== a && list.includes(parentOf.get(id)!) ? [...chain(parentOf.get(id)!), id] : [id]);\n list.sort((x, y) => {\n const cx = chain(x);\n const cy = chain(y);\n return natural(cx[0], cy[0]) || cx.length - cy.length || natural(x, y);\n });\n clusters.set(a, [a, ...list]);\n for (const id of [a, ...list]) clusterOf.set(id, a);\n }\n return { clusterOf, clusters, group, members, direct };\n}\n\n/** Affinity between components: a net of n members adds 1/(n−1) to each pair (a rail says little). */\nfunction affinities(nets: string[][]): Map<string, Map<string, number>> {\n const affinity = new Map<string, Map<string, number>>();\n const add = (a: string, b: string, w: number) => {\n const m = affinity.get(a) ?? new Map<string, number>();\n m.set(b, (m.get(b) ?? 0) + w);\n affinity.set(a, m);\n };\n for (const set of nets) {\n if (set.length < 2) continue;\n const w = 1 / (set.length - 1);\n for (let i = 0; i < set.length; i++)\n for (let j = i + 1; j < set.length; j++) {\n add(set[i], set[j], w);\n add(set[j], set[i], w);\n }\n }\n return affinity;\n}\n\ninterface Cluster {\n id: string;\n col: number;\n w: number;\n h: number;\n /** Offsets of each card inside the cluster. */\n cards: Record<string, { x: number; y: number }>;\n}\n\n/**\n * Top-left positions by node id for a board level. `edges` are the lines\n * drawn between nodes (component ↔ junction, or component ↔ component).\n */\nexport function boardLayout(nodes: BoardNode[], edges: [string, string][]): Record<string, { x: number; y: number }> {\n if (!nodes.length) return {};\n const byId = new Map(nodes.map((n) => [n.id, n]));\n const hubs = nodes.filter((n) => n.net).sort((a, b) => natural(a.id, b.id));\n const { clusterOf, clusters, group, members, direct } = boardClusters(nodes, edges);\n const hubMembers = (id: string) => members.get(id) ?? [];\n\n // ---- cluster shapes: the anchor on top, its satellites in up to two stacks below it ----\n // (left and right: a satellite goes on the side its junctions are, so its lines leave the cluster\n // without crossing the other stack; before the sides are known, alternately)\n const shapeCluster = (c: Cluster, side?: (id: string) => \"L\" | \"R\", order?: (id: string) => number) => {\n const [a, ...sats] = clusters.get(c.id)!;\n const an = byId.get(a)!;\n const cards: Record<string, { x: number; y: number }> = {};\n if (!sats.length) {\n cards[a] = { x: 0, y: 0 };\n Object.assign(c, { w: an.w, h: an.h, cards });\n return;\n }\n let L = sats.filter((id, i) => (side ? side(id) === \"L\" : i % 2 === 1));\n let R = sats.filter((id) => !L.includes(id));\n if (order) {\n L = L.slice().sort((x, y) => order(x) - order(y));\n R = R.slice().sort((x, y) => order(x) - order(y));\n }\n const stackW = (ids: string[]) => (ids.length ? Math.max(...ids.map((id) => byId.get(id)!.w)) : 0);\n const wl = stackW(L);\n const wr = stackW(R);\n const both = wl && wr;\n const gridW = wl + wr + (both ? GAP_IN_X : 0);\n const w = Math.max(an.w, gridW);\n cards[a] = { x: snapTo((w - an.w) / 2), y: 0 };\n const x0 = snapTo((w - gridW) / 2);\n let h = an.h;\n for (const [ids, x, sw] of [\n [L, x0, wl],\n [R, x0 + (wl ? wl + GAP_IN_X : 0), wr],\n ] as [string[], number, number][]) {\n let y = snapUp(an.h + GAP_IN_Y);\n for (const id of ids) {\n const n = byId.get(id)!;\n // a stack's cards line up on the cluster's outer edge (the side their lines leave from)\n cards[id] = { x: snapTo(ids === L ? x : x + sw - n.w), y };\n y = snapUp(y + n.h + GAP_IN_Y);\n h = Math.max(h, y - GAP_IN_Y);\n }\n }\n Object.assign(c, { w, h, cards });\n };\n const shapes: Cluster[] = [...clusters.keys()].map((id) => {\n const c: Cluster = { id, col: 0, w: 0, h: 0, cards: {} };\n shapeCluster(c);\n return c;\n });\n const shapeOf = new Map(shapes.map((c) => [c.id, c]));\n\n // cluster ↔ cluster weights, from the nets (each junction's members) and the direct lines\n // (a rail's taps count as the one net they are: what a rail joins belongs near its source, if weakly)\n const merged = new Map<string, Set<string>>();\n for (const [hub, list] of members) {\n const key = byId.get(hub)?.tapOf ?? hub;\n merged.set(key, new Set([...(merged.get(key) ?? []), ...list]));\n }\n const clusterWeights = (nets: string[][]) => {\n const out = new Map<string, Map<string, number>>();\n for (const [a, m] of affinities(nets)) {\n const ca = clusterOf.get(a);\n if (!ca) continue;\n for (const [b, w] of m) {\n const cb = clusterOf.get(b);\n if (!cb || ca === cb) continue;\n const row = out.get(ca) ?? new Map<string, number>();\n row.set(cb, (row.get(cb) ?? 0) + w);\n out.set(ca, row);\n }\n }\n return out;\n };\n const cw = clusterWeights([...[...merged.values()].map((x) => [...x]), ...direct]);\n // the lines actually drawn (a rail's taps stay within their cluster), for who drives whom\n const drawnCw = clusterWeights([...members.values(), ...direct]);\n\n // ---- columns: by function; a peripheral driven only by another peripheral one column further out ----\n const hasMcu = shapes.some((c) => group.get(c.id) === \"mcu\");\n for (const c of shapes) c.col = hasMcu ? GROUP_COLUMN[group.get(c.id)!] : GROUP_ORDER.indexOf(group.get(c.id)!);\n if (hasMcu) {\n for (let round = 0; round < 3; round++) {\n for (const c of shapes) {\n if (c.col < 3) continue;\n const ns = [...(drawnCw.get(c.id) ?? [])].map(([o]) => shapeOf.get(o)!);\n if (!ns.length || ns.some((o) => o.col < 3)) continue;\n // only to peripherals: beside the one it hangs from (the most connected)\n const best = [...(drawnCw.get(c.id) ?? [])].sort((a, b) => b[1] - a[1] || natural(a[0], b[0]))[0][0];\n const driver = shapeOf.get(best)!;\n // the driver itself answers to the processor or the power stage (two peripherals joined only to each other stay put)\n const driven = [...(drawnCw.get(driver.id) ?? [])].some(([o]) => shapeOf.get(o)!.col < 3);\n if (driven && driver.col >= c.col) c.col = driver.col + 1;\n }\n }\n }\n const used = [...new Set(shapes.map((c) => c.col))].sort((a, b) => a - b);\n for (const c of shapes) c.col = used.indexOf(c.col);\n\n // wrap a column taller than a landscape sheet allows into several\n const area = shapes.reduce((s, c) => s + (c.w + 2 * CHANNEL_PAD + 160) * (c.h + GAP_CLUSTER), 0);\n // (never below a screen's worth: a short column stays one column)\n const maxH = Math.max(Math.max(...shapes.map((c) => c.h)), Math.sqrt(area / 1.6), WRAP_MIN);\n const byCol: Cluster[][] = used.map((_, i) => shapes.filter((c) => c.col === i).sort((a, b) => b.h * b.w - a.h * a.w || natural(a.id, b.id)));\n const columns: Cluster[][] = [];\n for (const col of byCol) {\n const total = col.reduce((s, c) => s + c.h + GAP_CLUSTER, -GAP_CLUSTER);\n const n = Math.max(1, Math.ceil(total / maxH));\n const per = Math.ceil(col.length / n);\n for (let k = 0; k < n; k++) if (col.slice(k * per, k * per + per).length) columns.push(col.slice(k * per, k * per + per));\n }\n columns.forEach((col, i) => col.forEach((c) => (c.col = i)));\n\n const colOf = (id: string) => shapeOf.get(clusterOf.get(id)!)!.col;\n\n // ---- junctions: a channel each (channel k lies right of column k; −1 left of the first) ----\n const channelHubs = new Map<number, BoardNode[]>();\n const lastCol = columns.length - 1;\n const load = new Map<number, number>();\n const ordered = hubs.slice().sort((a, b) => hubMembers(b.id).length - hubMembers(a.id).length || natural(a.id, b.id));\n for (const hub of ordered) {\n const m = hubMembers(hub.id).filter((id) => clusterOf.has(id));\n let ch: number;\n if (!m.length) ch = lastCol;\n else {\n const cols = m.map(colOf).sort((a, b) => a - b);\n const lo = cols[0];\n const hi = cols[cols.length - 1];\n if (lo === hi) {\n // all in one column: the side with less in it already (the outer side of the edge columns last)\n const sides = [lo - 1, lo].filter((k) => k >= 0 && k < lastCol);\n const pool = sides.length ? sides : [lo === 0 ? 0 : lo - 1];\n ch = pool.sort((a, b) => (load.get(a) ?? 0) - (load.get(b) ?? 0) || b - a)[0];\n if (lastCol === 0) ch = 0;\n } else {\n // the channel with as many members on either side as it can have\n let best = lo;\n let score = Infinity;\n for (let k = lo; k < hi; k++) {\n const s = cols.reduce((t, c) => t + Math.abs(c - (k + 0.5)), 0);\n if (s < score - 1e-9) [best, score] = [k, s];\n }\n ch = best;\n }\n }\n channelHubs.set(ch, [...(channelHubs.get(ch) ?? []), hub]);\n load.set(ch, (load.get(ch) ?? 0) + 1);\n }\n\n // a junction is as tall as the ports on its busier side need (members left of its channel on its left)\n const hubH = new Map<string, number>();\n for (const [ch, list] of channelHubs)\n for (const h of list) {\n const m = hubMembers(h.id).filter((id) => clusterOf.has(id));\n const left = m.filter((id) => colOf(id) <= ch).length;\n hubH.set(h.id, Math.max(h.h, (Math.max(left, m.length - left) + 1) * STEP));\n }\n const H = (h: BoardNode) => hubH.get(h.id) ?? h.h;\n\n // cards as tall as their busier side will be (junctions left of their column on the left)\n for (const n of nodes) {\n if (n.net || !n.heightFor || !clusterOf.has(n.id)) continue;\n const chs = [...channelHubs].flatMap(([ch, list]) => list.filter((h) => hubMembers(h.id).includes(n.id)).map(() => ch));\n const l = chs.filter((ch) => ch < colOf(n.id)).length;\n const h = n.heightFor(Math.max(l, chs.length - l) + (n.otherPorts ?? 0) + 1);\n if (h > n.h) byId.set(n.id, { ...n, h });\n }\n for (const c of shapes) shapeCluster(c);\n\n // satellites to the side of the channel their junctions are in (the side with fewer, for one with none)\n const hubsOf = new Map<string, string[]>();\n for (const [ch, list] of channelHubs) for (const h of list) for (const m of hubMembers(h.id)) hubsOf.set(m, [...(hubsOf.get(m) ?? []), h.id]);\n const channelOf = new Map<string, number>();\n for (const [ch, list] of channelHubs) for (const h of list) channelOf.set(h.id, ch);\n const sideOf = new Map<string, \"L\" | \"R\">();\n for (const c of shapes) {\n const sats = clusters.get(c.id)!.slice(1);\n let nl = 0;\n let nr = 0;\n for (const id of sats) {\n const chs = (hubsOf.get(id) ?? []).map((h) => channelOf.get(h)!);\n const l = chs.filter((ch) => ch < c.col).length;\n const r = chs.length - l;\n const side = l > r || (l === r && !chs.length && nl < nr) ? \"L\" : \"R\";\n sideOf.set(id, side);\n if (side === \"L\") nl++;\n else nr++;\n }\n shapeCluster(c, (id) => sideOf.get(id)!);\n }\n\n // each junction hangs off its smallest member card (the LED, not its driver): the cluster of that card\n // is given room down the side of the junction's channel for it, so a channel's junctions fit one lane\n const demand = new Map<string, { L: number; R: number }>();\n for (const [ch, list] of channelHubs)\n for (const h of list) {\n const m = hubMembers(h.id).filter((id) => clusterOf.has(id));\n if (!m.length) continue;\n const owner = m.slice().sort((a, b) => byId.get(a)!.h - byId.get(b)!.h || natural(a, b))[0];\n const c = clusterOf.get(owner)!;\n const d = demand.get(c) ?? { L: 0, R: 0 };\n d[ch < colOf(owner) ? \"L\" : \"R\"] += H(h) + HUB_GAP_Y;\n demand.set(c, d);\n }\n const slot = (c: Cluster) => snapUp(Math.max(c.h, demand.get(c.id)?.L ?? 0, demand.get(c.id)?.R ?? 0));\n\n // ---- heights: barycentre sweeps, then each column packed toward the height of what it joins ----\n // (`top` is the top of a cluster's slot: its cards sit in the middle of it)\n const top = new Map<string, number>();\n const mid = (c: Cluster) => top.get(c.id)! + slot(c) / 2;\n for (const col of columns) {\n const total = col.reduce((s, c) => s + slot(c) + GAP_CLUSTER, -GAP_CLUSTER);\n let y = snapTo((maxH - total) / 2);\n for (const c of col) {\n top.set(c.id, y);\n y += slot(c) + GAP_CLUSTER;\n }\n }\n const sweepOrder = columns.map((_, i) => i).sort((a, b) => columns[b].reduce((s, c) => s + slot(c), 0) - columns[a].reduce((s, c) => s + slot(c), 0));\n for (let sweep = 0; sweep < 8; sweep++) {\n // the tallest column first: the others line up with it\n for (const i of sweep === 0 ? sweepOrder.slice(1) : sweepOrder) {\n const col = columns[i];\n const key = new Map<string, number>();\n for (const c of col) {\n let s = 0;\n let n = 0;\n for (const [o, w] of cw.get(c.id) ?? []) {\n const oc = shapeOf.get(o)!;\n if (oc.col === c.col) continue;\n // nearer columns pull harder\n const k = w / Math.abs(oc.col - c.col);\n s += mid(oc) * k;\n n += k;\n }\n key.set(c.id, n ? s / n : NaN);\n }\n // a cluster joined to nothing in another column (a cell's pads on a tapped rail) goes last, packed\n const last = Math.max(0, ...col.map((c) => key.get(c.id)!).filter((k) => !Number.isNaN(k)));\n for (const c of col) if (Number.isNaN(key.get(c.id)!)) key.set(c.id, last + 1);\n col.sort((a, b) => key.get(a.id)! - key.get(b.id)! || natural(a.id, b.id));\n const ys = pack(col.map((c) => key.get(c.id)! - slot(c) / 2), col.map(slot), GAP_CLUSTER);\n col.forEach((c, k) => top.set(c.id, ys[k]));\n }\n }\n\n // card positions without x yet: x comes once the channels are sized\n const cardY = new Map<string, number>();\n const cardMidY = (id: string) => cardY.get(id)! + byId.get(id)!.h / 2;\n const setCardY = () => {\n for (const c of shapes) for (const [id, o] of Object.entries(c.cards)) cardY.set(id, top.get(c.id)! + snapTo((slot(c) - c.h) / 2) + o.y);\n };\n setCardY();\n\n // lanes: junctions in order of the height of what they join; a new lane where one would be pushed far\n interface Lane {\n hubs: BoardNode[];\n ideal: number[];\n }\n // a junction's height: where the lines to it run shortest. A card's port can sit anywhere along its\n // side, so each member is the span of its card, and the best height is the one nearest every span\n // (ties: nearest the weighted mean of their middles)\n const hubIdeal = (h: BoardNode) => {\n const m = hubMembers(h.id).filter((id) => cardY.has(id));\n if (!m.length) return maxH / 2;\n const spans = m.map((id) => {\n const t = cardY.get(id)!;\n const bh = byId.get(id)!.h;\n const inset = Math.min(32, bh / 2);\n return [t + inset, t + bh - inset] as [number, number];\n });\n const cost = (y: number) => spans.reduce((s, [a, b]) => s + (y < a ? a - y : y > b ? y - b : 0), 0);\n // the middles weighted toward the small cards (an LED's junction sits by the LED, not its driver's middle)\n const wt = (id: string) => 1 / byId.get(id)!.h ** 2;\n const mean = m.reduce((s, id) => s + cardMidY(id) * wt(id), 0) / m.reduce((s, id) => s + wt(id), 0);\n let best = mean;\n let bc = cost(mean);\n for (const y of spans.flat()) {\n const c = cost(y);\n if (c < bc - 1e-6 || (Math.abs(c - bc) < 1e-6 && Math.abs(y - mean) < Math.abs(best - mean))) [best, bc] = [y, c];\n }\n // within the best range, as near the mean as it allows\n const lo = Math.min(...spans.flat().filter((y) => Math.abs(cost(y) - bc) < 1e-6), best);\n const hi = Math.max(...spans.flat().filter((y) => Math.abs(cost(y) - bc) < 1e-6), best);\n return Math.max(lo, Math.min(hi, mean));\n };\n const makeLanes = () => {\n const channelLanes = new Map<number, Lane[]>();\n for (const [ch, list] of channelHubs) {\n const sorted = list.slice().sort((a, b) => hubIdeal(a) - hubIdeal(b) || natural(a.id, b.id));\n const lanes: Lane[] = [];\n const bottoms: number[] = [];\n for (const h of sorted) {\n const ideal = hubIdeal(h) - H(h) / 2;\n let pick = -1;\n let push = Infinity;\n bottoms.forEach((b, i) => {\n const p = Math.max(0, b + HUB_GAP_Y - ideal);\n if (p < push - 1e-9) [pick, push] = [i, p];\n });\n // lanes side by side cross each other's lines: a second one only where one lane would push far\n if (pick < 0 || (push > LANE_PUSH && lanes.length < 3)) {\n lanes.push({ hubs: [], ideal: [] });\n bottoms.push(-Infinity);\n pick = lanes.length - 1;\n }\n lanes[pick].hubs.push(h);\n lanes[pick].ideal.push(ideal);\n bottoms[pick] = Math.max(bottoms[pick] + HUB_GAP_Y, ideal) + H(h);\n }\n channelLanes.set(ch, lanes);\n }\n return channelLanes;\n };\n\n // place the junctions once, then order each satellite stack by the height of its junctions, and again\n let channelLanes = makeLanes();\n const hubMid = new Map<string, number>();\n for (const lanes of channelLanes.values())\n for (const lane of lanes) {\n const ys = pack(lane.ideal, lane.hubs.map(H), HUB_GAP_Y);\n lane.hubs.forEach((h, i) => hubMid.set(h.id, ys[i] + H(h) / 2));\n }\n const satKey = (id: string) => {\n const hs = (hubsOf.get(id) ?? []).filter((h) => hubMid.has(h));\n return hs.length ? hs.reduce((t, h) => t + hubMid.get(h)!, 0) / hs.length : cardMidY(id);\n };\n for (const c of shapes) if (clusters.get(c.id)!.length > 2) shapeCluster(c, (id) => sideOf.get(id)!, satKey);\n setCardY();\n channelLanes = makeLanes();\n\n // lines into each side of a channel: room for their vertical runs\n const sideLines = (ch: number, side: \"left\" | \"right\") => {\n let n = 0;\n for (const h of channelHubs.get(ch) ?? []) for (const m of hubMembers(h.id)) if (clusterOf.has(m) && (side === \"left\" ? colOf(m) <= ch : colOf(m) > ch)) n++;\n return n;\n };\n const pad = (n: number) => snapUp(CHANNEL_PAD + Math.min(320, n * 8));\n\n // ---- x: columns and channels left to right ----\n const out: Record<string, { x: number; y: number }> = {};\n let x = 0;\n const place = (ch: number) => {\n const lanes = channelLanes.get(ch) ?? [];\n if (!lanes.length) {\n x += ch < 0 || ch >= lastCol ? 0 : snapUp(2 * CHANNEL_PAD + 64);\n return;\n }\n x += pad(sideLines(ch, \"left\"));\n for (const lane of lanes) {\n const w = Math.max(...lane.hubs.map((h) => h.w));\n const ys = pack(lane.ideal, lane.hubs.map(H), HUB_GAP_Y);\n lane.hubs.forEach((h, i) => (out[h.id] = { x: snapTo(x + (w - h.w) / 2), y: ys[i] }));\n x += w + LANE_GAP;\n }\n x += pad(sideLines(ch, \"right\")) - LANE_GAP;\n };\n place(-1);\n columns.forEach((col, i) => {\n const w = Math.max(...col.map((c) => c.w));\n for (const c of col) {\n const cx = snapTo(x + (w - c.w) / 2);\n for (const [id, o] of Object.entries(c.cards)) out[id] = { x: cx + o.x, y: cardY.get(id)! };\n }\n x = snapUp(x + w);\n place(i);\n });\n\n const all = Object.values(out);\n const minX = Math.min(...all.map((p) => p.x));\n const minY = Math.min(...all.map((p) => p.y));\n for (const p of all) {\n p.x -= minX;\n p.y -= minY;\n }\n return out;\n}\n","/**\n * Rail taps (PB-873): a supply rail drawn the way a schematic draws it.\n *\n * A rail joins most of a board (a 3V3 rail reaches 15–20 parts). Drawn as one\n * junction it pulls a line from every corner of the sheet. Drawn as a net\n * label at each place it is used, it reads at a glance: here the rail is\n * split into taps, one per cluster of parts (a part and the passives that\n * serve it, board-layout.ts), each joined only to the members of its cluster.\n * The taps carry the net's name and colour; the one with the most members\n * keeps the net's id, the others are `<net>~<cluster>` with `tapOf` set.\n *\n * Only the drawing changes: the inspector, the hierarchy and the findings\n * read the level's view model, where the net is one node.\n */\nimport type { ViewLink, ViewModel, ViewNode } from \"../model/types\";\nimport { boardClusters, functionGroup, type BoardNode } from \"./board-layout\";\n\n/** A power net with at least this many members is drawn as taps. */\nexport const RAIL_TAP_MIN = 5;\n\nconst GROUP_RANK = [\"power\", \"io\", \"mcu\", \"sensor\", \"output\", \"other\"];\nconst natural = (a: string, b: string) => a.localeCompare(b, undefined, { numeric: true });\n\nexport function tapRails(vm: ViewModel): ViewModel {\n const top = vm.nodes.filter((n) => !n.parent && !n.sheetPort);\n const rails = top.filter((n) => n.kind === \"net\" && n.net && !n.net.ground && n.net.signal === \"power\");\n if (!rails.length) return vm;\n const ids = new Set(top.map((n) => n.id));\n const lines = vm.links.filter((l) => !l.passThrough && !l.ground && ids.has(l.source.node) && ids.has(l.target.node));\n const nodes: BoardNode[] = top.map((n) => ({ id: n.id, w: 0, h: 0, net: n.kind === \"net\", category: n.category, label: n.label }));\n const { clusterOf } = boardClusters(\n nodes,\n lines.map((l) => [l.source.node, l.target.node]),\n );\n const byId = new Map(top.map((n) => [n.id, n]));\n\n const retarget = new Map<string, string>();\n const replaced = new Map<string, ViewNode[]>();\n for (const rail of rails) {\n const own = lines.filter((l) => l.target.node === rail.id && clusterOf.has(l.source.node));\n if (own.length < RAIL_TAP_MIN) continue;\n const groups = new Map<string, ViewLink[]>();\n for (const l of own) {\n const c = clusterOf.get(l.source.node)!;\n groups.set(c, [...(groups.get(c) ?? []), l]);\n }\n if (groups.size < 2) continue;\n const rank = (c: string) => GROUP_RANK.indexOf(functionGroup(byId.get(c)?.category));\n const order = [...groups.keys()].sort((a, b) => groups.get(b)!.length - groups.get(a)!.length || rank(a) - rank(b) || natural(a, b));\n const taps: ViewNode[] = order.map((c, i) => {\n const ports = new Set(groups.get(c)!.map((l) => l.target.port));\n const id = i === 0 ? rail.id : `${rail.id}~${c}`;\n for (const l of groups.get(c)!) retarget.set(l.id, id);\n return { ...rail, id, ports: rail.ports.filter((p) => ports.has(p.id)), ...(i === 0 ? {} : { tapOf: rail.id }) };\n });\n // the net's own ports with no line here (a member drawn elsewhere) stay on the main junction\n const kept = new Set(taps.flatMap((t) => t.ports.map((p) => p.id)));\n taps[0] = { ...taps[0], ports: [...taps[0].ports, ...rail.ports.filter((p) => !kept.has(p.id))] };\n replaced.set(rail.id, taps);\n }\n if (!replaced.size) return vm;\n return {\n ...vm,\n nodes: vm.nodes.flatMap((n) => replaced.get(n.id) ?? [n]),\n links: vm.links.map((l) => (retarget.has(l.id) ? { ...l, target: { ...l.target, node: retarget.get(l.id)! } } : l)),\n };\n}\n\n/** The node a selection names for a drawn node: a tap's net. */\nexport const selectionId = (node: ViewNode | undefined, id: string) => node?.tapOf ?? id;\n","/**\n * What a module card's body holds (its icon, its title and the chips that\n * count its unlinked interfaces by protocol) and how much height that needs.\n *\n * The layout grows a card to fit its body between the labels of the ports\n * on its top and bottom edges; the card then draws only the chips that fit\n * and folds the rest into \"+N\". Sizes follow `.module-body`, `.module-title`\n * and `.port-group` in styles/app.css.\n */\nimport type { PortGroup } from \"./layout\";\nimport type { Side } from \"../canvas/routing\";\n\nconst BORDER = 2;\nconst PAD_X = 34;\nconst ICON = 22;\nconst GAP = 7;\nconst TITLE_LINE = 13;\nconst TITLE_CHAR = 6.4;\n/** Room kept above and below the body: a port label's row on an edge with labelled ports, else a margin. */\nconst EDGE = 8;\nconst LABEL_ROW = 20;\n/** A side label: its offset from the edge, its width per character (8 px type), and the gap kept beside it. */\nconst LABEL_OFFSET = 9;\nconst LABEL_CHAR = 4.9;\nconst LABEL_GAP = 4;\nconst CHIP_H = 14;\nconst CHIP_GAP = 3;\nconst CHIP_CHAR = 4.9;\nconst CHIP_PAD = 12;\n/** Chips shown before the rest fold into \"+N\". */\nexport const MAX_CHIPS = 4;\n/** Chip rows a card grows for; more chips fold into \"+N\". */\nexport const MAX_CHIP_ROWS = 3;\n\nexport interface CardInsets {\n top: number;\n bottom: number;\n left: number;\n right: number;\n}\n\n/** A port's label as the card draws it: the name without its parenthesised or dashed qualifier. */\nexport function portLabelText(name: string): string {\n return name.replace(/\\s*\\(.*?\\)/g, \"\").replace(/\\s+[—–-]\\s+.*$/, \"\");\n}\n\n/** How wide a label on a card's left or right edge may run before it is cut with an ellipsis. */\nexport function sideLabelWidth(cardWidth: number): number {\n return Math.max(40, cardWidth / 2 - 54);\n}\n\n/** A card's width with nothing to fit, and the widest it grows to for its labels. */\nexport const CARD_W = 170;\nexport const CARD_W_MAX = 272;\n\n/** The widest a label on a card's top or bottom edge runs (its share of the edge, when that is less). */\nexport const TOP_LABEL_MAX = 160;\n\n/** A label's width as drawn (8 px type). */\nexport const labelWidth = (name: string): number => Math.ceil(portLabelText(name).length * LABEL_CHAR);\n\n/**\n * The width a card takes so the labels of its linked interfaces fit beside\n * its body: as wide as the longest needs (two may face each other across the\n * card), from the plain width up to `CARD_W_MAX`. A longer label is cut with\n * an ellipsis and says its whole name on hover.\n */\nexport function cardWidth(labels: readonly string[]): number {\n const widest = Math.max(0, ...labels.map(labelWidth));\n // the inverse of sideLabelWidth, with a pixel to spare for the ellipsis rule\n const need = 2 * (widest + 1 + 54);\n return Math.min(CARD_W_MAX, Math.max(CARD_W, need));\n}\n\n/** A label is drawn short: it does not fit `width`, or the card leaves out the name's qualifier. */\nexport function labelIsCut(name: string, width: number): boolean {\n return portLabelText(name) !== name || labelWidth(name) > width;\n}\n\n/**\n * Room the body keeps clear of the port labels: a label row on the top and\n * bottom edges that have labelled ports, and on the left and right as wide\n * as that edge's longest label.\n */\nexport function cardInsets(labels: { side: Side; name: string }[], cardWidth: number): CardInsets {\n const has = (side: Side) => labels.some((l) => l.side === side);\n const across = (side: Side) => {\n const widest = Math.max(0, ...labels.filter((l) => l.side === side).map((l) => portLabelText(l.name).length * LABEL_CHAR));\n return widest ? Math.max(PAD_X, LABEL_OFFSET + Math.min(sideLabelWidth(cardWidth), widest) + LABEL_GAP) : PAD_X;\n };\n return { top: has(\"top\") ? LABEL_ROW : EDGE, bottom: has(\"bottom\") ? LABEL_ROW : EDGE, left: across(\"left\"), right: across(\"right\") };\n}\n\nexport function chipText(g: PortGroup): string {\n return `${g.protocol.replace(/_/g, \" \").toUpperCase()} ×${g.count}`;\n}\n\nconst chipWidth = (text: string) => text.length * CHIP_CHAR + CHIP_PAD;\n\n/** Rows the chips wrap to in a body `width` wide (flex-wrap, centred). */\nfunction chipRows(texts: string[], width: number): number {\n let rows = 0;\n let used = Infinity;\n for (const t of texts) {\n const w = Math.min(chipWidth(t), width);\n if (used + CHIP_GAP + w > width) {\n rows++;\n used = w;\n } else used += CHIP_GAP + w;\n }\n return rows;\n}\n\nfunction titleLines(title: string, bodyWidth: number): number {\n const perLine = Math.max(6, Math.floor(bodyWidth / TITLE_CHAR));\n return Math.min(3, Math.max(1, Math.ceil(title.length / perLine)));\n}\n\n/** The chips in the order drawn: the first few groups, then \"+N\" for the interfaces of the rest. */\nfunction chipsFor(groups: PortGroup[], shown: number): { shown: PortGroup[]; rest: number; texts: string[] } {\n const list = groups.slice(0, shown);\n const rest = groups.slice(shown).reduce((n, g) => n + g.count, 0);\n return { shown: list, rest, texts: [...list.map(chipText), ...(rest > 0 ? [`+${rest}`] : [])] };\n}\n\nconst rowsHeight = (rows: number) => (rows > 0 ? GAP + rows * CHIP_H + (rows - 1) * CHIP_GAP : 0);\n\n/** The height a card needs for its body, with up to MAX_CHIP_ROWS rows of chips. */\nexport function cardHeight(title: string, width: number, groups: PortGroup[], insets: CardInsets): number {\n const body = width - insets.left - insets.right;\n const rows = groups.length ? Math.min(MAX_CHIP_ROWS, chipRows(chipsFor(groups, MAX_CHIPS).texts, body)) : 0;\n return 2 * BORDER + insets.top + insets.bottom + ICON + GAP + titleLines(title, body) * TITLE_LINE + rowsHeight(rows);\n}\n\n/**\n * The chips a card of this size draws: as many groups as fit its free rows,\n * the rest counted in \"+N\". A card with no room for a row draws none.\n */\nexport function fitChips(title: string, box: { w: number; h: number }, groups: PortGroup[], insets: CardInsets): { shown: PortGroup[]; rest: number } {\n if (!groups.length) return { shown: [], rest: 0 };\n const body = box.w - insets.left - insets.right;\n const free = box.h - 2 * BORDER - insets.top - insets.bottom - ICON - GAP - titleLines(title, body) * TITLE_LINE;\n let rows = 0;\n while (rows < MAX_CHIP_ROWS && rowsHeight(rows + 1) <= free) rows++;\n if (rows === 0) return { shown: [], rest: 0 };\n for (let k = Math.min(MAX_CHIPS, groups.length); k >= 0; k--) {\n const c = chipsFor(groups, k);\n if (chipRows(c.texts, body) <= rows) return { shown: c.shown, rest: c.rest };\n }\n return { shown: [], rest: 0 };\n}\n","/**\n * Geometry along a routed link (PB-803): positions by arc length, sub-paths,\n * lanes that fan out of the centre line, and harness regions traced around\n * whatever runs through them. Pure functions, no React.\n */\nimport { filletPath, offsetPolyline, type Pt } from \"./routing\";\n\nexport const RUN = 24; // length of one fan\nexport const LANE_PITCH = 16;\nexport const RIBBON_PITCH = 6;\nconst RADIUS = 12;\n\nexport function lengths(points: Pt[]): number[] {\n const out = [0];\n for (let i = 1; i < points.length; i++) out.push(out[i - 1] + Math.hypot(points[i][0] - points[i - 1][0], points[i][1] - points[i - 1][1]));\n return out;\n}\n\nexport const totalLength = (points: Pt[]) => lengths(points).at(-1) ?? 0;\n\n/** Point and unit direction at arc length `s`. */\nexport function at(points: Pt[], s: number): { p: Pt; d: Pt } {\n const L = lengths(points);\n const t = Math.max(0, Math.min(L[L.length - 1], s));\n for (let i = 1; i < points.length; i++) {\n if (L[i] >= t || i === points.length - 1) {\n const seg = L[i] - L[i - 1] || 1;\n const f = (t - L[i - 1]) / seg;\n const [a, b] = [points[i - 1], points[i]];\n return { p: [a[0] + (b[0] - a[0]) * f, a[1] + (b[1] - a[1]) * f], d: [(b[0] - a[0]) / seg, (b[1] - a[1]) / seg] };\n }\n }\n return { p: points[0], d: [1, 0] };\n}\n\n/** The polyline between arc lengths s0 and s1. */\nexport function subpath(points: Pt[], s0: number, s1: number): Pt[] {\n const L = lengths(points);\n const out: Pt[] = [at(points, s0).p];\n for (let i = 1; i < points.length - 1; i++) if (L[i] > s0 && L[i] < s1) out.push(points[i]);\n out.push(at(points, s1).p);\n return out;\n}\n\n/** Arc length of the point on the polyline nearest to `q`. */\nexport function project(points: Pt[], q: Pt): number {\n const L = lengths(points);\n let best = { d: Infinity, s: 0 };\n for (let i = 1; i < points.length; i++) {\n const [a, b] = [points[i - 1], points[i]];\n const vx = b[0] - a[0];\n const vy = b[1] - a[1];\n const len2 = vx * vx + vy * vy || 1;\n const f = Math.max(0, Math.min(1, ((q[0] - a[0]) * vx + (q[1] - a[1]) * vy) / len2));\n const px = a[0] + vx * f;\n const py = a[1] + vy * f;\n const d = Math.hypot(q[0] - px, q[1] - py);\n if (d < best.d) best = { d, s: L[i - 1] + f * Math.sqrt(len2) };\n }\n return best.s;\n}\n\nconst add = (a: Pt, b: Pt, k = 1): Pt => [a[0] + b[0] * k, a[1] + b[1] * k];\nconst normal = (d: Pt): Pt => [d[1], -d[0]]; // left of travel, as offsetPolyline\n\nexport function densify(points: Pt[], step = 3): Pt[] {\n const out: Pt[] = [];\n for (let i = 1; i < points.length; i++) {\n const [a, b] = [points[i - 1], points[i]];\n const n = Math.max(1, Math.ceil(Math.hypot(b[0] - a[0], b[1] - a[1]) / step));\n for (let k = 0; k < n; k++) out.push([a[0] + ((b[0] - a[0]) * k) / n, a[1] + ((b[1] - a[1]) * k) / n]);\n }\n if (points.length) out.push(points[points.length - 1]);\n return out;\n}\n\n/** Offsets for n lanes centred on the line. */\nexport const offsets = (n: number, pitch: number) => Array.from({ length: n }, (_, i) => (i - (n - 1) / 2) * pitch);\n\n/** Fillet radius for the centre line of a ribbon `width` wide, so its inner conductor still turns round. */\nexport const ribbonRadius = (width: number) => Math.max(RADIUS, width / 2 + 6);\n\n/** Stroke points of a ribbon (parallel conductors at a fixed pitch) along the whole route. */\nexport function ribbon(points: Pt[], n: number, radius = RADIUS): { d: string; samples: Pt[] }[] {\n return offsets(n, RIBBON_PITCH).map((o) => {\n const off = offsetPolyline(points, o, radius);\n return { d: filletPath(off.points, off.radii), samples: densify(off.points) };\n });\n}\n\n/**\n * The straight stretches of a route as arc-length intervals, each kept `clear`\n * of the corners at its ends (and `end` of the route's own ends).\n */\nexport function straights(points: Pt[], clear: number, end = 0): [number, number][] {\n const L = lengths(points);\n const out: [number, number][] = [];\n for (let i = 1; i < points.length; i++) {\n const a = L[i - 1] + (i > 1 ? clear : end);\n const b = L[i] - (i < points.length - 1 ? clear : end);\n if (b >= a) out.push([a, b]);\n }\n return out;\n}\n\n/**\n * The nearest arc length to `s` that sits on a straight stretch, clear of the\n * bends (handles and toggles never sit in a corner). Where no stretch is long\n * enough, the middle of the longest segment.\n */\nexport function clearOfBends(points: Pt[], s: number, clear: number, end = 0): number {\n const iv = straights(points, clear, end);\n if (!iv.length) {\n const L = lengths(points);\n let best = 1;\n for (let i = 2; i < points.length; i++) if (L[i] - L[i - 1] > L[best] - L[best - 1]) best = i;\n return (L[best - 1] + L[best]) / 2;\n }\n let out = s;\n let dist = Infinity;\n for (const [a, b] of iv) {\n const c = Math.max(a, Math.min(b, s));\n if (Math.abs(c - s) < dist) {\n dist = Math.abs(c - s);\n out = c;\n }\n }\n return out;\n}\n\n/** The straight stretch (with `clear` at its corners) that contains arc length `s`. */\nexport function stretchAt(points: Pt[], s: number, clear: number, end = 0): [number, number] {\n const L = lengths(points);\n for (let i = 1; i < points.length; i++) {\n if (s <= L[i] + 0.5 || i === points.length - 1) return [L[i - 1] + (i > 1 ? clear : end), L[i] - (i < points.length - 1 ? clear : end)];\n }\n return [0, L[L.length - 1]];\n}\n\n/**\n * Turn short S-jogs (a sidestep between two runs in the same direction,\n * shorter than `min`) into a gentle diagonal: a wide ribbon cannot take two\n * right angles in less than its own width without its conductors crossing.\n */\nexport function easeJogs(points: Pt[], min: number): Pt[] {\n let pts = points.map((p) => [...p] as Pt);\n for (let guard = 0; guard < 16; guard++) {\n let changed = false;\n for (let i = 1; i < pts.length - 2; i++) {\n const [a, b, c, e] = [pts[i - 1], pts[i], pts[i + 1], pts[i + 2]];\n const j = Math.hypot(c[0] - b[0], c[1] - b[1]);\n const lin = Math.hypot(b[0] - a[0], b[1] - a[1]);\n const lout = Math.hypot(e[0] - c[0], e[1] - c[1]);\n if (j >= min || j < 0.5 || !lin || !lout) continue;\n const din: Pt = [(b[0] - a[0]) / lin, (b[1] - a[1]) / lin];\n const dout: Pt = [(e[0] - c[0]) / lout, (e[1] - c[1]) / lout];\n if (din[0] * dout[0] + din[1] * dout[1] < 0.99) continue; // not an S-jog\n // leave the first and last runs (the port stubs) a little straight\n const k = Math.min(Math.max(min, 2 * j), lin - (i === 1 ? 10 : 2), lout - (i + 2 === pts.length - 1 ? 10 : 2));\n if (k < j / 2) continue;\n pts = [...pts.slice(0, i), add(b, din, -k), add(c, dout, k), ...pts.slice(i + 2)];\n changed = true;\n break;\n }\n if (!changed) break;\n }\n return pts;\n}\n\n/**\n * A closed outline around every sample (dilated by `pad`), traced on a 2 px\n * raster and smoothed: the harness region, tight to what runs through it.\n */\nexport function regionOutline(samples: Pt[], pad: number): string {\n if (!samples.length) return \"\";\n const C = 2;\n const xs = samples.map((p) => p[0]);\n const ys = samples.map((p) => p[1]);\n const x0 = Math.min(...xs) - pad - 4;\n const y0 = Math.min(...ys) - pad - 4;\n const W = Math.ceil((Math.max(...xs) + pad + 4 - x0) / C);\n const H = Math.ceil((Math.max(...ys) + pad + 4 - y0) / C);\n const grid = new Uint8Array(W * H);\n const r = Math.ceil(pad / C);\n const disc: [number, number][] = [];\n for (let dx = -r; dx <= r; dx++) for (let dy = -r; dy <= r; dy++) if (dx * dx + dy * dy <= r * r) disc.push([dx, dy]);\n for (const [x, y] of samples) {\n const cx = Math.round((x - x0) / C);\n const cy = Math.round((y - y0) / C);\n for (const [dx, dy] of disc) {\n const X = cx + dx;\n const Y = cy + dy;\n if (X >= 0 && Y >= 0 && X < W && Y < H) grid[Y * W + X] = 1;\n }\n }\n let start = -1;\n for (let i = 0; i < grid.length && start < 0; i++) if (grid[i]) start = i;\n if (start < 0) return \"\";\n const nb: [number, number][] = [[-1, 0], [-1, -1], [0, -1], [1, -1], [1, 0], [1, 1], [0, 1], [-1, 1]];\n const filled = (x: number, y: number) => x >= 0 && y >= 0 && x < W && y < H && grid[y * W + x] === 1;\n let cur: [number, number] = [start % W, Math.floor(start / W)];\n const first = cur;\n let back = 0;\n const contour: Pt[] = [cur];\n for (let guard = 0; guard < W * H * 4; guard++) {\n let moved = false;\n for (let k = 0; k < 8; k++) {\n const d = (back + 1 + k) % 8;\n const nx = cur[0] + nb[d][0];\n const ny = cur[1] + nb[d][1];\n if (filled(nx, ny)) {\n back = (d + 4) % 8;\n cur = [nx, ny];\n moved = true;\n break;\n }\n }\n if (!moved || (cur[0] === first[0] && cur[1] === first[1] && contour.length > 2)) break;\n contour.push(cur);\n }\n let poly: Pt[] = contour.filter((_, i) => i % 2 === 0).map(([x, y]) => [x0 + (x + 0.5) * C, y0 + (y + 0.5) * C]);\n for (let it = 0; it < 3; it++) {\n const next: Pt[] = [];\n for (let i = 0; i < poly.length; i++) {\n const p = poly[i];\n const q = poly[(i + 1) % poly.length];\n next.push([0.75 * p[0] + 0.25 * q[0], 0.75 * p[1] + 0.25 * q[1]], [0.25 * p[0] + 0.75 * q[0], 0.25 * p[1] + 0.75 * q[1]]);\n }\n poly = next;\n }\n return \"M\" + poly.filter((_, i) => i % 2 === 0).map((p) => `${p[0].toFixed(1)},${p[1].toFixed(1)}`).join(\"L\") + \"Z\";\n}\n\n/** A stretch of a line at a constant offset from the centre line, between arc lengths a and b. */\nexport interface Plateau {\n o: number;\n a: number;\n b: number;\n}\n\n/**\n * A line that steps between offsets from the centre line: it runs each\n * plateau parallel to the route and curves smoothly from one to the next over\n * the gap between them (b of one to a of the next). Consecutive plateaus at\n * the same offset join straight through. The building block of every\n * breakout: a lane leaving its parent line, and a conductor stepping out\n * level by level.\n */\nexport function stepped(points: Pt[], plateaus: Plateau[], radius = RADIUS): { d: string; samples: Pt[] } {\n const ps: Plateau[] = [];\n for (const p of plateaus) {\n const last = ps[ps.length - 1];\n if (last && Math.abs(last.o - p.o) < 0.01) last.b = Math.max(last.b, p.b);\n else ps.push({ ...p });\n }\n const pointAt = (s: number, o: number): Pt => {\n const { p, d } = at(points, s);\n return add(p, normal(d), o);\n };\n let d = \"\";\n const samples: Pt[] = [];\n let end: Pt | undefined;\n ps.forEach((p, i) => {\n const sub = p.b - p.a > 0.5 ? offsetPolyline(subpath(points, p.a, p.b), p.o, radius) : undefined;\n const start = sub ? sub.points[0] : pointAt(p.a, p.o);\n if (i === 0) d = `M${start[0]},${start[1]}`;\n else if (end) {\n const q = ps[i - 1];\n const h = Math.max(1, (p.a - q.b) / 2);\n d += ` C${add(end, at(points, q.b).d, h).join(\",\")} ${add(start, at(points, p.a).d, -h).join(\",\")} ${start[0]},${start[1]}`;\n samples.push(...densify([end, start]));\n }\n if (sub) {\n d += filletPath(sub.points, sub.radii).replace(/^M[^L]*/, \"\");\n samples.push(...densify(sub.points));\n end = sub.points[sub.points.length - 1];\n } else end = start;\n });\n return { d, samples };\n}\n","/**\n * Module-level layout (PB-1007): the default for a level of modules (no\n * nets), which used to be one long row. The cards go in a grid shaped like\n * a screen, each next to what it connects to:\n *\n * - the grid has about as many columns as a 16:10 screen holds for the\n * level's cards, so no level is a strip;\n * - the hub (the card with the most links: a flight controller, a processor)\n * starts in the middle, and the others are added in order of how strongly\n * they join what is placed, each at the free cell that suits it best;\n * - then cards swap cells while that lowers the cost: link length, links that\n * bend (neither in a row nor a column), lines crossing, lines that a card\n * sits in the way of, and, mildly, the reading order of a block diagram\n * (connectors and power left of the processor, what it drives right of it);\n * - empty rows and columns go, and each column is as wide, and each row as\n * tall, as its largest card, with room between them for the lines and\n * their labels.\n *\n * Same input, same output: every choice breaks ties by id.\n *\n * `fixed` cards keep their places (top-left, as saved); a `seed` (each card's\n * centre in an earlier layout) starts the grid from that arrangement instead\n * (a tidy keeps what the person laid out where it can).\n */\nimport { freeSpot, functionGroup, hits } from \"./board-layout\";\nimport { GRID } from \"./router\";\n\nexport interface GridNode {\n id: string;\n w: number;\n h: number;\n category?: string;\n}\n\nexport interface GridOptions {\n /** Cards that stay where they are: top-left positions. */\n fixed?: Record<string, { x: number; y: number }>;\n /** Where each card's centre was: the starting arrangement. */\n seed?: Record<string, { x: number; y: number }>;\n /** Width over height to aim for (default 1.6). */\n aspect?: number;\n}\n\n/** Room between columns (lines and their labels run there) and between rows. */\nexport const GRID_GAP_X = 192;\nexport const GRID_GAP_Y = 128;\n\nconst natural = (a: string, b: string) => a.localeCompare(b, undefined, { numeric: true });\nconst snapUp = (v: number) => Math.ceil(v / GRID) * GRID;\nconst snapTo = (v: number) => Math.round(v / GRID) * GRID;\n\n/** Reading order of a block diagram: what feeds the processor left of it (−1), what it drives right (+1). */\nfunction flowSide(category?: string): number {\n const g = functionGroup(category);\n return g === \"power\" || g === \"io\" ? -1 : g === \"sensor\" || g === \"output\" ? 1 : 0;\n}\n\ninterface Edge {\n a: number;\n b: number;\n w: number;\n}\n\n/**\n * Top-left positions by id for a level of modules. `edges` are the lines\n * between cards (one entry per line; several between two cards weigh more,\n * though less than that many).\n */\nexport function gridLayout(nodes: GridNode[], edges: [string, string][], opts: GridOptions = {}): Record<string, { x: number; y: number }> {\n // cards linked to nothing (a consumable, an adhesive pad, a seal) go in rows under the block, out of the lines' way\n const linked = new Set(edges.filter(([a, b]) => a !== b).flat());\n const loose = nodes.filter((n) => !linked.has(n.id) && !opts.fixed?.[n.id]).sort((a, b) => natural(a.id, b.id));\n if (!loose.length || loose.length === nodes.length) return gridCore(nodes, edges, opts);\n const out = gridCore(\n nodes.filter((n) => !loose.includes(n)),\n edges,\n opts,\n );\n const placed = nodes.filter((n) => out[n.id]).map((n) => ({ ...out[n.id], w: n.w, h: n.h }));\n const left = Math.min(...placed.map((b) => b.x));\n const right = Math.max(...placed.map((b) => b.x + b.w));\n let y = snapUp(Math.max(...placed.map((b) => b.y + b.h)) + GRID_GAP_Y);\n // as many to a row as fit under the block (three at least)\n const gap = GRID_GAP_X / 2;\n const rows: GridNode[][] = [];\n let row: GridNode[] = [];\n let width = 0;\n for (const n of loose) {\n if (row.length >= 3 && width + gap + n.w > right - left) {\n rows.push(row);\n row = [];\n width = 0;\n }\n width += (row.length ? gap : 0) + n.w;\n row.push(n);\n }\n if (row.length) rows.push(row);\n for (const r of rows) {\n const w = r.reduce((s, n) => s + n.w, 0) + gap * (r.length - 1);\n let x = snapTo(left + (right - left - w) / 2);\n for (const n of r) {\n out[n.id] = { x, y };\n x = snapUp(x + n.w + gap);\n }\n y = snapUp(y + Math.max(...r.map((n) => n.h)) + GRID_GAP_Y / 2);\n }\n return out;\n}\n\nfunction gridCore(nodes: GridNode[], edges: [string, string][], opts: GridOptions = {}): Record<string, { x: number; y: number }> {\n const out: Record<string, { x: number; y: number }> = {};\n if (!nodes.length) return out;\n const list = nodes.slice().sort((a, b) => natural(a.id, b.id));\n const index = new Map(list.map((n, i) => [n.id, i]));\n const n = list.length;\n const fixed = opts.fixed ?? {};\n\n // links between two cards, weighted 1 + ln(count)\n const pairCount = new Map<string, number>();\n for (const [a, b] of edges) {\n const i = index.get(a);\n const j = index.get(b);\n if (i === undefined || j === undefined || i === j) continue;\n const key = i < j ? `${i},${j}` : `${j},${i}`;\n pairCount.set(key, (pairCount.get(key) ?? 0) + 1);\n }\n const E: Edge[] = [...pairCount]\n .sort((x, y) => natural(x[0], y[0]))\n .map(([k, c]) => {\n const [a, b] = k.split(\",\").map(Number);\n return { a, b, w: 1 + Math.log(c) };\n });\n const incident: number[][] = list.map(() => []);\n E.forEach((e, k) => {\n incident[e.a].push(k);\n incident[e.b].push(k);\n });\n const degree = list.map((_, i) => incident[i].reduce((s, k) => s + E[k].w, 0));\n\n // the grid: about as many columns as a screen's shape holds for these cards\n const avgW = list.reduce((s, x) => s + x.w, 0) / n + GRID_GAP_X;\n const avgH = list.reduce((s, x) => s + x.h, 0) / n + GRID_GAP_Y;\n const aspect = opts.aspect ?? 1.6;\n let cols = Math.max(1, Math.min(n, Math.round(Math.sqrt((n * aspect * avgH) / avgW))));\n // two or three cards sit side by side\n if (n <= 3) cols = n;\n let rows = Math.ceil(n / cols);\n // a little room to move: one spare cell at least, beyond a handful of cards\n if (n > 4 && cols * rows === n) cols++;\n rows = Math.ceil(n / cols);\n const cells = cols * rows;\n const cW = avgW;\n const cH = avgH;\n\n const cellOf = new Int32Array(n).fill(-1);\n const at = new Int32Array(cells).fill(-1);\n const put = (i: number, c: number) => {\n cellOf[i] = c;\n at[c] = i;\n };\n const cx = (c: number) => c % cols;\n const cy = (c: number) => Math.floor(c / cols);\n\n // ---- cost ----\n const mcu = list.map((x) => functionGroup(x.category) === \"mcu\");\n const side = list.map((x) => flowSide(x.category));\n const edgeCost = (e: Edge): number => {\n const ca = cellOf[e.a];\n const cb = cellOf[e.b];\n if (ca < 0 || cb < 0) return 0;\n const dx = Math.abs(cx(ca) - cx(cb));\n const dy = Math.abs(cy(ca) - cy(cb));\n let c = e.w * (dx * cW + dy * cH);\n // a line that must bend (neither in a row nor a column)\n if (dx && dy) c += e.w * 0.35 * Math.min(dx * cW, dy * cH);\n // cards in the way of a straight line\n if (!dx || !dy) {\n const steps = Math.max(dx, dy);\n const sx = Math.sign(cx(cb) - cx(ca));\n const sy = Math.sign(cy(cb) - cy(ca));\n for (let k = 1; k < steps; k++) if (at[(cy(ca) + sy * k) * cols + cx(ca) + sx * k] >= 0) c += e.w * cW;\n }\n // reading order around a processor\n for (const [m, o] of [[e.a, e.b], [e.b, e.a]] as const) {\n if (!mcu[m] || !side[o]) continue;\n const d = cx(cellOf[o]) - cx(cellOf[m]);\n if (Math.sign(d) !== side[o]) c += e.w * 0.3 * cW;\n }\n return c;\n };\n // straight centre-to-centre lines of two links cross (links that share a card never count)\n const crosses = (e: Edge, f: Edge): boolean => {\n if (e.a === f.a || e.a === f.b || e.b === f.a || e.b === f.b) return false;\n const p = [cellOf[e.a], cellOf[e.b], cellOf[f.a], cellOf[f.b]];\n if (p.some((c) => c < 0)) return false;\n const P = p.map((c) => [cx(c) * cW, cy(c) * cH]);\n const d = (o: number[], q: number[], r: number[]) => (q[0] - o[0]) * (r[1] - o[1]) - (q[1] - o[1]) * (r[0] - o[0]);\n const d1 = d(P[2], P[3], P[0]);\n const d2 = d(P[2], P[3], P[1]);\n const d3 = d(P[0], P[1], P[2]);\n const d4 = d(P[0], P[1], P[3]);\n return ((d1 > 0 && d2 < 0) || (d1 < 0 && d2 > 0)) && ((d3 > 0 && d4 < 0) || (d3 < 0 && d4 > 0));\n };\n const CROSS = 0.9 * cW;\n /** The part of the cost that changes when the cards in `moved` (and the cells `cellsTouched`) change. */\n const localCost = (moved: number[], cellsTouched: number[]): number => {\n const mine = new Set<number>();\n for (const i of moved) if (i >= 0) for (const k of incident[i]) mine.add(k);\n let c = 0;\n for (const k of mine) c += edgeCost(E[k]);\n for (const k of mine)\n for (let f = 0; f < E.length; f++) {\n if (f === k || (mine.has(f) && f < k)) continue;\n if (crosses(E[k], E[f])) c += CROSS * Math.min(E[k].w, E[f].w);\n }\n // other links whose straight line passes the touched cells\n for (let f = 0; f < E.length; f++) {\n if (mine.has(f)) continue;\n const e = E[f];\n const ca = cellOf[e.a];\n const cb = cellOf[e.b];\n if (ca < 0 || cb < 0) continue;\n if (cx(ca) !== cx(cb) && cy(ca) !== cy(cb)) continue;\n for (const t of cellsTouched) {\n const tx = cx(t);\n const ty = cy(t);\n const between =\n (cy(ca) === cy(cb) && ty === cy(ca) && tx > Math.min(cx(ca), cx(cb)) && tx < Math.max(cx(ca), cx(cb))) ||\n (cx(ca) === cx(cb) && tx === cx(ca) && ty > Math.min(cy(ca), cy(cb)) && ty < Math.max(cy(ca), cy(cb)));\n if (between && at[t] >= 0) c += e.w * cW;\n }\n }\n // a card joined to nothing stays near the middle rather than at a far corner\n for (const i of moved) if (i >= 0 && !incident[i].length) c += 0.05 * (Math.abs(cx(cellOf[i]) - (cols - 1) / 2) * cW + Math.abs(cy(cellOf[i]) - (rows - 1) / 2) * cH);\n return c;\n };\n\n // ---- fixed cards: the cell nearest where they are, on a grid anchored on the first of them ----\n const fixedIds = Object.keys(fixed).filter((id) => index.has(id)).sort(natural);\n const locked = new Uint8Array(n);\n const order = list.map((_, i) => i).sort((a, b) => degree[b] - degree[a] || Number(mcu[b]) - Number(mcu[a]) || natural(list[a].id, list[b].id));\n if (fixedIds.length) {\n const centre = (id: string) => ({ x: fixed[id].x + list[index.get(id)!].w / 2, y: fixed[id].y + list[index.get(id)!].h / 2 });\n const a = centre(fixedIds[0]);\n const startX = Math.floor((cols - 1) / 2);\n const startY = Math.floor((rows - 1) / 2);\n for (const id of fixedIds) {\n const p = centre(id);\n const gx = Math.max(0, Math.min(cols - 1, startX + Math.round((p.x - a.x) / cW)));\n const gy = Math.max(0, Math.min(rows - 1, startY + Math.round((p.y - a.y) / cH)));\n // the nearest free cell to that\n let best = -1;\n let bd = Infinity;\n for (let c = 0; c < cells; c++) {\n if (at[c] >= 0) continue;\n const d = Math.abs(cx(c) - gx) + Math.abs(cy(c) - gy);\n if (d < bd) [best, bd] = [c, d];\n }\n if (best >= 0) {\n put(index.get(id)!, best);\n locked[index.get(id)!] = 1;\n }\n }\n }\n\n // ---- the starting arrangement ----\n const free = () => [...Array(cells).keys()].filter((c) => at[c] < 0);\n if (opts.seed && list.some((x) => opts.seed![x.id])) {\n // rows by height, then columns by x, as they were\n const seeded = order.filter((i) => cellOf[i] < 0).sort((a, b) => (opts.seed![list[a].id]?.y ?? Infinity) - (opts.seed![list[b].id]?.y ?? Infinity) || natural(list[a].id, list[b].id));\n const slots = free();\n const byRow = new Map<number, number[]>();\n for (const c of slots) byRow.set(cy(c), [...(byRow.get(cy(c)) ?? []), c]);\n let k = 0;\n for (const r of [...byRow.keys()].sort((a, b) => a - b)) {\n const row = byRow.get(r)!;\n const take = seeded.slice(k, k + row.length).sort((a, b) => (opts.seed![list[a].id]?.x ?? Infinity) - (opts.seed![list[b].id]?.x ?? Infinity) || natural(list[a].id, list[b].id));\n take.forEach((i, j) => put(i, row[j]));\n k += take.length;\n }\n } else {\n // the hub in the middle, then each card at the best free cell, strongest joined first\n const placed = new Set<number>(order.filter((i) => cellOf[i] >= 0));\n const weightTo = (i: number) => incident[i].reduce((s, k) => s + (placed.has(E[k].a === i ? E[k].b : E[k].a) ? E[k].w : 0), 0);\n while (placed.size < n) {\n let pick = -1;\n let best = -Infinity;\n for (const i of order) {\n if (placed.has(i)) continue;\n const w = weightTo(i);\n if (w > best) [pick, best] = [i, w];\n }\n if (!placed.size || best <= 0) {\n // nothing placed it joins: the middle (the hub), or the free cell nearest the middle\n const mid = Math.floor((rows - 1) / 2) * cols + Math.floor((cols - 1) / 2);\n const c = free().sort((a, b) => Math.abs(cx(a) - cx(mid)) + Math.abs(cy(a) - cy(mid)) - (Math.abs(cx(b) - cx(mid)) + Math.abs(cy(b) - cy(mid))) || a - b)[0];\n put(pick, c);\n } else {\n let bc = -1;\n let bv = Infinity;\n for (const c of free()) {\n put(pick, c);\n const v = localCost([pick], [c]);\n at[c] = -1;\n cellOf[pick] = -1;\n if (v < bv - 1e-9) [bc, bv] = [c, v];\n }\n put(pick, bc);\n }\n placed.add(pick);\n }\n }\n\n // ---- swaps (and moves to empty cells) while they help ----\n for (let pass = 0; pass < 24; pass++) {\n let improved = false;\n for (let c1 = 0; c1 < cells; c1++)\n for (let c2 = c1 + 1; c2 < cells; c2++) {\n const i = at[c1];\n const j = at[c2];\n if (i < 0 && j < 0) continue;\n if ((i >= 0 && locked[i]) || (j >= 0 && locked[j])) continue;\n const before = localCost([i, j], [c1, c2]);\n at[c1] = j;\n at[c2] = i;\n if (i >= 0) cellOf[i] = c2;\n if (j >= 0) cellOf[j] = c1;\n const after = localCost([i, j], [c1, c2]);\n if (after < before - 1e-6) improved = true;\n else {\n at[c1] = i;\n at[c2] = j;\n if (i >= 0) cellOf[i] = c1;\n if (j >= 0) cellOf[j] = c2;\n }\n }\n if (!improved) break;\n }\n\n // ---- positions: empty rows and columns dropped, each column as wide and each row as tall as its largest card ----\n const usedCols = [...new Set([...cellOf].map(cx))].sort((a, b) => a - b);\n const usedRows = [...new Set([...cellOf].map(cy))].sort((a, b) => a - b);\n const colW = usedCols.map((c) => Math.max(...list.filter((_, i) => cx(cellOf[i]) === c).map((x) => x.w)));\n const rowH = usedRows.map((r) => Math.max(...list.filter((_, i) => cy(cellOf[i]) === r).map((x) => x.h)));\n const colX: number[] = [];\n let x = 0;\n colW.forEach((w) => {\n colX.push(x);\n x = snapUp(x + w + GRID_GAP_X);\n });\n const rowY: number[] = [];\n let y = 0;\n rowH.forEach((h) => {\n rowY.push(y);\n y = snapUp(y + h + GRID_GAP_Y);\n });\n list.forEach((node, i) => {\n const ci = usedCols.indexOf(cx(cellOf[i]));\n const ri = usedRows.indexOf(cy(cellOf[i]));\n out[node.id] = { x: snapTo(colX[ci] + (colW[ci] - node.w) / 2), y: snapTo(rowY[ri] + (rowH[ri] - node.h) / 2) };\n });\n\n // fixed cards where they were: the grid moved so the first sits there, then each where it was\n if (fixedIds.length) {\n const first = fixedIds[0];\n const dx = fixed[first].x - out[first].x;\n const dy = fixed[first].y - out[first].y;\n for (const id of Object.keys(out)) out[id] = { x: out[id].x + dx, y: out[id].y + dy };\n for (const id of fixedIds) out[id] = { ...fixed[id] };\n // a card the move put on a fixed one goes to the nearest free spot\n const settled = fixedIds.map((id) => ({ ...out[id], w: list[index.get(id)!].w, h: list[index.get(id)!].h }));\n for (const i of order) {\n const node = list[i];\n if (locked[i]) continue;\n const b = { ...out[node.id], w: node.w, h: node.h };\n if (settled.some((o) => hits(b, o, GRID_GAP_Y / 4))) {\n const spot = freeSpot([b.x + b.w / 2, b.y + b.h / 2], b.w, b.h, settled, { x: GRID_GAP_X / 2, y: GRID_GAP_Y / 2 });\n out[node.id] = spot;\n b.x = spot.x;\n b.y = spot.y;\n }\n settled.push(b);\n }\n }\n return out;\n}\n","/**\n * Layout: node boxes, port placement, and link routes for one level.\n * Layout data lives outside UHD (design D3, D6); a level can ship a hand\n * layout (from the bundle's display hints) and the user's drags override it.\n */\nimport { CARD_W, cardHeight, cardInsets, cardWidth } from \"./card-body\";\nimport type { ViewLink, ViewModel, ViewNode, ViewPort } from \"../model/types\";\nimport { route, type Pt, type Side } from \"../canvas/routing\";\nimport { GridRouter, GRID, snap } from \"./router\";\nimport { at, clearOfBends, lengths } from \"../canvas/geometry\";\nimport type { LinkLayout } from \"../api\";\nimport { boardLayout, freeSpot, hits } from \"./board-layout\";\nimport { gridLayout } from \"./module-layout\";\n\n/** Distance kept between a corner and anything placed on a link (handles, toggles). */\nexport const BEND_CLEAR = 28;\n/** How far a link keeps its label from a corner (LinkEdge: the corner radius, half a toggle, 4 px). */\nconst LABEL_CLEAR = 24;\n\nexport interface Box {\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\n/** A link's hand layout: part of the host contract (src/api.ts). */\nexport type { LinkLayout };\n\nexport interface LevelLayout {\n /** Top-level nodes: absolute. Nodes inside a container: relative to it. */\n nodes: Record<string, Partial<Box>>;\n /** Port side overrides keyed \"node|port\". */\n ports?: Record<string, Side>;\n links?: Record<string, LinkLayout>;\n}\n\nexport interface PlacedPort {\n node: string;\n port: ViewPort;\n side: Side;\n /** Absolute position on the node outline. */\n x: number;\n y: number;\n /** Colour key: the link that decides this port's classification colour. */\n links: ViewLink[];\n}\n\nexport interface PortGroup {\n protocol: string;\n domain: string;\n count: number;\n}\n\nexport interface ComputedLayout {\n boxes: Record<string, Box>;\n ports: Record<string, PlacedPort>;\n /** Unlinked ports summarised per node (design D6: \"UART ×4\"). */\n groups: Record<string, PortGroup[]>;\n routes: Record<string, Pt[]>;\n /** Label anchor per link (absent: route too short to label). */\n labels: Record<string, Pt>;\n /** Label + toggle position as an arc length along the route. */\n labelAt: Record<string, number>;\n /** Harness region span along the route (arc lengths), for links that run through one. */\n runs: Record<string, [number, number]>;\n /** Pinned waypoints per link, and the automatic ones (the router's own bends). */\n pins: Record<string, Pt[]>;\n bends: Record<string, Pt[]>;\n /** Links whose label (and expansion point) the user or the display file placed. */\n labelFixed: Record<string, boolean>;\n /** The display file's and the user's label and tab placement per link, merged. */\n edits: Record<string, LinkLayout>;\n}\n\nexport const portKey = (node: string, port: string) => `${node}|${port}`;\n\nconst PORT_PITCH = 22;\n\n/** A card's size before it is placed: as wide as the labels of its linked interfaces (`labels`) need. */\nfunction defaultSize(node: ViewNode, visiblePorts: number, labels: readonly string[] = []): { w: number; h: number } {\n if (node.sheetPort) return { w: 150, h: 30 };\n if (node.kind === \"harness\") return { w: 150, h: Math.max(30, 14 + (visiblePorts / 2) * 16) };\n // a net junction: as wide as its name, as tall as its busiest side needs (grown once ports have sides)\n if (node.kind === \"net\") return { w: Math.max(64, node.label.length * 8 + 40), h: 32 };\n if (node.shape === \"circle\") return /prop/i.test(node.label) ? { w: 60, h: 60 } : { w: 78, h: 78 };\n const perSide = Math.ceil(visiblePorts / 2);\n return { w: labels.length ? cardWidth(labels) : CARD_W, h: Math.max(84, 40 + perSide * PORT_PITCH) };\n}\n\nfunction center(b: Box): Pt {\n return [b.x + b.w / 2, b.y + b.h / 2];\n}\n\nfunction sideFacing(from: Box, to: Pt): Side {\n const [cx, cy] = center(from);\n const dx = to[0] - cx;\n const dy = to[1] - cy;\n // normalise by the box aspect so wide boxes prefer top/bottom less eagerly\n const nx = dx / (from.w / 2 + 40);\n const ny = dy / (from.h / 2 + 40);\n if (Math.abs(nx) >= Math.abs(ny)) return dx >= 0 ? \"right\" : \"left\";\n return dy >= 0 ? \"bottom\" : \"top\";\n}\n\n/** How an automatic layout starts (PB-1007): cards that keep their places, and an earlier arrangement to keep. */\nexport interface ArrangeOptions {\n /** Top-level cards that stay where they are (top-left). */\n fixed?: Record<string, { x: number; y: number }>;\n /** Each top-level card's centre in an earlier layout: the arrangement to start from. */\n seed?: Record<string, { x: number; y: number }>;\n /** The old default (one row), for comparing against. */\n legacy?: boolean;\n}\n\n/**\n * Auto layout for levels without a hand layout: modules in a grid shaped like\n * a screen, each beside what it connects to (module-layout.ts), and each sheet\n * port (the drilled-into module's boundary) on the canvas edge nearest the\n * child it exposes, stacked beside it. A level with nets is laid out as a\n * board (board-layout.ts).\n */\nfunction autoPositions(vm: ViewModel, sizes: Record<string, { w: number; h: number }>, opts: ArrangeOptions = {}): Record<string, Box> {\n const top = vm.nodes.filter((n) => !n.parent && !n.sheetPort);\n const sheets = vm.nodes.filter((n) => n.sheetPort);\n if (top.some((n) => n.kind === \"net\")) {\n const boxes = netPositions(vm, top, sheets, sizes);\n for (const [id, p] of Object.entries(opts.fixed ?? {})) if (boxes[id]) Object.assign(boxes[id], p);\n return boxes;\n }\n if (opts.legacy) return rowPositions(vm, sizes);\n const ids = new Set(top.map((n) => n.id));\n const topOf = (id: string) => (ids.has(id) ? id : [...ids].find((t) => id.startsWith(`${t}/`)));\n const edges: [string, string][] = [];\n for (const l of vm.links) {\n if (l.passThrough || l.ground) continue;\n const a = topOf(l.source.node);\n const b = topOf(l.target.node);\n if (a && b && a !== b) edges.push([a, b]);\n }\n // a block with no category (a concept's placeholder) gets the role its links give it: one that mostly\n // supplies power feeds from the left, and the busiest block is the hub, so the reading order still holds\n const lines = vm.links.filter((l) => !l.passThrough && !l.ground);\n const busiest = top\n .map((n) => ({ id: n.id, k: lines.filter((l) => topOf(l.source.node) === n.id || topOf(l.target.node) === n.id).length }))\n .sort((a, b) => b.k - a.k || a.id.localeCompare(b.id))[0]?.id;\n const hasHub = top.some((n) => /^(microcontroller|processor|compute|fpga|soc)\\b/.test(n.category ?? \"\"));\n const roleOf = (n: ViewNode): string | undefined => {\n if (n.category) return n.category;\n if (!hasHub && n.id === busiest) return \"microcontroller\";\n const mine = lines.filter((l) => topOf(l.source.node) === n.id || topOf(l.target.node) === n.id);\n return mine.length && mine.filter((l) => l.domain === \"power\" || /power/i.test(l.protocol)).length * 2 > mine.length ? \"power\" : undefined;\n };\n const at = gridLayout(\n top.map((n) => ({ id: n.id, ...sizes[n.id], category: roleOf(n) })),\n edges,\n { fixed: opts.fixed, seed: opts.seed },\n );\n const x0 = sheets.length ? 400 : 60;\n const y0 = 100;\n const boxes: Record<string, Box> = {};\n const fixed = opts.fixed ?? {};\n for (const n of top) boxes[n.id] = fixed[n.id] ? { ...fixed[n.id], ...sizes[n.id] } : { x: at[n.id].x + (Object.keys(fixed).length ? 0 : x0), y: at[n.id].y + (Object.keys(fixed).length ? 0 : y0), ...sizes[n.id] };\n placeSheets(boxes, sheets, sizes, y0);\n return boxes;\n}\n\n/** The layout before PB-1007: modules in one centred row (kept to measure against). */\nfunction rowPositions(vm: ViewModel, sizes: Record<string, { w: number; h: number }>): Record<string, Box> {\n const boxes: Record<string, Box> = {};\n const top = vm.nodes.filter((n) => !n.parent && !n.sheetPort);\n const sheets = vm.nodes.filter((n) => n.sheetPort);\n const gapX = 300;\n const rowY = 140;\n let x = sheets.length ? 460 : 60;\n for (const n of top) {\n const s = sizes[n.id];\n boxes[n.id] = { x, y: rowY, ...s };\n x += s.w + gapX;\n }\n const rowRight = x - gapX;\n const mid = (sheets.length ? 460 : 60) + (rowRight - (sheets.length ? 460 : 60)) / 2;\n const columns: Record<\"left\" | \"right\", ViewNode[]> = { left: [], right: [] };\n for (const sheet of sheets) {\n const child = sheet.ports[0]?.exported?.child;\n const b = child ? boxes[child] : undefined;\n columns[b && b.x + b.w / 2 > mid ? \"right\" : \"left\"].push(sheet);\n }\n const rowH = Math.max(...top.map((n) => sizes[n.id].h), 100);\n for (const side of [\"left\", \"right\"] as const) {\n const col = columns[side];\n const pitch = 54;\n const y0 = rowY + rowH / 2 - ((col.length - 1) * pitch) / 2;\n col.forEach((n, i) => {\n const s = sizes[n.id];\n boxes[n.id] = { x: side === \"left\" ? 60 : rowRight + 180, y: y0 + i * pitch, ...s };\n });\n }\n return boxes;\n}\n\n/**\n * A level with nets (a board): components grouped by function and junctions\n * beside what they join (board-layout.ts), and each sheet port on the left\n * or right edge level with the child it exposes.\n */\nfunction netPositions(vm: ViewModel, top: ViewNode[], sheets: ViewNode[], sizes: Record<string, { w: number; h: number }>): Record<string, Box> {\n const ids = new Set(top.map((n) => n.id));\n const edges = vm.links\n .filter((l) => !l.passThrough && !l.ground && ids.has(l.source.node) && ids.has(l.target.node))\n .map((l) => [l.source.node, l.target.node] as [string, string]);\n const degree = new Map<string, number>();\n for (const [a, b] of edges) for (const id of [a, b]) degree.set(id, (degree.get(id) ?? 0) + 1);\n // a junction grows to fit its ports once they have sides: lay it out at the size it will likely have\n const planned = (n: ViewNode) => (n.kind === \"net\" ? { w: sizes[n.id].w, h: Math.max(sizes[n.id].h, (Math.ceil((degree.get(n.id) ?? 0) / 2) + 1) * GRID) } : sizes[n.id]);\n const grows = (n: ViewNode) => n.kind !== \"net\" && n.shape !== \"circle\";\n const isNet = new Set(top.filter((n) => n.kind === \"net\").map((n) => n.id));\n const otherPorts = (id: string) =>\n new Set(\n vm.links\n .filter((l) => !l.ground && (l.source.node === id || l.target.node === id) && !isNet.has(l.source.node) && !isNet.has(l.target.node))\n .map((l) => (l.source.node === id ? l.source.port : l.target.port)),\n ).size;\n const at = boardLayout(\n top.map((n) => ({\n id: n.id,\n ...planned(n),\n net: n.kind === \"net\",\n ...(n.tapOf ? { tapOf: n.tapOf } : {}),\n category: n.category,\n label: n.label,\n ...(grows(n) ? { heightFor: (k: number) => Math.ceil((44 + k * PORT_PITCH) / GRID) * GRID, otherPorts: otherPorts(n.id) } : {}),\n })),\n edges,\n );\n const x0 = sheets.length ? 400 : 60;\n const y0 = 100;\n const boxes: Record<string, Box> = {};\n for (const n of top) boxes[n.id] = { x: at[n.id].x + x0, y: at[n.id].y + y0, ...sizes[n.id] };\n placeSheets(boxes, sheets, sizes, y0);\n return boxes;\n}\n\n/** Sheet ports (the drilled-into module's boundary) in a column on the left or right edge, level with the child each exposes. */\nfunction placeSheets(boxes: Record<string, Box>, sheets: ViewNode[], sizes: Record<string, { w: number; h: number }>, y0: number) {\n const placed = Object.values(boxes);\n if (!sheets.length || !placed.length) return;\n const minX = Math.min(...placed.map((b) => b.x));\n const maxX = Math.max(...placed.map((b) => b.x + b.w));\n const mid = (minX + maxX) / 2;\n const columns: Record<\"left\" | \"right\", { node: ViewNode; y: number }[]> = { left: [], right: [] };\n for (const sheet of sheets) {\n const b = boxes[sheet.ports[0]?.exported?.child ?? \"\"];\n const side = b && b.x + b.w / 2 > mid ? \"right\" : \"left\";\n columns[side].push({ node: sheet, y: b ? b.y + b.h / 2 - sizes[sheet.id].h / 2 : y0 });\n }\n for (const side of [\"left\", \"right\"] as const) {\n let last = -Infinity;\n for (const { node, y } of columns[side].sort((a, b) => a.y - b.y)) {\n const s = sizes[node.id];\n const top = Math.max(y, last + 54);\n boxes[node.id] = { x: side === \"left\" ? minX - 340 : maxX + 180, y: top, ...s };\n last = top;\n }\n }\n}\n\n/**\n * Positions for the nodes a hand layout does not name (a part added since\n * the layout was saved, or the junctions of a layout that placed only the\n * components): each at the free spot nearest the nodes it is linked to,\n * sheet ports on the edges. Top-level nodes only; absolute.\n */\nfunction fillMissing(vm: ViewModel, hand: LevelLayout, sizes: Record<string, { w: number; h: number }>): Record<string, Box> {\n const top = vm.nodes.filter((n) => !n.parent);\n const missing = top.filter((n) => !hand.nodes[n.id] || hand.nodes[n.id].x === undefined || hand.nodes[n.id].y === undefined);\n if (!missing.length) return {};\n const boxes: Record<string, Box> = {};\n for (const n of top) if (!missing.includes(n)) boxes[n.id] = { x: hand.nodes[n.id].x!, y: hand.nodes[n.id].y!, ...sizes[n.id] };\n const known = Object.values(boxes);\n const right = known.length ? Math.max(...known.map((b) => b.x + b.w)) : 60;\n const bottom = known.length ? Math.max(...known.map((b) => b.y + b.h)) : 60;\n const neighbours = (id: string) =>\n vm.links\n .filter((l) => !l.passThrough && !l.ground && (l.source.node === id || l.target.node === id))\n .map((l) => (l.source.node === id ? l.target.node : l.source.node))\n .map((o) => o.split(\"/\")[0])\n .filter((o) => boxes[o]);\n const out: Record<string, Box> = {};\n // most-connected first, so a junction lands among its members before a lone part takes the spot\n const order = missing.filter((n) => !n.sheetPort).sort((a, b) => neighbours(b.id).length - neighbours(a.id).length || a.id.localeCompare(b.id));\n for (const n of order) {\n const ns = neighbours(n.id);\n const s = sizes[n.id];\n const ideal: [number, number] = ns.length\n ? [ns.reduce((t, o) => t + boxes[o].x + boxes[o].w / 2, 0) / ns.length, ns.reduce((t, o) => t + boxes[o].y + boxes[o].h / 2, 0) / ns.length]\n : [right + 120 + s.w / 2, bottom + 80];\n const at = freeSpot(ideal, s.w, s.h, Object.values(boxes), { x: 40, y: 24 });\n boxes[n.id] = out[n.id] = { ...at, ...s };\n }\n const sheets = missing.filter((n) => n.sheetPort);\n if (sheets.length) {\n const withSheets: Record<string, Box> = { ...boxes };\n placeSheets(withSheets, sheets, sizes, 100);\n for (const n of sheets) out[n.id] = withSheets[n.id];\n }\n return out;\n}\n\n/** Room kept inside a container expanded in place: left and right of its modules, under its label, and below them (where its links run). */\nconst CONTAINER_PAD = { left: 48, top: 64, right: 48, bottom: 48 };\n\n/**\n * A module expanded in place whose children the display file does not place\n * (PB-897): the children are laid out as their own level would be (a row, or\n * a board's clusters and junctions), inside the container, and the container\n * takes the size that holds them with room for their links. Deepest\n * containers first, so one that holds another is laid out around its size.\n * Returns the children's positions relative to their container; `sizes` gets\n * the containers' sizes. A container the display file sizes, or whose\n * children it places, is left as it says.\n */\nfunction containerLayouts(vm: ViewModel, hand: LevelLayout | undefined, sizes: Record<string, { w: number; h: number }>, arrange: ArrangeOptions = {}): Record<string, { x: number; y: number }> {\n const rel: Record<string, { x: number; y: number }> = {};\n const depth = (id: string) => {\n let d = 0;\n for (let n = vm.nodes.find((x) => x.id === id); n?.parent; n = vm.nodes.find((x) => x.id === n!.parent)) d++;\n return d;\n };\n const containers = vm.nodes.filter((n) => n.expanded).sort((a, b) => depth(b.id) - depth(a.id));\n for (const c of containers) {\n const kids = vm.nodes.filter((n) => n.parent === c.id);\n if (!kids.length) continue;\n const placed = (n: ViewNode) => hand?.nodes[n.id]?.x !== undefined && hand?.nodes[n.id]?.y !== undefined;\n const missing = kids.filter((n) => !placed(n));\n if (!missing.length) continue;\n const ids = new Set(kids.map((k) => k.id));\n if (missing.length === kids.length) {\n // none placed: the level's own automatic layout, moved into the container\n const sub: ViewModel = { ...vm, nodes: kids.map((k) => ({ ...k, parent: undefined })), links: vm.links.filter((l) => ids.has(l.source.node) && ids.has(l.target.node)) };\n const at = autoPositions(sub, sizes, { legacy: arrange.legacy });\n const minX = Math.min(...kids.map((k) => at[k.id].x));\n const minY = Math.min(...kids.map((k) => at[k.id].y));\n for (const k of kids) rel[k.id] = { x: snap(at[k.id].x - minX + CONTAINER_PAD.left), y: snap(at[k.id].y - minY + CONTAINER_PAD.top) };\n } else {\n // some placed (a part added since the layout was saved): the others at the free spot nearest what they are linked to\n const boxes: Record<string, Box> = {};\n for (const k of kids) if (placed(k)) boxes[k.id] = { x: hand!.nodes[k.id].x!, y: hand!.nodes[k.id].y!, ...sizes[k.id] };\n const neighbours = (id: string) =>\n vm.links\n .filter((l) => !l.ground && (l.source.node === id || l.target.node === id))\n .map((l) => (l.source.node === id ? l.target.node : l.source.node))\n .filter((o) => boxes[o]);\n for (const k of missing.sort((a, b) => neighbours(b.id).length - neighbours(a.id).length || a.id.localeCompare(b.id))) {\n const ns = neighbours(k.id);\n const known = Object.values(boxes);\n const s = sizes[k.id];\n const ideal: [number, number] = ns.length\n ? [ns.reduce((t, o) => t + boxes[o].x + boxes[o].w / 2, 0) / ns.length, ns.reduce((t, o) => t + boxes[o].y + boxes[o].h / 2, 0) / ns.length]\n : [Math.max(...known.map((b) => b.x + b.w)) + 80 + s.w / 2, CONTAINER_PAD.top + s.h / 2];\n const spot = freeSpot(ideal, s.w, s.h, known, { x: 40, y: 24 });\n // never left of, or above, the container's own padding\n const at = { x: Math.max(CONTAINER_PAD.left, spot.x), y: Math.max(CONTAINER_PAD.top, spot.y) };\n boxes[k.id] = { ...at, ...s };\n rel[k.id] = { x: snap(at.x), y: snap(at.y) };\n }\n }\n if (hand?.nodes[c.id]?.w) continue;\n const right = Math.max(...kids.map((k) => (rel[k.id]?.x ?? hand?.nodes[k.id]?.x ?? 0) + sizes[k.id].w));\n const bottom = Math.max(...kids.map((k) => (rel[k.id]?.y ?? hand?.nodes[k.id]?.y ?? 0) + sizes[k.id].h));\n const up = (v: number) => Math.ceil(v / GRID) * GRID;\n sizes[c.id] = { w: up(Math.max(sizes[c.id].w, right + CONTAINER_PAD.right)), h: up(Math.max(sizes[c.id].h, bottom + CONTAINER_PAD.bottom)) };\n }\n return rel;\n}\n\n/** The container (a module expanded in place) that holds both ends of a link, if one does: the innermost. */\nfunction sharedContainer(vm: ViewModel, byId: Map<string, ViewNode>, a: string, b: string): ViewNode | undefined {\n const chain = (id: string) => {\n const out: string[] = [];\n const self = byId.get(id);\n // a container's own boundary port is on its outline: the line from it inward is inside it\n if (self?.expanded) out.push(id);\n for (let p = self?.parent; p; p = byId.get(p)?.parent) out.push(p);\n return out;\n };\n const inB = new Set(chain(b));\n const id = chain(a).find((x) => inB.has(x));\n return id ? byId.get(id) : undefined;\n}\n\n/** Nearest free grid position between lo and hi (exclusive) on one side of a card. */\nfunction gridSlot(v: number, lo: number, hi: number, used: Map<string, Set<number>>, key: string): number {\n const taken = used.get(key) ?? new Set<number>();\n used.set(key, taken);\n const base = snap(v);\n for (let k = 0; k < 64; k++) {\n for (const c of k === 0 ? [base] : [base + k * GRID, base - k * GRID]) {\n if (c > lo && c < hi && !taken.has(c)) {\n taken.add(c);\n return c;\n }\n }\n }\n return v;\n}\n\n/**\n * A drag in progress: only the links touching what moves are rerouted, around\n * the routes the other links already have; everything is rerouted once the\n * drag ends. Keeps dragging a module or a waypoint at frame rate.\n */\nexport interface LiveLayout {\n previous: ComputedLayout;\n /** Nodes being dragged (their children move with them). */\n nodes?: Set<string>;\n /** Links whose waypoints are being dragged. */\n links?: Set<string>;\n}\n\nfunction linkedPortsOf(vm: ViewModel): Map<string, ViewLink[]> {\n const linkedPorts = new Map<string, ViewLink[]>();\n for (const link of vm.links) {\n for (const end of [link.source, link.target]) {\n const key = portKey(end.node, end.port);\n linkedPorts.set(key, [...(linkedPorts.get(key) ?? []), link]);\n }\n }\n return linkedPorts;\n}\n\n/** Each card's size before it is placed (a hand size wins), and the cards that grew wider than plain for their labels. */\nfunction baseSizes(vm: ViewModel, hand: LevelLayout | undefined, linkedPorts = linkedPortsOf(vm)) {\n const sizes: Record<string, { w: number; h: number }> = {};\n const up = (v: number) => Math.ceil(v / GRID) * GRID;\n /** Cards that grew wider than the plain card for their labels, with the plain width. */\n const grown = new Map<string, number>();\n for (const node of vm.nodes) {\n const linked = node.ports.filter((p) => linkedPorts.has(portKey(node.id, p.id)));\n const hand0 = hand?.nodes[node.id];\n // a card is as wide as the labels of its linked interfaces need, up to a limit (card-body.ts)\n const d = defaultSize(node, linked.length, linked.map((p) => p.name));\n const plain = defaultSize(node, linked.length);\n sizes[node.id] = { w: up(hand0?.w ?? d.w), h: up(hand0?.h ?? d.h) };\n if (!hand0?.w && sizes[node.id].w > up(plain.w)) grown.set(node.id, up(plain.w));\n }\n return { sizes, grown };\n}\n\n/**\n * The automatic layout of a level as a hand layout (PB-1007, for a host that\n * writes it to the display file): top-level nodes absolute, nodes inside an\n * expanded module relative to it. `fixed` cards keep their places; a `seed`\n * keeps an earlier arrangement where it can.\n */\nexport function arrangeLevel(vm: ViewModel, opts: ArrangeOptions = {}, keepSizes?: LevelLayout): LevelLayout {\n // sizes set by hand (`keepSizes`) are kept; the places are all new\n const sized: LevelLayout | undefined = keepSizes && {\n nodes: Object.fromEntries(Object.entries(keepSizes.nodes).flatMap(([id, n]) => (n.w !== undefined || n.h !== undefined ? [[id, { ...(n.w !== undefined ? { w: n.w } : {}), ...(n.h !== undefined ? { h: n.h } : {}) }]] : []))),\n };\n const { sizes } = baseSizes(vm, sized);\n const inner = containerLayouts(vm, sized, sizes, opts);\n const boxes = autoPositions(vm, sizes, opts);\n const nodes: LevelLayout[\"nodes\"] = {};\n for (const n of vm.nodes) {\n if (n.tapOf) continue;\n const p = n.parent ? inner[n.id] : boxes[n.id];\n if (p) nodes[n.id] = { x: snap(p.x), y: snap(p.y) };\n }\n return { nodes };\n}\n\nexport function computeLayout(\n vm: ViewModel,\n hand: LevelLayout | undefined,\n overrides: Record<string, { x: number; y: number }>,\n showGrounds: boolean,\n linkOverrides?: Record<string, LinkLayout>,\n live?: LiveLayout,\n arrange?: ArrangeOptions,\n): ComputedLayout {\n const linkedPorts = linkedPortsOf(vm);\n const up = (v: number) => Math.ceil(v / GRID) * GRID;\n const { sizes, grown } = baseSizes(vm, hand, linkedPorts);\n // a level the display file lays out placed its cards for the plain width: there a card grows only\n // into the room its neighbours on the right leave (three grid steps stay clear for the lines between them)\n if (hand) {\n for (const [id, plain] of grown) {\n const at = hand.nodes[id];\n const node = vm.nodes.find((n) => n.id === id)!;\n if (at?.x === undefined || at.y === undefined) continue;\n let room = Infinity;\n for (const other of vm.nodes) {\n const o = hand.nodes[other.id];\n if (other.id === id || other.parent !== node.parent || o?.x === undefined || o.y === undefined) continue;\n const oh = sizes[other.id].h;\n const apart = o.y >= at.y + sizes[id].h + GRID || o.y + oh + GRID <= at.y;\n if (!apart && o.x >= at.x + plain) room = Math.min(room, o.x - 3 * GRID - at.x);\n }\n sizes[id].w = Math.max(plain, Math.min(sizes[id].w, Math.floor(room / GRID) * GRID));\n }\n }\n\n // modules expanded in place: their children's places inside them, and the size that holds them\n const collapsed: Record<string, { w: number; h: number }> = {};\n for (const n of vm.nodes) if (n.expanded) collapsed[n.id] = { ...sizes[n.id] };\n const inner = containerLayouts(vm, hand, sizes, arrange);\n\n // positions (absolute)\n const auto = hand ? fillMissing(vm, hand, sizes) : autoPositions(vm, sizes, arrange);\n // a hand layout places the cards for their collapsed sizes: one that grew when expanded in place\n // makes room, moving the cards beside and below it by what it grew (not the ones the user dragged)\n const shift: Record<string, { x: number; y: number }> = {};\n if (hand) {\n for (const c of vm.nodes.filter((n) => n.expanded && !n.parent && !hand.nodes[n.id]?.w)) {\n const at = hand.nodes[c.id] ?? auto[c.id];\n if (at?.x === undefined || at?.y === undefined) continue;\n const was = collapsed[c.id];\n const grewX = sizes[c.id].w - was.w;\n const grewY = sizes[c.id].h - was.h;\n if (grewX <= 0 && grewY <= 0) continue;\n for (const n of vm.nodes) {\n if (n === c || n.parent || overrides[n.id]) continue;\n const p = hand.nodes[n.id] ?? auto[n.id];\n if (p?.x === undefined || p?.y === undefined) continue;\n const s = (shift[n.id] ??= { x: 0, y: 0 });\n // beside it (overlapping its rows) and to its right: pushed right; below it: pushed down\n const rows = p.y < at.y! + sizes[c.id].h && p.y + sizes[n.id].h > at.y!;\n if (grewX > 0 && rows && p.x >= at.x! + was.w) s.x += grewX;\n else if (grewY > 0 && p.y >= at.y! + was.h && p.x < at.x! + sizes[c.id].w && p.x + sizes[n.id].w > at.x!) s.y += grewY;\n }\n }\n }\n const boxes: Record<string, Box> = {};\n const place = (node: ViewNode) => {\n if (boxes[node.id]) return;\n const own = hand?.nodes[node.id];\n const size = sizes[node.id];\n let x = (own?.x ?? inner[node.id]?.x ?? auto[node.id]?.x ?? 0) + (shift[node.id]?.x ?? 0);\n let y = (own?.y ?? inner[node.id]?.y ?? auto[node.id]?.y ?? 0) + (shift[node.id]?.y ?? 0);\n if (node.parent) {\n const parent = vm.nodes.find((n) => n.id === node.parent)!;\n place(parent);\n const p = boxes[parent.id];\n x += p.x;\n y += p.y;\n }\n const o = overrides[node.id];\n if (o) {\n x = o.x;\n y = o.y;\n }\n if (node.parent) {\n // a module stays inside its container: it grows to the right and down, never to the left or above its label\n const p = boxes[node.parent];\n x = Math.max(x, p.x + GRID);\n y = Math.max(y, p.y + 2 * GRID);\n }\n boxes[node.id] = { x: snap(x), y: snap(y), ...size };\n };\n // containers without a hand size wrap their children\n for (const node of vm.nodes) place(node);\n const kidsOf = (id: string) => vm.nodes.filter((n) => n.parent === id);\n const wrapContainers = () => {\n // a size the display file gives is the least it draws at: it still holds its children (PB-1007)\n for (const node of vm.nodes.filter((n) => n.expanded)) {\n const kids = vm.nodes.filter((n) => n.parent === node.id).map((n) => boxes[n.id]);\n if (!kids.length) continue;\n const b = boxes[node.id];\n const maxX = Math.max(...kids.map((k) => k.x + k.w));\n const maxY = Math.max(...kids.map((k) => k.y + k.h));\n // a container laid out here keeps room for its links around its modules; one the display file lays out keeps its tighter wrap\n const laid = kidsOf(node.id).some((k) => inner[k.id]);\n b.w = Math.ceil(Math.max(b.w, maxX - b.x + (laid ? CONTAINER_PAD.right : 28)) / GRID) * GRID;\n b.h = Math.ceil(Math.max(b.h, maxY - b.y + (laid ? CONTAINER_PAD.bottom : 24)) / GRID) * GRID;\n }\n };\n wrapContainers();\n\n // port sides\n const ports: Record<string, PlacedPort> = {};\n const groups: Record<string, PortGroup[]> = {};\n const bySide = new Map<string, { key: string; order: number }[]>();\n\n for (const node of vm.nodes) {\n const box = boxes[node.id];\n const hidden = new Map<string, PortGroup>();\n for (const port of node.ports) {\n const key = portKey(node.id, port.id);\n const links = linkedPorts.get(key);\n if (!links) {\n const g = hidden.get(port.protocol) ?? { protocol: port.protocol, domain: port.domain, count: 0 };\n g.count++;\n hidden.set(port.protocol, g);\n continue;\n }\n // counterpart: prefer an external (non pass-through) link for boundary ports\n const external = links.find((l) => !l.passThrough) ?? links[0];\n const other = external.source.node === node.id && external.source.port === port.id ? external.target : external.source;\n const otherBox = boxes[other.node];\n const target: Pt = otherBox ? [...center(otherBox)] : [...center(box)];\n const inside = otherBox && node.expanded && other.node.startsWith(`${node.id}/`);\n if (node.parent && other.node === node.parent) {\n const parentPort = ports[portKey(other.node, other.port)];\n if (parentPort) {\n const [cx, cy] = center(box);\n const far = 400;\n const out: Record<Side, Pt> = { left: [cx - far, cy], right: [cx + far, cy], top: [cx, cy - far], bottom: [cx, cy + far] };\n target[0] = out[parentPort.side][0];\n target[1] = out[parentPort.side][1];\n }\n }\n // a line to or from a net junction leaves its card sideways, toward the junction's channel (a schematic's pins)\n const otherNode = vm.nodes.find((n) => n.id === other.node);\n const sideways = !node.parent && !node.expanded && !otherNode?.expanded && (node.kind === \"net\" || otherNode?.kind === \"net\");\n let side = hand?.ports?.[key] ?? (sideways ? (target[0] >= center(box)[0] ? \"right\" : \"left\") : sideFacing(box, target));\n if (node.sheetPort && !hand?.ports?.[key]) side = target[0] >= center(box)[0] ? \"right\" : \"left\";\n if (!hand?.ports?.[key] && inside) {\n // boundary port with only an inner counterpart: face outward on the nearest edge\n side = sideFacing(box, [target[0] + (target[0] - center(box)[0]) * 4, target[1] + (target[1] - center(box)[1]) * 4]);\n }\n ports[key] = { node: node.id, port, side, x: 0, y: 0, links };\n const sk = `${node.id}|${side}`;\n const order = side === \"left\" || side === \"right\" ? target[1] : target[0];\n bySide.set(sk, [...(bySide.get(sk) ?? []), { key, order }]);\n }\n groups[node.id] = [...hidden.values()].sort((a, b) => b.count - a.count);\n }\n\n // grow cards (without a hand-set height) so the busiest side fits its ports\n const sideCount = new Map<string, number>();\n for (const [sk, entries] of bySide) {\n const nodeId = sk.slice(0, sk.lastIndexOf(\"|\"));\n const side = sk.slice(sk.lastIndexOf(\"|\") + 1);\n if (side === \"left\" || side === \"right\") sideCount.set(nodeId, Math.max(sideCount.get(nodeId) ?? 0, entries.length));\n }\n for (const [nodeId, count] of sideCount) {\n const node = vm.nodes.find((n) => n.id === nodeId)!;\n if (hand?.nodes[nodeId]?.h || node.shape === \"circle\" || node.sheetPort || node.expanded || node.kind === \"harness\" || node.kind === \"net\") continue;\n boxes[nodeId].h = Math.ceil(Math.max(boxes[nodeId].h, 44 + count * PORT_PITCH) / GRID) * GRID;\n }\n // grow module cards (without a hand-set height) so the body (icon, title, protocol chips) clears the\n // labels of the ports on the top and bottom edges; a container then still wraps its grown children\n let grew = false;\n const labelsOf = new Map<string, { side: Side; name: string }[]>();\n for (const p of Object.values(ports)) labelsOf.set(p.node, [...(labelsOf.get(p.node) ?? []), { side: p.side, name: p.port.name }]);\n for (const node of vm.nodes) {\n if (hand?.nodes[node.id]?.h || node.shape === \"circle\" || node.sheetPort || node.expanded || node.kind === \"harness\" || node.kind === \"net\") continue;\n const b = boxes[node.id];\n const need = Math.ceil(cardHeight(node.label, b.w, groups[node.id] ?? [], cardInsets(labelsOf.get(node.id) ?? [], b.w)) / GRID) * GRID;\n if (need > b.h) {\n b.h = need;\n grew = true;\n }\n }\n if (grew) wrapContainers();\n // a junction keeps one grid step between its ports on every side\n for (const [sk, entries] of bySide) {\n const nodeId = sk.slice(0, sk.lastIndexOf(\"|\"));\n const side = sk.slice(sk.lastIndexOf(\"|\") + 1);\n const node = vm.nodes.find((n) => n.id === nodeId)!;\n if (node.kind !== \"net\" || hand?.nodes[nodeId]) continue;\n const need = (entries.length + 1) * GRID;\n if (side === \"left\" || side === \"right\") boxes[nodeId].h = Math.max(boxes[nodeId].h, need);\n else boxes[nodeId].w = Math.max(boxes[nodeId].w, need + 32);\n }\n\n // a grown junction placed automatically moves to the nearest spot where it overlaps nothing\n for (const node of vm.nodes) {\n if (node.kind !== \"net\" || node.parent || hand?.nodes[node.id]?.x !== undefined || overrides[node.id]) continue;\n const b = boxes[node.id];\n const others = vm.nodes.filter((n) => n !== node && !n.expanded && !n.parent).map((n) => boxes[n.id]);\n if (!others.some((o) => hits(b, o, 8))) continue;\n // ports get their positions below, from the box\n const at = freeSpot([b.x + b.w / 2, b.y + b.h / 2], b.w, b.h, others, { x: 24, y: 12 });\n b.x = at.x;\n b.y = at.y;\n }\n\n const counterpartOf = (key: string): Pt | undefined => {\n const p = ports[key];\n const link = p.links.find((l) => !l.passThrough) ?? p.links[0];\n const self = link.source.node === p.node && link.source.port === p.port.id;\n const other = ports[portKey(self ? link.target.node : link.source.node, self ? link.target.port : link.source.port)];\n return other ? [other.x, other.y] : undefined;\n };\n\n // distribute along each side, ordered by counterpart position; the second\n // pass re-orders by where the counterpart ports actually landed\n let used = new Map<string, Set<number>>();\n for (let pass = 0; pass < 2; pass++) {\n used = new Map();\n for (const [sk, entries] of bySide) {\n if (pass === 1) {\n for (const e of entries) {\n const c = counterpartOf(e.key);\n const side = ports[e.key].side;\n if (c) e.order = side === \"left\" || side === \"right\" ? c[1] : c[0];\n }\n }\n const [nodeId, side] = [sk.slice(0, sk.lastIndexOf(\"|\")), sk.slice(sk.lastIndexOf(\"|\") + 1) as Side];\n const box = boxes[nodeId];\n const node = vm.nodes.find((n) => n.id === nodeId)!;\n entries.sort((a, b) => a.order - b.order);\n const n = entries.length;\n entries.forEach(({ key }, i) => {\n const f = (i + 1) / (n + 1);\n const p = ports[key];\n if (node.shape === \"circle\") {\n const r = box.w / 2;\n const [cx, cy] = center(box);\n const spread = Math.min(0.9, 0.35 * n); // radians around the side's midpoint\n const base = { right: 0, bottom: Math.PI / 2, left: Math.PI, top: -Math.PI / 2 }[side];\n const angle = base + (n === 1 ? 0 : (f - 0.5) * 2 * spread);\n p.x = cx + Math.cos(angle) * r;\n p.y = cy + Math.sin(angle) * r;\n } else if (side === \"left\" || side === \"right\") {\n const harness = node.kind === \"harness\" || node.kind === \"net\";\n const inset = node.expanded ? 34 : harness ? 4 : 28;\n p.x = side === \"left\" ? box.x : box.x + box.w;\n p.y = gridSlot(box.y + inset + (box.h - inset - (harness ? 4 : 12)) * f, box.y, box.y + box.h, used, `${nodeId}|${side}`);\n } else {\n p.x = gridSlot(box.x + 16 + (box.w - 32) * f, box.x, box.x + box.w, used, `${nodeId}|${side}`);\n p.y = side === \"top\" ? box.y : box.y + box.h;\n }\n });\n }\n }\n\n // routes: the grid router, shortest links first, through any pinned waypoints\n const routes: Record<string, Pt[]> = {};\n const pins: Record<string, Pt[]> = {};\n const bends: Record<string, Pt[]> = {};\n const byId = new Map(vm.nodes.map((n) => [n.id, n]));\n /** Where a link between two modules of one container may run: inside it, under its label and off its outline. */\n const regionOf = (link: ViewLink): Box | undefined => {\n const c = sharedContainer(vm, byId, link.source.node, link.target.node);\n const b = c && boxes[c.id];\n return b ? { x: b.x + GRID, y: b.y + 2 * GRID, w: b.w - 2 * GRID, h: b.h - 3 * GRID } : undefined;\n };\n const obstacleNodes = vm.nodes.filter((n) => !n.expanded);\n const obstacles = obstacleNodes.map((n) => boxes[n.id]);\n const router = new GridRouter(obstacles, Object.values(ports).map((p) => [p.x, p.y] as Pt), 12, !live);\n const todo = vm.links\n .filter((link) => !(link.ground && !showGrounds))\n .map((link) => ({ link, a: ports[portKey(link.source.node, link.source.port)], b: ports[portKey(link.target.node, link.target.port)] }))\n .filter((x) => x.a && x.b)\n .sort((x, y) => Math.abs(x.a.x - x.b.x) + Math.abs(x.a.y - x.b.y) - (Math.abs(y.a.x - y.b.x) + Math.abs(y.a.y - y.b.y)));\n // live drag: keep the routes of links that nothing moved, and route the rest around them\n const moves = (node: string) => [...(live?.nodes ?? [])].some((m) => node === m || node.startsWith(`${m}/`));\n const affected = (link: ViewLink) =>\n !live || !live.previous.routes[link.id] || live.links?.has(link.linkId) || moves(link.source.node) || moves(link.target.node);\n for (const { link } of todo) {\n if (affected(link)) continue;\n routes[link.id] = live!.previous.routes[link.id];\n pins[link.id] = live!.previous.pins[link.id] ?? [];\n bends[link.id] = live!.previous.bends[link.id] ?? [];\n if (!link.passThrough) router.occupy(routes[link.id]);\n }\n for (const { link, a, b } of todo) {\n if (!affected(link)) continue;\n let sa = a.side;\n const fromContainer = vm.nodes.find((n) => n.id === link.source.node)?.expanded;\n if (link.passThrough && fromContainer) {\n sa = ({ left: \"right\", right: \"left\", top: \"bottom\", bottom: \"top\" } as const)[sa];\n }\n const wp = linkOverrides?.[link.id]?.waypoints ?? hand?.links?.[link.id]?.waypoints ?? [];\n pins[link.id] = wp;\n // a pass-through line (a container's boundary inward, a sheet port to its child) runs the plain way,\n // unless that would cross a card it does not end at (a sheet port's line across a board): then it\n // goes round the cards like the rest\n if (link.passThrough) {\n const plain = route([a.x, a.y], sa, [b.x, b.y], b.side, wp);\n const ends = new Set([link.source.node, link.target.node]);\n // a line from a container's boundary inward too: round the cards it does not end at, and inside the container\n routes[link.id] = !crossesCards(plain, obstacleNodes.filter((n) => !ends.has(n.id)).map((n) => boxes[n.id])) ? plain : router.route([a.x, a.y], sa, [b.x, b.y], b.side, wp, regionOf(link));\n } else routes[link.id] = router.route([a.x, a.y], sa, [b.x, b.y], b.side, wp, regionOf(link));\n const pts = routes[link.id];\n // automatic waypoints: every interior corner that is not a pin\n bends[link.id] = pts.slice(1, -1).filter((p) => !wp.some((w) => Math.abs(w[0] - p[0]) < 1 && Math.abs(w[1] - p[1]) < 1));\n }\n\n // harness regions: the middle of the route, clear of the port stubs\n const runs: Record<string, [number, number]> = {};\n for (const link of vm.links) {\n const pts = routes[link.id];\n if (!link.run || !pts) continue;\n const L = lengths(pts).at(-1)!;\n const inset = Math.min(56, L * 0.18);\n // the harness ends (connector handles) sit on straight stretches, never in a bend\n const a = clearOfBends(pts, inset, BEND_CLEAR, 12);\n const b = clearOfBends(pts, L - inset, BEND_CLEAR, 12);\n runs[link.id] = b - a >= 24 ? [a, b] : [inset, L - inset];\n }\n\n const labelAt = placeLabels(vm, routes, boxes, hand, linkOverrides, runs);\n const labels: Record<string, Pt> = Object.fromEntries(Object.entries(labelAt).map(([id, s]) => [id, at(routes[id], s).p]));\n const labelFixed = Object.fromEntries(vm.links.map((l) => [l.id, (linkOverrides?.[l.id]?.labelT ?? hand?.links?.[l.id]?.labelT) !== undefined]));\n const edits = Object.fromEntries(vm.links.map((l) => [l.id, { ...hand?.links?.[l.id], ...linkOverrides?.[l.id] }]));\n return { boxes, ports, groups, routes, labels, labelAt, runs, pins, bends, labelFixed, edits };\n}\n\n/** Whether an axis-aligned polyline runs through any of `cards` (inside them, not along an edge). */\nfunction crossesCards(pts: Pt[], cards: Box[]): boolean {\n for (let i = 1; i < pts.length; i++) {\n const [x0, x1] = [Math.min(pts[i - 1][0], pts[i][0]), Math.max(pts[i - 1][0], pts[i][0])];\n const [y0, y1] = [Math.min(pts[i - 1][1], pts[i][1]), Math.max(pts[i - 1][1], pts[i][1])];\n if (cards.some((b) => x1 > b.x + 1 && x0 < b.x + b.w - 1 && y1 > b.y + 1 && y0 < b.y + b.h - 1)) return true;\n }\n return false;\n}\n\nconst CANDIDATES = [0.5, 0.35, 0.65, 0.22, 0.78, 0.12, 0.88];\n\nfunction labelSize(link: ViewLink): { w: number; h: number } {\n return { w: link.name.length * 5.6 + (link.children.length > 1 ? 44 : 16), h: 16 };\n}\n\n/** Whether a link opens into lanes (its label carries the +/− toggle, so it is always drawn). */\nconst opens = (link: ViewLink) => (link.lanes?.length ?? 0) > 1 || link.children.length > 1;\n\n/**\n * Choose a label spot per link, as an arc length along its route. The label\n * reads along the line (design D13): above a horizontal stretch, turned\n * beside a vertical one. Candidates are spots along every straight stretch\n * long enough for the text, horizontal ones first; each is scored by what\n * the text would cover: a card or another label (never), other lines (as\n * few as possible). A label with no clear spot is left off (the line still\n * names itself in the inspector and on hover); a link that opens into lanes\n * keeps its label, as that is where its toggle is. A label made only of a\n * pin number (a resistor's \"1\") says nothing on the sheet and is left off.\n * Routes shorter than 70 px (e.g. prop-on-shaft) stay unlabelled.\n */\nfunction placeLabels(\n vm: ViewModel,\n routes: Record<string, Pt[]>,\n boxes: Record<string, Box>,\n hand: LevelLayout | undefined,\n linkOverrides: Record<string, LinkLayout> | undefined,\n runs: Record<string, [number, number]>,\n): Record<string, number> {\n const placed: Box[] = [];\n const out: Record<string, number> = {};\n const cards = [\n ...vm.nodes.filter((n) => !n.expanded).map((n) => boxes[n.id]),\n ...vm.nodes.filter((n) => n.expanded).map((n) => ({ ...boxes[n.id], h: 26 })),\n ];\n const overlaps = (a: Box, b: Box, pad = 3) =>\n a.x < b.x + b.w + pad && b.x < a.x + a.w + pad && a.y < b.y + b.h + pad && b.y < a.y + a.h + pad;\n // every drawn segment, for counting the lines a label would sit on\n const segs: { id: string; a: Pt; b: Pt }[] = [];\n for (const link of vm.links) {\n const pts = routes[link.id];\n if (pts) for (let i = 1; i < pts.length; i++) segs.push({ id: link.id, a: pts[i - 1], b: pts[i] });\n }\n const crossing = (r: Box, own: string) =>\n segs.filter(\n (s) => s.id !== own && Math.max(s.a[0], s.b[0]) > r.x && Math.min(s.a[0], s.b[0]) < r.x + r.w && Math.max(s.a[1], s.b[1]) > r.y && Math.min(s.a[1], s.b[1]) < r.y + r.h,\n ).length;\n /**\n * The text's box for a label asked for at arc length `s` along `pts`: where the link draws it (moved\n * off the bends onto a straight stretch, as LinkEdge does), above a horizontal stretch or right of a\n * vertical one. Returns the arc length it lands at too.\n */\n const rectAt = (pts: Pt[], s0: number, w: number): { rect: Box; vertical: boolean; s: number } => {\n const s = clearOfBends(pts, s0, LABEL_CLEAR, 12);\n const { p, d } = at(pts, s);\n const vertical = Math.abs(d[1]) > Math.abs(d[0]);\n // the drawn tab: text plus its padding and border, a few px off the line\n return vertical ? { rect: { x: p[0] + 2, y: p[1] - w / 2, w: 22, h: w }, vertical, s } : { rect: { x: p[0] - w / 2, y: p[1] - 22, w, h: 20 }, vertical, s };\n };\n\n const ordered = [...vm.links].sort((a, b) => Number(opens(b)) - Number(opens(a)) || b.children.length - a.children.length || a.id.localeCompare(b.id));\n for (const link of ordered) {\n const pts = routes[link.id];\n if (!pts || link.passThrough || link.segment === \"b\") continue;\n const L = pathLength(pts);\n if (L < 70) continue;\n const fixed = linkOverrides?.[link.id]?.labelT ?? hand?.links?.[link.id]?.labelT;\n const keep = opens(link);\n if (fixed === undefined && !keep && /^\\d+$/.test(link.name.trim())) continue;\n const size = labelSize(link);\n const [lo, hi] = runs[link.id] ?? [0, L];\n const within = (t: number) => (lo + (hi - lo) * t) / L;\n // fractions of the route: the given one, or the classic spots plus the middle of every straight stretch the text fits on\n const tries: number[] = [];\n if (fixed !== undefined) tries.push(fixed);\n else {\n let walked = 0;\n const stretches: { mid: number; len: number }[] = [];\n for (let i = 1; i < pts.length; i++) {\n const len = Math.hypot(pts[i][0] - pts[i - 1][0], pts[i][1] - pts[i - 1][1]);\n if (len >= size.w + 2 * BEND_CLEAR) stretches.push({ mid: walked + len / 2, len });\n walked += len;\n }\n stretches.sort((a, b) => b.len - a.len);\n for (const st of stretches) for (const f of [0, -0.25, 0.25]) tries.push((st.mid + f * (st.len - size.w - 2 * BEND_CLEAR)) / L);\n tries.push(longestMid(pts), ...CANDIDATES.map(within));\n }\n let best: { at: number; score: number; rect: Box } | undefined;\n for (const t of tries) {\n const { rect, vertical, s } = rectAt(pts, t * L, size.w);\n const hard = cards.filter((b) => overlaps(rect, b, 0)).length + placed.filter((b) => overlaps(rect, b)).length;\n const score = hard * 100 + crossing(rect, link.id) * 2 + (vertical ? 1 : 0);\n if (!best || score < best.score) best = { at: fixed !== undefined ? t * L : s, score, rect };\n if (score === 0) break;\n }\n if (!best || (best.score >= 100 && fixed === undefined && !keep)) continue;\n out[link.id] = best.at;\n placed.push(best.rect);\n }\n return out;\n}\n\nfunction pathLength(pts: Pt[]): number {\n let n = 0;\n for (let i = 1; i < pts.length; i++) n += Math.hypot(pts[i][0] - pts[i - 1][0], pts[i][1] - pts[i - 1][1]);\n return n;\n}\n\nfunction pointAlong(pts: Pt[], t: number): Pt {\n const target = pathLength(pts) * t;\n let walked = 0;\n for (let i = 1; i < pts.length; i++) {\n const seg = Math.hypot(pts[i][0] - pts[i - 1][0], pts[i][1] - pts[i - 1][1]);\n if (walked + seg >= target && seg > 0) {\n const f = (target - walked) / seg;\n return [pts[i - 1][0] + (pts[i][0] - pts[i - 1][0]) * f, pts[i - 1][1] + (pts[i][1] - pts[i - 1][1]) * f];\n }\n walked += seg;\n }\n return pts[pts.length - 1];\n}\n\nfunction longestMid(pts: Pt[]): number {\n const total = pathLength(pts) || 1;\n let best = 0;\n let mid = 0.5;\n let walked = 0;\n for (let i = 1; i < pts.length; i++) {\n const seg = Math.hypot(pts[i][0] - pts[i - 1][0], pts[i][1] - pts[i - 1][1]);\n if (seg > best) {\n best = seg;\n mid = (walked + seg / 2) / total;\n }\n walked += seg;\n }\n return mid;\n}\n","/**\n * Layout quality (PB-1007): numbers that say whether a diagram reads, measured\n * on what the viewer draws (the boxes, and the routes the grid router gives\n * the links), so an agent can check a layout without looking at it.\n *\n * - crossings: places where two links' lines cross;\n * - overlaps: pairs of boxes that overlap (a card and a junction, two cards);\n * - aspect: the drawing's width over its height (a screen is about 1.6);\n * - strip: the most cards one straight line, across or down, passes through\n * (a long row or column of parts; a tidy level of twenty cards has 4 or 5);\n * - underCards: links whose line runs under a card it does not end at;\n * - length: the total length of the lines, in diagram units.\n *\n * `findings` turns them into what to fix, with the thresholds below.\n */\nimport type { ViewModel } from \"../model/types\";\nimport type { Pt } from \"../canvas/routing\";\nimport type { Box, ComputedLayout } from \"./layout\";\n\nexport interface LayoutMetrics {\n /** Cards on the level: modules, components and harnesses (not junctions, sheet ports or open containers). */\n cards: number;\n /** Boundary ports drawn (the exports of the module this level shows). */\n boundary: number;\n /** Lines drawn. */\n links: number;\n crossings: number;\n overlaps: number;\n /** Width over height of the drawing (0 when it is empty). */\n aspect: number;\n width: number;\n height: number;\n strip: number;\n /** Whether the strip runs across (a row) or down (a column). */\n stripAxis: \"row\" | \"column\";\n /** The cards of the strip, in order. */\n stripCards: string[];\n underCards: number;\n length: number;\n /** The overlapping pairs and the links under cards, by id. */\n detail: { overlaps: [string, string][]; underCards: { link: string; card: string }[] };\n}\n\nexport interface LayoutFinding {\n severity: \"warning\" | \"info\";\n code: \"strip\" | \"crossings\" | \"overlaps\" | \"under-cards\" | \"aspect\";\n message: string;\n}\n\n/**\n * What `findings` flags. A row or column of up to `strip(cards)` cards is\n * fine (a row of a grid shaped like a screen: 6 for up to 16 cards, then\n * one and a half times the square root of the count); more reads as a strip.\n */\nexport const LAYOUT_LIMITS = {\n strip: (cards: number) => Math.max(6, Math.ceil(1.5 * Math.sqrt(cards))),\n /** Crossings allowed: a few, and more on a level with many lines. */\n crossings: (links: number) => Math.max(3, Math.ceil(links / 8)),\n /** Aspect ratios outside this range read as a strip too. */\n aspect: [1 / 3, 3] as [number, number],\n};\n\nconst ancestorOf = (a: string, b: string) => b.startsWith(`${a}/`);\n\n/** Whether two boxes overlap by more than a hairline. */\nfunction overlap(a: Box, b: Box): boolean {\n return a.x < b.x + b.w - 1 && b.x < a.x + a.w - 1 && a.y < b.y + b.h - 1 && b.y < a.y + a.h - 1;\n}\n\ninterface Seg {\n link: string;\n a: Pt;\n b: Pt;\n}\n\nfunction segments(id: string, pts: Pt[]): Seg[] {\n const out: Seg[] = [];\n for (let i = 1; i < pts.length; i++) if (pts[i - 1][0] !== pts[i][0] || pts[i - 1][1] !== pts[i][1]) out.push({ link: id, a: pts[i - 1], b: pts[i] });\n return out;\n}\n\n/** Whether a horizontal and a vertical segment cross inside both (not at an end, not touching). */\nfunction cross(s: Seg, t: Seg): boolean {\n const h = (x: Seg) => Math.abs(x.a[1] - x.b[1]) < 0.5;\n const v = (x: Seg) => Math.abs(x.a[0] - x.b[0]) < 0.5;\n let H: Seg;\n let V: Seg;\n if (h(s) && v(t)) [H, V] = [s, t];\n else if (v(s) && h(t)) [H, V] = [t, s];\n else return obliqueCross(s, t);\n const y = H.a[1];\n const x = V.a[0];\n const [x0, x1] = [Math.min(H.a[0], H.b[0]), Math.max(H.a[0], H.b[0])];\n const [y0, y1] = [Math.min(V.a[1], V.b[1]), Math.max(V.a[1], V.b[1])];\n return x > x0 + 0.5 && x < x1 - 0.5 && y > y0 + 0.5 && y < y1 - 0.5;\n}\n\n/** A crossing of two segments when either is not axis-aligned (pass-through lines drawn straight). */\nfunction obliqueCross(s: Seg, t: Seg): boolean {\n const d = (p: Pt, q: Pt, r: Pt) => (q[0] - p[0]) * (r[1] - p[1]) - (q[1] - p[1]) * (r[0] - p[0]);\n const d1 = d(t.a, t.b, s.a);\n const d2 = d(t.a, t.b, s.b);\n const d3 = d(s.a, s.b, t.a);\n const d4 = d(s.a, s.b, t.b);\n return ((d1 > 0 && d2 < 0) || (d1 < 0 && d2 > 0)) && ((d3 > 0 && d4 < 0) || (d3 < 0 && d4 > 0));\n}\n\n/** Whether a segment runs through the inside of a box (not along its edge). */\nfunction through(s: Seg, b: Box): boolean {\n const [x0, x1] = [Math.min(s.a[0], s.b[0]), Math.max(s.a[0], s.b[0])];\n const [y0, y1] = [Math.min(s.a[1], s.b[1]), Math.max(s.a[1], s.b[1])];\n return x1 > b.x + 2 && x0 < b.x + b.w - 2 && y1 > b.y + 2 && y0 < b.y + b.h - 2;\n}\n\n/**\n * The most boxes one line along an axis passes through, and which: a sweep\n * over the boxes' extents on the other axis.\n */\nfunction stab(boxes: { id: string; b: Box }[], axis: \"row\" | \"column\"): string[] {\n const lo = (x: { b: Box }) => (axis === \"row\" ? x.b.y : x.b.x);\n const hi = (x: { b: Box }) => (axis === \"row\" ? x.b.y + x.b.h : x.b.x + x.b.w);\n const along = (x: { b: Box }) => (axis === \"row\" ? x.b.x : x.b.y);\n let best: string[] = [];\n // the line through the middle of an overlap of extents: try each box's centre and edges (inset a little)\n const tries = [...new Set(boxes.flatMap((x) => [lo(x) + 4, (lo(x) + hi(x)) / 2, hi(x) - 4]))].sort((a, b) => a - b);\n for (const at of tries) {\n const hit = boxes.filter((x) => lo(x) <= at && hi(x) >= at);\n if (hit.length > best.length) best = hit.sort((a, b) => along(a) - along(b)).map((x) => x.id);\n }\n return best;\n}\n\n/** Measure a level as the viewer lays it out. `vm` is what is drawn (after rail taps). */\nexport function measureLayout(vm: ViewModel, layout: ComputedLayout): LayoutMetrics {\n const byId = new Map(vm.nodes.map((n) => [n.id, n]));\n const drawn = vm.nodes.filter((n) => layout.boxes[n.id]);\n const isCard = (id: string) => {\n const n = byId.get(id);\n return !!n && n.kind !== \"net\" && !n.sheetPort && !n.expanded;\n };\n const cards = drawn.filter((n) => isCard(n.id)).map((n) => ({ id: n.id, b: layout.boxes[n.id] }));\n\n // overlaps: any two boxes, except a container and what it holds\n const overlaps: [string, string][] = [];\n for (let i = 0; i < drawn.length; i++)\n for (let j = i + 1; j < drawn.length; j++) {\n const a = drawn[i].id;\n const b = drawn[j].id;\n if (ancestorOf(a, b) || ancestorOf(b, a)) continue;\n if (overlap(layout.boxes[a], layout.boxes[b])) overlaps.push([a, b].sort() as [string, string]);\n }\n\n // lines\n const routed = vm.links.filter((l) => layout.routes[l.id]?.length);\n const segs = routed.flatMap((l) => segments(l.id, layout.routes[l.id]));\n let crossings = 0;\n for (let i = 0; i < segs.length; i++)\n for (let j = i + 1; j < segs.length; j++) if (segs[i].link !== segs[j].link && cross(segs[i], segs[j])) crossings++;\n\n const under: { link: string; card: string }[] = [];\n for (const l of routed) {\n const ends = [l.source.node, l.target.node];\n const mine = (id: string) => ends.some((e) => e === id || ancestorOf(id, e) || ancestorOf(e, id));\n const own = segments(l.id, layout.routes[l.id]);\n for (const c of cards) {\n if (mine(c.id)) continue;\n if (own.some((s) => through(s, c.b))) under.push({ link: l.id, card: c.id });\n }\n }\n\n let length = 0;\n for (const s of segs) length += Math.hypot(s.b[0] - s.a[0], s.b[1] - s.a[1]);\n\n const all = drawn.map((n) => layout.boxes[n.id]);\n const minX = all.length ? Math.min(...all.map((b) => b.x)) : 0;\n const minY = all.length ? Math.min(...all.map((b) => b.y)) : 0;\n const width = all.length ? Math.max(...all.map((b) => b.x + b.w)) - minX : 0;\n const height = all.length ? Math.max(...all.map((b) => b.y + b.h)) - minY : 0;\n\n // the strip counts the level's boundary ports too (a drilled-into module's exports, drawn in a column at the edge)\n const sheets = drawn.filter((n) => n.sheetPort).map((n) => ({ id: n.id, b: layout.boxes[n.id] }));\n const row = stab([...cards, ...sheets], \"row\");\n const column = stab([...cards, ...sheets], \"column\");\n const [strip, stripAxis] = column.length > row.length ? [column, \"column\" as const] : [row, \"row\" as const];\n\n return {\n cards: cards.length,\n boundary: sheets.length,\n links: routed.length,\n crossings,\n overlaps: overlaps.length,\n aspect: height ? Math.round((width / height) * 100) / 100 : 0,\n width: Math.round(width),\n height: Math.round(height),\n strip: strip.length,\n stripAxis,\n stripCards: strip,\n underCards: new Set(under.map((u) => u.link)).size,\n length: Math.round(length),\n detail: { overlaps, underCards: under },\n };\n}\n\n/** What a level's layout needs fixed, worst first. */\nexport function layoutFindings(m: LayoutMetrics, limits: typeof LAYOUT_LIMITS = LAYOUT_LIMITS): LayoutFinding[] {\n const out: LayoutFinding[] = [];\n if (m.overlaps) out.push({ severity: \"warning\", code: \"overlaps\", message: `${m.overlaps} pair${m.overlaps === 1 ? \"\" : \"s\"} of boxes overlap (${m.detail.overlaps.slice(0, 3).map((p) => p.join(\" / \")).join(\", \")}${m.overlaps > 3 ? \", …\" : \"\"})` });\n const strip = limits.strip(m.cards + (m.boundary ?? 0));\n const ports = m.stripCards.filter((id) => id.startsWith(\"@\")).length * 2 > m.stripCards.length;\n if (m.strip > strip)\n out.push({\n severity: \"warning\",\n code: \"strip\",\n message: `${m.strip} cards in one ${m.stripAxis} (${m.stripCards.slice(0, 4).join(\", \")}${m.strip > 4 ? \", …\" : \"\"}): more than ${strip} reads as a strip; ${ports ? \"most are the level's boundary ports: export fewer, grouped interfaces from this module (composites) rather than one per signal\" : \"arrange them in a block around what they connect to\"}`,\n });\n const [lo, hi] = limits.aspect;\n if (m.cards > 3 && m.aspect && (m.aspect < lo || m.aspect > hi)) out.push({ severity: \"warning\", code: \"aspect\", message: `the drawing is ${m.aspect > 1 ? `${m.aspect}× as wide as it is tall` : `${Math.round(100 / m.aspect) / 100}× as tall as it is wide`}: aim for a screen's shape (about 1.6)` });\n const allowed = limits.crossings(m.links);\n if (m.crossings > allowed) out.push({ severity: \"warning\", code: \"crossings\", message: `${m.crossings} line crossings (up to ${allowed} is fine for ${m.links} lines): move cards next to what they connect to` });\n if (m.underCards) out.push({ severity: \"info\", code: \"under-cards\", message: `${m.underCards} line${m.underCards === 1 ? \" runs\" : \"s run\"} under a card (${m.detail.underCards.slice(0, 2).map((u) => `${u.link} under ${u.card}`).join(\", \")}${m.detail.underCards.length > 2 ? \", …\" : \"\"})` });\n return out;\n}\n","/**\n * Headless layout (PB-1007): the viewer's diagram layout without a browser,\n * for hosts that check or write a project's layout (`protoboard layout`).\n *\n * import { diagramLevels, measureLevel, proposeLevel } from \"@deltarobotics/uhd-viewer/headless\";\n *\n * Everything here computes what the viewer would draw for a level: the same\n * model (`buildView`, rail taps), the same layout and routes\n * (`computeLayout`), from the bundle and its display hints. No React, no DOM.\n */\nimport type { UhdBundle } from \"@uhd/types/bundle.js\";\nimport type { ModuleDef } from \"@uhd/types/index.js\";\nimport type { ModuleLookup } from \"@uhd/system/index.js\";\nimport { sourceFromBundle, type DisplayConfig } from \"./source/source\";\nimport { buildView, levelModule } from \"./model/from-uhd\";\nimport { tapRails } from \"./layout/taps\";\nimport { arrangeLevel, computeLayout, type ComputedLayout, type LevelLayout } from \"./layout/layout\";\nimport { layoutFindings, measureLayout, LAYOUT_LIMITS, type LayoutFinding, type LayoutMetrics } from \"./layout/metrics\";\nimport type { ViewModel } from \"./model/types\";\n\nexport { LAYOUT_LIMITS, layoutFindings, measureLayout };\nexport type { LayoutFinding, LayoutMetrics, LevelLayout };\n\n/** A level of the diagram: the inside of one module, keyed by its instance path (\"\" = the top level). */\nexport interface DiagramLevel {\n level: string;\n /** The module's name. */\n label: string;\n /** The level holds a board's nets (laid out as a schematic sheet, board-layout.ts). */\n board: boolean;\n}\n\n/** A level layout with the nodes the layout step must not move (PB-1007; the viewer ignores the list). */\nexport type PinnedLevelLayout = LevelLayout & { pinned?: string[] };\n\ninterface Loaded {\n system: ModuleDef;\n lookup: ModuleLookup;\n display: DisplayConfig;\n}\n\nfunction load(bundle: UhdBundle): Loaded {\n const src = sourceFromBundle(bundle, \"bundle.json\");\n const nominal = src.scenarios[0];\n return { system: nominal.system, lookup: nominal.lookup, display: src.display };\n}\n\n/** Every level of the diagram, top first: the top level and the inside of every module that has modules in it. */\nexport function diagramLevels(bundle: UhdBundle, maxDepth = 4): DiagramLevel[] {\n const { system, lookup } = load(bundle);\n const out: DiagramLevel[] = [];\n const walk = (def: ModuleDef, path: string[], label: string) => {\n const children = def.children ?? [];\n if (!children.length) return;\n const board = (def.interfaces ?? []).some((i) => (i as { protocol?: { type?: string } }).protocol?.type === \"Net\" || (i as { kind?: string }).kind === \"net\");\n out.push({ level: path.join(\"/\"), label, board: board || isBoardLevel(system, lookup, path) });\n if (path.length >= maxDepth) return;\n for (const c of children) {\n const next = lookup(c.moduleDefId);\n if (!next || next.kind === \"harness\") continue;\n walk(next, [...path, c.id], c.name ?? next.name);\n }\n };\n walk(system, [], system.name);\n return out;\n}\n\n/** Whether a level draws net junctions (a board): what the viewer's own view model says. */\nfunction isBoardLevel(system: ModuleDef, lookup: ModuleLookup, drill: string[]): boolean {\n try {\n return buildView(system, lookup, drill, { expanded: new Set() }).nodes.some((n) => n.kind === \"net\");\n } catch {\n return false;\n }\n}\n\nexport interface LevelOptions {\n /** The level's layout to use: the display file's when undefined; null for none (the automatic layout). */\n layout?: LevelLayout | null;\n /** Modules drawn expanded in place (default: the display file's `diagram.expanded`). */\n expanded?: string[];\n /** Lay a level without a layout out the way the viewer did before PB-1007 (one row), to compare. */\n legacy?: boolean;\n}\n\nexport interface MeasuredLevel {\n level: string;\n /** Whether the layout measured is a saved one (from the display file or given). */\n saved: boolean;\n metrics: LayoutMetrics;\n findings: LayoutFinding[];\n /** What the viewer draws: the model and the computed layout. */\n view: ViewModel;\n layout: ComputedLayout;\n}\n\n/** The display hints of a bundle: its `display`, as the viewer reads it. */\nexport function displayOf(bundle: UhdBundle): DisplayConfig {\n return (bundle.display ?? {}) as DisplayConfig;\n}\n\n/** Lay a level out as the viewer would, and measure it. */\nexport function measureLevel(bundle: UhdBundle, level: string, opts: LevelOptions = {}): MeasuredLevel {\n const { system, lookup, display } = load(bundle);\n const drill = level ? level.split(\"/\") : [];\n const known = levelModule(system, drill, lookup);\n if (known.path.length !== drill.length + 1) throw new Error(`no level \"${level}\" (levels are instance paths of modules with modules inside)`);\n const expanded = new Set(opts.expanded ?? display.diagram?.expanded ?? []);\n const vm = tapRails(buildView(system, lookup, drill, { expanded }));\n const hand = opts.layout === null ? undefined : (opts.layout ?? display.diagram?.layouts?.[level]);\n const layout = computeLayout(vm, hand, {}, false, undefined, undefined, { legacy: opts.legacy });\n const metrics = measureLayout(vm, layout);\n return { level, saved: !!hand, metrics, findings: layoutFindings(metrics), view: vm, layout };\n}\n\n/**\n * A display-file level that holds a computed layout: every node's position\n * (top-level nodes absolute, nodes inside an expanded module relative to\n * it), as the viewer writes them.\n */\nexport function levelLayoutOf(vm: ViewModel, layout: ComputedLayout): LevelLayout {\n const nodes: LevelLayout[\"nodes\"] = {};\n const byId = new Map(vm.nodes.map((n) => [n.id, n]));\n for (const n of [...vm.nodes].sort((a, b) => a.id.localeCompare(b.id))) {\n const b = layout.boxes[n.id];\n if (!b) continue;\n // a rail's taps are drawn from the net: they are placed again from it, never saved\n if (n.tapOf) continue;\n const p = n.parent ? layout.boxes[n.parent] : undefined;\n nodes[n.id] = p && byId.get(n.parent!) ? { x: b.x - p.x, y: b.y - p.y } : { x: b.x, y: b.y };\n // a module expanded in place keeps the size it was laid out at (else the viewer takes the layout as made\n // for its collapsed card, and moves what is beside and below it)\n if (n.expanded) Object.assign(nodes[n.id], { w: b.w, h: b.h });\n }\n return { nodes };\n}\n\nexport interface ProposeOptions extends LevelOptions {\n /**\n * \"default\": the level laid out afresh (the viewer's automatic layout);\n * \"tidy\": the saved layout's arrangement kept as the starting point, and\n * what reads badly (strips, overlaps, crossings) fixed.\n */\n mode?: \"default\" | \"tidy\";\n /** Nodes that keep their saved positions (added to the level's own `pinned`). */\n pinned?: string[];\n}\n\nexport interface Proposal {\n level: string;\n /** The level as it is drawn now. */\n before: MeasuredLevel;\n /** The level with the proposed layout. */\n after: MeasuredLevel;\n /** What to write to `diagram.layouts[level]`. */\n layout: PinnedLevelLayout;\n /** Whether the proposal reads clearly better than what is there (`readsBetter`). */\n better: boolean;\n}\n\n/**\n * A layout for a level: afresh, or tidied from the saved one; pinned nodes\n * keep their saved positions. Links whose ends moved lose their saved\n * waypoints (they were drawn for the old places); labels and tabs stay.\n */\nexport function proposeLevel(bundle: UhdBundle, level: string, opts: ProposeOptions = {}): Proposal {\n const before = measureLevel(bundle, level, opts);\n const saved: PinnedLevelLayout | undefined = opts.layout === null ? undefined : (opts.layout ?? (displayOf(bundle).diagram?.layouts?.[level] as PinnedLevelLayout | undefined));\n const pinned = [...new Set([...(saved?.pinned ?? []), ...(opts.pinned ?? [])])].filter((id) => saved?.nodes[id]?.x !== undefined).sort();\n const fixed: Record<string, { x: number; y: number }> = {};\n for (const id of pinned) fixed[id] = { x: saved!.nodes[id].x!, y: saved!.nodes[id].y! };\n // the starting arrangement: for a tidy, where the cards are drawn now\n const seed = opts.mode === \"tidy\" ? Object.fromEntries(Object.entries(before.layout.boxes).map(([id, b]) => [id, { x: b.x + b.w / 2, y: b.y + b.h / 2 }])) : undefined;\n // a tidy keeps the sizes set by hand; a fresh layout gives every card its own size again\n const keepSizes = opts.mode === \"tidy\" ? saved : undefined;\n const fresh = arrangeLevel(before.view, { fixed, seed }, keepSizes);\n // the arrangement as a hand layout, laid out once more so the saved positions are exactly what is drawn\n const draft = measureLevel(bundle, level, { ...opts, layout: { ...fresh, ...(keepSizes?.ports ? { ports: keepSizes.ports } : {}) } });\n const layout: PinnedLevelLayout = levelLayoutOf(draft.view, draft.layout);\n for (const id of pinned) layout.nodes[id] = { ...fixed[id] };\n // sizes and port sides set by hand stay; waypoints only where neither end moved\n if (keepSizes) for (const [id, n] of Object.entries(saved?.nodes ?? {})) if (layout.nodes[id] && (n.w !== undefined || n.h !== undefined)) layout.nodes[id] = { ...layout.nodes[id], ...(n.w !== undefined ? { w: n.w } : {}), ...(n.h !== undefined ? { h: n.h } : {}) };\n if (keepSizes?.ports) layout.ports = { ...keepSizes.ports };\n const moved = (id: string) => !pinned.includes(id.split(\"/\")[0]);\n const links: NonNullable<LevelLayout[\"links\"]> = {};\n for (const [id, l] of Object.entries(saved?.links ?? {})) {\n const link = before.view.links.find((x) => x.id === id);\n const keep = link && !moved(link.source.node) && !moved(link.target.node);\n const { waypoints, ...rest } = l;\n const next = keep && waypoints ? { ...rest, waypoints } : rest;\n if (Object.keys(next).length) links[id] = next;\n }\n if (Object.keys(links).length) layout.links = links;\n if (pinned.length) layout.pinned = pinned;\n const refined = before.view.nodes.some((n) => n.kind === \"net\") ? layout : refine(bundle, level, opts, layout, pinned);\n const after = measureLevel(bundle, level, { ...opts, layout: refined });\n return { level, before, after, layout: refined, better: readsBetter(after.metrics, before.metrics) };\n}\n\n/** Swaps tried at most when refining a level (the same count every run: the result does not depend on the machine). */\nexport const REFINE_BUDGET = 120;\n/** Levels with more cards than this keep the grid's arrangement (each try routes the whole level). */\nexport const REFINE_MAX_CARDS = 16;\n\n/**\n * Refine a proposed layout on what the viewer actually draws: swap two\n * cards' places (centre for centre) while that lowers the routed crossings,\n * overlaps or line length (`reads`), up to REFINE_BUDGET tries. Pinned cards\n * stay. Deterministic: pairs in id order, the first improvement taken.\n */\nfunction refine(bundle: UhdBundle, level: string, opts: LevelOptions, start: PinnedLevelLayout, pinned: string[]): PinnedLevelLayout {\n const ids = Object.keys(start.nodes)\n .filter((id) => !id.includes(\"/\") && !pinned.includes(id))\n .sort();\n if (ids.length < 3 || ids.length > REFINE_MAX_CARDS) return start;\n let best = start;\n let m = measureLevel(bundle, level, { ...opts, layout: best });\n let score = reads(m.metrics);\n let tries = 0;\n let improved = true;\n while (improved && tries < REFINE_BUDGET) {\n improved = false;\n for (let i = 0; i < ids.length && tries < REFINE_BUDGET; i++)\n for (let j = i + 1; j < ids.length && tries < REFINE_BUDGET; j++) {\n const a = m.layout.boxes[ids[i]];\n const b = m.layout.boxes[ids[j]];\n if (!a || !b) continue;\n const snap = (v: number) => Math.round(v / 16) * 16;\n const nodes = { ...best.nodes };\n nodes[ids[i]] = { ...nodes[ids[i]], x: snap(b.x + b.w / 2 - a.w / 2), y: snap(b.y + b.h / 2 - a.h / 2) };\n nodes[ids[j]] = { ...nodes[ids[j]], x: snap(a.x + a.w / 2 - b.w / 2), y: snap(a.y + a.h / 2 - b.h / 2) };\n const next: PinnedLevelLayout = { ...best, nodes };\n tries++;\n const nm = measureLevel(bundle, level, { ...opts, layout: next });\n const ns = reads(nm.metrics);\n if (ns < score - 1e-6) {\n best = next;\n m = nm;\n score = ns;\n improved = true;\n }\n }\n }\n return best;\n}\n\n\n\n/**\n * Whether layout `a` reads clearly better than `b`: fewer problems (warnings,\n * then overlaps, the strip's excess, crossings, lines under cards), or as\n * few and lines a quarter shorter. A layout with nothing to fix is not\n * replaced for a few pixels of line.\n */\nexport function readsBetter(a: LayoutMetrics, b: LayoutMetrics): boolean {\n const problems = (m: LayoutMetrics) => [\n layoutFindings(m).filter((x) => x.severity === \"warning\").length,\n m.overlaps,\n Math.max(0, m.strip - LAYOUT_LIMITS.strip(m.cards + m.boundary)),\n m.crossings,\n m.underCards,\n ];\n const pa = problems(a);\n const pb = problems(b);\n for (let i = 0; i < pa.length; i++) if (pa[i] !== pb[i]) return pa[i] < pb[i];\n return a.length < 0.75 * b.length;\n}\n\n/** A score for comparing two layouts of one level: lower reads better. */\nexport function reads(m: LayoutMetrics): number {\n const f = layoutFindings(m).filter((x) => x.severity === \"warning\").length;\n return f * 1e9 + m.overlaps * 1e7 + Math.max(0, m.strip - LAYOUT_LIMITS.strip(m.cards + m.boundary)) * 1e6 + m.crossings * 1e4 + m.underCards * 1e3 + m.length / 100;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["overlaps","trait","speaks","rolesOf","range","diag","speaks","rolesOf","trait","range","fmt","fmtR","diag","isGround","RANK","worst","natural","snapUp","snapTo","natural"],"sources":["../../../uhd/src/system/bundle.ts","../../../uhd/src/types/bundle.ts","../../../uhd/src/matching/roles.ts","../../../uhd/src/matching/protocol-match.ts","../../../uhd/src/drc/region-tree.ts","../../../uhd/src/parameters/range.ts","../../../uhd/src/drc/param-check.ts","../../../uhd/src/protocols/mechanical.ts","../../../uhd/src/drc/joint-check.ts","../../../uhd/src/drc/link-check.ts","../../../uhd/src/drc/drive-check.ts","../../../uhd/src/drc/signal-check.ts","../../../uhd/src/drc/types.ts","../../../uhd/src/drc/validate-pair.ts","../../../uhd/src/system/connectors.ts","../../../uhd/src/protocols/connector.ts","../../../uhd/src/protocols/net.ts","../../../uhd/src/system/nets.ts","../../../uhd/src/system/index.ts","../../src/source/tolerant.ts","../../src/source/source.ts","../../../uhd/src/system/derive.ts","../../src/model/nets.ts","../../src/model/from-uhd.ts","../../src/canvas/routing.ts","../../src/layout/router.ts","../../src/layout/board-layout.ts","../../src/layout/taps.ts","../../src/layout/card-body.ts","../../src/canvas/geometry.ts","../../src/layout/module-layout.ts","../../src/layout/layout.ts","../../src/layout/metrics.ts","../../src/headless.ts"],"sourcesContent":["/**\n * Reading a UHD bundle: the root and a lookup, optionally for a scenario.\n */\nimport type { UhdBundle } from \"../types/bundle.js\";\nimport type { ModuleDef } from \"../types/module.js\";\nimport type { ModuleLookup } from \"./index.js\";\n\nexport function bundleSystem(bundle: UhdBundle, scenarioId?: string): { root: ModuleDef; lookup: ModuleLookup } {\n const byId = new Map(bundle.definitions.map((d) => [d.id, d]));\n const scenario = scenarioId ? bundle.scenarios?.find((s) => s.id === scenarioId) : undefined;\n for (const d of scenario?.definitions ?? []) byId.set(d.id, d);\n const root = scenario?.root ?? byId.get(bundle.root);\n if (!root) throw new Error(`bundle root \"${bundle.root}\" is not among its definitions`);\n return { root, lookup: (id) => byId.get(id) };\n}\n\n/** Definitions reachable from a root (children and harness children, recursively). */\nexport function reachableDefinitions(root: ModuleDef, lookup: ModuleLookup): ModuleDef[] {\n const out = new Map<string, ModuleDef>([[root.id, root]]);\n const walk = (d: ModuleDef) => {\n for (const c of d.children ?? []) {\n const child = lookup(c.moduleDefId);\n if (child && !out.has(child.id)) {\n out.set(child.id, child);\n walk(child);\n }\n }\n };\n walk(root);\n return [...out.values()];\n}\n","/**\n * UHD bundle: the neutral, self-contained form of a system for tools that\n * only read UHD (the UHD viewer first). A root, every definition it\n * references, optional named variants, and per-definition artifact bases.\n * Producers (a build tool, a library script, a hand-written file)\n * resolve origins before writing it; consumers need nothing else.\n */\nimport type { ModuleDef } from \"./module.js\";\n\nexport const UHD_BUNDLE_SCHEMA = \"uhd.bundle/v0\";\n\nexport interface UhdBundleScenario {\n id: string;\n label: string;\n description?: string;\n /** A variant root definition (replaces the bundle root for this scenario). */\n root?: ModuleDef;\n /** Definitions that replace (by id) or add to the bundle's for this scenario. */\n definitions?: ModuleDef[];\n}\n\nexport interface UhdBundleDiagnostic {\n code: string;\n severity: \"error\" | \"warning\" | \"info\";\n message: string;\n /** What it is about: an instance path, link id, definition id… */\n entity?: { kind: string; id: string };\n source?: { file: string; line?: number };\n /** Who produced it (e.g. \"my-tool/fit-check\", \"uhd/checkSystem\"). */\n validator?: string;\n}\n\nexport interface UhdBundle {\n schema: typeof UHD_BUNDLE_SCHEMA;\n /** Id of the root definition. */\n root: string;\n /** The root and every definition it references (children, harness children). */\n definitions: ModuleDef[];\n /**\n * Base that each definition's relative artifact paths resolve against:\n * definition id → absolute path or URL prefix. Missing: relative to the\n * bundle's own location.\n */\n artifactBases?: Record<string, string>;\n scenarios?: UhdBundleScenario[];\n /** Findings from the producer (a consumer may add its own UHD checks). */\n diagnostics?: UhdBundleDiagnostic[];\n /**\n * Presentation hints keyed by instance path (layout, labels, placement\n * hints, appearance). Opaque to UHD: never topology.\n */\n display?: Record<string, unknown>;\n meta?: { name?: string; producer?: string; producerVersion?: string };\n}\n","/**\n * Protocol role pair compatibility table.\n *\n * Generic pairs apply to any protocol type unless overridden\n * by protocol-specific entries.\n */\n\nconst GENERIC_ROLE_PAIRS: Record<string, string[]> = {\n input: [\"output\"],\n output: [\"input\"],\n bidirectional: [\"input\", \"output\", \"bidirectional\"],\n master: [\"slave\"],\n slave: [\"master\"],\n host: [\"device\", \"peripheral\"],\n device: [\"host\", \"controller\"],\n peripheral: [\"host\", \"controller\"],\n controller: [\"device\", \"peripheral\"],\n source: [\"sink\"],\n sink: [\"source\"],\n transmitter: [\"receiver\"],\n receiver: [\"transmitter\"],\n transceiver: [\"transmitter\", \"receiver\", \"transceiver\"],\n peer: [\"peer\"],\n primary: [\"secondary\"],\n secondary: [\"primary\"],\n target: [\"controller\", \"source\", \"master\", \"host\"],\n};\n\n/**\n * Protocol-specific role pair overrides.\n * Only needed when the generic pairs are wrong or insufficient.\n */\n/** MIPI CSI-2 / DSI sub-roles: transmitter → receiver, clock and data lanes. */\nfunction MIPI_ROLES(): Record<string, string[]> {\n return {\n transmitter: [\"receiver\"],\n receiver: [\"transmitter\"],\n clock_tx_p: [\"clock_rx_p\"],\n clock_tx_n: [\"clock_rx_n\"],\n clock_rx_p: [\"clock_tx_p\"],\n clock_rx_n: [\"clock_tx_n\"],\n data_tx_p: [\"data_rx_p\"],\n data_tx_n: [\"data_rx_n\"],\n data_rx_p: [\"data_tx_p\"],\n data_rx_n: [\"data_tx_n\"],\n };\n}\n\nconst PROTOCOL_ROLE_PAIRS: Record<string, Record<string, string[]>> = {\n i2c: {\n master: [\"slave\"],\n slave: [\"master\"],\n // Sub-roles for slot matching within composed interfaces\n data: [\"data\"],\n clock: [\"clock\"],\n },\n spi: {\n master: [\"slave\"],\n slave: [\"master\"],\n data_out: [\"data_in\"],\n data_in: [\"data_out\"],\n clock: [\"clock\"],\n select: [\"select\"],\n },\n uart: {\n host: [\"device\"],\n device: [\"host\"],\n transmitter: [\"receiver\"],\n receiver: [\"transmitter\"],\n transceiver: [\"transmitter\", \"receiver\", \"transceiver\"],\n },\n power: {\n input: [\"output\"],\n output: [\"input\"],\n ground: [\"ground\"],\n },\n bolt_pattern: {\n structure: [\"component\"],\n component: [\"structure\"],\n },\n // a passive terminal joined to another by a conductor (an LED's anode soldered to a\n // board pad): on a board net, terminals still pair with nothing (system/derive.ts)\n passive: {\n terminal: [\"terminal\"],\n },\n motor_control: {\n controller: [\"target\"],\n target: [\"controller\"],\n source: [\"target\"],\n },\n // Stepper windings (StepperPhases). Older parts used driver/motor; they\n // pair with the output/input roles the builder emits.\n bipolar_stepper_phases: {\n output: [\"input\", \"motor\"],\n input: [\"output\", \"driver\"],\n driver: [\"motor\", \"input\"],\n motor: [\"driver\", \"output\"],\n },\n // CAN bus side (CAN): every node on the bus pairs with every other. Older\n // parts declared the bus as \"transceiver\" or \"peer\"; they are the same family.\n can: {\n node: [\"node\", \"transceiver\", \"peer\"],\n transceiver: [\"node\", \"transceiver\", \"peer\"],\n peer: [\"node\", \"transceiver\", \"peer\"],\n },\n can_signal: {\n node: [\"node\"],\n },\n // CAN logic side (CANLogic): a CAN controller's TX/RX to a transceiver's TXD/RXD.\n can_logic: {\n controller: [\"transceiver\"],\n transceiver: [\"controller\"],\n },\n // Fluid ports (FluidPort): flow goes from a source to a sink; fittings,\n // tubing and passthrough ports are bidirectional; a gauge or transducer\n // senses pressure where it is plumbed in.\n pneumatic: {\n source: [\"sink\", \"bidirectional\", \"sensing\"],\n sink: [\"source\", \"bidirectional\"],\n bidirectional: [\"source\", \"sink\", \"bidirectional\", \"sensing\"],\n sensing: [\"source\", \"bidirectional\"],\n },\n hydraulic: {\n source: [\"sink\", \"bidirectional\", \"sensing\"],\n sink: [\"source\", \"bidirectional\"],\n bidirectional: [\"source\", \"sink\", \"bidirectional\", \"sensing\"],\n sensing: [\"source\", \"bidirectional\"],\n }, // ---- Links. Each composite's slots carry a sub-role per conductor,\n // so ports pair conductor by conductor and nothing else.\n // PCIe: a root (root port, switch downstream port, host side of a slot) with\n // an endpoint (card, SSD, switch upstream port). Lanes TX→RX, clock, sideband.\n pcie: {\n root: [\"endpoint\"],\n endpoint: [\"root\"],\n tx_p: [\"rx_p\"],\n tx_n: [\"rx_n\"],\n rx_p: [\"tx_p\"],\n rx_n: [\"tx_n\"],\n refclk_out_p: [\"refclk_in_p\"],\n refclk_out_n: [\"refclk_in_n\"],\n refclk_in_p: [\"refclk_out_p\"],\n refclk_in_n: [\"refclk_out_n\"],\n perst_out: [\"perst_in\"],\n perst_in: [\"perst_out\"],\n clkreq_out: [\"clkreq_in\"],\n clkreq_in: [\"clkreq_out\"],\n wake_out: [\"wake_in\"],\n wake_in: [\"wake_out\"],\n },\n pcie_lane: {\n transmitter: [\"receiver\"],\n receiver: [\"transmitter\"],\n },\n // M.2: a socket takes a card.\n m2: {\n socket: [\"card\"],\n card: [\"socket\"],\n },\n // MIPI CSI-2 and DSI: transmitter → receiver, clock to clock, data lane to data lane.\n mipi_csi2: MIPI_ROLES(),\n mipi_dsi: MIPI_ROLES(),\n mipi_dphy: {\n transmitter: [\"receiver\"],\n receiver: [\"transmitter\"],\n },\n // Ethernet: any two ports link (auto MDI-X or the cable crosses the pairs).\n ethernet: {\n port: [\"port\"],\n mdi_p: [\"mdi_p\"],\n mdi_n: [\"mdi_n\"],\n },\n ethernet_mdi: {\n bidirectional: [\"bidirectional\"],\n },\n sfp: {\n cage: [\"module\"],\n module: [\"cage\"],\n },\n // I2S / PCM: the clock controller with a clock target (older parts said\n // master / slave); BCLK and WS out to in (or a port that can be either);\n // data out to data in; MCLK out to in.\n i2s: {\n controller: [\"target\", \"slave\"],\n target: [\"controller\", \"master\"],\n master: [\"slave\", \"target\"],\n slave: [\"master\", \"controller\"],\n bclk_out: [\"bclk_in\", \"bclk_io\"],\n bclk_in: [\"bclk_out\", \"bclk_io\"],\n bclk_io: [\"bclk_out\", \"bclk_in\", \"bclk_io\"],\n ws_out: [\"ws_in\", \"ws_io\"],\n ws_in: [\"ws_out\", \"ws_io\"],\n ws_io: [\"ws_out\", \"ws_in\", \"ws_io\"],\n dout_out: [\"din_in\"],\n din_in: [\"dout_out\"],\n mclk_out: [\"mclk_in\"],\n mclk_in: [\"mclk_out\"],\n },\n // DVP parallel camera bus: the camera drives data, PCLK, VSYNC and HREF; the host may drive XCLK.\n dvp: {\n camera: [\"host\"],\n host: [\"camera\"],\n data_out: [\"data_in\"],\n data_in: [\"data_out\"],\n pclk_out: [\"pclk_in\"],\n pclk_in: [\"pclk_out\"],\n vsync_out: [\"vsync_in\"],\n vsync_in: [\"vsync_out\"],\n href_out: [\"href_in\"],\n href_in: [\"href_out\"],\n xclk_out: [\"xclk_in\"],\n xclk_in: [\"xclk_out\"],\n },\n // SD: the host (slot, SDMMC peripheral) clocks the card.\n sd_card: {\n host: [\"card\"],\n card: [\"host\"],\n clk_out: [\"clk_in\"],\n clk_in: [\"clk_out\"],\n cmd: [\"cmd\"],\n dat: [\"dat\"],\n },\n // LED drive: a sinking driver channel to an LED's cathode, a sourcing one to its anode.\n led_drive: {\n sink: [\"cathode\"],\n cathode: [\"sink\"],\n source: [\"anode\"],\n anode: [\"source\"],\n },\n // USB: host with device; a dual-role port with either. Older parts used\n // \"bidirectional\" for a port that can be either.\n usb: {\n host: [\"device\", \"dual_role\", \"bidirectional\"],\n device: [\"host\", \"dual_role\", \"bidirectional\"],\n dual_role: [\"host\", \"device\", \"dual_role\", \"bidirectional\"],\n bidirectional: [\"host\", \"device\", \"dual_role\", \"bidirectional\"],\n d_p: [\"d_p\"],\n d_n: [\"d_n\"],\n sstx_p: [\"ssrx_p\"],\n sstx_n: [\"ssrx_n\"],\n ssrx_p: [\"sstx_p\"],\n ssrx_n: [\"sstx_n\"],\n cc: [\"cc\"],\n },\n usb_signal: {\n transmitter: [\"receiver\"],\n receiver: [\"transmitter\"],\n bidirectional: [\"bidirectional\"],\n },\n // Wireless (network domain).\n wifi: {\n client: [\"access_point\"],\n access_point: [\"client\"],\n peer: [\"peer\"],\n },\n bluetooth: {\n central: [\"peripheral\", \"peer\"],\n peripheral: [\"central\", \"peer\"],\n peer: [\"peer\", \"central\", \"peripheral\"],\n broadcaster: [\"observer\"],\n observer: [\"broadcaster\"],\n },\n ieee802154: {\n node: [\"node\"],\n },\n // ---- Mechanical: drive train, bearings, threads, tracks, wheels.\n gear_mesh: {\n mesh: [\"mesh\"],\n },\n bearing_fit: {\n bearing: [\"seat\"],\n seat: [\"bearing\"],\n },\n thread: {\n external: [\"internal\"],\n internal: [\"external\"],\n },\n t_slot: {\n track: [\"insert\"],\n insert: [\"track\"],\n },\n axial_stop: {\n face: [\"face\"],\n },\n rolling_contact: {\n wheel: [\"surface\"],\n surface: [\"wheel\"],\n },\n // ---- Serial links, IR, mains and coils.\n // RS-485: every node on the bus; half duplex A to A and B to B, full\n // duplex one side's driver pair (Y/Z) to the other's receiver pair (A/B).\n rs485: {\n node: [\"node\"],\n a: [\"a\"],\n b: [\"b\"],\n tx_p: [\"rx_p\"],\n tx_n: [\"rx_n\"],\n rx_p: [\"tx_p\"],\n rx_n: [\"tx_n\"],\n ground: [\"ground\"],\n },\n rs485_signal: {\n line: [],\n },\n // RS-232: DTE with DCE straight through; two DTEs (or two DCEs) through a\n // null modem, which crosses TXD/RXD, RTS/CTS and DTR/DSR (rs232_null_modem warns).\n rs232: {\n dte: [\"dce\", \"dte\"],\n dce: [\"dte\", \"dce\"],\n txd_out: [\"txd_in\", \"rxd_in\"],\n txd_in: [\"txd_out\", \"rxd_out\"],\n rxd_out: [\"rxd_in\", \"txd_in\"],\n rxd_in: [\"rxd_out\", \"txd_out\"],\n rts_out: [\"rts_in\", \"cts_in\"],\n rts_in: [\"rts_out\", \"cts_out\"],\n cts_out: [\"cts_in\", \"rts_in\"],\n cts_in: [\"cts_out\", \"rts_out\"],\n dtr_out: [\"dtr_in\", \"dsr_in\"],\n dtr_in: [\"dtr_out\", \"dsr_out\"],\n dsr_out: [\"dsr_in\", \"dtr_in\"],\n dsr_in: [\"dsr_out\", \"dtr_out\"],\n dcd_out: [\"dcd_in\"],\n dcd_in: [\"dcd_out\"],\n ri_out: [\"ri_in\"],\n ri_in: [\"ri_out\"],\n ground: [\"ground\"],\n },\n // SWD: a probe debugs a target. Older parts gave the target leaves role\n // \"target\", which the generic table pairs with host and controller.\n swd: {\n probe: [\"target\"],\n target: [\"probe\"],\n swdio: [\"swdio\"],\n swclk_out: [\"swclk_in\"],\n swclk_in: [\"swclk_out\"],\n swo_out: [\"swo_in\"],\n swo_in: [\"swo_out\"],\n nreset_out: [\"nreset_in\"],\n nreset_in: [\"nreset_out\"],\n vtref_out: [\"vtref_in\"],\n vtref_in: [\"vtref_out\"],\n ground: [\"ground\"],\n },\n ppm: {\n output: [\"input\"],\n input: [\"output\"],\n signal_out: [\"signal_in\"],\n signal_in: [\"signal_out\"],\n },\n ir_remote: {\n transmitter: [\"receiver\"],\n receiver: [\"transmitter\"],\n },\n ac_power: {\n input: [\"output\"],\n output: [\"input\"],\n line: [\"line\"],\n neutral: [\"neutral\"],\n earth: [\"earth\"],\n },\n ac_terminal: {\n terminal: [],\n },\n inductive_load: {\n driver: [\"load\"],\n load: [\"driver\"],\n drive_plus: [\"coil_plus\"],\n coil_plus: [\"drive_plus\"],\n drive_minus: [\"coil_minus\"],\n coil_minus: [\"drive_minus\"],\n },\n inductive_terminal: {\n terminal: [],\n },\n // Piezo loads (PiezoLoad, PiezoDrive): a driver output with the element it\n // drives, terminal by terminal; outputs and elements pair in order.\n piezo_drive: {\n driver: [\"load\"],\n load: [\"driver\"],\n drive_plus: [\"element_plus\"],\n element_plus: [\"drive_plus\"],\n drive_minus: [\"element_minus\"],\n element_minus: [\"drive_minus\"],\n },\n piezo_terminal: {\n terminal: [],\n },\n // Battery charge ports (ChargePort): a charger's battery terminals with\n // the battery it charges. Separate from `power`, where two outputs never pair.\n battery_charge: {\n charger: [\"battery\"],\n battery: [\"charger\"],\n charge_plus: [\"battery_plus\"],\n battery_plus: [\"charge_plus\"],\n charge_minus: [\"battery_minus\"],\n battery_minus: [\"charge_minus\"],\n },\n};\n\n/**\n * Protocols whose role table is complete: the generic pairs do not apply.\n * (Without this, two CAN transceivers' logic sides would pair through the\n * generic transceiver ↔ transceiver entry.)\n */\nconst NO_GENERIC_FALLBACK = new Set([\n \"can_logic\",\n \"pneumatic\",\n \"hydraulic\",\n \"pcie\",\n \"pcie_lane\",\n \"m2\",\n \"mipi_csi2\",\n \"mipi_dsi\",\n \"mipi_dphy\",\n \"ethernet\",\n \"ethernet_mdi\",\n \"sfp\",\n \"i2s\",\n \"dvp\",\n \"sd_card\",\n \"led_drive\",\n \"wifi\",\n \"bluetooth\",\n \"ieee802154\",\n \"gear_mesh\",\n \"bearing_fit\",\n \"thread\",\n \"t_slot\",\n \"axial_stop\",\n \"rolling_contact\",\n \"rs485\",\n \"rs485_signal\",\n \"rs232\",\n \"ppm\",\n \"ir_remote\",\n \"ac_power\",\n \"ac_terminal\",\n \"inductive_load\",\n \"inductive_terminal\",\n \"piezo_drive\",\n \"piezo_terminal\",\n \"battery_charge\",\n]);\n\n/**\n * Check whether two roles are compatible for a given protocol type.\n * Uses protocol-specific pairs first, falls back to generic pairs.\n */\nexport function areRolesCompatible(\n protocolType: string,\n roleA: string,\n roleB: string,\n): boolean {\n const normalA = roleA.toLowerCase();\n const normalB = roleB.toLowerCase();\n\n if (normalA === normalB && normalA === \"peer\") return true;\n if (normalA === normalB && normalA === \"bidirectional\") return true;\n\n // Check protocol-specific pairs\n const protocolPairs = PROTOCOL_ROLE_PAIRS[protocolType.toLowerCase()];\n if (protocolPairs) {\n const compatA = protocolPairs[normalA];\n if (compatA?.includes(normalB)) return true;\n\n const compatB = protocolPairs[normalB];\n if (compatB?.includes(normalA)) return true;\n }\n\n if (NO_GENERIC_FALLBACK.has(protocolType.toLowerCase())) return false;\n\n // Fall back to generic pairs\n const genericA = GENERIC_ROLE_PAIRS[normalA];\n if (genericA?.includes(normalB)) return true;\n\n const genericB = GENERIC_ROLE_PAIRS[normalB];\n if (genericB?.includes(normalA)) return true;\n\n return false;\n}\n\n/**\n * Return all roles compatible with the given role under a protocol type.\n */\nexport function getCompatibleRoles(\n protocolType: string,\n role: string,\n): string[] {\n const normal = role.toLowerCase();\n const result = new Set<string>();\n\n const protocolPairs = PROTOCOL_ROLE_PAIRS[protocolType.toLowerCase()];\n if (protocolPairs?.[normal]) {\n for (const r of protocolPairs[normal]) result.add(r);\n }\n\n if (GENERIC_ROLE_PAIRS[normal] && !NO_GENERIC_FALLBACK.has(protocolType.toLowerCase())) {\n for (const r of GENERIC_ROLE_PAIRS[normal]) result.add(r);\n }\n\n return [...result];\n}\n","import type { InterfaceDef, ProtocolDef } from \"../types/interface.js\";\nimport { areRolesCompatible } from \"./roles.js\";\n\nexport interface ProtocolMatchResult {\n compatible: boolean;\n confidence: number; // 1.0 = explicit match, 0.0 = no match\n matchedProtocol?: string;\n roleA?: string;\n roleB?: string;\n}\n\n/**\n * Try to match two protocol definitions.\n * Returns the best match if any role pair is compatible.\n */\nfunction matchProtocolDefs(a: ProtocolDef, b: ProtocolDef): ProtocolMatchResult {\n if (a.type.toLowerCase() !== b.type.toLowerCase()) {\n return { compatible: false, confidence: 0 };\n }\n\n // Try all role combinations\n for (const roleA of a.roles) {\n for (const roleB of b.roles) {\n if (areRolesCompatible(a.type, roleA, roleB)) {\n return {\n compatible: true,\n confidence: 1.0,\n matchedProtocol: a.type,\n roleA,\n roleB,\n };\n }\n }\n }\n\n return { compatible: false, confidence: 0 };\n}\n\n/**\n * Match two interfaces by finding the best protocol match.\n * Tries all protocol combinations between the two interfaces.\n */\nexport function matchProtocols(\n interfaceA: InterfaceDef,\n interfaceB: InterfaceDef,\n): ProtocolMatchResult {\n let best: ProtocolMatchResult = { compatible: false, confidence: 0 };\n\n for (const protoA of interfaceA.protocols) {\n for (const protoB of interfaceB.protocols) {\n const result = matchProtocolDefs(protoA, protoB);\n if (result.compatible && result.confidence > best.confidence) {\n best = result;\n }\n }\n }\n\n return best;\n}\n","import type { ModuleDef } from \"../types/module.js\";\nimport type { InterfaceDef, InterfaceProfile } from \"../types/interface.js\";\nimport type { RegionPath } from \"./types.js\";\n\n/**\n * A module's interfaces as a region tree (visualizer-spec §2.2). An interface\n * bound into another interface's active profile is a child region of it; every\n * other exposed interface is a root region.\n */\nexport interface RegionNode {\n iface: InterfaceDef;\n path: RegionPath;\n depth: number;\n parent?: RegionNode;\n children: RegionNode[];\n /** slot the parent's profile binds this region to (undefined at roots) */\n slotId?: string;\n}\n\n/** The profile whose bindings define the region tree: first default-active, else first. */\nexport function pickProfile(iface: InterfaceDef): InterfaceProfile | undefined {\n const profiles = iface.profiles ?? [];\n return profiles.find((p) => p.default_active !== false) ?? profiles[0];\n}\n\nfunction bindingTargets(profile: InterfaceProfile): { slotId: string; interfaceId: string }[] {\n const out: { slotId: string; interfaceId: string }[] = [];\n for (const [slotId, value] of Object.entries(profile.bindings)) {\n for (const interfaceId of Array.isArray(value) ? value : [value]) {\n out.push({ slotId, interfaceId });\n }\n }\n return out;\n}\n\nexport function buildRegionTree(module: ModuleDef): RegionNode[] {\n const byId = new Map(module.interfaces.map((i) => [i.id, i]));\n\n const boundIds = new Set<string>();\n for (const iface of module.interfaces) {\n const profile = pickProfile(iface);\n if (!profile) continue;\n for (const { interfaceId } of bindingTargets(profile)) boundIds.add(interfaceId);\n }\n\n const build = (\n iface: InterfaceDef,\n parent: RegionNode | undefined,\n slotId: string | undefined,\n visited: Set<string>,\n ): RegionNode => {\n const node: RegionNode = {\n iface,\n path: [...(parent?.path ?? []), iface.id],\n depth: parent ? parent.depth + 1 : 0,\n parent,\n children: [],\n slotId,\n };\n const profile = pickProfile(iface);\n if (profile) {\n for (const target of bindingTargets(profile)) {\n if (visited.has(target.interfaceId)) continue; // guard against binding cycles\n const child = byId.get(target.interfaceId);\n if (!child) continue;\n node.children.push(\n build(child, node, target.slotId, new Set([...visited, target.interfaceId])),\n );\n }\n }\n return node;\n };\n\n return module.interfaces\n .filter((i) => i.exposed && !boundIds.has(i.id))\n .map((i) => build(i, undefined, undefined, new Set([i.id])));\n}\n\nexport function flattenTree(roots: RegionNode[]): RegionNode[] {\n const out: RegionNode[] = [];\n const walk = (node: RegionNode) => {\n out.push(node);\n node.children.forEach(walk);\n };\n roots.forEach(walk);\n return out;\n}\n\nexport function descendants(node: RegionNode): RegionNode[] {\n const out: RegionNode[] = [];\n const walk = (n: RegionNode) => {\n for (const child of n.children) {\n out.push(child);\n walk(child);\n }\n };\n walk(node);\n return out;\n}\n\nexport function ancestors(node: RegionNode): RegionNode[] {\n const out: RegionNode[] = [];\n let current = node.parent;\n while (current) {\n out.push(current);\n current = current.parent;\n }\n return out;\n}\n","import type { Parameter } from \"../types/parameter.js\";\n\n/**\n * Get the effective range of a parameter, considering value, range, and tolerance.\n * Returns [min, max] or null if no range can be determined.\n */\nexport function getEffectiveRange(param: Parameter): [number, number] | null {\n if (param.range) {\n return param.range;\n }\n\n if (param.value !== undefined) {\n if (param.tolerance === undefined) {\n // Exact value, no tolerance — treat as point range\n return [param.value, param.value];\n }\n\n if (typeof param.tolerance === \"number\") {\n // Absolute tolerance\n return [param.value - param.tolerance, param.value + param.tolerance];\n }\n\n if (param.tolerance.type === \"absolute\") {\n return [\n param.value - param.tolerance.value,\n param.value + param.tolerance.value,\n ];\n }\n\n if (param.tolerance.type === \"percent\") {\n const delta = param.value * (param.tolerance.value / 100);\n return [param.value - delta, param.value + delta];\n }\n }\n\n return null;\n}\n\n/**\n * Check if two numeric ranges overlap.\n */\nexport function rangesOverlap(\n a: [number, number],\n b: [number, number],\n): boolean {\n return a[0] <= b[1] && b[0] <= a[1];\n}\n\nexport interface ParameterCompatibilityResult {\n compatible: boolean;\n reason?: string;\n rangeA?: [number, number];\n rangeB?: [number, number];\n}\n\n/**\n * Check if two parameters are compatible (their ranges overlap).\n * Parameters must have the same unit for comparison to be meaningful.\n */\nexport function parameterCompatible(\n paramA: Parameter,\n paramB: Parameter,\n): ParameterCompatibilityResult {\n if (paramA.unit !== paramB.unit) {\n return {\n compatible: false,\n reason: `Unit mismatch: \"${paramA.unit}\" vs \"${paramB.unit}\"`,\n };\n }\n\n const rangeA = getEffectiveRange(paramA);\n const rangeB = getEffectiveRange(paramB);\n\n if (!rangeA || !rangeB) {\n // Can't determine range for one or both — assume compatible\n return { compatible: true };\n }\n\n const overlap = rangesOverlap(rangeA, rangeB);\n\n return {\n compatible: overlap,\n rangeA,\n rangeB,\n reason: overlap\n ? undefined\n : `Range [${rangeA[0]}, ${rangeA[1]}] does not overlap [${rangeB[0]}, ${rangeB[1]}] ${paramA.unit}`,\n };\n}\n\n/**\n * Check parameter compatibility between two interfaces by matching parameter IDs.\n */\nexport function checkParameterCompatibility(\n paramsA: Parameter[],\n paramsB: Parameter[],\n): ParameterCompatibilityResult[] {\n const results: ParameterCompatibilityResult[] = [];\n\n for (const pA of paramsA) {\n const pB = paramsB.find((p) => p.id === pA.id);\n if (!pB) continue; // No matching parameter — skip\n\n results.push(parameterCompatible(pA, pB));\n }\n\n return results;\n}\n","import type { Parameter } from \"../types/parameter.js\";\nimport { getEffectiveRange, rangesOverlap } from \"../parameters/range.js\";\nimport type { Diagnostic } from \"./types.js\";\n\n/**\n * Parameters whose semantics are aggregation (sum of draws vs. a limit), not\n * range overlap — comparing a supply's max_current to a sink's draw as ranges\n * produces false errors. These are evaluated by the capacity engine (Phase 6,\n * scoped rule packs) or by a directional pair check in joint-check.ts\n * (`supply_current_rating`, `linear_motion_capacity`), so the pairwise\n * overlap check skips them.\n */\nexport const CAPACITY_PARAM_IDS = new Set([\n \"max_current\",\n \"burst_current\",\n \"drive_current\",\n \"current_draw\",\n \"min_supply_power\",\n \"min_supply_current\",\n \"stroke\",\n \"force\",\n \"linear_speed\",\n \"max_flow\",\n \"flow_rate\",\n \"load_rating\",\n \"coil_current\",\n]);\n\n/** SI-prefix normalization so 40 mA and 0.04 A compare in the same base unit. */\nconst UNIT_SCALE: Record<string, { base: string; scale: number }> = {\n mA: { base: \"A\", scale: 1e-3 },\n µA: { base: \"A\", scale: 1e-6 },\n uA: { base: \"A\", scale: 1e-6 },\n mV: { base: \"V\", scale: 1e-3 },\n kV: { base: \"V\", scale: 1e3 },\n kHz: { base: \"Hz\", scale: 1e3 },\n MHz: { base: \"Hz\", scale: 1e6 },\n GHz: { base: \"Hz\", scale: 1e9 },\n ms: { base: \"s\", scale: 1e-3 },\n µs: { base: \"s\", scale: 1e-6 },\n us: { base: \"s\", scale: 1e-6 },\n mm: { base: \"m\", scale: 1e-3 },\n kΩ: { base: \"Ω\", scale: 1e3 },\n MΩ: { base: \"Ω\", scale: 1e6 },\n kPa: { base: \"Pa\", scale: 1e3 },\n bar: { base: \"Pa\", scale: 1e5 },\n mW: { base: \"W\", scale: 1e-3 },\n kW: { base: \"W\", scale: 1e3 },\n};\n\nfunction normalized(param: Parameter): { base: string; range: [number, number] | null } {\n const scale = UNIT_SCALE[param.unit as string];\n const range = getEffectiveRange(param);\n if (!scale) return { base: param.unit as string, range };\n return {\n base: scale.base,\n range: range ? [range[0] * scale.scale, range[1] * scale.scale] : null,\n };\n}\n\n/**\n * Pairwise parameter check between two matched regions: for every parameter id\n * present on both sides (excluding capacity-semantics params), the effective\n * ranges must overlap in a common base unit.\n */\nexport function checkPairParameters(\n paramsA: Parameter[] | undefined,\n paramsB: Parameter[] | undefined,\n): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n\n for (const pA of paramsA ?? []) {\n if (CAPACITY_PARAM_IDS.has(pA.id)) continue;\n const pB = (paramsB ?? []).find((p) => p.id === pA.id);\n if (!pB) continue;\n\n const nA = normalized(pA);\n const nB = normalized(pB);\n\n if (nA.base !== nB.base) {\n diagnostics.push({\n severity: \"error\",\n code: \"param_unit_mismatch\",\n message: `${pA.id}: unit \"${pA.unit}\" is not comparable with \"${pB.unit}\"`,\n refs: [pA.id],\n });\n continue;\n }\n if (!nA.range || !nB.range) continue; // no determinable range — not checkable\n\n if (!rangesOverlap(nA.range, nB.range)) {\n diagnostics.push({\n severity: \"error\",\n code: \"param_range_disjoint\",\n message: `${pA.id}: ${fmtParam(pA)} vs ${fmtParam(pB)} (ranges do not overlap)`,\n refs: [pA.id],\n });\n }\n }\n\n return diagnostics;\n}\n\n/** A parameter in its own unit, e.g. \"30.5 mm\" or \"18–25.2 V\". */\nfunction fmtParam(param: Parameter): string {\n const range = getEffectiveRange(param);\n const unit = param.unit === \"dimensionless\" ? \"\" : ` ${param.unit}`;\n if (!range) return `?${unit}`;\n return range[0] === range[1] ? `${range[0]}${unit}` : `${range[0]}–${range[1]}${unit}`;\n}\n","import type { InterfaceDef } from \"../types/interface.js\";\nimport type { Parameter } from \"../types/parameter.js\";\nimport {\n angularPitchDeg,\n fastenerDiameterMm,\n forceN,\n holeCount,\n holePitchMm,\n holeSpacingMm,\n keyWidthMm,\n leadMm,\n linearSpeedMmS,\n shaftDiameterMm,\n slotLengthMm,\n strokeMm,\n threadPitchMm,\n} from \"./params.js\";\n\n/**\n * Mechanical interface builders: bolt patterns, rotating shafts and bores,\n * and linear motion.\n *\n * Mating features pair by role and their parameters must overlap:\n * a 30.5 mm stack pattern does not accept a 20 mm board, and an M3 pattern\n * does not accept M2 fasteners. The pair checks in `drc/joint-check.ts`\n * compare what parameters cannot: bolt pattern shapes, shaft profiles and\n * genders, and linear travel and force (docs/mechanical-interfaces.md).\n */\n\n/** \"structure\" = frame / plate providing the holes; \"component\" = part mounted to it. */\nexport type BoltPatternRole = \"structure\" | \"component\";\n\nexport interface BoltPatternConfig {\n id: string;\n name?: string;\n role: BoltPatternRole;\n /**\n * \"cross\": four holes on two perpendicular diagonals of different\n * lengths, as on motor bases (\"16 × 19\"): one pair `spacingMm` apart on x,\n * the other `spacingYmm` apart on y. A cross mates another cross; one\n * with equal diagonals d also mates a 4-hole circle of diameter d or a\n * square of side d/√2, which have the same holes.\n *\n * \"row\": `holeCount` holes in a straight line, `pitchMm` apart (a\n * bracket leg or a channel on a hole grid). hole_spacing is the span from\n * the first hole to the last. A row mates a row whose holes land on its\n * own (same pitch or a whole multiple of it, no longer than it), or a\n * slot at least as long as the row.\n *\n * \"slot\": a straight slot that takes fasteners anywhere along\n * `slotLengthMm` (an extrusion's T-slot, a slotted bracket). It mates a\n * row, a two-hole rectangle on a line (spacingYmm 0) that fits its length,\n * or another slot when one of them is a through slot. A slot has no fixed\n * holes. For holes slotted so their spacing can vary, keep the shape and\n * give spacingMm a range instead.\n *\n * \"grid\": holes on every point of a lattice (a plate, a channel or a gear\n * web drilled on a hole grid). `lattice` \"rectangular\" (rows `pitchYmm`\n * apart, columns `pitchMm` apart) or \"triangular\" (every hole six\n * neighbours `pitchMm` away: rows pitch × √3/2 apart, every other row\n * offset by half a pitch; one grid line along x). The extent is `rows` ×\n * `columns`, centred on the frame, or a disc: every lattice point within\n * `withinDiameterMm` of the frame origin (a lattice point) and outside\n * `minDiameterMm` (a hub or bore). The hole count is derived; give\n * `holeCount` to have the builder confirm it. A grid mates any pattern\n * whose holes all land on its points (`bolt_pattern_holes`): a row along a\n * grid line, a square on the grid, a six-hole circle of diameter 2 ×\n * pitch on a triangular grid. Fasteners through one line of a grid fit a\n * slot.\n *\n * \"arc\": a partial bolt circle: `holeCount` holes on a circle of diameter\n * `spacingMm`, `angularPitchDeg` apart, the first at `startAngleDeg` from\n * the frame's x axis (counter-clockwise about the normal): five of six\n * positions drilled (start −30°, pitch 60°) or four (0°, 60°, 120°,\n * 180°). An arc mates a full circle whose holes include its own, an arc\n * or grid that has its holes, or a pattern whose holes are among its own.\n */\n shape: \"square\" | \"rectangle\" | \"circle\" | \"cross\" | \"row\" | \"slot\" | \"grid\" | \"arc\";\n /**\n * Square side, rectangle X spacing, bolt-circle diameter, or the cross's\n * x diagonal, in mm. Required for those shapes; a row derives it (the\n * span, pitch × (holes − 1)) and a slot has none.\n * A [min, max] range models slotted holes accepting any spacing within it.\n */\n spacingMm?: number | [number, number];\n /** Rectangle Y spacing, or the cross's y diagonal, in mm. */\n spacingYmm?: number | [number, number];\n /** Row: hole-to-hole pitch in mm. Grid: the pitch along x (rectangular), or between neighbours (triangular). */\n pitchMm?: number;\n /** Rectangular grid: the pitch along y (between rows), when it is not `pitchMm`. */\n pitchYmm?: number;\n /** Grid: the lattice (default \"rectangular\"). */\n lattice?: \"rectangular\" | \"triangular\";\n /** Grid: number of rows (along y) and columns (along x), centred on the frame. */\n rows?: number;\n columns?: number;\n /** Grid: a disc extent instead of rows × columns: lattice points within this diameter of the origin. */\n withinDiameterMm?: number;\n /** Grid with a disc extent: leave out the points closer to the origin than half this (a hub). */\n minDiameterMm?: number;\n /** Arc: the angle between neighbouring holes, in degrees. */\n angularPitchDeg?: number;\n /** Arc: the first hole's angle from the frame's x axis, counter-clockwise, in degrees (default 0). */\n startAngleDeg?: number;\n /** Slot: the length along which fasteners can sit, in mm. */\n slotLengthMm?: number;\n /**\n * Slot: \"t_slot\" holds a nut or a screw head captive in a channel (an\n * extrusion); \"through\" is an open slot a fastener passes through (a\n * slotted bracket or plate).\n */\n slotKind?: \"t_slot\" | \"through\";\n /** Number of holes. Required except on a slot (any number of fasteners). */\n holeCount?: number;\n /** Fastener designation, e.g. \"M3\". */\n fastener: string;\n /** Nominal fastener diameter in mm (M3 → 3). A range for holes that take several sizes. */\n fastenerDiameterMm: number | [number, number];\n /** Holes are threaded (true) or clearance/through holes (false). */\n threaded?: boolean;\n /** Anything else the source states (grommets, countersink, slot length). */\n note?: string;\n maxInstances?: number;\n exposed?: boolean;\n defaultActive?: boolean;\n}\n\nexport function BoltPattern(config: BoltPatternConfig): InterfaceDef {\n const fail = (why: string): never => {\n throw new Error(`BoltPattern ${config.id}: ${why}`);\n };\n const gridFields = [\"pitchYmm\", \"lattice\", \"rows\", \"columns\", \"withinDiameterMm\", \"minDiameterMm\"] as const;\n if (config.shape !== \"grid\" && gridFields.some((k) => config[k] !== undefined)) fail(`${gridFields.filter((k) => config[k] !== undefined).join(\", \")}: for a grid`);\n if (config.shape !== \"arc\" && (config.angularPitchDeg !== undefined || config.startAngleDeg !== undefined)) fail(\"angularPitchDeg and startAngleDeg are for an arc\");\n if (config.shape === \"grid\" || config.shape === \"arc\") return holePatternInterface(config, fail);\n if (config.shape === \"cross\" && (config.spacingYmm === undefined || config.holeCount !== 4)) {\n fail(\"a cross pattern has four holes and needs spacingYmm (the second diagonal)\");\n }\n if (config.shape !== \"row\" && config.pitchMm !== undefined) fail(\"pitchMm is for a row or a grid\");\n if (config.shape !== \"slot\" && (config.slotLengthMm !== undefined || config.slotKind !== undefined)) fail(\"slotLengthMm and slotKind are for a slot\");\n\n const parameters: Parameter[] = [];\n if (config.shape === \"row\") {\n if (config.pitchMm === undefined || !(config.pitchMm > 0)) fail(\"a row needs pitchMm\");\n if (config.holeCount === undefined || config.holeCount < 2) fail(\"a row has two or more holes\");\n if (config.spacingMm !== undefined || config.spacingYmm !== undefined) fail(\"a row's span comes from pitchMm and holeCount; leave spacingMm and spacingYmm out\");\n const span = Number((config.pitchMm! * (config.holeCount! - 1)).toFixed(6));\n parameters.push(holeSpacingMm(span), holeCount(config.holeCount!), holePitchMm(config.pitchMm!));\n } else if (config.shape === \"slot\") {\n if (config.slotLengthMm === undefined || !(config.slotLengthMm > 0)) fail(\"a slot needs slotLengthMm\");\n if (config.spacingMm !== undefined || config.spacingYmm !== undefined) fail(\"a slot has no hole spacing; give slotLengthMm\");\n parameters.push(slotLengthMm(config.slotLengthMm!));\n if (config.holeCount !== undefined) parameters.push(holeCount(config.holeCount));\n } else {\n if (config.spacingMm === undefined) fail(`a ${config.shape} pattern needs spacingMm`);\n if (config.holeCount === undefined) fail(`a ${config.shape} pattern needs holeCount`);\n parameters.push(holeSpacingMm(config.spacingMm!), holeCount(config.holeCount!));\n }\n parameters.push(fastenerDiameterMm(config.fastenerDiameterMm));\n if (config.spacingYmm !== undefined) parameters.push(holeSpacingMm(config.spacingYmm, \"y\"));\n\n return {\n id: config.id,\n name: config.name,\n domain: \"mechanical\",\n exposed: config.exposed ?? true,\n default_active: config.defaultActive ?? true,\n protocols: [{ type: \"bolt_pattern\", roles: [config.role] }],\n capabilities: [\"bolt_pattern\"],\n parameters,\n ...(config.maxInstances !== undefined ? { max_instances: config.maxInstances } : {}),\n traits: [\n {\n type: \"bolt_pattern\",\n params: {\n shape: config.shape,\n fastener: config.fastener,\n ...(config.slotKind !== undefined ? { slot_kind: config.slotKind } : {}),\n ...(config.threaded !== undefined ? { threaded: config.threaded } : {}),\n ...(config.note !== undefined ? { note: config.note } : {}),\n },\n },\n ],\n };\n}\n\n/** Lattice description a grid's `bolt_pattern` trait carries; `latticeHoles` places its holes. */\nexport interface GridSpec {\n lattice: \"rectangular\" | \"triangular\";\n pitch: number;\n pitchY?: number;\n rows?: number;\n columns?: number;\n withinDiameter?: number;\n minDiameter?: number;\n}\n\nconst r6 = (v: number) => Number(v.toFixed(6)) + 0;\n\n/**\n * The holes of a grid in its frame's x/y, in mm: rows × columns centred on\n * the origin, or every lattice point (the origin is one) within the disc.\n * Rows run along x; a triangular lattice offsets every other row by half a\n * pitch, rows pitch × √3/2 apart.\n */\nexport function latticeHoles(g: GridSpec): [number, number][] {\n const tri = g.lattice === \"triangular\";\n const dy = tri ? (g.pitch * Math.sqrt(3)) / 2 : (g.pitchY ?? g.pitch);\n const out: [number, number][] = [];\n if (g.withinDiameter !== undefined) {\n const rMax = g.withinDiameter / 2 + 1e-6;\n const rMin = (g.minDiameter ?? 0) / 2 - 1e-6;\n const nj = Math.ceil(rMax / dy) + 1;\n const ni = Math.ceil(rMax / g.pitch) + 2;\n for (let j = -nj; j <= nj; j++) {\n for (let i = -ni - Math.abs(j); i <= ni + Math.abs(j); i++) {\n const x = g.pitch * i + (tri ? (g.pitch / 2) * j : 0);\n const y = dy * j;\n const r = Math.hypot(x, y);\n if (r <= rMax && r >= rMin) out.push([r6(x), r6(y)]);\n }\n }\n return out.sort((p, q) => p[1] - q[1] || p[0] - q[0]);\n }\n const rows = g.rows ?? 1;\n const cols = g.columns ?? 1;\n const shift = tri && rows > 1 ? g.pitch / 4 : 0; // centre the offset rows\n for (let j = 0; j < rows; j++) {\n for (let i = 0; i < cols; i++) {\n const off = tri && j % 2 === 1 ? g.pitch / 2 : 0;\n out.push([r6(-((cols - 1) * g.pitch) / 2 + i * g.pitch + off - shift), r6(-((rows - 1) * dy) / 2 + j * dy)]);\n }\n }\n return out;\n}\n\n/** The holes of a partial bolt circle in its frame's x/y, in mm. */\nexport function arcHoles(diameter: number, count: number, pitchDeg: number, startDeg = 0): [number, number][] {\n return Array.from({ length: count }, (_, k) => {\n const a = ((startDeg + k * pitchDeg) * Math.PI) / 180;\n return [r6((Math.cos(a) * diameter) / 2), r6((Math.sin(a) * diameter) / 2)] as [number, number];\n });\n}\n\nfunction holePatternInterface(config: BoltPatternConfig, fail: (why: string) => never): InterfaceDef {\n const parameters: Parameter[] = [];\n const params: Record<string, unknown> = { shape: config.shape, fastener: config.fastener };\n if (config.slotLengthMm !== undefined || config.slotKind !== undefined) fail(\"slotLengthMm and slotKind are for a slot\");\n if (config.spacingYmm !== undefined) fail(`a ${config.shape} has no spacingYmm`);\n if (config.shape === \"grid\") {\n const lattice = config.lattice ?? \"rectangular\";\n if (config.pitchMm === undefined || !(config.pitchMm > 0)) fail(\"a grid needs pitchMm\");\n if (config.spacingMm !== undefined) fail(\"a grid has no spacingMm; give pitchMm and the extent\");\n if (lattice === \"triangular\" && config.pitchYmm !== undefined) fail(\"a triangular grid has one pitch; leave pitchYmm out\");\n const disc = config.withinDiameterMm !== undefined;\n if (disc && (config.rows !== undefined || config.columns !== undefined)) fail(\"give rows and columns, or withinDiameterMm, not both\");\n if (!disc && (config.rows === undefined || config.columns === undefined)) fail(\"a grid needs rows and columns, or withinDiameterMm\");\n if (config.minDiameterMm !== undefined && !disc) fail(\"minDiameterMm is for a disc extent\");\n if (!disc && (config.rows! < 1 || config.columns! < 1 || !Number.isInteger(config.rows) || !Number.isInteger(config.columns))) fail(\"rows and columns are whole numbers from 1\");\n if (!disc && (config.rows === 1 || config.columns === 1)) fail(\"a grid of one row or one column is a row: use shape \\\"row\\\"\");\n const spec: GridSpec = {\n lattice,\n pitch: config.pitchMm!,\n ...(config.pitchYmm !== undefined ? { pitchY: config.pitchYmm } : {}),\n ...(disc ? { withinDiameter: config.withinDiameterMm! } : { rows: config.rows!, columns: config.columns! }),\n ...(config.minDiameterMm !== undefined ? { minDiameter: config.minDiameterMm } : {}),\n };\n const count = latticeHoles(spec).length;\n if (count < 2) fail(\"the extent holds fewer than two lattice points\");\n if (config.holeCount !== undefined && config.holeCount !== count) fail(`the lattice and extent give ${count} holes, not ${config.holeCount}`);\n parameters.push(holeCount(count), holePitchMm(config.pitchMm!));\n if (lattice === \"rectangular\") parameters.push(holePitchMm(config.pitchYmm ?? config.pitchMm!, \"y\"));\n params.lattice = lattice;\n if (disc) {\n params.within_diameter_mm = config.withinDiameterMm;\n if (config.minDiameterMm !== undefined) params.min_diameter_mm = config.minDiameterMm;\n } else {\n params.rows = config.rows;\n params.columns = config.columns;\n }\n } else {\n if (config.spacingMm === undefined || Array.isArray(config.spacingMm) || !(config.spacingMm > 0)) fail(\"an arc needs spacingMm, the circle's diameter\");\n if (config.holeCount === undefined || config.holeCount < 2) fail(\"an arc has two or more holes\");\n if (config.angularPitchDeg === undefined || !(config.angularPitchDeg > 0)) fail(\"an arc needs angularPitchDeg\");\n if (config.pitchMm !== undefined) fail(\"pitchMm is for a row or a grid\");\n if (config.angularPitchDeg! * config.holeCount! >= 360 - 1e-9) fail(\"the holes go round the whole circle (or overlap): use shape \\\"circle\\\"\");\n parameters.push(holeSpacingMm(config.spacingMm as number), holeCount(config.holeCount!), angularPitchDeg(config.angularPitchDeg!));\n params.start_angle_deg = config.startAngleDeg ?? 0;\n }\n parameters.push(fastenerDiameterMm(config.fastenerDiameterMm));\n if (config.threaded !== undefined) params.threaded = config.threaded;\n if (config.note !== undefined) params.note = config.note;\n return {\n id: config.id,\n name: config.name,\n domain: \"mechanical\",\n exposed: config.exposed ?? true,\n default_active: config.defaultActive ?? true,\n protocols: [{ type: \"bolt_pattern\", roles: [config.role] }],\n capabilities: [\"bolt_pattern\"],\n parameters,\n ...(config.maxInstances !== undefined ? { max_instances: config.maxInstances } : {}),\n traits: [{ type: \"bolt_pattern\", params }],\n };\n}\n\n/**\n * Cross-section of a shaft and of the bore it fits. shaft_diameter is the\n * across-flats size for hex, rounded hex and square; the nominal diameter\n * for round, D-cut, double-D and keyed; the major diameter for a spline.\n *\n * - round: plain cylinder (torque by set screw, clamp or press fit).\n * - hex: hexagon with sharp corners (REV and FTC 5 mm hex, 1/2 in hex).\n * - rounded_hex: hexagon with turned corners (REV UltraHex); fits a hex\n * bore of the same across-flats size.\n * - d_cut: one flat; double_d: two opposite flats.\n * - keyed: round with a keyway and key (`keyWidthMm`).\n * - spline: teeth (`spline` names the standard, e.g. \"25T\" servo spline).\n * - square: square section (across flats).\n */\nexport type ShaftProfile = \"round\" | \"hex\" | \"rounded_hex\" | \"d_cut\" | \"double_d\" | \"keyed\" | \"spline\" | \"square\";\n\n/** \"shaft\" = the male part (a motor shaft, a hex shaft); \"bore\" = the female part (a hub, a gear's bore, a hollow output). */\nexport type ShaftGender = \"shaft\" | \"bore\";\n\nexport interface ShaftConfig {\n id: string;\n name?: string;\n /**\n * Which way torque flows: \"output\" drives (a motor's shaft or hollow\n * output), \"input\" is driven (a propeller hub, a pulley, a gearbox\n * input), \"bidirectional\" carries torque from a driver to a load (a loose\n * shaft, a spacer, a coupler). Independent of `gender`: a motor with a\n * hollow hex output is an output bore.\n */\n role: \"output\" | \"input\" | \"bidirectional\";\n /** Shaft diameter, or bore diameter, in mm (across flats for hex, rounded hex and square). */\n diameterMm: number;\n /** Cross-section. Stated profiles are checked against the mating side's. */\n profile?: ShaftProfile;\n /** Male shaft or female bore. Two shafts or two bores do not mate. */\n gender?: ShaftGender;\n /** Keyed: key (shaft) or keyway (bore) width in mm. */\n keyWidthMm?: number;\n /** Spline: the standard or tooth count as the source states it (\"25T\", \"MAXSpline\"). */\n spline?: string;\n /** Thread designation if threaded, e.g. \"M5\". */\n thread?: string;\n /**\n * A round bore made to go over a shaft of another profile and clamp on it\n * (an adapter: a shaft collar's Ø6 bore on a 5 mm hex shaft, held by a set\n * screw on a flat). The pair check fits it to a shaft of that profile and\n * size instead of comparing the diameters; `by` says what holds it.\n * Only on a round bore, which must clear the shaft's corners.\n */\n clampsOn?: { profile: ShaftProfile; diameterMm: number; by: \"set_screw\" | \"clamp_screw\" | \"press\" | \"adhesive\" };\n /** Anything else the source states (shaft length, hub type, rotation). */\n note?: string;\n exposed?: boolean;\n defaultActive?: boolean;\n}\n\nexport function Shaft(config: ShaftConfig): InterfaceDef {\n if (config.keyWidthMm !== undefined && config.profile !== \"keyed\") {\n throw new Error(`Shaft ${config.id}: keyWidthMm is for a keyed profile`);\n }\n if (config.spline !== undefined && config.profile !== \"spline\") {\n throw new Error(`Shaft ${config.id}: spline is for a spline profile`);\n }\n if (config.clampsOn !== undefined) {\n if (config.gender !== \"bore\" || (config.profile ?? \"round\") !== \"round\") throw new Error(`Shaft ${config.id}: clampsOn is for a round bore`);\n const c = config.clampsOn;\n const corners = c.profile === \"hex\" ? (c.diameterMm * 2) / Math.sqrt(3) : c.profile === \"square\" ? c.diameterMm * Math.SQRT2 : c.diameterMm;\n if (config.diameterMm + 1e-9 < corners - 0.05) {\n throw new Error(`Shaft ${config.id}: a Ø${config.diameterMm} mm bore does not clear a ${c.diameterMm} mm ${c.profile} shaft (${+corners.toFixed(3)} mm across corners)`);\n }\n }\n const parameters: Parameter[] = [shaftDiameterMm(config.diameterMm)];\n if (config.keyWidthMm !== undefined) parameters.push(keyWidthMm(config.keyWidthMm));\n const params: Record<string, unknown> = {\n ...(config.clampsOn !== undefined ? { clamps_on: { profile: config.clampsOn.profile, diameter_mm: config.clampsOn.diameterMm, by: config.clampsOn.by } } : {}),\n ...(config.profile !== undefined ? { profile: config.profile } : {}),\n ...(config.gender !== undefined ? { gender: config.gender } : {}),\n ...(config.spline !== undefined ? { spline: config.spline } : {}),\n ...(config.thread !== undefined ? { thread: config.thread } : {}),\n ...(config.note !== undefined ? { note: config.note } : {}),\n };\n return {\n id: config.id,\n name: config.name,\n domain: \"mechanical\",\n exposed: config.exposed ?? true,\n default_active: config.defaultActive ?? true,\n protocols: [{ type: \"shaft\", roles: [config.role] }],\n capabilities: [\"shaft\"],\n parameters,\n max_instances: 1,\n ...(Object.keys(params).length > 0 ? { traits: [{ type: \"shaft\", params }] } : {}),\n };\n}\n\n/** How a linear output is produced, as the source describes it. */\nexport type LinearMechanism = \"lead_screw\" | \"ball_screw\" | \"belt\" | \"rack_and_pinion\" | \"pneumatic\" | \"hydraulic\" | \"solenoid\" | \"linear_motor\" | \"other\";\n\nexport interface LinearMotionConfig {\n id: string;\n name?: string;\n /**\n * \"output\": the moving member that pushes or pulls (an actuator's rod or\n * inner tube, a lead screw nut's carriage); \"input\": a load or slide\n * driven by one. A load may state the stroke and force it needs.\n */\n role: \"output\" | \"input\";\n /** Travel in mm: given (output) or needed (input). */\n strokeMm?: number;\n /** Travel per input revolution in mm (pitch × starts). */\n leadMm?: number;\n /** Screw thread pitch in mm. */\n threadPitchMm?: number;\n /** Thread starts (lead = pitch × starts). */\n starts?: number;\n /** Rated axial force in N (output), or the force the load needs (input). Say in `note` whether it is dynamic, static or peak. */\n forceN?: number;\n /** Rated linear speed in mm/s. */\n speedMmS?: number;\n mechanism?: LinearMechanism;\n /** True when a load on the output can turn the input (an unpowered actuator does not hold). */\n backdrivable?: boolean;\n /** Anything else the source states (end stops, rod end, side-load limits). */\n note?: string;\n exposed?: boolean;\n defaultActive?: boolean;\n}\n\n/**\n * A linear motion interface: the moving output of a linear actuator, lead\n * screw or slide (role output), or the load it drives (role input). Stroke\n * and force are capacities: the pair check requires the output's stroke and\n * force to cover what the load states (`linear_motion_capacity`). Lead and\n * thread pitch must agree when both sides state them (a screw and its nut).\n */\nexport function LinearMotion(config: LinearMotionConfig): InterfaceDef {\n if (config.starts !== undefined && config.leadMm !== undefined && config.threadPitchMm !== undefined) {\n const lead = config.threadPitchMm * config.starts;\n if (Math.abs(lead - config.leadMm) > 1e-6 * Math.max(1, lead)) {\n throw new Error(`LinearMotion ${config.id}: lead ${config.leadMm} mm is not pitch ${config.threadPitchMm} mm × ${config.starts} starts`);\n }\n }\n const parameters: Parameter[] = [];\n if (config.strokeMm !== undefined) parameters.push(strokeMm(config.strokeMm));\n if (config.leadMm !== undefined) parameters.push(leadMm(config.leadMm));\n if (config.threadPitchMm !== undefined) parameters.push(threadPitchMm(config.threadPitchMm));\n if (config.forceN !== undefined) parameters.push(forceN(config.forceN));\n if (config.speedMmS !== undefined) parameters.push(linearSpeedMmS(config.speedMmS));\n const params: Record<string, unknown> = {\n ...(config.mechanism !== undefined ? { mechanism: config.mechanism } : {}),\n ...(config.starts !== undefined ? { starts: config.starts } : {}),\n ...(config.backdrivable !== undefined ? { backdrivable: config.backdrivable } : {}),\n ...(config.note !== undefined ? { note: config.note } : {}),\n };\n return {\n id: config.id,\n name: config.name,\n domain: \"mechanical\",\n exposed: config.exposed ?? true,\n default_active: config.defaultActive ?? true,\n protocols: [{ type: \"linear_motion\", roles: [config.role] }],\n capabilities: [\"linear_motion\"],\n ...(parameters.length > 0 ? { parameters } : {}),\n max_instances: 1,\n ...(Object.keys(params).length > 0 ? { traits: [{ type: \"linear_motion\", params }] } : {}),\n };\n}\n","import type { InterfaceDef } from \"../types/interface.js\";\nimport type { Diagnostic } from \"./types.js\";\nimport { getEffectiveRange } from \"../parameters/range.js\";\nimport { arcHoles, latticeHoles, type GridSpec } from \"../protocols/mechanical.js\";\n\n/**\n * Pair checks on how two matched interfaces physically join, beyond their\n * protocols and parameters:\n *\n * - `fluid_joint_mismatch`: two fluid ports (FluidPort's `fluid_joint`\n * trait) whose joints do not mate. Threads need the same standard (NPT and\n * NPTF count as one) and size and opposite genders; a push-to-connect\n * fitting or a hose barb takes a tube; quick couplers need the same style\n * and opposite genders. Thread sizes compare without inch marks, spaces\n * or case, and a BSPP or BSPT size may carry ISO 228's \"G\" or ISO 7's\n * \"R\"/\"Rc\"/\"Rp\" prefix (\"G1/4\" is \"1/4\"). Tube diameters are checked as\n * parameters.\n * - `bolt_pattern_shape`: a cross bolt pattern (two diagonals, BoltPattern\n * shape \"cross\") against a pattern of another shape whose holes differ. A\n * cross with equal diagonals d has the holes of a 4-hole circle of\n * diameter d and of a square of side d/√2, so those pairs are compared by\n * that diagonal instead (see boltPatternsShareHoles). Square, rectangle and\n * circle patterns are compared by their parameters only.\n * - `bolt_pattern_line`: a row (BoltPattern shape \"row\") or a slot (shape\n * \"slot\") against a pattern whose holes do not land on it. A row mates a\n * row whose holes fall on its own: the shorter row's pitch is the\n * longer's or a whole multiple of it, and it is no longer. A rectangle\n * with hole_spacing_y 0 counts as a two-hole row (or, when its spacing is\n * a range from 0, as a slot: the older way to write one). A row fits a\n * slot no shorter than the row. Two T-slots do not mate (neither has a\n * hole for the fastener); a through slot mates any slot. A row or slot\n * never mates a pattern whose holes are not on one line (square, circle,\n * cross, a rectangle with a y spacing). The check compares the spans,\n * pitches and lengths itself (see pairCheckedParams).\n * - `bolt_pattern_holes`: a grid (BoltPattern shape \"grid\") or a partial\n * circle (shape \"arc\") against another pattern: the pattern with fewer\n * holes must land on the other's holes under some rotation and shift (or\n * their mirror image), within 0.05 mm. A grid fits a slot (fasteners\n * through one line of the grid); an arc does not.\n * - `shaft_fit`: a shaft and a bore (Shaft `gender`, `profile`) that do not\n * fit: two shafts or two bores; or profiles that do not fit (a hex shaft\n * in a round bore, two different splines). A round shaft in a keyed bore,\n * or a keyed shaft in a round one, fits without its key carrying torque\n * (warning). Diameters and key widths are compared as parameters.\n * - `linear_motion_capacity`: a linear output whose stroke or force is less\n * than the load it drives states it needs.\n * - `supply_current_rating`: a source (a power output, a controller\n * channel) rated for less continuous current than the input it feeds says\n * its source must be rated for (`min_supply_current`); info when the\n * source states no rating.\n */\nexport function checkPairJoints(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n return [...fluidJoint(a, b), ...boltHoles(a, b), ...boltShape(a, b), ...boltLine(a, b), ...shaftFit(a, b), ...linearCapacity(a, b), ...supplyCurrent(a, b)];\n}\n\n/**\n * Pairings whose protocols and roles match but which never mate as they\n * are: two shafts or two bores (a gear's hex bore and another gear's).\n * `validatePair` does not auto-connect them; it lists them as potentials,\n * and an explicit link reports `shaft_fit`.\n */\nexport function neverMates(a: InterfaceDef, b: InterfaceDef): boolean {\n if (!a.protocols.some((p) => p.type === \"shaft\") || !b.protocols.some((p) => p.type === \"shaft\")) return false;\n const [ga, gb] = [traitParams(a, \"shaft\")?.gender, traitParams(b, \"shaft\")?.gender];\n return ga !== undefined && ga === gb;\n}\n\n/**\n * Parameters the joint check compares itself for this pair, which the\n * pairwise overlap check must skip: hole spacings of bolt patterns that share\n * holes in another shape (a cross and a circle), and the spans, counts,\n * pitches and lengths of row and slot patterns.\n */\nexport function pairCheckedParams(a: InterfaceDef, b: InterfaceDef): Set<string> {\n if (holeRule(a, b)) return new Set([\"hole_spacing\", \"hole_spacing_y\", \"hole_count\", \"hole_pitch\", \"hole_pitch_y\", \"angular_pitch\", \"slot_length\"]);\n if (clampFit(a, b)) return new Set([\"shaft_diameter\"]);\n if (lineRule(a, b)) return new Set([\"hole_spacing\", \"hole_spacing_y\", \"hole_count\", \"hole_pitch\", \"slot_length\"]);\n if (boltPatternsShareHoles(a, b)) return new Set([\"hole_spacing\", \"hole_spacing_y\"]);\n return new Set();\n}\n\nconst traitParams = (iface: InterfaceDef, type: string): Record<string, unknown> | undefined =>\n iface.traits?.find((t) => t.type === type)?.params as Record<string, unknown> | undefined;\n\nconst THREAD_FAMILY: Record<string, string> = { npt: \"npt\", nptf: \"npt\" };\nconst threadFamily = (s: unknown) => {\n const k = String(s ?? \"\").toLowerCase();\n return THREAD_FAMILY[k] ?? k;\n};\n/** BSP threads: ISO 228 parallel sizes are written \"G1/4\", ISO 7 taper sizes \"R1/4\", \"Rc1/4\" or \"Rp1/4\". */\nconst BSP_PREFIX = /^(g|rc|rp|r)(?=\\d)/;\nconst normSize = (s: unknown, standard?: unknown) => {\n const size = String(s ?? \"\").replace(/[\"″\\s]/g, \"\").toLowerCase();\n return /^bsp/.test(String(standard ?? \"\").toLowerCase()) ? size.replace(BSP_PREFIX, \"\") : size;\n};\n\n/** Joint kinds that mate with each other (unordered). */\nconst MATES: Record<string, string[]> = {\n thread: [\"thread\"],\n push_to_connect: [\"tube\"],\n tube: [\"push_to_connect\", \"barb\"],\n barb: [\"tube\"],\n quick_coupler: [\"quick_coupler\"],\n};\n\nfunction describe(j: Record<string, unknown>): string {\n if (j.kind === \"thread\") return `${j.standard} ${j.size} ${j.gender} thread`;\n if (j.kind === \"quick_coupler\") return `${j.style} ${j.gender} quick coupler`;\n return String(j.kind).replace(/_/g, \"-\");\n}\n\nfunction fluidJoint(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n const ja = traitParams(a, \"fluid_joint\");\n const jb = traitParams(b, \"fluid_joint\");\n if (!ja || !jb) return [];\n const problem = (why: string): Diagnostic[] => [\n { severity: \"error\", code: \"fluid_joint_mismatch\", message: `${describe(ja)} does not mate with ${describe(jb)}: ${why}`, refs: [a.id, b.id] },\n ];\n if (!(MATES[String(ja.kind)] ?? []).includes(String(jb.kind))) return problem(\"these joint kinds do not connect without a fitting\");\n if (ja.kind === \"thread\") {\n if (threadFamily(ja.standard) !== threadFamily(jb.standard)) return problem(\"different thread standards\");\n if (normSize(ja.size, ja.standard) !== normSize(jb.size, jb.standard)) return problem(\"different thread sizes\");\n }\n if (ja.kind === \"quick_coupler\" && String(ja.style).toLowerCase() !== String(jb.style).toLowerCase()) return problem(\"different coupler styles\");\n if ((ja.kind === \"thread\" || ja.kind === \"quick_coupler\") && ja.gender === jb.gender) return problem(`both are ${ja.gender}`);\n if ((ja.kind === \"barb\" || jb.kind === \"barb\") && ![a, b].every((x) => x.parameters?.some((p) => p.id === \"tube_id\"))) {\n return [{ severity: \"warning\", code: \"fluid_joint_mismatch\", message: \"a hose barb's fit cannot be checked: the tube states no inside diameter\", refs: [a.id, b.id] }];\n }\n return [];\n}\n\n/** How close two hole positions must be to count as the same hole, in mm. */\nconst HOLE_TOLERANCE_MM = 0.05;\n\nconst paramRange = (iface: InterfaceDef, id: string): [number, number] | undefined => {\n const p = iface.parameters?.find((x) => x.id === id);\n return (p && getEffectiveRange(p)) ?? undefined;\n};\n\n/**\n * The diagonal of a 4-hole pattern whose holes lie on a square (equal\n * diagonals), as a range in mm, or undefined for any other pattern: a 4-hole\n * circle's diameter, a square's side × √2, or a cross whose two diagonals can\n * be equal (their ranges overlap).\n */\nfunction squareDiagonal(iface: InterfaceDef): [number, number] | undefined {\n const shape = traitParams(iface, \"bolt_pattern\")?.shape;\n const count = paramRange(iface, \"hole_count\");\n if (count && (count[0] !== 4 || count[1] !== 4)) return undefined;\n const x = paramRange(iface, \"hole_spacing\");\n if (!x) return undefined;\n if (shape === \"circle\") return x;\n if (shape === \"square\") return [x[0] * Math.SQRT2, x[1] * Math.SQRT2];\n if (shape === \"cross\") {\n const y = paramRange(iface, \"hole_spacing_y\") ?? x;\n const lo = Math.max(x[0], y[0]);\n const hi = Math.min(x[1], y[1]);\n return lo <= hi + HOLE_TOLERANCE_MM ? [Math.min(lo, hi), Math.max(lo, hi)] : undefined;\n }\n return undefined;\n}\n\nconst overlaps = (a: [number, number], b: [number, number]) => a[0] <= b[1] + HOLE_TOLERANCE_MM && b[0] <= a[1] + HOLE_TOLERANCE_MM;\n\n/**\n * Two bolt patterns of different shapes, one a cross, that have the same\n * holes: a cross with equal diagonals against a 4-hole circle or a square of\n * the same diagonal. Their hole_spacing parameters mean different lengths\n * (a square's side, a cross's diagonal), so the pair check compares the\n * diagonal here and does not compare those parameters.\n */\nexport function boltPatternsShareHoles(a: InterfaceDef, b: InterfaceDef): boolean {\n const sa = traitParams(a, \"bolt_pattern\")?.shape;\n const sb = traitParams(b, \"bolt_pattern\")?.shape;\n if (sa === undefined || sb === undefined || sa === sb || (sa !== \"cross\" && sb !== \"cross\")) return false;\n const da = squareDiagonal(a);\n const db = squareDiagonal(b);\n return !!da && !!db && overlaps(da, db);\n}\n\nconst fmtRange = (r: [number, number]) => (Math.abs(r[1] - r[0]) <= HOLE_TOLERANCE_MM ? `${+r[0].toFixed(2)}` : `${+r[0].toFixed(2)}–${+r[1].toFixed(2)}`);\n\nfunction boltShape(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n const sa = traitParams(a, \"bolt_pattern\")?.shape;\n const sb = traitParams(b, \"bolt_pattern\")?.shape;\n if (sa === undefined || sb === undefined || sa === sb) return [];\n if (lineRule(a, b) || holeRule(a, b)) return [];\n if (sa !== \"cross\" && sb !== \"cross\") return [];\n if (boltPatternsShareHoles(a, b)) return [];\n const [da, db] = [squareDiagonal(a), squareDiagonal(b)];\n const why =\n da && db\n ? `both have four holes on a square, but the diagonals differ (${fmtRange(da)} mm and ${fmtRange(db)} mm)`\n : \"their holes are not in the same places\";\n return [\n {\n severity: \"error\",\n code: \"bolt_pattern_shape\",\n message: `a ${sa} bolt pattern does not line up with a ${sb} one: ${why}`,\n refs: [a.id, b.id],\n },\n ];\n}\n\n// ---------------------------------------------------------------------------\n// Rows and slots\n// ---------------------------------------------------------------------------\n\n/** A pattern's holes as a line: a row (pitch, possibly a range for slotted holes, and count), a slot, or not on a line. */\ntype Line =\n | { kind: \"row\"; pitch: [number, number]; count: number }\n | { kind: \"slot\"; length: number; slotKind?: string }\n | { kind: \"plane\"; shape: string };\n\nconst isLineShape = (iface: InterfaceDef) => {\n const shape = traitParams(iface, \"bolt_pattern\")?.shape;\n return shape === \"row\" || shape === \"slot\";\n};\n\n/** The line rule applies when both sides are bolt patterns, at least one is a row or a slot, and neither is a grid or an arc (the hole rule). */\nconst lineRule = (a: InterfaceDef, b: InterfaceDef) =>\n traitParams(a, \"bolt_pattern\") !== undefined && traitParams(b, \"bolt_pattern\") !== undefined && (isLineShape(a) || isLineShape(b)) && !holeRule(a, b);\n\n// ---------------------------------------------------------------------------\n// Grids and arcs: compare the holes themselves\n// ---------------------------------------------------------------------------\n\nconst isHoleShape = (iface: InterfaceDef) => {\n const shape = traitParams(iface, \"bolt_pattern\")?.shape;\n return shape === \"grid\" || shape === \"arc\";\n};\n\n/** The hole rule applies when both sides are bolt patterns and at least one is a grid or an arc. */\nconst holeRule = (a: InterfaceDef, b: InterfaceDef) =>\n traitParams(a, \"bolt_pattern\") !== undefined && traitParams(b, \"bolt_pattern\") !== undefined && (isHoleShape(a) || isHoleShape(b));\n\nconst paramNum = (iface: InterfaceDef, id: string) => paramRange(iface, id)?.[0];\n\n/**\n * The holes of any bolt pattern in its frame's x/y (mm), from its\n * parameters and trait; undefined for a slot (no fixed holes) or a pattern\n * whose spacing is a range (slotted holes).\n */\nexport function patternHoles(iface: InterfaceDef): [number, number][] | undefined {\n const t = traitParams(iface, \"bolt_pattern\");\n if (!t) return undefined;\n const shape = String(t.shape);\n if (shape === \"slot\") return undefined;\n if (shape === \"grid\") {\n const spec: GridSpec = {\n lattice: t.lattice === \"triangular\" ? \"triangular\" : \"rectangular\",\n pitch: paramNum(iface, \"hole_pitch\") ?? 0,\n ...(paramNum(iface, \"hole_pitch_y\") !== undefined ? { pitchY: paramNum(iface, \"hole_pitch_y\") } : {}),\n ...(t.within_diameter_mm !== undefined ? { withinDiameter: Number(t.within_diameter_mm) } : { rows: Number(t.rows), columns: Number(t.columns) }),\n ...(t.min_diameter_mm !== undefined ? { minDiameter: Number(t.min_diameter_mm) } : {}),\n };\n return latticeHoles(spec);\n }\n const x = paramRange(iface, \"hole_spacing\");\n if (!x || x[1] - x[0] > HOLE_TOLERANCE_MM) return undefined;\n const count = paramNum(iface, \"hole_count\") ?? 4;\n const d = x[0];\n if (shape === \"arc\") return arcHoles(d, count, paramNum(iface, \"angular_pitch\") ?? 0, Number(t.start_angle_deg ?? 0));\n if (shape === \"row\") {\n const pitch = paramNum(iface, \"hole_pitch\") ?? (count > 1 ? d / (count - 1) : 0);\n return Array.from({ length: count }, (_, k) => [-d / 2 + k * pitch, 0] as [number, number]);\n }\n if (shape === \"circle\") return arcHoles(d, count, 360 / count, 0);\n const yr = paramRange(iface, \"hole_spacing_y\");\n if (yr && yr[1] - yr[0] > HOLE_TOLERANCE_MM) return undefined;\n const y = yr?.[0] ?? d;\n if (shape === \"cross\") return [[-d / 2, 0], [d / 2, 0], [0, -y / 2], [0, y / 2]];\n if (shape === \"rectangle\" && y <= HOLE_TOLERANCE_MM) return count <= 2 ? [[-d / 2, 0], [d / 2, 0]] : undefined;\n return [[-d / 2, -y / 2], [d / 2, -y / 2], [d / 2, y / 2], [-d / 2, y / 2]];\n}\n\n/**\n * Whether every hole of `small` lands on a hole of `large` under one rigid\n * motion of the plane (a rotation and a shift, or their mirror image),\n * within `tol`. Two holes of `small` fix the motion: its first hole and the\n * one farthest from it go onto every pair of `large` holes as far apart.\n */\nexport function holesFitOn(small: [number, number][], large: [number, number][], tol = HOLE_TOLERANCE_MM): boolean {\n if (small.length === 0) return true;\n if (small.length > large.length) return false;\n if (small.length === 1) return large.length > 0;\n const cell = Math.max(tol * 4, 0.5);\n const key = (x: number, y: number) => `${Math.round(x / cell)},${Math.round(y / cell)}`;\n const index = new Map<string, [number, number][]>();\n for (const p of large) {\n const k = key(p[0], p[1]);\n index.set(k, [...(index.get(k) ?? []), p]);\n }\n const has = (x: number, y: number) => {\n const [i, j] = [Math.round(x / cell), Math.round(y / cell)];\n for (let di = -1; di <= 1; di++)\n for (let dj = -1; dj <= 1; dj++) for (const p of index.get(`${i + di},${j + dj}`) ?? []) if (Math.hypot(p[0] - x, p[1] - y) <= tol) return true;\n return false;\n };\n const s0 = small[0];\n let s1 = small[1];\n for (const p of small) if (Math.hypot(p[0] - s0[0], p[1] - s0[1]) > Math.hypot(s1[0] - s0[0], s1[1] - s0[1])) s1 = p;\n const d = Math.hypot(s1[0] - s0[0], s1[1] - s0[1]);\n for (const mirror of [false, true]) {\n const pts = small.map(([x, y]) => [x - s0[0], mirror ? -(y - s0[1]) : y - s0[1]] as [number, number]);\n const v = [s1[0] - s0[0], mirror ? -(s1[1] - s0[1]) : s1[1] - s0[1]];\n const aS = Math.atan2(v[1], v[0]);\n for (const li of large) {\n for (const lj of large) {\n if (li === lj || Math.abs(Math.hypot(lj[0] - li[0], lj[1] - li[1]) - d) > tol) continue;\n const rot = Math.atan2(lj[1] - li[1], lj[0] - li[0]) - aS;\n const [c, s] = [Math.cos(rot), Math.sin(rot)];\n if (pts.every(([x, y]) => has(li[0] + c * x - s * y, li[1] + s * x + c * y))) return true;\n }\n }\n }\n return false;\n}\n\nconst describeHoles = (iface: InterfaceDef) => {\n const t = traitParams(iface, \"bolt_pattern\") ?? {};\n const n = paramNum(iface, \"hole_count\");\n if (t.shape === \"grid\") return `a ${t.lattice} grid of ${n} holes (pitch ${fmtRange(paramRange(iface, \"hole_pitch\") ?? [0, 0])} mm)`;\n if (t.shape === \"arc\") return `a partial circle of ${n} holes on Ø${fmtRange(paramRange(iface, \"hole_spacing\") ?? [0, 0])} mm`;\n return `a ${t.shape} pattern`;\n};\n\nfunction boltHoles(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!holeRule(a, b)) return [];\n const problem = (why: string): Diagnostic[] => [{ severity: \"error\", code: \"bolt_pattern_holes\", message: `${describeHoles(a)} does not line up with ${describeHoles(b)}: ${why}`, refs: [a.id, b.id] }];\n const slotSide = [a, b].find((x) => traitParams(x, \"bolt_pattern\")?.shape === \"slot\");\n if (slotSide) {\n const other = slotSide === a ? b : a;\n if (traitParams(other, \"bolt_pattern\")?.shape === \"grid\") {\n return [{ severity: \"info\", code: \"bolt_pattern_holes\", message: \"fasteners go into the slot through one line of the grid's holes\", refs: [a.id, b.id] }];\n }\n return problem(\"a partial circle's holes are not on one line\");\n }\n const [ha, hb] = [patternHoles(a), patternHoles(b)];\n if (!ha || !hb) return [];\n const [small, large] = ha.length <= hb.length ? [ha, hb] : [hb, ha];\n if (holesFitOn(small, large)) return [];\n return problem(`the ${small.length} holes of one do not all land on the other's ${large.length}`);\n}\n\nfunction lineOf(iface: InterfaceDef): Line {\n const t = traitParams(iface, \"bolt_pattern\") ?? {};\n const shape = String(t.shape);\n if (shape === \"row\") {\n return { kind: \"row\", pitch: paramRange(iface, \"hole_pitch\") ?? [0, 0], count: paramRange(iface, \"hole_count\")?.[0] ?? 2 };\n }\n if (shape === \"slot\") {\n return { kind: \"slot\", length: paramRange(iface, \"slot_length\")?.[1] ?? 0, ...(t.slot_kind !== undefined ? { slotKind: String(t.slot_kind) } : {}) };\n }\n const y = paramRange(iface, \"hole_spacing_y\");\n const x = paramRange(iface, \"hole_spacing\");\n if (shape === \"rectangle\" && x && y && y[1] <= HOLE_TOLERANCE_MM) {\n // the older encodings: a slot as a spacing range from 0, a row as its two end holes\n if (x[0] <= HOLE_TOLERANCE_MM && x[1] > HOLE_TOLERANCE_MM) return { kind: \"slot\", length: x[1] };\n return { kind: \"row\", pitch: x, count: 2 };\n }\n return { kind: \"plane\", shape };\n}\n\nconst span = (r: { pitch: [number, number]; count: number }) => r.pitch[0] * (r.count - 1);\n\n/** Whether every hole of row s lands on a hole of row l. */\nfunction rowOnRow(s: { pitch: [number, number]; count: number }, l: { pitch: [number, number]; count: number }): boolean {\n const fixed = l.pitch[1] - l.pitch[0] <= HOLE_TOLERANCE_MM;\n if (!fixed) return s.count <= 2 && overlaps(s.pitch, l.pitch); // two holes slotted to any spacing in the range\n const p = l.pitch[0];\n if (s.count <= 1) return true;\n for (let k = 1; (s.count - 1) * k <= l.count - 1; k++) {\n if (overlaps(s.pitch, [k * p, k * p])) return true;\n }\n return false;\n}\n\nconst describeLine = (l: Line) =>\n l.kind === \"row\"\n ? `a ${l.count}-hole row (pitch ${fmtRange(l.pitch)} mm)`\n : l.kind === \"slot\"\n ? `a ${+l.length.toFixed(2)} mm ${l.slotKind === \"t_slot\" ? \"T-slot\" : l.slotKind === \"through\" ? \"through slot\" : \"slot\"}`\n : `a ${l.shape} pattern`;\n\nfunction boltLine(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!lineRule(a, b)) return [];\n const la = lineOf(a);\n const lb = lineOf(b);\n const problem = (why: string): Diagnostic[] => [\n { severity: \"error\", code: \"bolt_pattern_line\", message: `${describeLine(la)} does not line up with ${describeLine(lb)}: ${why}`, refs: [a.id, b.id] },\n ];\n if (la.kind === \"plane\" || lb.kind === \"plane\") return problem(\"a row's or a slot's holes lie on one line and the other pattern's do not\");\n if (la.kind === \"slot\" && lb.kind === \"slot\") {\n return la.slotKind === \"t_slot\" && lb.slotKind === \"t_slot\" ? problem(\"neither T-slot has a hole for the fastener; join them with a bracket\") : [];\n }\n if (la.kind === \"slot\" || lb.kind === \"slot\") {\n const [slot, row] = (la.kind === \"slot\" ? [la, lb] : [lb, la]) as [Extract<Line, { kind: \"slot\" }>, Extract<Line, { kind: \"row\" }>];\n return span(row) <= slot.length + HOLE_TOLERANCE_MM ? [] : problem(`the row spans ${+span(row).toFixed(2)} mm, longer than the slot`);\n }\n const [ra, rb] = [la, lb] as Extract<Line, { kind: \"row\" }>[];\n if (rowOnRow(ra, rb) || rowOnRow(rb, ra)) return [];\n return problem(\"the holes of neither row land on the other's (pitch not a whole multiple, or the row is longer)\");\n}\n\n// ---------------------------------------------------------------------------\n// Shafts and bores\n// ---------------------------------------------------------------------------\n\n/** For a shaft profile, the bore profiles it goes into: \"ok\", or \"warn\" when it fits without the key carrying torque. */\nconst SHAFT_FITS: Record<string, Record<string, \"ok\" | \"warn\">> = {\n round: { round: \"ok\", keyed: \"warn\" },\n hex: { hex: \"ok\" },\n rounded_hex: { hex: \"ok\", rounded_hex: \"ok\" },\n d_cut: { d_cut: \"ok\", round: \"ok\" },\n double_d: { double_d: \"ok\", d_cut: \"ok\", round: \"ok\" },\n keyed: { keyed: \"ok\", round: \"warn\" },\n spline: { spline: \"ok\" },\n square: { square: \"ok\" },\n};\n\nconst normSpline = (s: unknown) => String(s).replace(/[\\s_-]/g, \"\").toLowerCase();\nconst profileName = (p: unknown) => String(p).replace(/_/g, \"-\");\n\n/** A bore that clamps on another profile (Shaft `clampsOn`) against a shaft: [bore, shaft], or undefined. */\nfunction clampFit(a: InterfaceDef, b: InterfaceDef): [InterfaceDef, InterfaceDef] | undefined {\n if (!a.protocols.some((p) => p.type === \"shaft\") || !b.protocols.some((p) => p.type === \"shaft\")) return undefined;\n for (const [bore, shaft] of [[a, b], [b, a]] as const) {\n if (traitParams(bore, \"shaft\")?.clamps_on !== undefined && traitParams(shaft, \"shaft\")?.gender !== \"bore\") return [bore, shaft];\n }\n return undefined;\n}\n\nfunction shaftFit(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n const ta = traitParams(a, \"shaft\");\n const tb = traitParams(b, \"shaft\");\n if (!a.protocols.some((p) => p.type === \"shaft\") || !b.protocols.some((p) => p.type === \"shaft\")) return [];\n const diag = (severity: \"error\" | \"warning\" | \"info\", why: string): Diagnostic[] => [{ severity, code: \"shaft_fit\", message: why, refs: [a.id, b.id] }];\n const clamp = clampFit(a, b);\n if (clamp) {\n const [bore, shaft] = clamp;\n const on = traitParams(bore, \"shaft\")!.clamps_on as { profile: string; diameter_mm: number; by: string };\n const profile = traitParams(shaft, \"shaft\")?.profile;\n const d = paramRange(shaft, \"shaft_diameter\");\n const boreD = paramRange(bore, \"shaft_diameter\");\n const sameProfile = profile === undefined || profile === on.profile || (on.profile === \"hex\" && profile === \"rounded_hex\");\n if (sameProfile && d && overlaps(d, [on.diameter_mm, on.diameter_mm])) {\n return diag(\"info\", `the Ø${boreD ? fmtRange(boreD) : \"?\"} mm round bore goes over the ${on.diameter_mm} mm ${profileName(on.profile)} shaft and is held by ${String(on.by).replace(/_/g, \" \")}`);\n }\n if (profile === \"round\" && d && boreD && overlaps(d, boreD)) return []; // it is still a round bore\n return diag(\"error\", `the bore clamps on a ${on.diameter_mm} mm ${profileName(on.profile)} shaft, not a ${d ? fmtRange(d) : \"?\"} mm ${profileName(profile ?? \"unstated\")} one`);\n }\n const [ga, gb] = [ta?.gender, tb?.gender];\n if (ga !== undefined && ga === gb) return diag(\"error\", ga === \"shaft\" ? \"two shafts do not mate without a coupler\" : \"two bores need a shaft between them\");\n const [pa, pb] = [ta?.profile, tb?.profile];\n if (pa === undefined || pb === undefined) return [];\n if (pa === \"spline\" && pb === \"spline\" && ta?.spline !== undefined && tb?.spline !== undefined && normSpline(ta.spline) !== normSpline(tb.spline)) {\n return diag(\"error\", `different splines (${ta.spline} and ${tb.spline})`);\n }\n // which side is the shaft: from either gender; with neither stated, the better fit of the two readings\n const aIsShaft = ga === \"shaft\" || gb === \"bore\" ? true : gb === \"shaft\" || ga === \"bore\" ? false : undefined;\n const fits = (shaft: unknown, bore: unknown) => SHAFT_FITS[String(shaft)]?.[String(bore)];\n const fit =\n aIsShaft === true ? fits(pa, pb) : aIsShaft === false ? fits(pb, pa) : fits(pa, pb) === \"ok\" || fits(pb, pa) === \"ok\" ? \"ok\" : (fits(pa, pb) ?? fits(pb, pa));\n const [shaftP, boreP] = aIsShaft === false ? [pb, pa] : [pa, pb];\n if (fit === \"ok\") return [];\n if (fit === \"warn\") {\n return diag(\n \"warning\",\n boreP === \"keyed\"\n ? `a round shaft in a keyed bore: the keyway is unused, so torque relies on a set screw or clamp`\n : `a keyed shaft in a round bore: it fits without its key, so torque relies on a set screw or clamp`,\n );\n }\n return diag(\"error\", `a ${profileName(shaftP)} shaft does not fit a ${profileName(boreP)} bore`);\n}\n\n// ---------------------------------------------------------------------------\n// Linear motion and supply current: an output's rating against what the input needs\n// ---------------------------------------------------------------------------\n\nconst hasRoleIn = (iface: InterfaceDef, roles: Set<string>, protocol?: string) =>\n iface.protocols.some((p) => (protocol === undefined || p.type === protocol) && p.roles.some((r) => roles.has(r.toLowerCase())));\n\n/** A parameter's value in its base unit (A for mA), or undefined. \"low\" takes a range's lower end, \"high\" its upper end. */\nfunction amount(iface: InterfaceDef, id: string, end: \"low\" | \"high\"): number | undefined {\n const p = iface.parameters?.find((x) => x.id === id);\n const r = p && getEffectiveRange(p);\n if (!r) return undefined;\n const v = end === \"low\" ? r[0] : r[1];\n return p!.unit === \"mA\" ? v / 1000 : v;\n}\n\nconst fmtNum = (v: number) => `${+v.toFixed(3)}`;\n\nfunction linearCapacity(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n const out: Diagnostic[] = [];\n const OUTPUT = new Set([\"output\"]);\n const INPUT = new Set([\"input\"]);\n for (const [o, load] of [[a, b], [b, a]] as const) {\n if (!hasRoleIn(o, OUTPUT, \"linear_motion\") || !hasRoleIn(load, INPUT, \"linear_motion\")) continue;\n for (const [id, what, unit] of [[\"stroke\", \"stroke\", \"mm\"], [\"force\", \"force\", \"N\"]] as const) {\n const need = amount(load, id, \"low\");\n if (need === undefined) continue;\n const give = amount(o, id, \"high\");\n if (give === undefined) {\n out.push({ severity: \"info\", code: \"linear_motion_capacity\", message: `the load needs ${fmtNum(need)} ${unit} of ${what}; the output states no ${what}, so it cannot be checked`, refs: [o.id, load.id] });\n } else if (give + 1e-9 < need) {\n out.push({ severity: \"error\", code: \"linear_motion_capacity\", message: `the output gives ${fmtNum(give)} ${unit} of ${what}, less than the ${fmtNum(need)} ${unit} the load needs`, refs: [o.id, load.id] });\n }\n }\n }\n return out;\n}\n\nconst SUPPLYING = new Set([\"output\", \"source\"]);\n\nfunction supplyCurrent(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n const out: Diagnostic[] = [];\n for (const [load, source] of [[a, b], [b, a]] as const) {\n const need = amount(load, \"min_supply_current\", \"low\");\n if (need === undefined || !hasRoleIn(source, SUPPLYING)) continue;\n const rating = amount(source, \"max_current\", \"high\");\n if (rating === undefined) {\n out.push({ severity: \"info\", code: \"supply_current_rating\", message: `${load.id} needs a source rated for at least ${fmtNum(need)} A; ${source.id} states no current rating`, refs: [source.id, load.id] });\n } else if (rating + 1e-9 < need) {\n out.push({ severity: \"error\", code: \"supply_current_rating\", message: `${source.id} is rated for ${fmtNum(rating)} A; ${load.id} needs a source rated for at least ${fmtNum(need)} A`, refs: [source.id, load.id] });\n }\n }\n return out;\n}\n","import type { InterfaceDef } from \"../types/interface.js\";\nimport type { Diagnostic } from \"./types.js\";\nimport { getEffectiveRange } from \"../parameters/range.js\";\n\n/**\n * Pair checks on links that negotiate or must agree beyond overlapping\n * parameters: PCIe, M.2, MIPI, Ethernet and PoE, SFP, I2S, DVP,\n * SD, LED drive, and wireless.\n *\n * - `link_width` (info): a PCIe link (or an M.2 socket and card carrying PCIe) trains to the widest width and\n * highest generation both ends support; when that is less than either\n * end has, the check says what it runs at. MIPI states the lane count the\n * two can share.\n * - `lane_rate` (warning): a MIPI transmitter whose highest lane rate is\n * above the receiver's: its faster modes do not work.\n * - `m2_key`, `m2_size`, `m2_interface` (errors): a card whose keys do not\n * include the socket's key; a card length the socket has no standoff\n * for; a socket and card with no interface in common.\n * - `ethernet_speed`: no speed in common (error), or the speed they link\n * at when it is below either end's fastest (info). Ethernet and SFP.\n * - `ethernet_medium` (error): copper against fibre.\n * - `fiber_mismatch` (error): single-mode against multi-mode, a transmit\n * wavelength that is not the other end's receive wavelength, or a duplex\n * module against a BiDi one.\n * - `poe_power`: a powered device that needs more power than the PSE gives\n * (error); passive PoE against an 802.3 end (warning); a device powered\n * only by PoE on a port that gives none (warning).\n * - `sfp_form` (error): an SFP-family module in a QSFP cage, or the reverse.\n * - `audio_format` (error): I2S ports with no frame format in common.\n * - `audio_direction` (error): two ports that both only send, or both only\n * receive.\n * - `dvp_width`: a host narrower than the camera takes its upper bits\n * (warning); a wider host leaves its low bits unused (info).\n * - `sd_form`, `sd_mode`, `sd_capacity` (errors): another card form, no\n * bus mode in common, a card class the host does not read.\n * - `led_drive_current` (warning): a driver that can be set above the\n * LED's maximum current.\n * - `usb_speed`: USB ports with no speed in common (error), or the speed\n * they fall back to when it is below either end's fastest (info).\n * - `wireless_band` (error): radios with no band in common.\n * - `wireless_stack` (error): Bluetooth with no mode in common (Classic\n * against LE), 802.15.4 radios with no stack in common (Zigbee against\n * Thread).\n * - `zigbee_roles` (warning): two Zigbee radios that can only be end\n * devices.\n */\nexport function checkPairLinks(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n return [\n ...linkWidth(a, b),\n ...laneRate(a, b),\n ...m2(a, b),\n ...ethernet(a, b),\n ...poe(a, b),\n ...sfp(a, b),\n ...audio(a, b),\n ...dvp(a, b),\n ...sd(a, b),\n ...ledDrive(a, b),\n ...usb(a, b),\n ...wireless(a, b),\n ];\n}\n\n/** Parameters `checkPairLinks` compares itself, which the pairwise overlap check skips. */\nexport const LINK_CHECKED_PARAMS = new Set([\"link_speed\", \"lane_rate\", \"bus_width\", \"poe_power\", \"wavelength\"]);\n\n/** The link-checked parameters this pair carries (both ends speak a link protocol that `checkPairLinks` covers). */\nexport function linkCheckedParams(a: InterfaceDef, b: InterfaceDef): Set<string> {\n const ids = (x: InterfaceDef) => new Set((x.parameters ?? []).map((p) => p.id));\n const [ia, ib] = [ids(a), ids(b)];\n return new Set([...LINK_CHECKED_PARAMS].filter((id) => ia.has(id) && ib.has(id)));\n}\n\nconst trait = (iface: InterfaceDef, type: string): Record<string, unknown> | undefined =>\n iface.traits?.find((t) => t.type === type)?.params as Record<string, unknown> | undefined;\nconst speaks = (iface: InterfaceDef, type: string) => iface.protocols.some((p) => p.type === type);\nconst rolesOf = (iface: InterfaceDef, type: string) => new Set(iface.protocols.filter((p) => p.type === type).flatMap((p) => p.roles));\nconst range = (iface: InterfaceDef, id: string): [number, number] | undefined => {\n const p = iface.parameters?.find((x) => x.id === id);\n return (p && getEffectiveRange(p)) ?? undefined;\n};\nconst list = (v: unknown): string[] => (Array.isArray(v) ? v.map(String) : v === undefined ? [] : [String(v)]);\nconst common = (x: unknown, y: unknown) => list(x).filter((v) => list(y).includes(v));\nconst diag = (severity: Diagnostic[\"severity\"], code: string, message: string, a: InterfaceDef, b: InterfaceDef): Diagnostic => ({ severity, code, message, refs: [a.id, b.id] });\n\n// ---------------------------------------------------------------------------\n// Lanes\n// ---------------------------------------------------------------------------\n\nfunction linkWidth(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if ((speaks(a, \"pcie\") && speaks(b, \"pcie\")) || (speaks(a, \"m2\") && speaks(b, \"m2\"))) {\n const [la, lb, ga, gb] = [range(a, \"lane_count\"), range(b, \"lane_count\"), range(a, \"pcie_generation\"), range(b, \"pcie_generation\")];\n if (!la || !lb) return [];\n const lanes = Math.min(la[1], lb[1]);\n const gen = ga && gb ? Math.min(ga[1], gb[1]) : undefined;\n const narrower = lanes < Math.max(la[1], lb[1]);\n const slower = ga && gb ? gen! < Math.max(ga[1], gb[1]) : false;\n if (!narrower && !slower) return [];\n return [diag(\"info\", \"link_width\", `the link trains at x${lanes}${gen ? ` Gen ${gen}` : \"\"} (x${la[1]}${ga ? ` Gen ${ga[1]}` : \"\"} against x${lb[1]}${gb ? ` Gen ${gb[1]}` : \"\"})`, a, b)];\n }\n for (const type of [\"mipi_csi2\", \"mipi_dsi\"]) {\n if (!speaks(a, type) || !speaks(b, type)) continue;\n const [la, lb] = [range(a, \"lane_count\"), range(b, \"lane_count\")];\n if (!la || !lb) return [];\n const hi = Math.min(la[1], lb[1]);\n const lo = Math.max(la[0], lb[0]);\n if (lo > hi) return []; // the overlap check reports it\n if (hi < Math.max(la[1], lb[1])) return [diag(\"info\", \"link_width\", `the link runs on at most ${hi} lane${hi === 1 ? \"\" : \"s\"}`, a, b)];\n }\n return [];\n}\n\nfunction laneRate(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n for (const type of [\"mipi_csi2\", \"mipi_dsi\"]) {\n if (!speaks(a, type) || !speaks(b, type)) continue;\n const tx = rolesOf(a, type).has(\"transmitter\") ? a : rolesOf(b, type).has(\"transmitter\") ? b : undefined;\n if (!tx) return [];\n const rx = tx === a ? b : a;\n const [rt, rr] = [range(tx, \"lane_rate\"), range(rx, \"lane_rate\")];\n if (rt && rr && rt[1] > rr[1]) return [diag(\"warning\", \"lane_rate\", `the transmitter runs lanes up to ${rt[1]} Mbit/s, the receiver up to ${rr[1]} Mbit/s: modes above ${rr[1]} Mbit/s per lane do not work`, a, b)];\n }\n return [];\n}\n\n// ---------------------------------------------------------------------------\n// M.2\n// ---------------------------------------------------------------------------\n\nfunction m2(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n const [ta, tb] = [trait(a, \"m2\"), trait(b, \"m2\")];\n if (!ta || !tb) return [];\n const socketSide = rolesOf(a, \"m2\").has(\"socket\") ? a : rolesOf(b, \"m2\").has(\"socket\") ? b : undefined;\n if (!socketSide) return [];\n const [socket, card] = socketSide === a ? [ta, tb] : [tb, ta];\n const out: Diagnostic[] = [];\n const key = list(socket.key)[0];\n if (key && !list(card.key).includes(key)) out.push(diag(\"error\", \"m2_key\", `a ${list(card.key).join(\"+\")}-key card does not fit an ${key}-key socket`, a, b));\n const size = list(card.sizes)[0];\n if (size && list(socket.sizes).length && !list(socket.sizes).includes(size)) out.push(diag(\"error\", \"m2_size\", `the socket holds ${list(socket.sizes).join(\", \")} cards, not ${size}`, a, b));\n if (!common(socket.carries, card.carries).length) out.push(diag(\"error\", \"m2_interface\", `the socket carries ${list(socket.carries).join(\", \")}; the card uses ${list(card.carries).join(\", \")}`, a, b));\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Ethernet, PoE, SFP\n// ---------------------------------------------------------------------------\n\nconst speedsOf = (iface: InterfaceDef) => (trait(iface, \"ethernet\") ?? trait(iface, \"sfp\"))?.speeds_mbps as number[] | undefined;\nconst fmtSpeed = (s: number) => (s >= 1000 ? `${s / 1000} Gbit/s` : `${s} Mbit/s`);\n\nfunction ethernet(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n const both = (speaks(a, \"ethernet\") && speaks(b, \"ethernet\")) || (speaks(a, \"sfp\") && speaks(b, \"sfp\"));\n if (!both) return [];\n const out: Diagnostic[] = [];\n const [sa, sb] = [speedsOf(a), speedsOf(b)];\n if (sa && sb) {\n const shared = sa.filter((s) => sb.includes(s));\n if (!shared.length) out.push(diag(\"error\", \"ethernet_speed\", `no speed in common (${sa.map(fmtSpeed).join(\", \")} against ${sb.map(fmtSpeed).join(\", \")})`, a, b));\n else if (Math.max(...shared) < Math.max(...sa, ...sb)) out.push(diag(\"info\", \"ethernet_speed\", `the link runs at ${fmtSpeed(Math.max(...shared))}`, a, b));\n }\n const [ea, eb] = [trait(a, \"ethernet\"), trait(b, \"ethernet\")];\n if (ea && eb) {\n if (ea.medium !== eb.medium) out.push(diag(\"error\", \"ethernet_medium\", `a ${ea.medium} port does not link to a ${eb.medium} port without a media converter`, a, b));\n const [fa, fb] = [ea.fiber as Record<string, number | string> | undefined, eb.fiber as Record<string, number | string> | undefined];\n if (fa && fb) {\n if (fa.mode !== fb.mode) out.push(diag(\"error\", \"fiber_mismatch\", `${String(fa.mode).replace(\"_\", \"-\")} optics against ${String(fb.mode).replace(\"_\", \"-\")}`, a, b));\n if (fa.strands !== fb.strands) out.push(diag(\"error\", \"fiber_mismatch\", `a ${fa.strands}-strand port against a ${fb.strands}-strand one`, a, b));\n if (fa.tx_nm !== fb.rx_nm || fb.tx_nm !== fa.rx_nm) out.push(diag(\"error\", \"fiber_mismatch\", `wavelengths do not cross over: ${fa.tx_nm}/${fa.rx_nm} nm (tx/rx) against ${fb.tx_nm}/${fb.rx_nm} nm`, a, b));\n }\n }\n return out;\n}\n\nfunction poe(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"ethernet\") || !speaks(b, \"ethernet\")) return [];\n const [pa, pb] = [trait(a, \"poe\"), trait(b, \"poe\")];\n const out: Diagnostic[] = [];\n for (const [pd, pdIf, other, otherIf] of [[pa, a, pb, b], [pb, b, pa, a]] as const) {\n if (pd?.role !== \"pd\") continue;\n if (other?.role !== \"pse\") {\n if (pd.required) out.push(diag(\"warning\", \"poe_power\", `${pdIf.id} is powered only over Ethernet; ${otherIf.id} gives no PoE, so it needs an injector`, a, b));\n continue;\n }\n if ((pd.standard === \"passive\") !== (other.standard === \"passive\")) {\n out.push(diag(\"warning\", \"poe_power\", `${other.standard === \"passive\" ? \"passive PoE\" : `${other.standard} PoE`} feeding ${pd.standard === \"passive\" ? \"a passive PoE device\" : `an ${pd.standard} device`}: one side does no 802.3 detection, so the device may not power up, or may be damaged`, a, b));\n }\n const need = range(pdIf, \"poe_power\");\n const give = range(otherIf, \"poe_power\");\n if (need && give && give[1] + 1e-9 < need[1]) out.push(diag(\"error\", \"poe_power\", `${otherIf.id} gives ${give[1]} W; ${pdIf.id} draws up to ${need[1]} W`, a, b));\n }\n return out;\n}\n\nconst SFP_FAMILY: Record<string, string> = { sfp: \"sfp\", \"sfp+\": \"sfp\", sfp28: \"sfp\", \"qsfp+\": \"qsfp\", qsfp28: \"qsfp\" };\n\nfunction sfp(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n const [ta, tb] = [trait(a, \"sfp\"), trait(b, \"sfp\")];\n if (!ta || !tb) return [];\n if (SFP_FAMILY[String(ta.form)] === SFP_FAMILY[String(tb.form)]) return [];\n return [diag(\"error\", \"sfp_form\", `an ${String(ta.form).toUpperCase()} ${[...rolesOf(a, \"sfp\")][0]} does not take an ${String(tb.form).toUpperCase()} ${[...rolesOf(b, \"sfp\")][0]}`, a, b)];\n}\n\n// ---------------------------------------------------------------------------\n// Audio, cameras, SD, LEDs\n// ---------------------------------------------------------------------------\n\nfunction audio(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n const [ta, tb] = [trait(a, \"audio_port\"), trait(b, \"audio_port\")];\n if (!ta || !tb) return [];\n const out: Diagnostic[] = [];\n if (!common(ta.formats, tb.formats).length) out.push(diag(\"error\", \"audio_format\", `no frame format in common (${list(ta.formats).join(\", \")} against ${list(tb.formats).join(\", \")})`, a, b));\n if (ta.direction !== \"duplex\" && ta.direction === tb.direction) out.push(diag(\"error\", \"audio_direction\", `both ports only ${ta.direction === \"out\" ? \"send\" : \"receive\"} audio`, a, b));\n return out;\n}\n\nfunction dvp(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"dvp\") || !speaks(b, \"dvp\")) return [];\n const cam = rolesOf(a, \"dvp\").has(\"camera\") ? a : rolesOf(b, \"dvp\").has(\"camera\") ? b : undefined;\n if (!cam) return [];\n const host = cam === a ? b : a;\n const [wc, wh] = [range(cam, \"bus_width\")?.[1], range(host, \"bus_width\")?.[1]];\n if (wc === undefined || wh === undefined || wc === wh) return [];\n return wh < wc\n ? [diag(\"warning\", \"dvp_width\", `an ${wh}-bit host takes the upper ${wh} of the camera's ${wc} data bits (D${wc - 1}..D${wc - wh})`, a, b)]\n : [diag(\"info\", \"dvp_width\", `the camera's ${wc} data bits land on the host's upper bits; D${wh - wc - 1}..D0 of the host are unused`, a, b)];\n}\n\nfunction sd(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n const [ta, tb] = [trait(a, \"sd_card\"), trait(b, \"sd_card\")];\n if (!ta || !tb) return [];\n const out: Diagnostic[] = [];\n if (ta.form && tb.form && ta.form !== tb.form) out.push(diag(\"error\", \"sd_form\", `a ${ta.form} ${[...rolesOf(a, \"sd_card\")][0]} against a ${tb.form} ${[...rolesOf(b, \"sd_card\")][0]}`, a, b));\n if (!common(ta.modes, tb.modes).length) out.push(diag(\"error\", \"sd_mode\", `no bus mode in common (${list(ta.modes).join(\", \")} against ${list(tb.modes).join(\", \")})`, a, b));\n const hostSide = rolesOf(a, \"sd_card\").has(\"host\") ? ta : rolesOf(b, \"sd_card\").has(\"host\") ? tb : undefined;\n const cardSide = hostSide === ta ? tb : ta;\n if (hostSide?.capacity_classes && cardSide.capacity_classes && !common(hostSide.capacity_classes, cardSide.capacity_classes).length) {\n out.push(diag(\"error\", \"sd_capacity\", `the host reads ${list(hostSide.capacity_classes).join(\", \").toUpperCase()} cards, not ${list(cardSide.capacity_classes).join(\", \").toUpperCase()}`, a, b));\n }\n return out;\n}\n\nfunction ledDrive(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"led_drive\") || !speaks(b, \"led_drive\")) return [];\n const isLed = (x: InterfaceDef) => [...rolesOf(x, \"led_drive\")].some((r) => r === \"anode\" || r === \"cathode\");\n const led = isLed(a) ? a : isLed(b) ? b : undefined;\n if (!led) return [];\n const driver = led === a ? b : a;\n const [max, set] = [range(led, \"led_current\")?.[1], range(driver, \"led_current\")];\n if (max === undefined || !set || set[0] > max) return []; // disjoint: the overlap check reports it\n return set[1] > max ? [diag(\"warning\", \"led_drive_current\", `the driver can be set up to ${set[1]} mA, above the LED's ${max} mA maximum: set it at or below ${max} mA`, a, b)] : [];\n}\n\nconst USB_ORDER = [\"low\", \"full\", \"high\", \"super\", \"super_plus\", \"super_plus_2x2\", \"usb4\"];\n\nfunction usb(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n const [ta, tb] = [trait(a, \"usb\"), trait(b, \"usb\")];\n if (!ta || !tb) return [];\n const shared = common(ta.speeds, tb.speeds).sort((x, y) => USB_ORDER.indexOf(y) - USB_ORDER.indexOf(x));\n if (!shared.length) return [diag(\"error\", \"usb_speed\", `no speed in common (${list(ta.speeds).join(\", \")} against ${list(tb.speeds).join(\", \")})`, a, b)];\n const top = Math.max(...[...list(ta.speeds), ...list(tb.speeds)].map((s) => USB_ORDER.indexOf(s)));\n return USB_ORDER.indexOf(shared[0]!) < top ? [diag(\"info\", \"usb_speed\", `the ports run at ${shared[0]!.replace(/_/g, \" \")} speed`, a, b)] : [];\n}\n\n// ---------------------------------------------------------------------------\n// Wireless\n// ---------------------------------------------------------------------------\n\nfunction wireless(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n const [wa, wb] = [trait(a, \"wireless\"), trait(b, \"wireless\")];\n if (!wa || !wb || wa.standard !== wb.standard) return [];\n const out: Diagnostic[] = [];\n if (!common(wa.bands, wb.bands).length) out.push(diag(\"error\", \"wireless_band\", `no band in common (${list(wa.bands).join(\", \")} against ${list(wb.bands).join(\", \")})`, a, b));\n if ((wa.standard === \"bluetooth\" || wa.standard === \"ieee802154\") && !common(wa.stacks, wb.stacks).length) {\n out.push(diag(\"error\", \"wireless_stack\", `nothing in common to speak (${list(wa.stacks).join(\", \")} against ${list(wb.stacks).join(\", \")})`, a, b));\n }\n if (wa.standard === \"ieee802154\" && common(wa.stacks, wb.stacks).includes(\"zigbee\")) {\n const endOnly = (w: Record<string, unknown>) => list(w.zigbee_roles).length > 0 && list(w.zigbee_roles).every((r) => r === \"end_device\");\n if (endOnly(wa) && endOnly(wb)) out.push(diag(\"warning\", \"zigbee_roles\", \"two Zigbee end devices do not talk directly: the network needs a coordinator (and routers)\", a, b));\n }\n return out;\n}\n","import type { InterfaceDef } from \"../types/interface.js\";\nimport type { Diagnostic } from \"./types.js\";\nimport { getEffectiveRange } from \"../parameters/range.js\";\n\n/**\n * Pair checks for the drive-train and fastening vocabulary\n * (`protocols/drive.ts`):\n *\n * - `gear_mesh`: two gears with a different module or pressure angle\n * (error); kinds that do not go together (two racks, two internal gears,\n * a spur gear against a helical one, a bevel against a spur, a worm\n * without its wheel); helical gears on parallel shafts whose helix angles\n * differ or whose hands are the same; an internal gear against a pinion\n * with as many teeth or more. Otherwise an info with the ratio, the centre\n * distance and the engaged face width.\n * - `bearing_fit`: a bearing whose outside diameter is not the seat's\n * (error, within 0.05 mm); a kind the seat is not made for (warning); a\n * bearing wider than a blind seat is deep (info: it stands proud).\n * - `thread_fit`: threads of a different diameter, pitch or hand (error);\n * otherwise an info with the engaged length when both state a length.\n * - `t_slot_fit`: an insert whose neck does not pass the track's opening,\n * whose head is no wider than the opening (nothing holds it) or wider or\n * taller than the channel (errors); an insert that only slides in from an\n * end on a track that only takes drop-in hardware (error); different named\n * profiles when the dimensions cannot be compared (warning).\n * - `axial_face`: two faces whose annuli do not overlap (one passes inside\n * the other: error), or that turn relative to each other (warning: they rub).\n * - `rolling_contact`: a wheel smaller than the surface is made for (error).\n */\nexport function checkPairDrive(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n return [...gearMesh(a, b), ...bearingFit(a, b), ...threadFit(a, b), ...tSlotFit(a, b), ...axialFace(a, b), ...rollingContact(a, b)];\n}\n\n/** Parameters `checkPairDrive` compares itself, by protocol: the pairwise overlap check skips them for that pair. */\nconst DRIVE_CHECKED: Record<string, string[]> = {\n gear_mesh: [\"gear_module\", \"pressure_angle\", \"tooth_count\", \"face_width\"],\n bearing_fit: [\"bearing_od\", \"bearing_width\", \"bearing_bore\", \"seat_depth\", \"load_rating\"],\n // `length` is a screw's length under the head or an insert's length (what fastener stacks read), not a fit\n thread: [\"fastener_diameter\", \"thread_pitch\", \"thread_length\", \"length\"],\n t_slot: [\"slot_opening\", \"channel_width\", \"channel_depth\", \"slot_length\", \"neck_width\", \"head_width\", \"head_height\"],\n axial_stop: [\"face_od\", \"face_id\", \"axial_length\"],\n rolling_contact: [\"wheel_diameter\", \"tread_width\", \"load_rating\", \"min_wheel_diameter\"],\n};\n\n/** The drive-checked parameters of this pair (both ends speak the same drive protocol). */\nexport function driveCheckedParams(a: InterfaceDef, b: InterfaceDef): Set<string> {\n for (const [protocol, ids] of Object.entries(DRIVE_CHECKED)) if (speaks(a, protocol) && speaks(b, protocol)) return new Set(ids);\n return new Set();\n}\n\nconst TOL_MM = 0.05;\n\nconst speaks = (iface: InterfaceDef, type: string) => iface.protocols.some((p) => p.type === type);\nconst rolesOf = (iface: InterfaceDef, type: string) => new Set(iface.protocols.filter((p) => p.type === type).flatMap((p) => p.roles));\nconst trait = (iface: InterfaceDef, type: string): Record<string, unknown> => (iface.traits?.find((t) => t.type === type)?.params as Record<string, unknown>) ?? {};\nconst range = (iface: InterfaceDef, id: string): [number, number] | undefined => {\n const p = iface.parameters?.find((x) => x.id === id);\n return (p && getEffectiveRange(p)) ?? undefined;\n};\nconst value = (iface: InterfaceDef, id: string): number | undefined => {\n const r = range(iface, id);\n return r ? r[0] : undefined;\n};\nconst fmt = (v: number) => `${+v.toFixed(3)}`;\nconst fmtR = (r: [number, number]) => (Math.abs(r[1] - r[0]) <= 1e-9 ? fmt(r[0]) : `${fmt(r[0])}–${fmt(r[1])}`);\nconst diag = (severity: Diagnostic[\"severity\"], code: string, message: string, a: InterfaceDef, b: InterfaceDef): Diagnostic => ({ severity, code, message, refs: [a.id, b.id] });\nconst overlaps = (x: [number, number], y: [number, number], tol: number) => x[0] <= y[1] + tol && y[0] <= x[1] + tol;\n\n// ---------------------------------------------------------------------------\n// Gears\n// ---------------------------------------------------------------------------\n\n/** Kinds that mesh with each other (unordered). */\nconst GEAR_MATES: Record<string, string[]> = {\n spur: [\"spur\", \"internal\", \"rack\"],\n helical: [\"helical\", \"internal\", \"rack\"],\n internal: [\"spur\", \"helical\"],\n rack: [\"spur\", \"helical\"],\n bevel: [\"bevel\"],\n worm: [\"worm_wheel\"],\n worm_wheel: [\"worm\"],\n};\n\nfunction gearMesh(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"gear_mesh\") || !speaks(b, \"gear_mesh\")) return [];\n const [ta, tb] = [trait(a, \"gear_mesh\"), trait(b, \"gear_mesh\")];\n const [ka, kb] = [String(ta.kind ?? \"spur\"), String(tb.kind ?? \"spur\")];\n const err = (why: string) => [diag(\"error\", \"gear_mesh\", why, a, b)];\n const [ma, mb] = [value(a, \"gear_module\"), value(b, \"gear_module\")];\n if (ma !== undefined && mb !== undefined && Math.abs(ma - mb) > 1e-3 * Math.max(ma, mb)) return err(`module ${fmt(ma)} mm and module ${fmt(mb)} mm teeth do not mesh`);\n const [pa, pb] = [value(a, \"pressure_angle\"), value(b, \"pressure_angle\")];\n if (pa !== undefined && pb !== undefined && Math.abs(pa - pb) > 0.01) return err(`pressure angles ${fmt(pa)}° and ${fmt(pb)}° do not mesh`);\n if (!(GEAR_MATES[ka] ?? []).includes(kb)) return err(`a ${ka.replace(/_/g, \" \")} gear does not mesh with a ${kb.replace(/_/g, \" \")} gear`);\n const [za, zb] = [value(a, \"tooth_count\"), value(b, \"tooth_count\")];\n if (ka === \"helical\" && kb === \"helical\") {\n const [ha, hb] = [Number(ta.helix_angle_deg), Number(tb.helix_angle_deg)];\n if (Math.abs(ha - hb) > 0.01) return err(`helix angles ${fmt(ha)}° and ${fmt(hb)}° differ: helical gears on parallel shafts need the same angle`);\n if (ta.hand !== undefined && ta.hand === tb.hand) return err(`both are ${ta.hand}-hand: helical gears on parallel shafts need opposite hands`);\n }\n if ((ka === \"internal\" || kb === \"internal\") && za !== undefined && zb !== undefined) {\n const [ring, pinion] = ka === \"internal\" ? [za, zb] : [zb, za];\n if (pinion >= ring) return err(`a ${pinion}-tooth pinion does not fit inside a ${ring}-tooth internal gear`);\n }\n if (ma === undefined || za === undefined || zb === undefined) return [];\n const parts: string[] = [];\n if (ka === \"rack\" || kb === \"rack\") {\n const z = ka === \"rack\" ? zb : za;\n parts.push(`the pinion's axis sits ${fmt((ma * z) / 2)} mm from the rack's pitch line; ${fmt(Math.PI * ma * z)} mm of travel per turn`);\n } else if (ka === \"worm\" || kb === \"worm\") {\n const [worm, wheel] = ka === \"worm\" ? [za, zb] : [zb, za];\n parts.push(`ratio ${fmt(wheel / worm)}:1 (${wheel} teeth, ${worm} start${worm === 1 ? \"\" : \"s\"})`);\n } else {\n const internal = ka === \"internal\" || kb === \"internal\";\n const beta = ka === \"helical\" ? (Number(ta.helix_angle_deg) * Math.PI) / 180 : 0;\n const centre = ((internal ? Math.abs(za - zb) : za + zb) * ma) / (2 * Math.cos(beta));\n parts.push(`${za} teeth to ${zb}: ratio ${fmt(Math.max(za, zb) / Math.min(za, zb))}:1; centre distance ${fmt(centre)} mm`);\n }\n const [fa, fb] = [value(a, \"face_width\"), value(b, \"face_width\")];\n if (fa !== undefined && fb !== undefined) parts.push(`engaged face width ${fmt(Math.min(fa, fb))} mm`);\n return [diag(\"info\", \"gear_mesh\", parts.join(\"; \"), a, b)];\n}\n\n// ---------------------------------------------------------------------------\n// Bearings\n// ---------------------------------------------------------------------------\n\nfunction bearingFit(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"bearing_fit\") || !speaks(b, \"bearing_fit\")) return [];\n const [bearing, seat] = rolesOf(a, \"bearing_fit\").has(\"bearing\") ? [a, b] : [b, a];\n if (!rolesOf(seat, \"bearing_fit\").has(\"seat\") || !rolesOf(bearing, \"bearing_fit\").has(\"bearing\")) return [];\n const out: Diagnostic[] = [];\n const [od, seatOd] = [range(bearing, \"bearing_od\"), range(seat, \"bearing_od\")];\n if (od && seatOd && !overlaps(od, seatOd, TOL_MM)) {\n return [diag(\"error\", \"bearing_fit\", `a Ø${fmtR(od)} mm bearing does not fit a Ø${fmtR(seatOd)} mm seat`, bearing, seat)];\n }\n const [tb, ts] = [trait(bearing, \"bearing_fit\"), trait(seat, \"bearing_fit\")];\n const kinds = Array.isArray(ts.kinds) ? ts.kinds.map(String) : [];\n if (kinds.length && tb.kind !== undefined && !kinds.includes(String(tb.kind))) {\n out.push(diag(\"warning\", \"bearing_fit\", `the seat is made for ${kinds.join(\" or \")} bearings, not a ${tb.kind} bearing`, bearing, seat));\n }\n const [w, depth] = [value(bearing, \"bearing_width\"), value(seat, \"seat_depth\")];\n if (w !== undefined && depth !== undefined && !ts.through && w > depth + TOL_MM) {\n const flange = tb.flange_od_mm !== undefined ? \" (its flange outside the seat)\" : \"\";\n out.push(diag(\"info\", \"bearing_fit\", `the ${fmt(w)} mm wide bearing stands ${fmt(w - depth)} mm proud of the ${fmt(depth)} mm deep seat${flange}`, bearing, seat));\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Threads\n// ---------------------------------------------------------------------------\n\nfunction threadFit(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"thread\") || !speaks(b, \"thread\")) return [];\n const [ta, tb] = [trait(a, \"thread\"), trait(b, \"thread\")];\n const name = (t: Record<string, unknown>) => String(t.designation ?? \"thread\");\n const err = (why: string) => [diag(\"error\", \"thread_fit\", `${name(ta)} and ${name(tb)} do not fit: ${why}`, a, b)];\n const [da, db] = [range(a, \"fastener_diameter\"), range(b, \"fastener_diameter\")];\n if (da && db && !overlaps(da, db, TOL_MM)) return err(`diameters ${fmtR(da)} mm and ${fmtR(db)} mm`);\n const [pa, pb] = [range(a, \"thread_pitch\"), range(b, \"thread_pitch\")];\n if (pa && pb && !overlaps(pa, pb, 0.005)) return err(`pitches ${fmtR(pa)} mm and ${fmtR(pb)} mm`);\n if ((ta.hand ?? \"right\") !== (tb.hand ?? \"right\")) return err(`a ${ta.hand ?? \"right\"}-hand and a ${tb.hand ?? \"right\"}-hand thread`);\n const [la, lb] = [value(a, \"thread_length\"), value(b, \"thread_length\")];\n if (la === undefined || lb === undefined) return [];\n const internal = rolesOf(a, \"thread\").has(\"internal\") ? a : b;\n const ti = internal === a ? ta : tb;\n const [li, le] = internal === a ? [la, lb] : [lb, la];\n const engaged = Math.min(li, le);\n return [diag(\"info\", \"thread_fit\", `up to ${fmt(engaged)} mm of thread engaged (${fmt(le)} mm external, ${fmt(li)} mm internal${ti.through ? \", through\" : \"\"})`, a, b)];\n}\n\n// ---------------------------------------------------------------------------\n// T-slots\n// ---------------------------------------------------------------------------\n\nconst normProfile = (s: unknown) => String(s ?? \"\").replace(/[\\s_-]/g, \"\").toLowerCase();\n\nfunction tSlotFit(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"t_slot\") || !speaks(b, \"t_slot\")) return [];\n const [track, insert] = rolesOf(a, \"t_slot\").has(\"track\") ? [a, b] : [b, a];\n if (!rolesOf(track, \"t_slot\").has(\"track\") || !rolesOf(insert, \"t_slot\").has(\"insert\")) return [];\n const [tt, ti] = [trait(track, \"t_slot\"), trait(insert, \"t_slot\")];\n const err = (why: string) => diag(\"error\", \"t_slot_fit\", why, track, insert);\n const out: Diagnostic[] = [];\n const opening = value(track, \"slot_opening\");\n const [neck, head, height] = [value(insert, \"neck_width\"), value(insert, \"head_width\"), value(insert, \"head_height\")];\n const [cw, cd] = [value(track, \"channel_width\"), value(track, \"channel_depth\")];\n let compared = false;\n if (opening !== undefined && neck !== undefined) {\n compared = true;\n if (neck > opening + TOL_MM) out.push(err(`the ${fmt(neck)} mm neck does not pass the ${fmt(opening)} mm opening`));\n }\n if (opening !== undefined && head !== undefined) {\n compared = true;\n if (head <= opening + TOL_MM) out.push(err(`the ${fmt(head)} mm head passes through the ${fmt(opening)} mm opening: the lips do not hold it`));\n }\n if (cw !== undefined && head !== undefined) {\n compared = true;\n if (head > cw + TOL_MM) out.push(err(`the ${fmt(head)} mm head is wider than the ${fmt(cw)} mm channel`));\n }\n if (cd !== undefined && height !== undefined) {\n compared = true;\n if (height > cd + TOL_MM) out.push(err(`the ${fmt(height)} mm head is taller than the ${fmt(cd)} mm channel is deep`));\n }\n const [et, ei] = [Array.isArray(tt.entry) ? tt.entry.map(String) : [], Array.isArray(ti.entry) ? ti.entry.map(String) : []];\n if (et.length && ei.length && !ei.some((e) => et.includes(e))) out.push(err(`the insert goes in ${ei.join(\" or \")}; the track takes ${et.join(\" or \")}`.replace(/drop_in/g, \"drop-in\").replace(/\\bend\\b/g, \"from an end\")));\n if (!compared && tt.profile !== undefined && ti.profile !== undefined && normProfile(tt.profile) !== normProfile(ti.profile)) {\n out.push(diag(\"warning\", \"t_slot_fit\", `the track is a ${tt.profile} slot and the insert is made for ${ti.profile}: no dimensions to compare`, track, insert));\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Axial faces\n// ---------------------------------------------------------------------------\n\nfunction axialFace(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"axial_stop\") || !speaks(b, \"axial_stop\")) return [];\n const [oa, ob, ia, ib] = [value(a, \"face_od\"), value(b, \"face_od\"), value(a, \"face_id\"), value(b, \"face_id\")];\n if (oa === undefined || ob === undefined) return [];\n const contactOd = Math.min(oa, ob);\n const contactId = Math.max(ia ?? 0, ib ?? 0);\n if (contactOd <= contactId + TOL_MM) {\n return [diag(\"error\", \"axial_face\", `the faces do not touch: a Ø${fmt(contactOd)} mm face passes inside the other's Ø${fmt(contactId)} mm bore`, a, b)];\n }\n const [ta, tb] = [trait(a, \"axial_stop\"), trait(b, \"axial_stop\")];\n if (ta.turns_with !== undefined && tb.turns_with !== undefined && ta.turns_with !== tb.turns_with) {\n return [diag(\"warning\", \"axial_face\", `one face turns with the ${ta.turns_with}, the other with the ${tb.turns_with}: they rub (touch only the bearing's inner ring, or use a thrust washer)`, a, b)];\n }\n return [];\n}\n\n// ---------------------------------------------------------------------------\n// Wheels\n// ---------------------------------------------------------------------------\n\nfunction rollingContact(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"rolling_contact\") || !speaks(b, \"rolling_contact\")) return [];\n const [wheel, surface] = rolesOf(a, \"rolling_contact\").has(\"wheel\") ? [a, b] : [b, a];\n const [d, min] = [value(wheel, \"wheel_diameter\"), value(surface, \"min_wheel_diameter\")];\n if (d !== undefined && min !== undefined && d + TOL_MM < min) return [diag(\"error\", \"rolling_contact\", `a Ø${fmt(d)} mm wheel is smaller than the Ø${fmt(min)} mm the surface is made for`, wheel, surface)];\n return [];\n}\n","import type { InterfaceDef } from \"../types/interface.js\";\nimport type { Diagnostic } from \"./types.js\";\nimport { getEffectiveRange } from \"../parameters/range.js\";\n\n/**\n * Pair checks for serial links, IR remotes, AC mains, coils, piezo loads\n * and battery charge ports (`protocols/serial.ts`,\n * `protocols/actuation.ts`, `protocols/battery.ts`):\n *\n * - `rs485_duplex` (error): a half-duplex port against a full-duplex one.\n * - `rs232_null_modem` (warning): two DTEs or two DCEs: the link needs a\n * null-modem (crossover) cable.\n * - `ppm_channels` (warning): an input that decodes fewer channels than the\n * output sends drops the rest. `ppm_polarity` (error): positive pulses\n * into an input that takes only negative ones, or the reverse.\n * - `ir_link`: a carrier outside the receiver's band (a warning within 10 %,\n * where range drops; an error beyond); an emitter wavelength outside the\n * receiver's band (warning); no coding protocol in common (error).\n * - `ac_power`: a plug that does not go into the socket (IEC 60320 and NEMA\n * pairs; error); an input that needs protective earth on an outlet\n * without one (error).\n * - `inductive_load`: a coil that draws more than the channel is rated for\n * (error); nothing that clamps the turn-off spike (warning, or info when\n * the channel does not say); a polarised coil on a channel that reverses\n * (warning).\n * - `piezo_drive`: a driver whose lowest output voltage is above what the\n * element takes (error), or that can be set above it (warning); an element\n * count the driver has too few outputs for (error).\n * - `battery_charge`: no chemistry in common (error); a charge voltage above\n * the battery's (error), one that can be set above it (warning) or one\n * below it (warning: the battery is not filled); a charge current above\n * what the battery accepts (error), or one that can be set above it\n * (warning).\n */\nexport function checkPairSignals(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n return [...rs485(a, b), ...rs232(a, b), ...ppm(a, b), ...irLink(a, b), ...acPower(a, b), ...inductive(a, b), ...piezo(a, b), ...batteryCharge(a, b)];\n}\n\nconst SIGNAL_CHECKED: Record<string, string[]> = {\n ppm: [\"channel_count\"],\n ir_remote: [\"ir_carrier\", \"wavelength\"],\n inductive_load: [\"coil_current\", \"coil_resistance\"],\n piezo_drive: [\"drive_voltage\"],\n battery_charge: [\"charge_voltage\", \"charge_current\"],\n};\n\n/** Parameters `checkPairSignals` compares itself for this pair, which the overlap check skips. */\nexport function signalCheckedParams(a: InterfaceDef, b: InterfaceDef): Set<string> {\n for (const [protocol, ids] of Object.entries(SIGNAL_CHECKED)) if (speaks(a, protocol) && speaks(b, protocol)) return new Set(ids);\n return new Set();\n}\n\nconst speaks = (iface: InterfaceDef, type: string) => iface.protocols.some((p) => p.type === type);\nconst rolesOf = (iface: InterfaceDef, type: string) => new Set(iface.protocols.filter((p) => p.type === type).flatMap((p) => p.roles));\nconst trait = (iface: InterfaceDef, type: string): Record<string, unknown> => (iface.traits?.find((t) => t.type === type)?.params as Record<string, unknown>) ?? {};\nconst range = (iface: InterfaceDef, id: string): [number, number] | undefined => {\n const p = iface.parameters?.find((x) => x.id === id);\n return (p && getEffectiveRange(p)) ?? undefined;\n};\nconst fmt = (v: number) => `${+v.toFixed(3)}`;\nconst fmtR = (r: [number, number]) => (Math.abs(r[1] - r[0]) <= 1e-9 ? fmt(r[0]) : `${fmt(r[0])}–${fmt(r[1])}`);\nconst diag = (severity: Diagnostic[\"severity\"], code: string, message: string, a: InterfaceDef, b: InterfaceDef): Diagnostic => ({ severity, code, message, refs: [a.id, b.id] });\nconst pick = (a: InterfaceDef, b: InterfaceDef, type: string, role: string): [InterfaceDef, InterfaceDef] | undefined =>\n rolesOf(a, type).has(role) ? [a, b] : rolesOf(b, type).has(role) ? [b, a] : undefined;\n\nfunction rs485(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"rs485\") || !speaks(b, \"rs485\")) return [];\n const [da, db] = [trait(a, \"rs485\").duplex ?? \"half\", trait(b, \"rs485\").duplex ?? \"half\"];\n return da === db ? [] : [diag(\"error\", \"rs485_duplex\", `a ${da}-duplex RS-485 port does not link with a ${db}-duplex one without an adapter`, a, b)];\n}\n\nfunction rs232(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"rs232\") || !speaks(b, \"rs232\")) return [];\n const ra = rolesOf(a, \"rs232\");\n const rb = rolesOf(b, \"rs232\");\n const both = (r: string) => ra.has(r) && rb.has(r) && ra.size === 1 && rb.size === 1;\n if (both(\"dte\") || both(\"dce\")) {\n const r = [...ra][0].toUpperCase();\n return [diag(\"warning\", \"rs232_null_modem\", `two ${r}s: the link needs a null-modem cable (TXD to RXD, RTS to CTS, DTR to DSR crossed)`, a, b)];\n }\n return [];\n}\n\nfunction ppm(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"ppm\") || !speaks(b, \"ppm\")) return [];\n const p = pick(a, b, \"ppm\", \"output\");\n if (!p) return [];\n const [out, inp] = p;\n const res: Diagnostic[] = [];\n const [co, ci] = [range(out, \"channel_count\"), range(inp, \"channel_count\")];\n if (co && ci && co[1] > ci[1]) res.push(diag(\"warning\", \"ppm_channels\", `the output sends ${fmt(co[1])} channels; the input decodes ${fmt(ci[1])}, so the last ${fmt(co[1] - ci[1])} are lost`, out, inp));\n const [po, pi] = [trait(out, \"ppm\").polarity, trait(inp, \"ppm\").polarity];\n if (po !== undefined && pi !== undefined && po !== \"either\" && pi !== \"either\" && po !== pi) res.push(diag(\"error\", \"ppm_polarity\", `${po} pulses into an input that takes ${pi} pulses (an inverter between them fixes it)`, out, inp));\n return res;\n}\n\nfunction irLink(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"ir_remote\") || !speaks(b, \"ir_remote\")) return [];\n const p = pick(a, b, \"ir_remote\", \"transmitter\");\n if (!p || !rolesOf(p[1], \"ir_remote\").has(\"receiver\")) return [];\n const [tx, rx] = p;\n const out: Diagnostic[] = [];\n const [ct, cr] = [range(tx, \"ir_carrier\"), range(rx, \"ir_carrier\")];\n if (ct && cr) {\n const f = (ct[0] + ct[1]) / 2;\n const off = f < cr[0] ? (cr[0] - f) / cr[0] : f > cr[1] ? (f - cr[1]) / cr[1] : 0;\n if (off > 0.1) out.push(diag(\"error\", \"ir_link\", `a ${fmtR(ct)} kHz carrier is outside the receiver's ${fmtR(cr)} kHz band`, tx, rx));\n else if (off > 0.005) out.push(diag(\"warning\", \"ir_link\", `a ${fmtR(ct)} kHz carrier is ${fmt(off * 100)} % off the receiver's ${fmtR(cr)} kHz band: it works at a shorter range`, tx, rx));\n }\n const [wt, wr] = [range(tx, \"wavelength\"), range(rx, \"wavelength\")];\n if (wt && wr && wr[1] > wr[0] && (wt[1] < wr[0] || wt[0] > wr[1])) out.push(diag(\"warning\", \"ir_link\", `the ${fmtR(wt)} nm emitter is outside the receiver's ${fmtR(wr)} nm band`, tx, rx));\n const [pt, pr] = [trait(tx, \"ir_remote\").protocols, trait(rx, \"ir_remote\").protocols];\n if (Array.isArray(pt) && Array.isArray(pr) && pt.length && pr.length) {\n const norm = (s: unknown) => String(s).replace(/[\\s_-]/g, \"\").toLowerCase();\n if (!pt.some((x) => pr.map(norm).includes(norm(x)))) out.push(diag(\"error\", \"ir_link\", `the transmitter codes ${pt.join(\", \")}; the receiver decodes ${pr.join(\", \")}`, tx, rx));\n }\n return out;\n}\n\n/** IEC 60320 inlets (male) and the connectors that go into them; NEMA receptacles and the plugs they take. */\nconst SOCKET_TAKES: Record<string, string[]> = {\n c2: [\"c1\"],\n c4: [\"c3\"],\n c6: [\"c5\"],\n c8: [\"c7\"],\n c14: [\"c13\", \"c15\"],\n c16: [\"c15\"],\n c18: [\"c17\"],\n c20: [\"c19\", \"c21\"],\n c22: [\"c21\"],\n \"nema1-15r\": [\"nema1-15p\"],\n \"nema5-15r\": [\"nema1-15p\", \"nema5-15p\"],\n \"nema5-20r\": [\"nema1-15p\", \"nema5-15p\", \"nema5-20p\"],\n \"nema6-15r\": [\"nema6-15p\"],\n \"nema6-20r\": [\"nema6-15p\", \"nema6-20p\"],\n};\nconst normPlug = (s: unknown): string | undefined => {\n const t = String(s ?? \"\").toLowerCase().replace(/\\s+/g, \"\");\n const iec = /(?:^|iec(?:60320)?-?)c(\\d{1,2})(?![\\d])/.exec(t);\n if (iec) return `c${iec[1]}`;\n const nema = /nema(\\d{1,2}-\\d{2}[pr])/.exec(t);\n return nema ? `nema${nema[1]}` : undefined;\n};\nconst isSocket = (k: string) => k in SOCKET_TAKES;\nconst fits = (x: string, y: string) => (SOCKET_TAKES[x] ?? []).includes(y) || (SOCKET_TAKES[y] ?? []).includes(x);\n\nfunction acPower(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"ac_power\") || !speaks(b, \"ac_power\")) return [];\n const out: Diagnostic[] = [];\n const [ta, tb] = [trait(a, \"ac_power\"), trait(b, \"ac_power\")];\n const [pa, pb] = [normPlug(ta.plug), normPlug(tb.plug)];\n // a cord's two ends are compared against what they plug into: both ends known and neither takes the other\n if (pa && pb && (isSocket(pa) || isSocket(pb)) && !fits(pa, pb)) out.push(diag(\"error\", \"ac_power\", `a ${ta.plug} does not mate with a ${tb.plug}`, a, b));\n const p = pick(a, b, \"ac_power\", \"input\");\n if (p) {\n const [inp, src] = p;\n if (trait(inp, \"ac_power\").earth === true && trait(src, \"ac_power\").earth === false) out.push(diag(\"error\", \"ac_power\", \"the input needs protective earth; the outlet has none\", inp, src));\n }\n return out;\n}\n\nfunction inductive(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"inductive_load\") || !speaks(b, \"inductive_load\")) return [];\n const p = pick(a, b, \"inductive_load\", \"driver\");\n if (!p || !rolesOf(p[1], \"inductive_load\").has(\"load\")) return [];\n const [drv, load] = p;\n const out: Diagnostic[] = [];\n const [cur, max] = [range(load, \"coil_current\"), range(drv, \"max_current\")];\n if (cur && max && cur[1] > max[1] + 1e-9) out.push(diag(\"error\", \"inductive_load\", `the coil draws ${fmt(cur[1])} A; the channel is rated for ${fmt(max[1])} A`, drv, load));\n const [td, tl] = [trait(drv, \"inductive_drive\"), trait(load, \"inductive_load\")];\n const loadClamps = tl.suppression !== undefined && tl.suppression !== \"none\";\n if (!loadClamps && tl.suppression === \"none\" && td.flyback === \"none\") out.push(diag(\"warning\", \"inductive_load\", \"neither the coil nor the channel has a flyback diode or clamp: add one across the coil\", drv, load));\n else if (!loadClamps && td.flyback === undefined && td.switching !== \"relay\") out.push(diag(\"info\", \"inductive_load\", \"the channel does not say whether it clamps the coil's turn-off spike\", drv, load));\n if (tl.polarized === true && td.switching === \"h_bridge\") out.push(diag(\"warning\", \"inductive_load\", \"the channel can reverse the coil, whose suppression is polarised: drive it one way only\", drv, load));\n return out;\n}\n\nconst EPS = 1e-9;\n\nfunction piezo(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"piezo_drive\") || !speaks(b, \"piezo_drive\")) return [];\n const p = pick(a, b, \"piezo_drive\", \"driver\");\n if (!p || !rolesOf(p[1], \"piezo_drive\").has(\"load\")) return [];\n const [drv, load] = p;\n const out: Diagnostic[] = [];\n const [vd, vl] = [range(drv, \"drive_voltage\"), range(load, \"drive_voltage\")];\n if (vd && vl) {\n if (vd[0] > vl[1] + EPS) out.push(diag(\"error\", \"piezo_drive\", `the driver puts out ${fmtR(vd)} V peak to peak; the element takes ${fmt(vl[1])}`, drv, load));\n else if (vd[1] > vl[1] + EPS) out.push(diag(\"warning\", \"piezo_drive\", `the driver can put out ${fmt(vd[1])} V peak to peak; the element takes ${fmt(vl[1])}: set the amplitude no higher`, drv, load));\n }\n const [outputs, elements] = [trait(drv, \"piezo_drive\").outputs, trait(load, \"piezo_load\").elements];\n if (typeof outputs === \"number\" && typeof elements === \"number\" && elements > outputs) {\n out.push(diag(\"error\", \"piezo_drive\", `the load has ${elements} elements driven separately; the driver has ${outputs} output${outputs === 1 ? \"\" : \"s\"}`, drv, load));\n }\n return out;\n}\n\nfunction batteryCharge(a: InterfaceDef, b: InterfaceDef): Diagnostic[] {\n if (!speaks(a, \"battery_charge\") || !speaks(b, \"battery_charge\")) return [];\n const p = pick(a, b, \"battery_charge\", \"charger\");\n if (!p || !rolesOf(p[1], \"battery_charge\").has(\"battery\")) return [];\n const [chg, bat] = p;\n const out: Diagnostic[] = [];\n const [cc, cb] = [trait(chg, \"battery_charge\").chemistry, trait(bat, \"battery_charge\").chemistry];\n if (Array.isArray(cc) && Array.isArray(cb) && cc.length && cb.length) {\n const norm = (s: unknown) => String(s).replace(/[\\s_-]/g, \"\").toLowerCase();\n if (!cb.some((x) => cc.map(norm).includes(norm(x)))) out.push(diag(\"error\", \"battery_charge\", `the charger charges ${cc.join(\", \")}; the battery is ${cb.join(\", \")}`, chg, bat));\n }\n const [vc, vb] = [range(chg, \"charge_voltage\"), range(bat, \"charge_voltage\")];\n if (vc && vb) {\n if (vc[0] > vb[1] + EPS) out.push(diag(\"error\", \"battery_charge\", `the charger charges to ${fmtR(vc)} V; the battery's charge voltage is ${fmtR(vb)} V`, chg, bat));\n else if (vc[1] > vb[1] + EPS) out.push(diag(\"warning\", \"battery_charge\", `the charger can be set to ${fmt(vc[1])} V; the battery's charge voltage is ${fmtR(vb)} V: set it no higher`, chg, bat));\n else if (vc[1] < vb[0] - EPS) out.push(diag(\"warning\", \"battery_charge\", `the charger charges to ${fmtR(vc)} V; the battery's charge voltage is ${fmtR(vb)} V, so it is not charged fully`, chg, bat));\n }\n const [ic, ib] = [range(chg, \"charge_current\"), range(bat, \"charge_current\")];\n if (ic && ib) {\n if (ic[0] > ib[1] + EPS) out.push(diag(\"error\", \"battery_charge\", `the charger charges at ${fmtR(ic)} A; the battery accepts ${fmt(ib[1])} A`, chg, bat));\n else if (ic[1] > ib[1] + EPS) out.push(diag(\"warning\", \"battery_charge\", `the charger can charge at ${fmt(ic[1])} A; the battery accepts ${fmt(ib[1])} A: set the charge current no higher`, chg, bat));\n }\n return out;\n}\n","import type { SlotMatch } from \"../types/interface.js\";\n\n/**\n * DRC result model — the serializable contract between the engine and every\n * renderer (web PairScene, ASCII, JSON export). See docs/drc-implementation-plan.md\n * Phase 1 and docs/visualizer-spec.md §10.\n *\n * Everything here must survive JSON.parse(JSON.stringify(x)) unchanged.\n */\n\nexport type Tier = \"protocol\" | \"compositional\" | \"inferred\" | \"manual\" | \"none\";\n\nexport const TIER_CONFIDENCE: Record<Tier, number> = {\n protocol: 1.0,\n compositional: 0.8,\n inferred: 0.5,\n manual: 0.3,\n none: 0.0,\n};\n\nexport type ConnectionState =\n | \"valid\"\n | \"valid_inferred\"\n | \"valid_manual\"\n | \"configuration_needed\"\n | \"warning\"\n | \"incompatible\"\n | \"not_configured\";\n\nexport interface Diagnostic {\n severity: \"error\" | \"warning\" | \"info\";\n code: string;\n message: string;\n /** ids of the things this diagnostic is about (param ids, interface ids, slot ids) */\n refs?: string[];\n}\n\n/**\n * Path from a module's surface down to a region: [\"actuator_port_1\", \"uart\"].\n * The attachment altitude of a match is where this path ends — NOT just an\n * interface id (visualizer-spec §4 rule 1).\n */\nexport type RegionPath = string[];\n\nexport interface EndpointRef {\n moduleId: string;\n regionPath: RegionPath;\n}\n\nexport interface EndpointAttachment extends EndpointRef {\n /** role played on the matched protocol (\"master\", \"device\", \"input\", …) */\n role: string;\n /** derived from regionPath.length; sub↔top asymmetry is legal */\n altitude: \"top\" | \"sub\";\n}\n\n/** One end of a conductor: a leaf interface, plus how it was reached. */\nexport interface LeafRef {\n moduleId: string;\n interfaceId: string;\n /** slot on the composed parent this leaf fills (absent for bare leaves) */\n slotId?: string;\n /** physical pin label if known (\"D16\", \"pin 3\") */\n pin?: string;\n}\n\n/** One conductor / wire inside a connection. */\nexport interface SubLinkResult {\n id: string;\n from: LeafRef;\n to: LeafRef;\n method: \"protocol\" | \"manual\" | \"inferred\";\n locked: boolean;\n /** split fulfillment: which module actually supplies this slot */\n provenance?: { moduleId: string };\n /** mirrored-ordering hint: from/to render at the same row index */\n rowPair: number;\n diagnostics: Diagnostic[];\n}\n\nexport interface UnresolvedSlot {\n moduleId: string;\n regionPath: RegionPath;\n slotId: string;\n required: boolean;\n match: SlotMatch;\n}\n\n/** A realized pairing between two regions — one shared region in the B8 view. */\nexport interface ConnectionResult {\n id: string;\n a: EndpointAttachment;\n b: EndpointAttachment;\n topology: \"wire\" | \"bus\" | \"split\" | \"or\";\n /** protocol type the pairing matched on */\n protocol: string;\n tier: Tier;\n confidence: number;\n state: ConnectionState;\n subLinks: SubLinkResult[];\n /** required slots with no counterpart → amber sockets, CONFIGURATION_NEEDED */\n unresolvedSlots: UnresolvedSlot[];\n /** bus multi-drop extras beyond a/b */\n drops?: EndpointAttachment[];\n diagnostics: Diagnostic[];\n}\n\n/** One entry per region node per module — \"everything is shown\" (spec §5.1). */\nexport interface InterfaceCensusEntry {\n moduleId: string;\n regionPath: RegionPath;\n /** protocol summary for rail rendering (\"i2c · master, slave\") */\n label: string;\n status: \"connected\" | \"partial\" | \"compatible\" | \"no_counterpart\" | \"conflict\";\n /** donut data for partially-engaged parents */\n engagement?: { engaged: number; total: number };\n /** human-readable qualifier (\"compatible: d3\", \"∅ range vs power_5v_out\") */\n reason?: string;\n}\n\n/** A compatible-but-unconnected pairing — ◉ ports and dashed potential bands. */\nexport interface PotentialConnection {\n a: EndpointRef;\n b: EndpointRef;\n protocol: string;\n tier: Tier;\n confidence: number;\n /** true when every checked parameter is compatible */\n clean: boolean;\n diagnostics: Diagnostic[];\n}\n\n/**\n * Capacity findings (Phase 6). Shaped for scoped rule packs: `ruleId` names the\n * rule that produced the report and `scope` names where that rule was declared\n * (domain pack, protocol def, interface), so domains with different physics\n * (current vs. flow vs. bandwidth) reuse the same report shape.\n */\nexport interface CapacityReport {\n id: string;\n ruleId: string;\n scope: { level: \"domain\" | \"protocol\" | \"interface\"; id: string };\n resource: string;\n unit: string;\n used: number;\n limit: number;\n contributors: EndpointRef[];\n severity: \"error\" | \"warning\" | \"info\";\n message: string;\n}\n\n/** Explicit user-authored link (Phase 4). Locked links always win over derived. */\nexport interface ManualLinkDef {\n id: string;\n from: LeafRef;\n to: LeafRef;\n locked?: boolean;\n}\n\nexport interface PairVerdict {\n state: ConnectionState;\n counts: {\n connections: number;\n valid: number;\n warnings: number;\n errors: number;\n configurationNeeded: number;\n potentials: number;\n };\n}\n\nexport interface ModuleSummary {\n id: string;\n name: string;\n interfaceCount: number;\n}\n\nexport interface PairValidationResult {\n modules: { a: ModuleSummary; b: ModuleSummary };\n connections: ConnectionResult[];\n census: InterfaceCensusEntry[];\n potentials: PotentialConnection[];\n capacity: CapacityReport[];\n verdict: PairVerdict;\n}\n\nexport interface ValidatePairOptions {\n /** ghost third-party modules for split fulfillment (Phase 3+) */\n context?: import(\"../types/module.js\").ModuleDef[];\n /** user-authored links overlaid on discovery (Phase 4) */\n manualLinks?: ManualLinkDef[];\n /** compute census suggestions / potentials (default true) */\n includePotentials?: boolean;\n /**\n * The pair is a link someone made (a stored or derived system link), not a\n * discovery: pairings that never mate (two shafts, two bores) are accepted\n * as connections so their diagnostics say why. Discovery lists them as\n * potentials only.\n */\n explicit?: boolean;\n}\n","import type { ModuleDef } from \"../types/module.js\";\nimport { matchProtocols, type ProtocolMatchResult } from \"../matching/protocol-match.js\";\nimport { areRolesCompatible } from \"../matching/roles.js\";\nimport {\n buildRegionTree,\n flattenTree,\n descendants,\n pickProfile,\n type RegionNode,\n} from \"./region-tree.js\";\nimport { checkPairParameters } from \"./param-check.js\";\nimport { checkPairJoints, neverMates, pairCheckedParams } from \"./joint-check.js\";\nimport { checkPairLinks, linkCheckedParams } from \"./link-check.js\";\nimport { checkPairDrive, driveCheckedParams } from \"./drive-check.js\";\nimport { checkPairSignals, signalCheckedParams } from \"./signal-check.js\";\nimport type {\n ConnectionResult,\n ConnectionState,\n Diagnostic,\n InterfaceCensusEntry,\n LeafRef,\n PairValidationResult,\n PotentialConnection,\n SubLinkResult,\n UnresolvedSlot,\n ValidatePairOptions,\n} from \"./types.js\";\nimport { TIER_CONFIDENCE } from \"./types.js\";\n\ninterface Candidate {\n a: RegionNode;\n b: RegionNode;\n match: ProtocolMatchResult;\n diagnostics: Diagnostic[];\n clean: boolean;\n /** Never auto-connected (two shafts, two bores): a potential only, unless the pair is explicit. */\n potentialOnly: boolean;\n}\n\n/**\n * Validate a pair of modules: discover connections across both region trees,\n * resolve conductors, run parameter checks, and produce the full serializable\n * result the visualizer renders from (docs/drc-implementation-plan.md Phase 2).\n *\n * v1 scope: protocol-tier matching only. Compositional/inferred discovery\n * (Phase 3a), manual links (Phase 4), bridges (Phase 5), and capacity (Phase 6)\n * layer on top of this pipeline.\n */\nexport function validatePair(\n moduleA: ModuleDef,\n moduleB: ModuleDef,\n opts: ValidatePairOptions = {},\n): PairValidationResult {\n const includePotentials = opts.includePotentials !== false;\n\n const rootsA = buildRegionTree(moduleA);\n const rootsB = buildRegionTree(moduleB);\n const regionsA = flattenTree(rootsA);\n const regionsB = flattenTree(rootsB);\n\n // --- Stage 1: discovery — enumerate every compatible region pairing ---\n const candidates: Candidate[] = [];\n for (const a of regionsA) {\n for (const b of regionsB) {\n if (a.iface.domain !== b.iface.domain) continue;\n const match = matchProtocols(a.iface, b.iface);\n if (!match.compatible) continue;\n // parameters the joint check compares itself (a cross against a circle, a row against a slot)\n // and those the link check compares (speeds, lane rates, bus widths, PoE power)\n // and those the drive and signal checks compare (gear modules, bearing diameters, IR carriers)\n const skip = new Set([\n ...pairCheckedParams(a.iface, b.iface),\n ...linkCheckedParams(a.iface, b.iface),\n ...driveCheckedParams(a.iface, b.iface),\n ...signalCheckedParams(a.iface, b.iface),\n ]);\n const params = checkPairParameters(a.iface.parameters, b.iface.parameters).filter((d) => !d.refs?.some((r) => skip.has(r)));\n const diagnostics = [\n ...params,\n ...checkPairJoints(a.iface, b.iface),\n ...checkPairLinks(a.iface, b.iface),\n ...checkPairDrive(a.iface, b.iface),\n ...checkPairSignals(a.iface, b.iface),\n ];\n candidates.push({\n a,\n b,\n match,\n diagnostics,\n clean: diagnostics.every((d) => d.severity !== \"error\"),\n potentialOnly: !opts.explicit && neverMates(a.iface, b.iface),\n });\n }\n }\n\n // Highest common altitude first, then parametric cleanliness, then stable ids.\n candidates.sort(\n (x, y) =>\n x.a.depth + x.b.depth - (y.a.depth + y.b.depth) ||\n Number(y.clean) - Number(x.clean) ||\n candidateKey(x).localeCompare(candidateKey(y)),\n );\n\n // --- Stage 2: acceptance — auto-connect only unambiguous pairings ---\n // A region (or any of its ancestors/descendants) participates in at most one\n // connection; consumed subtrees drop out of the alive set as we accept.\n const consumedA = new Set<RegionNode>();\n const consumedB = new Set<RegionNode>();\n const accepted: Candidate[] = [];\n\n const blocked = (node: RegionNode, consumed: Set<RegionNode>): boolean =>\n consumed.has(node) ||\n descendants(node).some((d) => consumed.has(d)) ||\n ancestorConsumed(node, consumed);\n\n // A mechanical feature that has interchangeable twins (an extrusion's four identical slots, a\n // bracket's identical legs, a plate's identical bearing seats) is one choice, not several: one\n // connection per pair of twin classes is made, on the first twin of each, and the rest stay potentials.\n const twinClassesDone = new Set<string>();\n const twinPair = (c: Candidate) => {\n const [ka, kb] = [twinKey(c.a), twinKey(c.b)];\n return ka !== undefined && kb !== undefined ? `${ka}\\u0000${kb}` : undefined;\n };\n const alive = (c: Candidate) =>\n !c.potentialOnly && !blocked(c.a, consumedA) && !blocked(c.b, consumedB) && !(twinPair(c) !== undefined && twinClassesDone.has(twinPair(c)!));\n\n let progressed = true;\n while (progressed) {\n progressed = false;\n const aliveCandidates = candidates.filter(alive);\n for (const c of aliveCandidates) {\n if (!alive(c)) continue; // may have been consumed earlier this sweep\n // an endpoint whose clean pairings are taken by a twin's connection waits rather than\n // falling back to a pairing with errors\n const twinHeld = candidates.filter((x) => x.clean && !x.potentialOnly && twinPair(x) !== undefined && twinClassesDone.has(twinPair(x)!));\n if (!c.clean && twinHeld.some((x) => x.a === c.a || x.b === c.b)) continue;\n if (!isUnambiguous(c, aliveCandidates.filter(alive))) continue;\n accepted.push(c);\n const tp = twinPair(c);\n if (tp !== undefined) twinClassesDone.add(tp);\n consumedA.add(c.a);\n for (const d of descendants(c.a)) consumedA.add(d);\n consumedB.add(c.b);\n for (const d of descendants(c.b)) consumedB.add(d);\n progressed = true;\n }\n }\n\n // --- Stage 3: build connection results (sub-links, states) ---\n const connections = accepted.map((c) => buildConnection(c, moduleA.id, moduleB.id));\n\n // --- Stage 4: potentials — compatible pairings that were not auto-connected ---\n const potentials: PotentialConnection[] = includePotentials\n ? candidates\n .filter((c) => !accepted.includes(c))\n .map((c) => ({\n a: { moduleId: moduleA.id, regionPath: c.a.path },\n b: { moduleId: moduleB.id, regionPath: c.b.path },\n protocol: c.match.matchedProtocol ?? \"\",\n tier: \"protocol\" as const,\n confidence: c.match.confidence,\n clean: c.clean,\n diagnostics: c.diagnostics,\n }))\n : [];\n\n // --- Stage 5: census — every region of both modules is represented ---\n const census = [\n ...buildCensus(moduleA.id, regionsA, consumedA, accepted.map((c) => c.a), candidates.map((c) => c.a), candidates, \"a\"),\n ...buildCensus(moduleB.id, regionsB, consumedB, accepted.map((c) => c.b), candidates.map((c) => c.b), candidates, \"b\"),\n ];\n\n // --- Stage 6: verdict rollup ---\n const counts = {\n connections: connections.length,\n valid: connections.filter((c) => c.state === \"valid\" || c.state === \"valid_inferred\" || c.state === \"valid_manual\").length,\n warnings: connections.filter((c) => c.state === \"warning\").length,\n errors: connections.filter((c) => c.state === \"incompatible\").length,\n configurationNeeded: connections.filter((c) => c.state === \"configuration_needed\").length,\n potentials: potentials.length,\n };\n const state: ConnectionState =\n connections.length === 0\n ? \"not_configured\"\n : counts.errors > 0\n ? \"incompatible\"\n : counts.configurationNeeded > 0\n ? \"configuration_needed\"\n : counts.warnings > 0\n ? \"warning\"\n : \"valid\";\n\n return {\n modules: {\n a: { id: moduleA.id, name: moduleA.name, interfaceCount: regionsA.length },\n b: { id: moduleB.id, name: moduleB.name, interfaceCount: regionsB.length },\n },\n connections,\n census,\n potentials,\n capacity: [], // Phase 6\n verdict: { state, counts },\n };\n}\n\nfunction candidateKey(c: Candidate): string {\n return `${c.a.path.join(\".\")}~${c.b.path.join(\".\")}`;\n}\n\nfunction ancestorConsumed(node: RegionNode, consumed: Set<RegionNode>): boolean {\n let current = node.parent;\n while (current) {\n if (consumed.has(current)) return true;\n current = current.parent;\n }\n return false;\n}\n\n/**\n * Auto-connect policy: a candidate is accepted only when it is the sole viable\n * choice for BOTH of its endpoints — the only clean alive candidate, or (when an\n * endpoint has no clean options at all) the only alive candidate. Ambiguous\n * matches (a GPIO that a dozen pins could serve) surface as potentials for the\n * user to click instead. Connections are never auto-locked.\n */\nfunction isUnambiguous(c: Candidate, aliveCandidates: Candidate[]): boolean {\n for (const side of [\"a\", \"b\"] as const) {\n const other = side === \"a\" ? \"b\" : \"a\";\n // a pairing with a region inside c's other end (a power port's own pin, when the ports match) is\n // the same connection at a lower altitude, not a rival to it; and a composite and the leaves it\n // binds are one choice, not several: when a composite pairs with a composite and also with that\n // composite's own leaves, the composite pairing counts (highest altitude first). A composite\n // against a lone leaf stays ambiguous with the leaves inside it.\n const below = new Set(descendants(c[other]));\n const composite = (n: RegionNode) => Boolean(n.iface.slots?.length);\n const forEndpoint = aliveCandidates\n .filter((x) => x[side] === c[side] && !below.has(x[other]))\n .filter((x, _, all) => !all.some((y) => y !== x && composite(y[side]) && composite(y[other]) && isAncestor(y[other], x[other])));\n const clean = forEndpoint.filter((x) => x.clean);\n const pool = clean.length > 0 ? clean : forEndpoint;\n if (pool.length === 1 && pool[0] === c) continue;\n // rivals that differ only by which interchangeable twin they use are the same choice: take the first\n const twin = twinKey(c[other]);\n if (twin === undefined || pool[0] !== c || !pool.every((x) => twinKey(x[other]) === twin)) return false;\n }\n return true;\n}\n\nfunction isAncestor(node: RegionNode, of: RegionNode): boolean {\n let current = of.parent;\n while (current) {\n if (current === node) return true;\n current = current.parent;\n }\n return false;\n}\n\nfunction buildConnection(c: Candidate, moduleIdA: string, moduleIdB: string): ConnectionResult {\n const id = `${moduleIdA}:${c.a.path.join(\".\")}~${moduleIdB}:${c.b.path.join(\".\")}`;\n const { subLinks, unresolvedSlots } = resolveSubLinks(id, c, moduleIdA, moduleIdB);\n\n const allDiagnostics = [...c.diagnostics, ...subLinks.flatMap((l) => l.diagnostics)];\n const hasError = allDiagnostics.some((d) => d.severity === \"error\");\n const hasWarning = allDiagnostics.some((d) => d.severity === \"warning\");\n const state: ConnectionState = hasError\n ? \"incompatible\"\n : unresolvedSlots.some((s) => s.required)\n ? \"configuration_needed\"\n : hasWarning\n ? \"warning\"\n : \"valid\";\n\n return {\n id,\n a: {\n moduleId: moduleIdA,\n regionPath: c.a.path,\n role: c.match.roleA ?? \"\",\n altitude: c.a.depth === 0 ? \"top\" : \"sub\",\n },\n b: {\n moduleId: moduleIdB,\n regionPath: c.b.path,\n role: c.match.roleB ?? \"\",\n altitude: c.b.depth === 0 ? \"top\" : \"sub\",\n },\n topology: \"wire\",\n protocol: c.match.matchedProtocol ?? \"\",\n tier: \"protocol\",\n confidence: TIER_CONFIDENCE.protocol,\n state,\n subLinks,\n unresolvedSlots,\n diagnostics: c.diagnostics,\n };\n}\n\n/**\n * Pair the matched regions' slots into conductors. When both sides declare\n * slots, slots pair by protocol + complementary role and each side's conductor\n * endpoint is the leaf its active profile binds. When either side is a bare\n * leaf, the connection is a single conductor between the regions themselves.\n * rowPair indices carry the mirrored row ordering the layout engine uses.\n */\nfunction resolveSubLinks(\n connectionId: string,\n c: Candidate,\n moduleIdA: string,\n moduleIdB: string,\n): { subLinks: SubLinkResult[]; unresolvedSlots: UnresolvedSlot[] } {\n const slotsA = c.a.iface.slots ?? [];\n const slotsB = c.b.iface.slots ?? [];\n const subLinks: SubLinkResult[] = [];\n const unresolvedSlots: UnresolvedSlot[] = [];\n\n if (slotsA.length === 0 || slotsB.length === 0) {\n subLinks.push({\n id: `${connectionId}#0`,\n from: { moduleId: moduleIdA, interfaceId: c.a.iface.id },\n to: { moduleId: moduleIdB, interfaceId: c.b.iface.id },\n method: \"protocol\",\n locked: false,\n rowPair: 0,\n diagnostics: [],\n });\n return { subLinks, unresolvedSlots };\n }\n\n const profileA = pickProfile(c.a.iface);\n const profileB = pickProfile(c.b.iface);\n const usedB = new Set<string>();\n let row = 0;\n\n for (const slotA of slotsA) {\n const protocol = slotA.match.protocol;\n const partner = slotsB.find(\n (slotB) =>\n !usedB.has(slotB.id) &&\n protocol !== undefined &&\n slotB.match.protocol?.toLowerCase() === protocol.toLowerCase() &&\n (slotA.match.role === undefined ||\n slotB.match.role === undefined ||\n areRolesCompatible(protocol, slotA.match.role, slotB.match.role)),\n );\n\n if (!partner) {\n if (slotA.required) {\n unresolvedSlots.push({\n moduleId: moduleIdA,\n regionPath: c.a.path,\n slotId: slotA.id,\n required: true,\n match: slotA.match,\n });\n }\n continue;\n }\n usedB.add(partner.id);\n\n subLinks.push({\n id: `${connectionId}#${row}`,\n from: leafRef(moduleIdA, c.a.iface.id, slotA.id, profileA?.bindings[slotA.id]),\n to: leafRef(moduleIdB, c.b.iface.id, partner.id, profileB?.bindings[partner.id]),\n method: \"protocol\",\n locked: false,\n rowPair: row,\n diagnostics: [],\n });\n row++;\n }\n\n for (const slotB of slotsB) {\n if (slotB.required && !usedB.has(slotB.id)) {\n unresolvedSlots.push({\n moduleId: moduleIdB,\n regionPath: c.b.path,\n slotId: slotB.id,\n required: true,\n match: slotB.match,\n });\n }\n }\n\n return { subLinks, unresolvedSlots };\n}\n\nfunction leafRef(\n moduleId: string,\n ownerInterfaceId: string,\n slotId: string,\n binding: string | string[] | undefined,\n): LeafRef {\n const bound = Array.isArray(binding) ? binding[0] : binding;\n return { moduleId, interfaceId: bound ?? ownerInterfaceId, slotId };\n}\n\nfunction buildCensus(\n moduleId: string,\n regions: RegionNode[],\n consumed: Set<RegionNode>,\n connectedNodes: RegionNode[],\n candidateNodes: RegionNode[],\n candidates: Candidate[],\n side: \"a\" | \"b\",\n): InterfaceCensusEntry[] {\n const connectedSet = new Set(connectedNodes);\n const candidateSet = new Set(candidateNodes);\n\n return regions.map((node) => {\n const label = node.iface.protocols\n .map((p) => `${p.type} · ${p.roles.join(\", \")}`)\n .join(\" | \");\n const base = { moduleId, regionPath: node.path, label };\n\n if (connectedSet.has(node)) {\n return { ...base, status: \"connected\" as const };\n }\n\n const engagedChildren = node.children.filter(\n (child) => connectedSet.has(child) || descendants(child).some((d) => connectedSet.has(d)),\n );\n if (engagedChildren.length > 0) {\n return {\n ...base,\n status: \"partial\" as const,\n engagement: { engaged: engagedChildren.length, total: node.children.length },\n };\n }\n\n if (consumed.has(node)) {\n // inside a connected parent's shared territory — engaged via the parent\n return { ...base, status: \"connected\" as const, reason: \"via parent\" };\n }\n\n if (candidateSet.has(node)) {\n const counterparts = candidates\n .filter((c) => c[side] === node)\n .map((c) => (side === \"a\" ? c.b : c.a).iface.id);\n return {\n ...base,\n status: \"compatible\" as const,\n reason: `compatible: ${[...new Set(counterparts)].join(\", \")}`,\n };\n }\n\n return { ...base, status: \"no_counterpart\" as const };\n });\n}\n\n/**\n * Interchangeable mechanical features: a mechanical interface without a pin,\n * keyed by everything but its id, name and geometry (protocols,\n * capabilities, parameters, traits, slots). Two interfaces of one module with\n * the same key are twins: bolting a bracket to one face of an extrusion or\n * another is the same connection. Electrical interfaces are never twins\n * (choosing a pin is a wiring decision).\n */\nconst twinKeys = new WeakMap<RegionNode, string | undefined>();\nfunction twinKey(node: RegionNode): string | undefined {\n if (twinKeys.has(node)) return twinKeys.get(node);\n const i = node.iface;\n const key =\n i.domain === \"mechanical\" && i.pin === undefined && node.parent === undefined\n ? JSON.stringify([i.protocols, i.capabilities ?? [], i.parameters ?? [], i.traits ?? [], i.slots ?? []])\n : undefined;\n twinKeys.set(node, key);\n return key;\n}\n","/**\n * Connector links: a link between two connector composites (or a\n * connector and a link-scoped composition) mates positions, not protocols.\n * Checked here: connector type, gender, position count and compose slots.\n * What the positions carry is checked on the links derived from them\n * (derive.ts).\n */\nimport type { InterfaceDef } from \"../types/interface.js\";\nimport type { InterfaceLink } from \"../types/module.js\";\nimport type { Diagnostic } from \"../drc/types.js\";\nimport { isConnector } from \"../protocols/connector.js\";\nimport type { LinkChildResult, LinkResult, ResolvedEndpoint } from \"./index.js\";\n\n\ninterface ConnectorParams {\n connector_type?: string;\n gender?: string;\n positions?: number;\n mates_with?: string[];\n}\n\nfunction connectorParams(iface: InterfaceDef): ConnectorParams[] {\n return (iface.traits ?? []).filter((t) => t.type === \"connector\").map((t) => (t.params ?? {}) as ConnectorParams);\n}\n\n/** Connector type slugs declared on an interface (its `connector` traits). */\nexport function connectorTypes(iface: InterfaceDef): string[] {\n return connectorParams(iface)\n .map((p) => String(p.connector_type ?? \"\"))\n .filter(Boolean);\n}\n\n/** Slot → bound interface id, from the connector's default (first) profile. */\nexport function slotBindings(iface: InterfaceDef): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [slot, v] of Object.entries(iface.profiles?.[0]?.bindings ?? {})) {\n const id = Array.isArray(v) ? v[0] : v;\n if (id) out[slot] = id;\n }\n return out;\n}\n\n/** Slot ids of a connector, in position order. */\nexport function slotIds(iface: InterfaceDef): string[] {\n return (iface.slots ?? []).map((s) => s.id);\n}\n\n/** Position pairs of a connector link: stored child links, else same slot id. */\nexport function positionPairs(link: InterfaceLink, a: ResolvedEndpoint, b: ResolvedEndpoint): { a: string; b: string }[] {\n if (link.childLinks?.length) return link.childLinks.map((c) => ({ a: c.a, b: c.b }));\n const bSlots = new Set(slotIds(b.iface));\n return slotIds(a.iface)\n .filter((s) => bSlots.has(s))\n .map((s) => ({ a: s, b: s }));\n}\n\nconst OPPOSITE_ONLY = new Set([\"plug\", \"receptacle\", \"male\", \"female\", \"socket\", \"header\"]);\n\nfunction mateProblems(link: InterfaceLink, a: ResolvedEndpoint, b: ResolvedEndpoint): Diagnostic[] {\n const out: Diagnostic[] = [];\n const pa = connectorParams(a.iface);\n const pb = connectorParams(b.iface);\n const ta = connectorTypes(a.iface);\n const tb = connectorTypes(b.iface);\n if (ta.length && tb.length) {\n const accepts = (x: ConnectorParams[], y: string[]) => x.some((p) => (p.mates_with ?? []).some((m) => y.includes(m)));\n if (!ta.some((t) => tb.includes(t)) && !accepts(pa, tb) && !accepts(pb, ta)) {\n out.push({ severity: \"error\", code: \"connector_mismatch\", message: `${a.path} is ${ta.join(\"/\")} but ${b.path} is ${tb.join(\"/\")}`, refs: [a.path, b.path] });\n }\n }\n const ga = pa.find((p) => p.gender)?.gender;\n const gb = pb.find((p) => p.gender)?.gender;\n if (ga && gb && ga === gb && OPPOSITE_ONLY.has(ga)) {\n out.push({ severity: \"error\", code: \"connector_gender\", message: `${a.path} and ${b.path} are both ${ga}`, refs: [a.path, b.path] });\n }\n if (!a.composed && !b.composed) {\n const na = slotIds(a.iface).length;\n const nb = slotIds(b.iface).length;\n if (na && nb && na !== nb && !link.childLinks?.length) {\n out.push({ severity: \"error\", code: \"connector_positions\", message: `${a.path} has ${na} positions but ${b.path} has ${nb}`, refs: [a.path, b.path] });\n }\n }\n for (const [composed, other] of [[a, b], [b, a]] as const) {\n if (!composed.composed) continue;\n const known = new Set(slotIds(other.iface));\n for (const slot of Object.keys(composed.composed)) {\n if (!known.has(slot)) {\n out.push({ severity: \"error\", code: \"compose_unknown_slot\", message: `${composed.path} composes ${slot}, which ${other.path} does not have (${[...known].join(\", \")})`, refs: [composed.path, other.path] });\n }\n }\n }\n return out;\n}\n\nfunction leafFor(end: ResolvedEndpoint, slot: string): LinkChildResult[\"a\"] {\n const composed = end.composed?.[slot];\n if (composed) return { slotId: slot, leafId: composed.iface.id, pin: composed.iface.pin === undefined ? undefined : String(composed.iface.pin) };\n const leafId = slotBindings(end.iface)[slot];\n const leaf = leafId ? end.owner.interfaces.find((i) => i.id === leafId) : undefined;\n return { slotId: slot, leafId: leafId ?? slot, pin: leaf?.pin === undefined ? undefined : String(leaf.pin) };\n}\n\n/** Validate a stored link between two connectors: mating only, by position. */\nexport function validateConnectorLink(link: InterfaceLink, a: ResolvedEndpoint, b: ResolvedEndpoint): LinkResult {\n const diagnostics = mateProblems(link, a, b);\n const children: LinkChildResult[] = positionPairs(link, a, b).map((p) => ({\n a: leafFor(a, p.a),\n b: leafFor(b, p.b),\n method: link.childLinks?.length ? \"manual\" : \"protocol\",\n locked: false,\n }));\n return {\n link,\n a,\n b,\n state: diagnostics.some((d) => d.severity === \"error\") ? \"incompatible\" : \"configured\",\n protocol: \"connector\",\n children,\n unresolvedSlots: [],\n diagnostics,\n };\n}\n","import type { TraitDef } from \"../types/trait.js\";\nimport type { InterfaceDef } from \"../types/interface.js\";\nimport type { DomainKind } from \"../types/domain.js\";\n\n/**\n * Physical connector or termination on an interface.\n *\n * Emits the `connector` trait shape the audited parts library already uses\n * (`{ connector_type }`), plus optional detail such as gender, pin count,\n * and the physical pin order.\n */\nexport interface ConnectorDetail {\n /** e.g. \"female\", \"male\", \"receptacle\", \"plug\". */\n gender?: string;\n /** Number of positions on the connector. */\n positions?: number;\n /** Signal names in physical pin order, pin 1 first. */\n pinout?: string[];\n /** Free-form note citing the source for the connector details. */\n note?: string;\n /**\n * On a harness module's end: which end of the links it carries this\n * connector mates with (\"a\" or \"b\"). Checked by the harness_connector rule.\n */\n mates?: \"a\" | \"b\";\n /**\n * How the connector comes with the part: \"fitted\" (the default)\n * when it is attached, \"loose\" when it ships in the bag and is fitted\n * during assembly (a shield's header strips, soldered by the builder).\n */\n supplied?: \"fitted\" | \"loose\";\n}\n\n/**\n * Build a `connector` trait. `connectorType` is a lowercase slug such as\n * \"xt60\", \"jst_sh_8\", \"solder_pad\", \"bare_wire_lead\", or \"mmcx\".\n */\nexport function connectorTrait(connectorType: string, detail: ConnectorDetail = {}): TraitDef {\n return {\n type: \"connector\",\n params: {\n connector_type: connectorType,\n ...(detail.gender !== undefined ? { gender: detail.gender } : {}),\n ...(detail.positions !== undefined ? { positions: detail.positions } : {}),\n ...(detail.pinout !== undefined ? { pinout: detail.pinout } : {}),\n ...(detail.note !== undefined ? { note: detail.note } : {}),\n ...(detail.mates !== undefined ? { mates: detail.mates } : {}),\n ...(detail.supplied !== undefined ? { supplied: detail.supplied } : {}),\n },\n };\n}\n\n/** The interfaces of a part whose connector ships loose, to be fitted during assembly (`supplied: \"loose\"`). */\nexport function looseConnectors(def: { interfaces: InterfaceDef[] }): { iface: InterfaceDef; connectorType: string; note?: string }[] {\n return def.interfaces.flatMap((iface) =>\n (iface.traits ?? [])\n .filter((t) => t.type === \"connector\" && (t.params as { supplied?: string } | undefined)?.supplied === \"loose\")\n .map((t) => {\n const p = t.params as { connector_type?: string; note?: string };\n return { iface, connectorType: String(p.connector_type ?? \"connector\"), ...(p.note ? { note: p.note } : {}) };\n }),\n );\n}\n\n// ---------------------------------------------------------------------------\n// Connector composites\n// ---------------------------------------------------------------------------\n\n\n/** One physical position: its printed label and the interface it carries (none: unused, e.g. VOID). */\nexport type ConnectorPin = string | { label: string; to?: string; note?: string } | [label: string, to?: string];\n\nexport interface ConnectorConfig extends ConnectorDetail {\n id: string;\n name?: string;\n /** Connector type slug, e.g. \"jst_sh_8\", \"dji_6pin\", \"xt60\". */\n connector: string;\n /** Positions in physical order, pin 1 first. Slot ids are `p1`, `p2`, …. */\n pins: ConnectorPin[];\n domain?: DomainKind;\n exposed?: boolean;\n /** Other connector types this one mates with (default: the same type only). */\n matesWith?: string[];\n traits?: TraitDef[];\n}\n\n/** The protocol type every connector composite speaks. */\nexport const CONNECTOR_PROTOCOL = \"connector\";\n\n/** True for a connector composite (or a link-scoped composition). */\nexport function isConnector(iface: InterfaceDef): boolean {\n return iface.protocols.some((p) => p.type === CONNECTOR_PROTOCOL);\n}\n\n/**\n * A physical connector as one interface: one slot per position\n * (`p1…pN`) and a default profile binding each used position to the pad or\n * leaf interface it carries. Links between two connectors are matched by\n * position; the functional links (power, UART, …) are derived by tracing\n * conductors through harnesses (`deriveLinks`).\n *\n * Part-authoring rule: every physical connector on a part is a connector\n * composite. A connector carrying exactly one functional interface (USB-C,\n * an RF jack) may keep the connector trait on that interface instead.\n */\nexport function Connector(config: ConnectorConfig): InterfaceDef {\n const pins = config.pins.map((p) =>\n typeof p === \"string\" ? { label: p } : Array.isArray(p) ? { label: p[0], to: p[1] } : p,\n );\n const bindings: Record<string, string> = {};\n pins.forEach((p, i) => {\n if (p.to) bindings[`p${i + 1}`] = p.to;\n });\n const trait = connectorTrait(config.connector, {\n gender: config.gender,\n positions: pins.length,\n pinout: pins.map((p) => p.label),\n note: config.note,\n mates: config.mates,\n supplied: config.supplied,\n });\n if (config.matesWith?.length) (trait.params as Record<string, unknown>).mates_with = config.matesWith;\n return {\n id: config.id,\n name: config.name,\n domain: config.domain ?? \"electrical\",\n exposed: config.exposed ?? true,\n default_active: true,\n protocols: [{ type: CONNECTOR_PROTOCOL, roles: [\"mate\"] }],\n slots: pins.map((p, i) => ({ id: `p${i + 1}`, label: p.label, required: false, match: {} })),\n profiles: [{ id: `${config.id}_pinout`, label: \"Pinout\", default_active: true, bindings }],\n max_instances: 1,\n traits: [trait, ...(config.traits ?? [])],\n };\n}\n","import type { InterfaceDef } from \"../types/interface.js\";\nimport type { InterfaceLink } from \"../types/module.js\";\nimport type { TraitDef } from \"../types/trait.js\";\nimport { voltageRangeV, voltageV } from \"./params.js\";\n\n/**\n * Nets: the conductors of a board joining two or more pins.\n *\n * A net is an interface on the board module itself (protocol `net`, not\n * exposed). Each pin on the net is joined to it by an ordinary stored link\n * from the pin (`child`) to the net (`self`). The functional links between\n * the pins (supply output to inputs, I2C master to target) are derived from\n * the memberships by `deriveLinks`, so system checks see a board the same way\n * they see a cable. See docs/boards-and-nets.md.\n */\nexport const NET_PROTOCOL = \"net\";\n\nexport interface NetConfig {\n id: string;\n /** Net name as a schematic would print it, e.g. \"3V3\", \"GND\", \"SDA\". */\n name?: string;\n /**\n * Design voltage of the net: what the board intends this rail to be, not\n * what a part allows (a 1.2–5.5 V adjustable regulator set to 3.3 V). Every\n * pin on the net with a `voltage` parameter is checked against it.\n */\n voltageV?: number | [number, number];\n traits?: TraitDef[];\n}\n\n/** True for a net interface. */\nexport function isNet(iface: InterfaceDef): boolean {\n return iface.protocols.some((p) => p.type === NET_PROTOCOL);\n}\n\n/** A net on a board: the node that its pins' membership links join. */\nexport function Net(config: NetConfig): InterfaceDef {\n const v = config.voltageV;\n return {\n id: config.id,\n name: config.name ?? config.id,\n domain: \"electrical\",\n exposed: false,\n default_active: true,\n protocols: [{ type: NET_PROTOCOL, roles: [\"node\"] }],\n ...(v !== undefined ? { parameters: [Array.isArray(v) ? voltageRangeV(v[0], v[1]) : voltageV(v)] } : {}),\n ...(config.traits?.length ? { traits: config.traits } : {}),\n };\n}\n\n/**\n * Membership links joining pins to a net on the linking module. Members are\n * `\"<child>:<interface>\"` (an interface or export of a direct child). Link\n * ids are `<net>.<child>.<interface>`.\n *\n * links: [...netLinks(\"gnd\", [\"u1:pad_gnd\", \"u2:pin_6\", \"u2:pin_7\", \"u3:pgnd\"])]\n */\nexport function netLinks(net: string, members: string[]): InterfaceLink[] {\n return members.map((member) => {\n const [child, interfaceId, extra] = member.split(\":\");\n if (!child || !interfaceId || extra !== undefined || child.includes(\"/\")) {\n throw new Error(`Net \"${net}\": member \"${member}\" is not \"<child>:<interface>\"`);\n }\n return {\n id: `${net}.${child}.${interfaceId}`,\n a: { child, interfaceId },\n b: { self: true, interfaceId: net },\n };\n });\n}\n","/**\n * Boards and nets: a custom PCB is an ordinary module whose\n * children are its components and whose nets are `Net` interfaces on the\n * board itself, each pin joined to its net by a stored membership link\n * (docs/boards-and-nets.md).\n *\n * Here: validation of membership links, the net index of a module, and the\n * board rules that need whole nets rather than pairs of pins:\n *\n * net a net with fewer than two pins; a pin on two nets;\n * several modules driving one supply net; ground joined\n * to a supply; a supply pin whose voltage range\n * excludes the net's design voltage, or a logic pin\n * rated below it\n * (netRule); a passive with every terminal on one net, a\n * part's power input on the net of an output it feeds,\n * a strap on a net that carries another part's signal\n * (partWiringRule)\n * bus_pullup an I2C link over nets with no pull-up resistor to a supply\n * design_envelope a stated body larger than the module's design envelope\n *\n * The functional links between the pins of a net are derived in derive.ts.\n */\nimport type { InterfaceDef } from \"../types/interface.js\";\nimport type { InterfaceLink, ModuleDef } from \"../types/module.js\";\nimport type { Parameter } from \"../types/parameter.js\";\nimport type { DesignEnvelopeTrait, StrapTrait } from \"../types/trait.js\";\nimport type { Diagnostic } from \"../drc/types.js\";\nimport { getEffectiveRange, rangesOverlap } from \"../parameters/range.js\";\nimport { isNet, NET_PROTOCOL } from \"../protocols/net.js\";\nimport { passiveInstance, passiveOf } from \"../protocols/passive.js\";\nimport { isConnector } from \"../protocols/connector.js\";\nimport { slotBindings } from \"./connectors.js\";\nimport { formatPath, netPortOf, validateLinks, type LinkResult, type ModuleLookup, type ResolvedEndpoint } from \"./index.js\";\nimport type { SystemDiagnostic } from \"./checks.js\";\n\n// ---------------------------------------------------------------------------\n// Membership links\n// ---------------------------------------------------------------------------\n\n/**\n * Validate a stored link with a net at one end: it joins one pin to a net\n * declared on the linking module. Nothing is matched; what the pins on a net\n * carry is checked on the links derived from it.\n *\n * A child's net port (a net the child exports) is joined like a pin: to a\n * net of the linking module, or by a pin linked to the port, which puts the\n * pin on the child's net. Two net ports join through a net of the linking\n * module, not to each other.\n */\nexport function validateNetLink(link: InterfaceLink, a: ResolvedEndpoint, b: ResolvedEndpoint): LinkResult {\n const diagnostics: Diagnostic[] = [];\n // a net port is the member of the linking module's own net\n const netIsA = isNet(a.iface) && !(a.netPort && isNet(b.iface) && \"self\" in link.b);\n const [net, member] = netIsA ? [a, b] : [b, a];\n const netTarget = netIsA ? link.a : link.b;\n if (isNet(member.iface)) {\n if (!(member.netPort && \"self\" in netTarget)) {\n const message = member.netPort && net.netPort\n ? `${a.path} and ${b.path} are both net ports; join them through a net of this module`\n : `${a.path} and ${b.path} are both nets; a pin joins a net, and two nets that are one conductor are one net`;\n diagnostics.push({ severity: \"error\", code: \"net_to_net\", message, refs: [a.path, b.path] });\n }\n } else if (member.iface.slots?.length || isConnector(member.iface)) {\n diagnostics.push({ severity: \"error\", code: \"net_member_composite\", message: `${member.path} is a composite interface; a net joins pins, so link its leaves`, refs: [member.path, net.path] });\n }\n if (!(\"self\" in netTarget) && !net.netPort) {\n diagnostics.push({ severity: \"error\", code: \"net_not_own\", message: `${net.path} is a net of a child; nets join pins on the module that declares them, or a child exports the net as a net port`, refs: [net.path] });\n }\n return {\n link,\n a,\n b,\n state: diagnostics.length ? \"incompatible\" : \"configured\",\n protocol: NET_PROTOCOL,\n children: [],\n unresolvedSlots: [],\n diagnostics,\n };\n}\n\n/** True for a link result that is a net membership rather than a functional link. */\nexport function isNetMembership(r: LinkResult): boolean {\n return r.protocol === NET_PROTOCOL;\n}\n\n/**\n * The ends of a valid membership link: the linking module's own net and its\n * member (a pin, or a child's net port), or, for a pin linked straight to a\n * child's net port, that port and the pin.\n */\nexport function membershipEnds(r: LinkResult): { net: ResolvedEndpoint; member: ResolvedEndpoint } | { port: ResolvedEndpoint; member: ResolvedEndpoint } {\n if (isNet(r.a.iface) && \"self\" in r.link.a) return { net: r.a, member: r.b };\n if (isNet(r.b.iface) && \"self\" in r.link.b) return { net: r.b, member: r.a };\n return r.a.netPort ? { port: r.a, member: r.b } : { port: r.b, member: r.a };\n}\n\n/** Canonical path of the module instance and interface an endpoint finally resolves to (`sensor/u1:pin_3`). */\nexport function physicalPath(end: ResolvedEndpoint): string {\n return formatPath(end.ownerPath, end.iface.id);\n}\n\n// ---------------------------------------------------------------------------\n// Net index\n// ---------------------------------------------------------------------------\n\nexport interface NetMember {\n /**\n * Canonical path of the pin, e.g. `u2:pin_8`. A pin reached through a net\n * port has the path of the part below the linking module, `sensor/u1:pin_7`.\n */\n path: string;\n end: ResolvedEndpoint;\n /**\n * The membership link. One stored on a sub-module is prefixed with the\n * sub-module's instance path, `sensor/vdd.u1.pin_7`.\n */\n link: string;\n /**\n * Set on a pin reached through a net port: the nets of sub-modules it was\n * reached through, outermost first (`[\"sensor:vdd\"]`). The last is the net\n * the pin is a member of.\n */\n through?: string[];\n}\n\n/** A net of a sub-module on a conductor, reached through a net port. */\nexport interface NestedNet {\n /** Canonical path of the net below the linking module, `sensor:vdd`. */\n path: string;\n iface: InterfaceDef;\n}\n\nexport interface BoardNet {\n iface: InterfaceDef;\n /**\n * Canonical path of the net on the module, `:<id>`. A conductor with no\n * net of the module (pins linked straight to a child's net port) is named\n * by the port's net, `sensor:vdd`, and so is its `iface.id`.\n */\n path: string;\n /** The pins on the net; with a lookup, also the pins its net ports reach (`through` set). */\n members: NetMember[];\n /** Children's net ports joined to the net. Present only when there are any. */\n ports?: NetMember[];\n /** Sub-module nets on the conductor through those ports, at any depth. Present only with a lookup and ports. */\n nested?: NestedNet[];\n}\n\ntype LinkCache = Map<ModuleDef, LinkResult[]>;\n\nfunction storedLinks(def: ModuleDef, lookup: ModuleLookup, cache: LinkCache): LinkResult[] {\n let links = cache.get(def);\n if (!links) {\n links = validateLinks(def, lookup);\n cache.set(def, links);\n }\n return links;\n}\n\n/**\n * What a child's net port reaches inside the child: the pins on the net, at\n * any depth (through the net ports of the child's own children, and pins\n * the child links straight to them), with canonical paths below the module\n * that links the port; and the nets passed through, outermost first.\n */\nexport function netPortReach(port: ResolvedEndpoint, lookup: ModuleLookup): { members: NetMember[]; nets: NestedNet[] } {\n return reachPort(port, lookup, new Map(), 0);\n}\n\nfunction reachPort(port: ResolvedEndpoint, lookup: ModuleLookup, cache: LinkCache, depth: number): { members: NetMember[]; nets: NestedNet[] } {\n const base = port.ownerPath;\n const netPath = physicalPath(port);\n const out = { members: [] as NetMember[], nets: [{ path: netPath, iface: port.iface }] };\n if (depth >= 16) return out;\n const below = (e: ResolvedEndpoint): ResolvedEndpoint => {\n const ownerPath = [...base, ...e.ownerPath];\n return { ...e, path: formatPath(ownerPath, e.iface.id), ownerPath };\n };\n const linkId = (id: string) => `${base.join(\"/\")}/${id}`;\n const valid = storedLinks(port.owner, lookup, cache).filter((r) => isNetMembership(r) && r.state !== \"incompatible\");\n const inner: ResolvedEndpoint[] = [];\n for (const r of valid) {\n const m = membershipEnds(r);\n if (!(\"net\" in m) || m.net.iface.id !== port.iface.id) continue;\n if (m.member.netPort) inner.push(m.member);\n else out.members.push({ path: physicalPath(below(m.member)), end: below(m.member), link: linkId(r.link.id), through: [netPath] });\n }\n for (const p of inner) {\n const deeper = below(p);\n const innerPath = physicalPath(deeper);\n // pins the child links straight to its own child's port are on that net too\n for (const r of valid) {\n const m = membershipEnds(r);\n if (\"port\" in m && physicalPath(m.port) === physicalPath(p)) {\n out.members.push({ path: physicalPath(below(m.member)), end: below(m.member), link: linkId(r.link.id), through: [netPath, innerPath] });\n }\n }\n const reached = reachPort(deeper, lookup, cache, depth + 1);\n out.members.push(...reached.members.map((x) => ({ ...x, through: [netPath, ...(x.through ?? [])] })));\n out.nets.push(...reached.nets);\n }\n return out;\n}\n\n/**\n * Every net declared on `def`, with the pins its valid membership links\n * join. A child's net port on a net is listed in `ports`; given a lookup,\n * the pins the port reaches inside the child are members too (with\n * `through`), and the child's nets are `nested`. Pins linked straight to a\n * child's net port are members of the net the port is on, or of a net of\n * their own named by the port when it is on none.\n */\nexport function moduleNets(def: ModuleDef, links: LinkResult[], lookup?: ModuleLookup): BoardNet[] {\n const nets = new Map<string, BoardNet>();\n for (const iface of def.interfaces) {\n if (isNet(iface)) nets.set(iface.id, { iface, path: formatPath([], iface.id), members: [] });\n }\n const straight: { port: ResolvedEndpoint; member: NetMember }[] = [];\n for (const r of links) {\n if (!isNetMembership(r) || r.state === \"incompatible\") continue;\n const m = membershipEnds(r);\n const entry: NetMember = { path: m.member.path, end: m.member, link: r.link.id };\n if (\"port\" in m) {\n straight.push({ port: m.port, member: entry });\n continue;\n }\n const net = nets.get(m.net.iface.id);\n if (!net) continue;\n if (m.member.netPort) (net.ports ??= []).push(entry);\n else net.members.push(entry);\n }\n for (const { port, member } of straight) {\n const key = physicalPath(port);\n const host = [...nets.values()].find((n) => n.ports?.some((p) => physicalPath(p.end) === key));\n if (host) {\n host.members.push(member);\n continue;\n }\n const own = nets.get(`port#${key}`) ?? { iface: { ...port.iface, id: key }, path: key, members: [], ports: [{ path: port.path, end: port, link: member.link }] };\n own.members.push(member);\n nets.set(`port#${key}`, own);\n }\n if (lookup) {\n const cache: LinkCache = new Map();\n for (const net of nets.values()) {\n for (const p of net.ports ?? []) {\n const reached = reachPort(p.end, lookup, cache, 0);\n net.members.push(...reached.members);\n (net.nested ??= []).push(...reached.nets);\n }\n }\n }\n return [...nets.values()];\n}\n\n/**\n * Design voltage of a conductor: its own net's, else the shallowest nested\n * net that states one (a sub-module's 3V3 joined by a net that states none).\n */\nexport function conductorVoltageRange(net: BoardNet): [number, number] | undefined {\n const own = netVoltageRange(net.iface);\n if (own) return own;\n const nested = [...(net.nested ?? [])].sort((x, y) => x.path.split(\"/\").length - y.path.split(\"/\").length);\n for (const n of nested) {\n const r = netVoltageRange(n.iface);\n if (r) return r;\n }\n return undefined;\n}\n\n/** True when every one of `members` is a pin reached through the same sub-module net: that module's own check covers it. */\nfunction sameNested(members: NetMember[]): boolean {\n if (!members.length || members.some((m) => !m.through)) return false;\n return new Set(members.map((m) => m.through![m.through!.length - 1])).size === 1;\n}\n\nfunction param(iface: InterfaceDef, id: string): Parameter | undefined {\n return iface.parameters?.find((p) => p.id === id);\n}\n\nconst hasRole = (iface: InterfaceDef, type: string, role: string) =>\n iface.protocols.some((p) => p.type === type && p.roles.includes(role));\n\n/** Design voltage of a net (its `voltage` parameter) as a range, if stated. */\nexport function netVoltageRange(net: InterfaceDef): [number, number] | undefined {\n const p = param(net, \"voltage\");\n return (p && getEffectiveRange(p)) ?? undefined;\n}\n\n/** Nominal design voltage of a net: its value, else the lower end of its range. */\nexport function netVoltage(net: InterfaceDef): number | undefined {\n const p = param(net, \"voltage\");\n return p?.value ?? p?.range?.[0];\n}\n\nconst fmtRange = (r: [number, number]) => (r[0] === r[1] ? `${r[0]} V` : `${r[0]}–${r[1]} V`);\n\n/**\n * Paths a module's boundary supplies from outside: its exported child\n * interfaces, the leaves those exports bind, every pin on a net it exports\n * as a net port, and every pin on a net that carries one of them. A power input here is fed through the board edge, so\n * the unpowered rule does not report it when the board is checked alone.\n */\nexport function edgeFedPaths(def: ModuleDef, lookup: ModuleLookup, nets: BoardNet[]): Set<string> {\n const fed = new Set<string>();\n for (const ex of def.exports ?? []) {\n if (!(\"child\" in ex.from)) {\n // a net port: everything on the net is supplied through it\n const netId = ex.from.interfaceId;\n for (const m of nets.find((n) => n.iface.id === netId)?.members ?? []) fed.add(m.path);\n continue;\n }\n const { child, interfaceId } = ex.from;\n fed.add(`${child}:${interfaceId}`);\n const ref = def.children?.find((c) => c.id === child);\n const iface = ref ? lookup(ref.moduleDefId)?.interfaces.find((i) => i.id === interfaceId) : undefined;\n for (const leaf of iface ? Object.values(slotBindings(iface)) : []) fed.add(`${child}:${leaf}`);\n }\n for (const net of nets) {\n if (net.members.some((m) => fed.has(m.path))) for (const m of net.members) fed.add(m.path);\n }\n return fed;\n}\n\n// ---------------------------------------------------------------------------\n// Rules\n// ---------------------------------------------------------------------------\n\n/**\n * Rules over whole nets. Given a lookup, a net's children's net ports are\n * followed into the children, so a conductor that runs on both sides of a\n * module's edge is checked once here: its supplies, its ground, and every\n * pin on it against one design voltage (`conductorVoltageRange`). What lies\n * wholly inside one sub-module's net is left to that module's own check.\n */\nexport function netRule(def: ModuleDef, links: LinkResult[], lookup?: ModuleLookup): SystemDiagnostic[] {\n const nets = moduleNets(def, links, lookup);\n const out: SystemDiagnostic[] = [];\n const netsOf = new Map<string, string[]>();\n // pins reached through a net port, by where they finally are: net -> the routes (ports, or \"direct\") reaching them\n const physical = new Map<string, Map<string, Set<string>>>();\n\n for (const net of nets) {\n const id = net.iface.id;\n const label = net.iface.name && net.iface.name !== id ? `${id} (${net.iface.name})` : id;\n const refs = [net.path, ...net.members.map((m) => m.path)];\n const direct = net.members.filter((m) => !m.through);\n for (const m of [...direct, ...(net.ports ?? [])]) netsOf.set(m.path, [...(netsOf.get(m.path) ?? []), id]);\n for (const m of net.members) {\n const key = physicalPath(m.end);\n const byNet = physical.get(key) ?? new Map<string, Set<string>>();\n byNet.set(id, (byNet.get(id) ?? new Set()).add(m.through ? m.through[0] : \"direct\"));\n physical.set(key, byNet);\n }\n\n const joined = [...direct, ...(net.ports ?? [])];\n // a net the module exports as a net port has its other end outside\n if (joined.length + (netPortOf(def, id) ? 1 : 0) < 2) {\n out.push({\n id: `net:${id}:members`,\n rule: \"net\",\n severity: \"warning\",\n message: joined.length\n ? `net ${label} joins only ${joined[0].path}; nothing else is on it.`\n : `net ${label} joins no pins.`,\n refs,\n });\n }\n\n // more than one module driving a supply net. A connector or land carries power, it does not make\n // it, and a terminal that both gives and takes it (a cell's +, beside its charger) is storage\n const drivers = new Map<string, string[]>();\n const driving: NetMember[] = [];\n for (const m of net.members) {\n if (!hasRole(m.end.iface, \"power\", \"output\")) continue;\n if (hasRole(m.end.iface, \"power\", \"input\")) continue;\n if ((m.end.owner.categories ?? []).some((c) => c === \"connector\" || c.startsWith(\"connector.\"))) continue;\n const owner = m.end.ownerPath.join(\"/\");\n drivers.set(owner, [...(drivers.get(owner) ?? []), m.path]);\n driving.push(m);\n }\n if (drivers.size > 1 && !sameNested(driving)) {\n const paths = [...drivers.values()].flat();\n out.push({\n id: `net:${id}:drivers`,\n rule: \"net\",\n severity: \"error\",\n message: `net ${label} is driven by ${drivers.size} supplies (${paths.join(\", \")}); outputs in parallel fight each other.`,\n refs: [net.path, ...paths],\n });\n }\n\n // ground joined to a supply rail\n const groundMembers = net.members.filter((m) => hasRole(m.end.iface, \"power\", \"ground\"));\n const railMembers = net.members.filter((m) => hasRole(m.end.iface, \"power\", \"input\") || hasRole(m.end.iface, \"power\", \"output\"));\n const grounds = groundMembers.map((m) => m.path);\n const rails = railMembers.map((m) => m.path);\n if (grounds.length && rails.length && !sameNested([...groundMembers, ...railMembers])) {\n out.push({\n id: `net:${id}:ground`,\n rule: \"net\",\n severity: \"error\",\n message: `net ${label} joins ground (${grounds.join(\", \")}) to supply pins (${rails.join(\", \")}): a short.`,\n refs: [net.path, ...grounds, ...rails],\n });\n }\n\n // each pin with a stated voltage takes the net's design voltage. A supply\n // output's range is what it produces, so it must overlap; a supply input's\n // is what it accepts, so the whole rail must lie within it (a 4.2 V cell\n // rail on a 3.3 V input is a fault even though 3.0-3.3 V overlaps). A logic\n // or analog pin's range is its signal level: tied to a lower rail (a strap\n // to GND) it is driven low, so only a net above its maximum is reported.\n const design = conductorVoltageRange(net);\n const nestedRange = new Map((net.nested ?? []).map((n) => [n.path, netVoltageRange(n.iface)]));\n if (design) {\n // one conductor has one voltage: a sub-module's net joined here must state the same\n for (const n of net.nested ?? []) {\n const r = nestedRange.get(n.path);\n if (!r || rangesOverlap(r, design)) continue;\n out.push({\n id: `net:${id}:port_voltage:${n.path}`,\n rule: \"net\",\n severity: \"error\",\n message: `net ${label} is ${fmtRange(design)}, but ${n.path} (${n.iface.name ?? n.iface.id}), joined to it through a net port, is ${fmtRange(r)}.`,\n refs: [net.path, n.path],\n details: { net: design, nested: r },\n });\n }\n for (const m of net.members) {\n // a pin on a sub-module net that states this voltage is checked by that module\n const local = m.through ? nestedRange.get(m.through[m.through.length - 1]) : undefined;\n if (local && local[0] === design[0] && local[1] === design[1]) continue;\n const p = param(m.end.iface, \"voltage\");\n const range = p && getEffectiveRange(p);\n if (!range) continue;\n const supply = m.end.iface.protocols.some((x) => x.type === \"power\");\n const inputOnly = supply && hasRole(m.end.iface, \"power\", \"input\") && !hasRole(m.end.iface, \"power\", \"output\");\n const eps = 1e-9;\n const ok = inputOnly\n ? range[0] - eps <= design[0] && design[1] <= range[1] + eps\n : supply\n ? rangesOverlap(range, design)\n : design[1] <= range[1] || grounds.length > 0;\n if (ok) continue;\n out.push({\n id: `net:${id}:voltage:${m.path}`,\n rule: \"net\",\n severity: \"error\",\n message: supply\n ? `${m.path} (${m.end.iface.name ?? m.end.iface.id}) is rated ${fmtRange(range)} but net ${label} is ${fmtRange(design)}${inputOnly && rangesOverlap(range, design) ? \", outside its rating at one end\" : \"\"}.`\n : `${m.path} (${m.end.iface.name ?? m.end.iface.id}) is rated to ${range[1]} V but net ${label} reaches ${design[1]} V.`,\n refs: [net.path, m.path, `link:${m.link}`],\n details: { pin: range, net: design },\n });\n }\n }\n }\n\n // a push-pull logic output drives its net up to its own supply. When the\n // driving part has one supply net (a charger's STAT on its VDD), the net\n // reaches that supply's voltage, and a logic or analog input rated below it\n // is overdriven (an MCP73831's STAT at VBUS on a 3 V MCU pin). Open-drain\n // outputs, pins that are also inputs, and parts with several supplies are\n // left alone: their high level is not known from the model.\n const supplyNetsOf = (ownerPath: string): string[] => {\n const ids = new Set<string>();\n for (const net of nets) {\n if (net.members.some((m) => m.end.ownerPath.join(\"/\") === ownerPath && hasRole(m.end.iface, \"power\", \"input\") && !hasRole(m.end.iface, \"power\", \"ground\"))) ids.add(net.iface.id);\n }\n return [...ids];\n };\n for (const net of nets) {\n const label = net.iface.name && net.iface.name !== net.iface.id ? `${net.iface.id} (${net.iface.name})` : net.iface.id;\n for (const d of net.members) {\n const di = d.end.iface;\n if (!di.protocols.some((p) => p.type === \"digital\" && p.roles.includes(\"output\") && !p.roles.includes(\"input\") && !p.roles.includes(\"bidirectional\"))) continue;\n if ((di.capabilities ?? []).includes(\"open_drain\")) continue;\n const owner = d.end.ownerPath.join(\"/\");\n const supplies = supplyNetsOf(owner);\n if (supplies.length !== 1) continue;\n const supply = nets.find((n) => n.iface.id === supplies[0])!;\n const level = conductorVoltageRange(supply)?.[1];\n if (level === undefined) continue;\n for (const m of net.members) {\n if (m === d || m.end.ownerPath.join(\"/\") === owner) continue;\n if (m.end.iface.protocols.some((x) => x.type === \"power\")) continue;\n const p = param(m.end.iface, \"voltage\");\n const range = p && getEffectiveRange(p);\n if (!range || range[1] >= level - 1e-9) continue;\n out.push({\n id: `net:${net.iface.id}:drive:${m.path}`,\n rule: \"net\",\n severity: \"error\",\n message: `${d.path} (${di.name ?? di.id}) drives net ${label} up to its supply ${supply.iface.name ?? supply.iface.id} (${level} V), but ${m.path} (${m.end.iface.name ?? m.end.iface.id}) is rated to ${range[1]} V: divide, clamp or use an open-drain output.`,\n refs: [net.path, d.path, m.path, supply.path],\n details: { driver: d.path, supply: supply.path, level, pin: range },\n });\n }\n }\n }\n\n for (const [path, ids] of netsOf) {\n if (ids.length < 2) continue;\n out.push({\n id: `net:short:${path}`,\n rule: \"net\",\n severity: \"error\",\n message: `${path} is on nets ${ids.join(\", \")}, which joins them into one conductor.`,\n refs: [path, ...ids.map((n) => formatPath([], n))],\n });\n }\n // a pin inside a sub-module reached on two nets by two routes (its net's port on one, an exported pin on the\n // other); one port on two nets is reported above, by the port\n for (const [path, byNet] of physical) {\n const routes = new Set([...byNet.values()].flatMap((r) => [...r]));\n if (byNet.size < 2 || routes.size < 2) continue;\n const ids = [...byNet.keys()];\n out.push({\n id: `net:short:${path}`,\n rule: \"net\",\n severity: \"error\",\n message: `${path} is on nets ${ids.join(\", \")} (through a net port and an export), which joins them into one conductor.`,\n refs: [path, ...ids.map((n) => formatPath([], n))],\n });\n }\n return out;\n}\n\n/**\n * Faults of one part's own pins on the board's nets. Each is stated\n * from the model, not from a part's name:\n *\n * - **A shorted passive.** A two-terminal passive (resistor, capacitor,\n * inductor, ferrite bead) with every terminal on one net is a component\n * that does nothing: a capacitor across nothing, a resistor in series with\n * nothing. Its terminals belong on two nets.\n * - **An output tied back to its own input.** A part's power output (output\n * only) on one net with a power input (input only) of the same part that\n * feeds it short-circuits the converter: VOUT on VIN. Which input feeds\n * which output is the part's `bridgesTo` (a leaf or the composite binding\n * it); a part that states no bridge for its supply pins is taken as a\n * converter whose every power input feeds every power output. A part that\n * states its bridges may supply its own other inputs (an MCU's\n * core-regulator output on its own core supply pins). Connectors and lands carry power, they do\n * not convert it, and are skipped.\n * - **A strap on a signal.** A leaf with a `strap` trait, while its part runs\n * an interface in the strap's `when` (or always, without `when`), must sit\n * at a fixed level: on a supply or ground net, or on a net of its own with\n * a resistor to one (a pull-up or pull-down). On a net that carries\n * another pin's logic signal (a bus line) and no supply or ground pin, its\n * level follows the signal, whatever pull-up the line has: an IMU's\n * address strap moved onto SDA.\n */\nexport function partWiringRule(def: ModuleDef, links: LinkResult[], lookup?: ModuleLookup): SystemDiagnostic[] {\n const nets = moduleNets(def, links, lookup);\n const out: SystemDiagnostic[] = [];\n const ownerKey = (m: NetMember) => m.end.ownerPath.join(\"/\");\n const label = (n: BoardNet) => (n.iface.name && n.iface.name !== n.iface.id ? `${n.iface.id} (${n.iface.name})` : n.iface.id);\n const netsOfPin = new Map<string, BoardNet[]>();\n for (const n of nets) for (const m of n.members) netsOfPin.set(m.path, [...(netsOfPin.get(m.path) ?? []), n]);\n const isPower = (i: InterfaceDef) => i.protocols.some((p) => p.type === \"power\");\n const isPassivePin = (i: InterfaceDef) => i.protocols.length > 0 && i.protocols.every((p) => p.type === \"passive\");\n const isConnectorPart = (d: ModuleDef) => (d.categories ?? []).some((c) => c === \"connector\" || c.startsWith(\"connector.\"));\n\n // 1. passives with every terminal on one net\n const passives = new Map<string, { owner: ModuleDef; ownerPath: string[]; members: NetMember[] }>();\n for (const n of nets) {\n for (const m of n.members) {\n if (!passiveOf(m.end.owner)) continue;\n const k = ownerKey(m);\n const e = passives.get(k) ?? { owner: m.end.owner, ownerPath: m.end.ownerPath, members: [] };\n e.members.push(m);\n passives.set(k, e);\n }\n }\n for (const [path, { owner, ownerPath, members }] of passives) {\n const terminals = owner.interfaces.filter(isPassivePin);\n if (terminals.length < 2 || sameNested(members)) continue;\n const netIds = terminals.map((t) => (netsOfPin.get(formatPath(ownerPath, t.id)) ?? []).map((n) => n.iface.id));\n if (netIds.some((ids) => ids.length !== 1) || new Set(netIds.map((ids) => ids[0])).size !== 1) continue;\n const net = nets.find((n) => n.iface.id === netIds[0][0])!;\n const kind = passiveOf(owner)!.kind.replace(\"_\", \" \");\n out.push({\n id: `net:${net.iface.id}:shorted:${path}`,\n rule: \"net\",\n severity: \"error\",\n message: `${path} (${kind}, ${owner.name ?? owner.id}) has every terminal on net ${label(net)}: it is shorted and does nothing. Its terminals belong on two nets.`,\n refs: [net.path, ...members.map((m) => m.path)],\n details: { part: path, kind, net: net.iface.id },\n });\n }\n\n // 2. a power output on a net with an input of the same part that feeds it\n const outputOnly = (i: InterfaceDef) => hasRole(i, \"power\", \"output\") && !hasRole(i, \"power\", \"input\") && !hasRole(i, \"power\", \"ground\");\n const inputOnly = (i: InterfaceDef) => hasRole(i, \"power\", \"input\") && !hasRole(i, \"power\", \"output\") && !hasRole(i, \"power\", \"ground\");\n /** The ids an interface stands for: itself and every composite binding it. */\n const withComposites = (owner: ModuleDef, id: string) => [id, ...owner.interfaces.filter((c) => Object.values(slotBindings(c)).includes(id)).map((c) => c.id)];\n const bridges = (owner: ModuleDef, inputId: string, outputId: string) => {\n const targets = new Set(withComposites(owner, outputId));\n return withComposites(owner, inputId).some((id) => (owner.interfaces.find((i) => i.id === id)?.bridgesTo ?? []).some((t) => targets.has(t)));\n };\n const statesBridges = (owner: ModuleDef) =>\n owner.interfaces.some((i) => isPower(i) && (i.bridgesTo ?? []).some((t) => { const x = owner.interfaces.find((j) => j.id === t); return !!x && isPower(x); }));\n for (const n of nets) {\n const byOwner = new Map<string, NetMember[]>();\n for (const m of n.members) byOwner.set(ownerKey(m), [...(byOwner.get(ownerKey(m)) ?? []), m]);\n for (const [path, ms] of byOwner) {\n const owner = ms[0].end.owner;\n if (isConnectorPart(owner) || passiveOf(owner)) continue;\n const outs = ms.filter((m) => outputOnly(m.end.iface));\n const ins = ms.filter((m) => inputOnly(m.end.iface));\n if (!outs.length || !ins.length) continue;\n const declared = statesBridges(owner);\n const fed = ins.filter((i) => outs.some((o) => !declared || bridges(owner, i.end.iface.id, o.end.iface.id)));\n if (!fed.length || sameNested([...outs, ...fed])) continue;\n const name = (m: NetMember) => `${m.path} (${m.end.iface.name ?? m.end.iface.id})`;\n out.push({\n id: `net:${n.iface.id}:feedback:${path}`,\n rule: \"net\",\n severity: \"error\",\n message: `net ${label(n)} ties ${path}'s output ${outs.map(name).join(\", \")} to its own input ${fed.map(name).join(\", \")}, which feeds it: the output is shorted to the input.`,\n refs: [n.path, ...outs.map((m) => m.path), ...fed.map((m) => m.path)],\n details: { part: path, outputs: outs.map((m) => m.path), inputs: fed.map((m) => m.path) },\n });\n }\n }\n\n // 3. a strap on a net that carries another pin's signal and nothing that fixes its level\n const inUse = (ownerPath: string, ids: string[]) =>\n links.some((r) => !isNetMembership(r) && [r.a, r.b].some((e) => e.ownerPath.join(\"/\") === ownerPath && ids.includes(e.iface.id)));\n const strapOf = (m: NetMember) => {\n const t = m.end.iface.traits?.find((x) => x.type === \"strap\") as StrapTrait | undefined;\n if (!t) return undefined;\n const when = t.params?.when ?? [];\n return !when.length || inUse(ownerKey(m), when) ? t : undefined;\n };\n for (const n of nets) {\n // a supply or ground pin on the net fixes its level (a strap through a resistor is on a net of its own)\n if (n.members.some((m) => isPower(m.end.iface))) continue;\n for (const s of n.members) {\n const strap = strapOf(s);\n if (!strap) continue;\n const signals = n.members.filter((m) => m !== s && !isPower(m.end.iface) && !isPassivePin(m.end.iface) && !strapOf(m));\n if (!signals.length || sameNested([s, ...signals])) continue;\n out.push({\n id: `net:${n.iface.id}:strap:${s.path}`,\n rule: \"net\",\n severity: \"error\",\n message: `${s.path} (${s.end.iface.name ?? s.end.iface.id}) is a strap (${strap.params.function}) but net ${label(n)} carries ${signals.map((m) => m.path).join(\", \")}: its level follows that signal. Tie it to a supply or ground, directly or through a resistor.`,\n refs: [n.path, s.path, ...signals.map((m) => m.path)],\n details: { strap: s.path, function: strap.params.function, signals: signals.map((m) => m.path) },\n });\n }\n }\n return out;\n}\n\n/**\n * An I2C link derived over nets needs a pull-up on each of its nets: a\n * resistor (a `passive` resistor child) with one terminal on the bus net and\n * the other on a supply net (a net with a power output or a positive design\n * voltage). Parts with internal pull-ups are not modelled, so this warns.\n */\nexport function busPullupRule(def: ModuleDef, links: LinkResult[], lookup: ModuleLookup): SystemDiagnostic[] {\n const nets = moduleNets(def, links, lookup);\n const byId = new Map(nets.map((n) => [n.iface.id, n]));\n const netsOfPath = new Map<string, string[]>();\n for (const n of nets) for (const m of n.members) netsOfPath.set(m.path, [...(netsOfPath.get(m.path) ?? []), n.iface.id]);\n\n const isSupply = (n: BoardNet) =>\n n.members.some((m) => hasRole(m.end.iface, \"power\", \"output\")) || (netVoltage(n.iface) ?? 0) > 0;\n\n // the part a member pin is on: a direct child, or a part inside a sub-module reached through a net port\n const partOf = (m: NetMember): ModuleDef | undefined => {\n if (m.through) return m.end.owner;\n if (m.end.ownerPath.length !== 1) return undefined;\n const ref = def.children?.find((c) => c.id === m.end.ownerPath[0]);\n return ref ? lookup(ref.moduleDefId) : undefined;\n };\n\n const pulledUp = (n: BoardNet) =>\n n.members.some((m) => {\n const child = partOf(m);\n if (!child || passiveOf(child)?.kind !== \"resistor\") return false;\n return child.interfaces\n .filter((t) => t.id !== m.end.iface.id)\n .some((t) => (netsOfPath.get(formatPath(m.end.ownerPath, t.id)) ?? []).some((other) => {\n const on = byId.get(other);\n return on !== undefined && on !== n && isSupply(on);\n }));\n });\n\n const out: SystemDiagnostic[] = [];\n const reported = new Set<string>();\n // a net that carries a device's I2C line (a pad its I2C composite binds) and reaches another part is\n // an I2C bus even when no I2C link is derived (a controller whose bus pins are assigned in firmware)\n for (const n of nets) {\n if (reported.has(n.iface.id) || n.members.length < 2 || pulledUp(n)) continue;\n const owners = new Set(n.members.map((m) => m.end.ownerPath.join(\"/\")));\n if (owners.size < 2) continue;\n const device = n.members.find((m) => {\n const child = partOf(m);\n // a target's (slave's) I2C composite: a controller's composites are pin options, not a bus in use\n return !!child?.interfaces.some((i) => i.protocols.some((p) => p.type === \"i2c\" && p.roles.length > 0 && p.roles.every((r) => r === \"slave\" || r === \"target\")) && i.slots?.length && Object.values(slotBindings(i)).includes(m.end.iface.id));\n });\n if (!device) continue;\n reported.add(n.iface.id);\n out.push({\n id: `bus_pullup:${n.iface.id}`,\n rule: \"bus_pullup\",\n severity: \"warning\",\n message: `net ${n.iface.id} carries I2C (${device.path}) but no resistor pulls it up to a supply.`,\n refs: [n.path, device.path],\n });\n }\n for (const r of links) {\n if (r.protocol !== \"i2c\" || r.state === \"incompatible\" || !r.derived?.nets?.length) continue;\n for (const id of r.derived.nets) {\n const n = byId.get(id);\n if (!n || reported.has(id) || pulledUp(n)) continue;\n reported.add(id);\n out.push({\n id: `bus_pullup:${id}`,\n rule: \"bus_pullup\",\n severity: \"warning\",\n message: `net ${id} carries I2C (${r.a.path} ↔ ${r.b.path}) but no resistor pulls it up to a supply.`,\n refs: [n.path, `link:${r.link.id}`, r.a.path, r.b.path],\n });\n }\n }\n return out;\n}\n\n/**\n * Per-placement passive values (`ChildModuleRef.overrides` on a passive, at\n * any depth): each override must be one the part allows and agree with its\n * series (grades, ranges, ordering code). See `passiveInstance`.\n */\nexport function passiveOverrideRule(system: ModuleDef, lookup: ModuleLookup): SystemDiagnostic[] {\n const out: SystemDiagnostic[] = [];\n const seen = new Set<string>();\n const visit = (d: ModuleDef, prefix: string[]) => {\n if (seen.has(d.id)) return;\n seen.add(d.id);\n for (const c of d.children ?? []) {\n const def = lookup(c.moduleDefId);\n if (!def) continue;\n const path = [...prefix, c.id].join(\"/\");\n if (c.overrides && Object.keys(c.overrides).length) {\n const inst = passiveInstance(def, c.overrides);\n for (const [i, problem] of (inst?.problems ?? []).entries()) {\n out.push({\n id: `passive_override:${path}:${i}`,\n rule: \"passive_override\",\n severity: \"error\",\n message: `${path} (${def.id}): ${problem}`,\n refs: [path],\n details: { overrides: c.overrides },\n });\n }\n }\n visit(def, [...prefix, c.id]);\n }\n };\n visit(system, []);\n return out;\n}\n\n/** A stated body (`dimensions_mm`) larger than the module's `design_envelope`. */\nexport function designEnvelopeRule(def: ModuleDef): SystemDiagnostic[] {\n const env = def.traits?.find((t) => t.type === \"design_envelope\")?.params as DesignEnvelopeTrait[\"params\"] | undefined;\n if (!env) return [];\n const body = def.domains?.find((d) => d.domain === \"mechanical\" && d.dimensions_mm)?.dimensions_mm;\n if (!body) return [];\n const out: SystemDiagnostic[] = [];\n for (const axis of [\"length\", \"width\", \"height\"] as const) {\n const max = env.max_mm[axis];\n const size = body[axis];\n if (max === undefined || size === undefined || size <= max) continue;\n out.push({\n id: `design_envelope:${axis}`,\n rule: \"design_envelope\",\n severity: \"error\",\n message: `${def.id}: ${axis} ${size} mm exceeds the design envelope's ${max} mm${env.reason ? ` (${env.reason})` : \"\"}.`,\n refs: [],\n details: { axis, size, max },\n });\n }\n return out;\n}\n","/**\n * System-level helpers for modules with children: canonical paths, boundary\n * interfaces (own + exported), and validation of stored interface links.\n */\nimport type { InterfaceDef } from \"../types/interface.js\";\nimport type {\n ChildLink,\n EndpointTarget,\n InterfaceExport,\n InterfaceLink,\n ModuleDef,\n} from \"../types/module.js\";\nimport type { ConnectionResult, ConnectionState, Diagnostic, SubLinkResult } from \"../drc/types.js\";\nimport { validatePair } from \"../drc/validate-pair.js\";\nimport { matchProtocols } from \"../matching/protocol-match.js\";\nimport { validateConnectorLink } from \"./connectors.js\";\nimport { isConnector } from \"../protocols/connector.js\";\nimport { isNet } from \"../protocols/net.js\";\nimport { validateNetLink } from \"./nets.js\";\n\n/** Resolves a child's `moduleDefId` to its definition. */\nexport type ModuleLookup = (moduleDefId: string) => ModuleDef | undefined;\n\n// ---------------------------------------------------------------------------\n// Canonical paths\n// ---------------------------------------------------------------------------\n\n/**\n * Canonical path of a module instance or interface below a root module:\n * `child/grandchild` for modules, `child/grandchild:interface` for interfaces,\n * and `...:interface/slot` for a child interface under a composed one.\n */\nexport function formatPath(modules: string[], interfaceId?: string, slotId?: string): string {\n const base = modules.join(\"/\");\n if (interfaceId === undefined) return base;\n return `${base}:${interfaceId}${slotId !== undefined ? `/${slotId}` : \"\"}`;\n}\n\nexport function parsePath(path: string): { modules: string[]; interfaceId?: string; slotId?: string } {\n const [modulePart, interfacePart] = path.split(\":\");\n const modules = modulePart ? modulePart.split(\"/\") : [];\n if (interfacePart === undefined) return { modules };\n const [interfaceId, slotId] = interfacePart.split(\"/\");\n return { modules, interfaceId, ...(slotId !== undefined ? { slotId } : {}) };\n}\n\n// ---------------------------------------------------------------------------\n// Interfaces\n// ---------------------------------------------------------------------------\n\n/**\n * Interfaces that appear on a module's outline: every interface that is not\n * bound as a leaf into another interface's profile (pins behind a UART port\n * are revealed by opening the link, not drawn on the outline). Power and\n * ground leaves stay primary even when a connector binds them, because a\n * supply net is shared by every consumer. Connector composites do\n * not hide what they bind: a pad on a socket is still a pad.\n */\nexport function primaryInterfaces(def: ModuleDef): InterfaceDef[] {\n const bound = new Set<string>();\n for (const iface of def.interfaces) {\n if (isConnector(iface)) continue;\n for (const profile of iface.profiles ?? []) {\n for (const value of Object.values(profile.bindings)) {\n for (const id of Array.isArray(value) ? value : [value]) {\n if (id !== iface.id) bound.add(id);\n }\n }\n }\n }\n const isPower = (iface: InterfaceDef) => iface.protocols.some((p) => p.type === \"power\");\n return def.interfaces.filter((iface) => iface.exposed && (!bound.has(iface.id) || isPower(iface)));\n}\n\n/** Interfaces reachable from `iface` through its profiles (the slice DRC needs). */\nfunction boundClosure(def: ModuleDef, root: InterfaceDef): InterfaceDef[] {\n const byId = new Map(def.interfaces.map((i) => [i.id, i]));\n const seen = new Map<string, InterfaceDef>([[root.id, root]]);\n const queue = [root];\n while (queue.length) {\n const current = queue.shift()!;\n for (const profile of current.profiles ?? []) {\n for (const value of Object.values(profile.bindings)) {\n for (const id of Array.isArray(value) ? value : [value]) {\n const leaf = byId.get(id);\n if (leaf && !seen.has(id)) {\n seen.set(id, leaf);\n queue.push(leaf);\n }\n }\n }\n }\n }\n return [...seen.values()];\n}\n\nexport interface ResolvedExport extends InterfaceExport {\n /** The child module the export comes from (the module itself for a net port). */\n childDef: ModuleDef;\n /** The child interface being exported (the net, for a net port). */\n iface: InterfaceDef;\n /** True when implied by `kind: \"group\"` rather than declared. */\n implicit: boolean;\n}\n\nfunction childDef(def: ModuleDef, childId: string, lookup: ModuleLookup): ModuleDef {\n const ref = def.children?.find((c) => c.id === childId);\n if (!ref) throw new Error(`Module \"${def.id}\" has no child \"${childId}\"`);\n const resolved = lookup(ref.moduleDefId);\n if (!resolved) throw new Error(`Child \"${childId}\" of \"${def.id}\" references unknown module \"${ref.moduleDefId}\"`);\n return resolved;\n}\n\n/** True for an export of the module's own net (`from: { self: true, interfaceId }`). */\nexport function isNetPort(ex: InterfaceExport): ex is InterfaceExport & { from: { self: true; interfaceId: string } } {\n return \"self\" in ex.from && ex.from.self === true;\n}\n\n/** The net port that exports net `netId` of `def`, if the module declares one. */\nexport function netPortOf(def: ModuleDef, netId: string): InterfaceExport | undefined {\n return (def.exports ?? []).find((ex) => isNetPort(ex) && ex.from.interfaceId === netId);\n}\n\n/** True for a module marked as one printed circuit board (`kind: \"board\"`). */\nexport function isBoard(def: ModuleDef): boolean {\n return def.kind === \"board\";\n}\n\n/**\n * Exports of a module: its declared `exports`, plus — for `kind: \"group\"` —\n * every primary interface of every child that no internal link consumes.\n * Implicit export ids are `<child>__<interface>`. A net port resolves to the\n * module's own net, with `childDef` the module itself.\n */\nexport function resolveExports(def: ModuleDef, lookup: ModuleLookup): ResolvedExport[] {\n const out: ResolvedExport[] = [];\n const declared = new Set<string>();\n for (const ex of def.exports ?? []) {\n if (!(\"child\" in ex.from)) {\n const netId = ex.from.interfaceId;\n const net = def.interfaces.find((i) => i.id === netId);\n if (!net || !isNet(net)) throw new Error(`Export \"${ex.id}\" of \"${def.id}\": \"${netId}\" is not a net of the module; only a net is exported from the module itself`);\n out.push({ ...ex, childDef: def, iface: net, implicit: false });\n continue;\n }\n const child = childDef(def, ex.from.child, lookup);\n const iface = boundaryInterfaces(child, lookup).find((i) => i.id === ex.from.interfaceId);\n if (!iface) throw new Error(`Export \"${ex.id}\" of \"${def.id}\": child \"${ex.from.child}\" has no interface \"${ex.from.interfaceId}\"`);\n out.push({ ...ex, childDef: child, iface, implicit: false });\n declared.add(`${ex.from.child}:${ex.from.interfaceId}`);\n }\n if (def.kind !== \"group\") return out;\n\n const linkedInternally = new Set<string>();\n for (const link of def.links ?? []) {\n for (const end of [link.a, link.b]) {\n if (\"child\" in end) linkedInternally.add(`${end.child}:${end.interfaceId}`);\n }\n }\n for (const ref of def.children ?? []) {\n const child = childDef(def, ref.id, lookup);\n for (const iface of boundaryInterfaces(child, lookup)) {\n const key = `${ref.id}:${iface.id}`;\n if (declared.has(key) || linkedInternally.has(key)) continue;\n out.push({\n id: `${ref.id}__${iface.id}`,\n name: `${ref.name ?? child.name} · ${iface.name ?? iface.id}`,\n from: { child: ref.id, interfaceId: iface.id },\n childDef: child,\n iface,\n implicit: true,\n });\n }\n }\n return out;\n}\n\n/** Everything a neighbour can attach to: primary own interfaces plus exports. */\nexport function boundaryInterfaces(def: ModuleDef, lookup: ModuleLookup): InterfaceDef[] {\n const own = primaryInterfaces(def);\n if (!def.exports?.length && def.kind !== \"group\") return own;\n const exported = resolveExports(def, lookup).map((ex) => ({\n ...ex.iface,\n id: ex.id,\n name: ex.name ?? ex.iface.name,\n // a net port is on the edge, though the net it exports is not drawn on the outline\n ...(isNetPort(ex) ? { exposed: true } : {}),\n }));\n return [...own, ...exported];\n}\n\n// ---------------------------------------------------------------------------\n// Link validation\n// ---------------------------------------------------------------------------\n\nexport interface ResolvedEndpoint {\n /** Canonical path of the endpoint interface relative to the linking module. */\n path: string;\n /** The module that finally owns the interface (after following exports). */\n owner: ModuleDef;\n iface: InterfaceDef;\n /** Instance path of `owner` below the linking module (export hops included). */\n ownerPath: string[];\n /** Link-scoped composition: each slot of the ad-hoc connector, resolved. */\n composed?: Record<string, ResolvedEndpoint>;\n /**\n * Set when the endpoint is a child's net reached through the net port the\n * child exports (`iface` is that net, `owner` the module declaring it).\n */\n netPort?: true;\n}\n\n/**\n * Follow an endpoint through exports down to the module that owns the\n * interface. A child's net is reached only through the net port the child\n * exports for it (the port's id, or the net's own id when the port takes\n * it); the result is then marked `netPort`. A child's net without a port\n * resolves too, and the link to it is refused (`net_not_own`).\n */\nexport function resolveEndpoint(def: ModuleDef, end: EndpointTarget, lookup: ModuleLookup): ResolvedEndpoint {\n if (\"child\" in end && end.compose) return resolveComposition(def, end.child, end.interfaceId, end.compose, lookup);\n let owner = \"child\" in end ? childDef(def, end.child, lookup) : def;\n let interfaceId = end.interfaceId;\n const modules = \"child\" in end ? [end.child] : [];\n const ownerPath = [...modules];\n let throughPort = false;\n\n for (let depth = 0; depth < 16; depth++) {\n const own = owner.interfaces.find((i) => i.id === interfaceId);\n if (own) {\n const port = modules.length > 0 && isNet(own) && (throughPort || netPortOf(owner, own.id)?.id === own.id);\n return { path: formatPath(modules, end.interfaceId), owner, iface: own, ownerPath, ...(port ? { netPort: true as const } : {}) };\n }\n const ex = resolveExports(owner, lookup).find((e) => e.id === interfaceId);\n if (!ex) break;\n interfaceId = ex.from.interfaceId;\n if (!(\"child\" in ex.from)) {\n // a net port: the net is on the same module\n throughPort = true;\n continue;\n }\n owner = ex.childDef;\n ownerPath.push(ex.from.child);\n }\n throw new Error(`Link endpoint ${formatPath(modules, end.interfaceId)} not found on \"${owner.id}\"`);\n}\n\n/**\n * Resolve `value` below child `childId`: an interface on the child's boundary\n * (`\"rail_4v5\"`) or a canonical path below it (`\"fc:uart1_tx\"`,\n * `\"arm/motor:phases\"`). Paths are relative to the linking module.\n */\nexport function resolveBelow(def: ModuleDef, childId: string, value: string, lookup: ModuleLookup): ResolvedEndpoint {\n if (!value.includes(\":\")) return resolveEndpoint(def, { child: childId, interfaceId: value }, lookup);\n const { modules, interfaceId } = parsePath(value);\n let current = childDef(def, childId, lookup);\n const prefix = [childId];\n for (const m of modules.slice(0, -1)) {\n current = childDef(current, m, lookup);\n prefix.push(m);\n }\n const inner = resolveEndpoint(current, { child: modules[modules.length - 1], interfaceId: interfaceId! }, lookup);\n return { ...inner, path: formatPath([...prefix, modules[modules.length - 1]], interfaceId), ownerPath: [...prefix, ...inner.ownerPath] };\n}\n\n/**\n * A link-scoped composition: an ad-hoc connector on the child,\n * valid for this link only, whose slots are the other end's positions.\n */\nfunction resolveComposition(def: ModuleDef, childId: string, interfaceId: string, compose: Record<string, string>, lookup: ModuleLookup): ResolvedEndpoint {\n const owner = childDef(def, childId, lookup);\n if (owner.interfaces.some((i) => i.id === interfaceId)) {\n throw new Error(`Link-scoped composition \"${interfaceId}\" on \"${childId}\" shadows an existing interface; give it a new name`);\n }\n const composed: Record<string, ResolvedEndpoint> = {};\n for (const [slot, value] of Object.entries(compose)) composed[slot] = resolveBelow(def, childId, value, lookup);\n const first = Object.values(composed)[0];\n const iface: InterfaceDef = {\n id: interfaceId,\n name: interfaceId,\n domain: first?.iface.domain ?? \"electrical\",\n exposed: true,\n protocols: [{ type: \"connector\", roles: [\"mate\"] }],\n slots: Object.entries(composed).map(([slot, r]) => ({ id: slot, label: r.iface.name ?? r.iface.id, required: false, match: {} })),\n profiles: [{ id: \"link\", label: \"Link-scoped\", bindings: Object.fromEntries(Object.entries(compose).map(([slot, v]) => [slot, v])) }],\n traits: [{ type: \"link_scoped\", params: { note: \"Composed on the link: the module has no interface grouping these.\" } }],\n };\n return { path: formatPath([childId], interfaceId), owner, iface, ownerPath: [childId], composed };\n}\n\nexport type LinkState = \"configured\" | \"partial\" | \"incompatible\" | \"unconfigured\";\n\nexport interface LinkChildResult {\n a: { slotId?: string; leafId: string; pin?: string };\n b: { slotId?: string; leafId: string; pin?: string };\n /** protocol: derived by DRC; manual: stored child links; wired: traced through a harness. */\n method: \"protocol\" | \"manual\" | \"wired\";\n locked: boolean;\n}\n\nexport interface LinkResult {\n link: InterfaceLink;\n a: ResolvedEndpoint;\n b: ResolvedEndpoint;\n state: LinkState;\n /** Protocol type the pairing matched on (or the a-side's first type if none matched). */\n protocol: string;\n children: LinkChildResult[];\n unresolvedSlots: string[];\n diagnostics: Diagnostic[];\n /**\n * Set on links derived from conductors: the stored connector links\n * and harness children the conductors run through, and the board nets\n * they join through, when any.\n */\n derived?: { via: string[]; harnesses: string[]; nets?: string[] };\n}\n\nconst STATE_MAP: Record<ConnectionState, LinkState> = {\n valid: \"configured\",\n valid_inferred: \"configured\",\n valid_manual: \"configured\",\n configuration_needed: \"partial\",\n warning: \"partial\",\n incompatible: \"incompatible\",\n not_configured: \"unconfigured\",\n};\n\nfunction slice(owner: ModuleDef, iface: InterfaceDef): ModuleDef {\n return { ...owner, interfaces: boundClosure(owner, iface), interfaceGroups: [] };\n}\n\nfunction leafPin(owner: ModuleDef, leafId: string): string | undefined {\n const pin = owner.interfaces.find((i) => i.id === leafId)?.pin;\n return pin === undefined ? undefined : String(pin);\n}\n\nfunction childFromSubLink(sub: SubLinkResult, aOwner: ModuleDef, bOwner: ModuleDef): LinkChildResult {\n return {\n a: { slotId: sub.from.slotId, leafId: sub.from.interfaceId, pin: leafPin(aOwner, sub.from.interfaceId) },\n b: { slotId: sub.to.slotId, leafId: sub.to.interfaceId, pin: leafPin(bOwner, sub.to.interfaceId) },\n method: \"protocol\",\n locked: false,\n };\n}\n\nfunction storedChildren(stored: ChildLink[], a: ResolvedEndpoint, b: ResolvedEndpoint): LinkChildResult[] {\n const leafFor = (end: ResolvedEndpoint, slotOrLeaf: string) => {\n const binding = end.iface.profiles?.[0]?.bindings[slotOrLeaf];\n const leafId = typeof binding === \"string\" ? binding : slotOrLeaf;\n return { slotId: binding !== undefined ? slotOrLeaf : undefined, leafId, pin: leafPin(end.owner, leafId) };\n };\n return stored.map((c) => ({\n a: leafFor(a, c.a),\n b: leafFor(b, c.b),\n method: \"manual\",\n locked: c.locked ?? false,\n }));\n}\n\n/**\n * Validate one stored interface link: DRC runs on slices of the two owning\n * modules containing just the linked interfaces and the leaves they bind, so\n * the result describes exactly this connection (auto-discovery ambiguity\n * elsewhere on a module does not matter).\n */\nexport function validateLink(def: ModuleDef, link: InterfaceLink, lookup: ModuleLookup): LinkResult {\n const a = resolveEndpoint(def, link.a, lookup);\n const b = resolveEndpoint(def, link.b, lookup);\n if (isNet(a.iface) || isNet(b.iface)) return validateNetLink(link, a, b);\n if (isConnector(a.iface) && isConnector(b.iface)) return validateConnectorLink(link, a, b);\n return validateResolved(link, a, b);\n}\n\n/** Validate a link whose ends are already resolved (stored or derived). */\nexport function validateResolved(link: InterfaceLink, a: ResolvedEndpoint, b: ResolvedEndpoint): LinkResult {\n const pair = validatePair(slice(a.owner, a.iface), slice(b.owner, b.iface), { includePotentials: false, explicit: true });\n const connection: ConnectionResult | undefined = pair.connections.find(\n (c) => c.a.regionPath[0] === a.iface.id && c.b.regionPath[0] === b.iface.id,\n );\n\n if (!connection) {\n const match = matchProtocols(a.iface, b.iface);\n const reason = a.iface.domain !== b.iface.domain\n ? `domains differ (${a.iface.domain} vs ${b.iface.domain})`\n : match.compatible\n ? \"interfaces match by protocol but parameters conflict\"\n : `no compatible protocol/role between ${a.path} and ${b.path}`;\n const paramDiagnostics = pair.connections.flatMap((c) => c.diagnostics);\n return {\n link,\n a,\n b,\n state: \"incompatible\",\n protocol: a.iface.protocols[0]?.type ?? \"custom\",\n children: link.childLinks ? storedChildren(link.childLinks, a, b) : [],\n unresolvedSlots: [],\n diagnostics: [{ severity: \"error\", code: \"link_incompatible\", message: reason, refs: [] }, ...paramDiagnostics],\n };\n }\n\n const storedProblems = link.childLinks ? childLinkProblems(link.childLinks) : [];\n const children = link.childLinks\n ? storedChildren(link.childLinks, a, b)\n : connection.subLinks\n .filter((s) => s.from.interfaceId !== a.iface.id || s.to.interfaceId !== b.iface.id)\n .map((s) => childFromSubLink(s, a.owner, b.owner));\n\n const state: LinkState = storedProblems.length\n ? \"incompatible\"\n : link.childLinks && STATE_MAP[connection.state] === \"partial\"\n ? \"configured\"\n : STATE_MAP[connection.state];\n return {\n link,\n a,\n b,\n state,\n protocol: connection.protocol,\n children,\n unresolvedSlots: connection.unresolvedSlots.map((u) => `${u.moduleId}:${u.slotId}`),\n diagnostics: [...storedProblems, ...connection.diagnostics],\n };\n}\n\n/** Stored child links must use each slot at most once on each side. */\nfunction childLinkProblems(stored: ChildLink[]): Diagnostic[] {\n const problems: Diagnostic[] = [];\n for (const side of [\"a\", \"b\"] as const) {\n const seen = new Map<string, number>();\n for (const c of stored) seen.set(c[side], (seen.get(c[side]) ?? 0) + 1);\n for (const [slot, n] of seen) {\n if (n > 1) {\n problems.push({\n severity: \"error\",\n code: \"child_link_duplicate\",\n message: `stored child links map ${side}-side ${slot} ${n} times; each conductor must land on a distinct slot`,\n refs: [slot],\n });\n }\n }\n }\n return problems;\n}\n\n/** Validate every stored link on a module. */\nexport function validateLinks(def: ModuleDef, lookup: ModuleLookup): LinkResult[] {\n return (def.links ?? []).map((link) => validateLink(def, link, lookup));\n}\n","/**\n * A bundle that does not hold everything it names still draws.\n *\n * UHD's resolvers throw on a child whose definition is not in the bundle, and\n * on a link or an export that names an interface nobody has. A producer that\n * could not fetch some definitions (a library that was unreachable) writes\n * exactly such a bundle, and the viewer drew nothing at all for it.\n *\n * `tolerantSystem` gives the viewer a system the resolvers accept: a missing\n * definition is stood in for by a placeholder that has the interfaces its\n * parents' links and exports name, and a link or an export that still cannot\n * be resolved is left out. What was stood in for and what was left out is\n * returned, so the views can say so.\n */\nimport type { InterfaceDef, ModuleDef } from \"@uhd/types/index.js\";\nimport type { EndpointTarget } from \"@uhd/types/module.js\";\nimport { boundaryInterfaces, resolveEndpoint, type ModuleLookup } from \"@uhd/system/index.js\";\nimport { isNet } from \"@uhd/protocols/net.js\";\n\n/** A definition the bundle names and does not hold. */\nexport interface MissingDefinition {\n /** The definition id the children name. */\n id: string;\n /** Where it is used: the parent definition and the child's id and label there. */\n usedBy: { parent: string; child: string; name?: string }[];\n}\n\n/** A link or an export left out because it could not be resolved. */\nexport interface LeftOut {\n kind: \"link\" | \"export\";\n /** The definition it was on. */\n on: string;\n id: string;\n /** The resolver's message. */\n why: string;\n}\n\nexport interface TolerantSystem {\n root: ModuleDef;\n lookup: ModuleLookup;\n missing: MissingDefinition[];\n leftOut: LeftOut[];\n}\n\nconst PLACEHOLDERS = new WeakSet<ModuleDef>();\n\n/** Whether a definition is a placeholder for one the bundle does not hold. */\nexport function isPlaceholder(def: ModuleDef | undefined): boolean {\n return !!def && PLACEHOLDERS.has(def);\n}\n\n/** The interface ids one end of a link names on `child`'s boundary. */\nfunction namedOn(end: EndpointTarget, child: string): string[] {\n if (!(\"child\" in end) || end.child !== child) return [];\n if (!end.compose) return [end.interfaceId];\n // a composition's values are boundary interfaces, or paths below the child (which a placeholder cannot have)\n return Object.values(end.compose).filter((v) => !v.includes(\":\"));\n}\n\nexport function tolerantSystem(root: ModuleDef, lookup: ModuleLookup): TolerantSystem {\n const missing = new Map<string, MissingDefinition>();\n const wanted = new Map<string, Map<string, InterfaceDef>>();\n\n // 1. what is missing, and the interfaces its parents name on it\n const seen = new Set<ModuleDef>();\n const walk = (def: ModuleDef) => {\n if (seen.has(def)) return;\n seen.add(def);\n for (const ref of def.children ?? []) {\n const child = lookup(ref.moduleDefId);\n if (child) {\n walk(child);\n continue;\n }\n const m = missing.get(ref.moduleDefId) ?? { id: ref.moduleDefId, usedBy: [] };\n m.usedBy.push({ parent: def.id, child: ref.id, ...(ref.name ? { name: ref.name } : {}) });\n missing.set(ref.moduleDefId, m);\n const ifaces = wanted.get(ref.moduleDefId) ?? new Map<string, InterfaceDef>();\n wanted.set(ref.moduleDefId, ifaces);\n const want = (id: string, like?: InterfaceDef) => {\n if (ifaces.has(id) && !like) return;\n // the other end's domain, so the line is drawn in its colour; no protocol is claimed\n ifaces.set(id, { id, name: id, domain: like?.domain ?? ifaces.get(id)?.domain ?? \"electrical\", exposed: true, protocols: [{ type: \"custom\", roles: [] }] });\n };\n for (const link of def.links ?? []) {\n for (const [end, other] of [[link.a, link.b], [link.b, link.a]] as const) {\n const ids = namedOn(end, ref.id);\n if (!ids.length) continue;\n let like: InterfaceDef | undefined;\n try {\n like = resolveEndpoint(def, other, lookup).iface;\n } catch {\n like = undefined;\n }\n for (const id of ids) want(id, \"child\" in end && end.compose ? undefined : like);\n }\n }\n for (const ex of def.exports ?? []) if (\"child\" in ex.from && ex.from.child === ref.id) want(ex.from.interfaceId);\n for (const u of ref.unconnected ?? []) want(u.interfaceId);\n }\n };\n walk(root);\n\n const placeholders = new Map<string, ModuleDef>();\n for (const [id, m] of missing) {\n const def: ModuleDef = {\n id,\n name: m.usedBy[0]?.name ?? id,\n description: `The definition \"${id}\" is not in this bundle. This is a placeholder with the interfaces its links name.`,\n interfaces: [...(wanted.get(id)?.values() ?? [])],\n };\n PLACEHOLDERS.add(def);\n placeholders.set(id, def);\n }\n const withPlaceholders: ModuleLookup = (id) => lookup(id) ?? placeholders.get(id);\n\n // 2. leave out what still cannot be resolved, children before their parents\n const leftOut: LeftOut[] = [];\n const cleaned = new Map<ModuleDef, ModuleDef>();\n const cleanLookup: ModuleLookup = (id) => {\n const d = withPlaceholders(id);\n return d && clean(d);\n };\n function clean(def: ModuleDef): ModuleDef {\n const done = cleaned.get(def);\n if (done) return done;\n cleaned.set(def, def); // a definition that holds itself is not followed twice\n for (const ref of def.children ?? []) cleanLookup(ref.moduleDefId);\n\n const why = (e: unknown) => (e instanceof Error ? e.message : String(e));\n const children = (def.children ?? []).filter((ref) => withPlaceholders(ref.moduleDefId));\n const exports = (def.exports ?? []).filter((ex) => {\n try {\n const from = ex.from;\n if (!(\"child\" in from)) {\n // a net port (UHD 0.3.0): the module exports one of its own nets\n if (!def.interfaces.some((i) => i.id === from.interfaceId && isNet(i))) throw new Error(`\"${from.interfaceId}\" is not a net of \"${def.id}\"`);\n return true;\n }\n const ref = children.find((c) => c.id === from.child);\n const child = ref && cleanLookup(ref.moduleDefId);\n if (!child) throw new Error(`\"${def.id}\" has no child \"${from.child}\"`);\n if (!boundaryInterfaces(child, cleanLookup).some((i) => i.id === from.interfaceId)) throw new Error(`child \"${from.child}\" has no interface \"${from.interfaceId}\"`);\n return true;\n } catch (e) {\n leftOut.push({ kind: \"export\", on: def.id, id: ex.id, why: why(e) });\n return false;\n }\n });\n const base: ModuleDef = exports.length === (def.exports?.length ?? 0) ? def : { ...def, exports };\n const links = (def.links ?? []).filter((link) => {\n try {\n resolveEndpoint(base, link.a, cleanLookup);\n resolveEndpoint(base, link.b, cleanLookup);\n return true;\n } catch (e) {\n leftOut.push({ kind: \"link\", on: def.id, id: link.id, why: why(e) });\n return false;\n }\n });\n const out = links.length === (def.links?.length ?? 0) ? base : { ...base, links };\n if (PLACEHOLDERS.has(def) && out !== def) PLACEHOLDERS.add(out);\n cleaned.set(def, out);\n return out;\n }\n const cleanRoot = clean(root);\n return { root: cleanRoot, lookup: cleanLookup, missing: [...missing.values()], leftOut };\n}\n","/**\n * Viewer input (docs: protoboard-cli/docs/specs/uhd-boundary.md, \"The viewer\n * contract\"). The viewer shows whatever a UHD bundle describes: a root, its\n * definitions, scenarios, artifact bases, producer diagnostics and display\n * hints. It knows nothing about any particular project.\n */\nimport { bundleSystem } from \"@uhd/system/bundle.js\";\nimport { UHD_BUNDLE_SCHEMA, type UhdBundle, type UhdBundleDiagnostic } from \"@uhd/types/bundle.js\";\nimport type { ModuleDef } from \"@uhd/types/index.js\";\nimport type { ModuleLookup } from \"@uhd/system/index.js\";\nimport type { LevelLayout } from \"../layout/layout\";\nimport type { ArtifactResolver, ViewerOptions } from \"../api\";\nimport { tolerantSystem, type LeftOut, type MissingDefinition } from \"./tolerant\";\n\nexport interface ViewerScenario {\n id: string;\n label: string;\n description: string;\n system: ModuleDef;\n lookup: ModuleLookup;\n /** Definitions the bundle names and does not hold: drawn as placeholders (source/tolerant.ts). */\n missing: MissingDefinition[];\n /** Links and exports that could not be resolved, and are not drawn. */\n leftOut: LeftOut[];\n}\n\n/** Surface appearance for a definition (and optionally named sub-bodies of its CAD). */\nexport interface Appearance {\n color?: string;\n metalness?: number;\n roughness?: number;\n opacity?: number;\n parts?: Record<string, Omit<Appearance, \"parts\">>;\n}\n\nexport interface LabelHint {\n title?: string;\n sub?: string;\n hide?: boolean;\n}\n\n/** Presentation hints keyed by instance path. Never topology. */\nexport interface DisplayConfig {\n diagram?: {\n /** Hand layouts per drill level (\"\" = top). */\n layouts?: Record<string, LevelLayout>;\n /** Instance paths drawn expanded in place by default. */\n expanded?: string[];\n /** Links opened (conductors shown) by default. */\n openLinks?: string[];\n };\n spatial?: {\n /** Instance path the assembly is placed from (default: the best-connected structure). */\n root?: string;\n /** Explicit placements for modules no mate reaches (row-major 4×4, root coordinates). */\n placements?: Record<string, { matrix: number[]; note?: string }>;\n labels?: {\n modules?: Record<string, LabelHint>;\n /** Fastener harnesses and routed wire harnesses, by instance path. */\n harnesses?: Record<string, LabelHint>;\n };\n /** By definition id. */\n appearance?: Record<string, Appearance>;\n /** How the 3D view opens (PB-873). */\n view?: SpatialView;\n };\n}\n\n/**\n * The 3D view's opening camera, in the root's coordinates. Presentation only:\n * a watch modelled display-down (its case's frame has the display at −z)\n * says `up: [0, 0, -1]` and opens display-up, without changing the model.\n */\nexport interface SpatialView {\n /** The direction drawn up (default [0, 0, 1]): the camera's up, the orbit axis and the ground grid follow it. */\n up?: [number, number, number];\n /** A saved camera: azimuth and elevation (degrees, about `up`), distance (mm) and target. Without a distance the model is fitted. */\n camera?: { azimuth?: number; elevation?: number; distance?: number; target?: [number, number, number] };\n}\n\nexport interface LoadedSource {\n name: string;\n bundleUrl: string;\n scenarios: ViewerScenario[];\n /** URL for a definition's artifact file path, or undefined if it cannot be resolved. */\n resolveArtifact: ArtifactResolver;\n /** Findings from the bundle's producer (e.g. Protoboard's aggregated check). */\n hostDiagnostics: UhdBundleDiagnostic[];\n display: DisplayConfig;\n /** The bundle as loaded (for host views that read more of it than the viewer draws). */\n bundle: UhdBundle;\n}\n\nexport interface SourceOptions {\n /** Development only: absolute filesystem bases are served through Vite's /@fs route. */\n fsRoute?: boolean;\n /** A host's resolver; it receives the default one as `fallback`. */\n resolveArtifact?: ViewerOptions[\"resolveArtifact\"];\n}\n\n/**\n * The bundle URL for the standalone app: `?bundle=<url>`, then the URL a\n * server injected into the page, then the development default (none in a\n * production build).\n */\nexport function pickBundleUrl(search: string, injected?: string | null, fallback?: string | null): string | undefined {\n return new URLSearchParams(search).get(\"bundle\") ?? injected ?? fallback ?? undefined;\n}\n\n/**\n * URL prefix for an artifact base (`UhdBundle.artifactBases`: an absolute\n * path or a URL prefix), or undefined when it cannot be fetched over HTTP.\n * Absolute filesystem paths only resolve in development, through /@fs.\n */\nexport function baseToUrl(base: string, options: Pick<SourceOptions, \"fsRoute\"> = {}): string | undefined {\n if (!base.startsWith(\"/\")) return base.replace(/\\/$/, \"\");\n // compiled out of production builds\n if (import.meta.env.DEV && options.fsRoute) return (base.startsWith(\"/@fs/\") ? base : `/@fs${base}`).replace(/\\/$/, \"\");\n return undefined;\n}\n\n/** The default resolver: a definition's artifact base, or the bundle's own location. */\nexport function bundleResolver(bundle: UhdBundle, bundleUrl: string, options: Pick<SourceOptions, \"fsRoute\"> = {}): ArtifactResolver {\n const here = bundleUrl.replace(/[^/]*$/, \"\").replace(/\\/$/, \"\");\n const warned = new Set<string>();\n return (definitionId, filePath) => {\n if (/^https?:\\/\\//.test(filePath)) return filePath;\n const base = bundle.artifactBases?.[definitionId];\n const prefix = base ? baseToUrl(base, options) : here;\n if (prefix !== undefined) return `${prefix}/${filePath}`;\n if (base && !warned.has(base)) {\n warned.add(base);\n console.warn(`uhd-viewer: artifact base ${base} is a filesystem path; serve the bundle with \\`uhd-viewer serve\\` or give the viewer a resolver`);\n }\n return undefined;\n };\n}\n\nexport async function loadBundle(url: string, options: SourceOptions = {}): Promise<LoadedSource> {\n const res = await fetch(url);\n if (!res.ok) throw new Error(`could not load UHD bundle ${url} (${res.status})`);\n return sourceFromBundle((await res.json()) as UhdBundle, url, options);\n}\n\nexport function sourceFromBundle(bundle: UhdBundle, url: string, options: SourceOptions = {}): LoadedSource {\n if (bundle.schema !== UHD_BUNDLE_SCHEMA) throw new Error(`${url} is not a UHD bundle (schema ${String(bundle.schema)})`);\n const scenarios: ViewerScenario[] = [\n { id: \"nominal\", label: \"Nominal\", description: \"\", ...sys(bundle) },\n ...(bundle.scenarios ?? []).filter((s) => s.id !== \"nominal\").map((s) => ({ id: s.id, label: s.label, description: s.description ?? \"\", ...sys(bundle, s.id) })),\n ];\n const nominal = bundle.scenarios?.find((s) => s.id === \"nominal\");\n if (nominal) scenarios[0].label = nominal.label;\n const fallback = bundleResolver(bundle, url, options);\n const host = options.resolveArtifact;\n return {\n name: bundle.meta?.name ?? bundle.root,\n bundleUrl: url,\n scenarios,\n resolveArtifact: host ? (definitionId, filePath) => host(definitionId, filePath, fallback) : fallback,\n hostDiagnostics: bundle.diagnostics ?? [],\n display: (bundle.display ?? {}) as DisplayConfig,\n bundle,\n };\n}\n\nfunction sys(bundle: UhdBundle, scenario?: string): Pick<ViewerScenario, \"system\" | \"lookup\" | \"missing\" | \"leftOut\"> {\n const raw = bundleSystem(bundle, scenario);\n // a bundle that names what it does not hold still draws, and says what it lacks\n const { root, lookup, missing, leftOut } = tolerantSystem(raw.root, raw.lookup);\n return { system: root, lookup, missing, leftOut };\n}\n","/**\n * Derived links: the functional connections a physical wiring makes.\n *\n * Stored links between connectors mate positions; harness modules carry\n * conductors between their own ends (internal `self` ↔ `self` links whose\n * child links are the wires, straight through by default). Walking those\n * conductors from a pad on one part to a pad on another gives leaf pairs.\n * Each pad is lifted back to the functional interface it belongs to — the\n * composite (UART, I2C, FC/ESC port…) whose bound pads all travel to the same\n * module, else the pad itself — and each lifted pair becomes an ordinary link\n * result, validated like a stored link and tagged `derived`.\n *\n * System checks run on stored and derived links together, so supply budgets,\n * interface reuse, unpowered inputs and bus addresses see through cables.\n * The walk also checks the wiring: conductor pairs inside a composite must\n * match the pairing the protocol expects (TX to RX).\n *\n * Board nets join the same walk: each net is a node that its\n * member pins' membership links reach, so every pin on a net reaches every\n * other. On a net, a pair of pads is a link only when the interfaces they\n * lift to pair by protocol (a supply output with an input, an I2C master\n * with a target); pads that do not pair (two loads, two targets) share the\n * net without a link between them. A rail (a net with a supply or ground pin\n * on it, or a design voltage) carries power only: a logic or analog pin tied\n * to it is a strap and pairs with nothing, and ground pins on one net share\n * it without a link per pair. The net rule checks what pairs cannot (nets.ts).\n *\n * A supply output on a rail that states its design voltage (a `Net` with a\n * `voltage`) is validated at that voltage: the board sets the rail (an\n * adjustable regulator by its feedback divider, a charger by its cell), so\n * the output's full adjustable or charge range is not what its loads see.\n * The net rule still checks every pin against the rail's voltage.\n *\n * A composite lifts when every pad it binds reaches the other module. Each\n * pairing its protocol expects must then be wired inside it: a pad wired to\n * the wrong counterpart is `harness_wiring`, a required one wired elsewhere\n * or not at all is `bus_incomplete`.\n *\n * Net ports: a child's net that the child exports as a net port, joined\n * here to a net (or to a pin), is followed into the child, and through its\n * own children's net ports at any depth. Every pin on the child's net is\n * then on the conductor, so a supply or bus whose ends sit on both sides of\n * the child's edge is derived once, here: a regulator on this module with\n * the loads inside the child, a controller here with a sensor inside it. A\n * pair whose conductor stays inside one child (two of its pins on its own\n * net) is the child's own and is derived when the child is checked. Without\n * net ports, derivation stops at each module's edge as before.\n *\n * Scope: harnesses that are children of the linking module, and connector\n * links and nets stored on it, and the nets of children behind net ports.\n * Parts may be nested (a pad on stack/fc).\n */\nimport type { InterfaceDef } from \"../types/interface.js\";\nimport type { InterfaceLink, ModuleDef } from \"../types/module.js\";\nimport type { Diagnostic } from \"../drc/types.js\";\nimport {\n formatPath,\n resolveEndpoint,\n resolveExports,\n validateLinks,\n validateResolved,\n type LinkChildResult,\n type LinkResult,\n type ModuleLookup,\n type ResolvedEndpoint,\n} from \"./index.js\";\nimport { positionPairs, slotBindings } from \"./connectors.js\";\nimport { isConnector } from \"../protocols/connector.js\";\nimport { isNet, NET_PROTOCOL } from \"../protocols/net.js\";\nimport { membershipEnds, netPortReach, physicalPath } from \"./nets.js\";\nimport { matchProtocols } from \"../matching/protocol-match.js\";\nimport { getEffectiveRange } from \"../parameters/range.js\";\n\ninterface Terminal {\n key: string;\n owner: ModuleDef;\n ownerPath: string[];\n leaf: InterfaceDef;\n}\n\ninterface Edge {\n to: string;\n link?: string;\n harness?: string;\n net?: string;\n /** A membership stored inside a child, reached through its net port. */\n inner?: true;\n}\n\nconst pathKey = (p: string[]) => p.join(\"/\");\n\n/** The conductor node for one position of a resolved connector end. */\nfunction nodeFor(end: ResolvedEndpoint, slot: string, lookup: ModuleLookup): { key: string; terminal?: Terminal; harness?: string } | undefined {\n const composed = end.composed?.[slot];\n if (composed) {\n const key = `${pathKey(composed.ownerPath)}#${composed.iface.id}`;\n if (composed.owner.kind === \"harness\") return { key, harness: composed.ownerPath[0] };\n return { key, terminal: { key, owner: composed.owner, ownerPath: composed.ownerPath, leaf: composed.iface } };\n }\n if (end.owner.kind === \"harness\") return { key: `${pathKey(end.ownerPath)}#${end.iface.id}/${slot}`, harness: end.ownerPath[0] };\n const leafId = slotBindings(end.iface)[slot];\n if (!leafId) return undefined; // unused position (VOID)\n const leaf = end.owner.interfaces.find((i) => i.id === leafId);\n if (!leaf) return undefined;\n const key = `${pathKey(end.ownerPath)}#${leafId}`;\n return { key, terminal: { key, owner: end.owner, ownerPath: end.ownerPath, leaf } };\n}\n\n/** Composite interfaces (not connectors) that bind `leafId` in their default profile. */\nfunction compositesBinding(owner: ModuleDef, leafId: string): { iface: InterfaceDef; leaves: string[] }[] {\n const out: { iface: InterfaceDef; leaves: string[] }[] = [];\n for (const iface of owner.interfaces) {\n if (isConnector(iface) || !iface.profiles?.length) continue;\n const leaves = Object.values(slotBindings(iface));\n if (leaves.includes(leafId)) out.push({ iface, leaves });\n }\n return out;\n}\n\ninterface Candidate {\n iface: InterfaceDef;\n /** Pads it binds (1 for the pad itself). */\n size: number;\n /** The pads that are not ground (the pad's own id for a pad). */\n live: string[];\n}\n\n/**\n * What a pad can lift to, largest first: each composite binding it whose\n * bound pads all travel to the same module, then the pad itself.\n */\nfunction liftCandidates(owner: ModuleDef, leaf: InterfaceDef, carried: Set<string>): Candidate[] {\n const eligible = compositesBinding(owner, leaf.id)\n .filter((c) => c.leaves.every((l) => carried.has(l)))\n .sort((x, y) => y.leaves.length - x.leaves.length)\n .map((c) => ({ iface: c.iface, size: c.leaves.length, live: c.leaves.filter((l) => !isGround(owner.interfaces.find((i) => i.id === l) ?? leaf)) }));\n return [...eligible, { iface: leaf, size: 1, live: [leaf.id] }];\n}\n\nconst isComposite = (iface: InterfaceDef) => Boolean(iface.slots?.length);\n\n/**\n * The functional interfaces a pad pair lifts to: the largest pair that pairs\n * by protocol, composite with composite or pad with pad (a composite port is\n * not validated against a lone pad). With none, a conductor still links the\n * largest candidates of one kind (two composites, else the two pads it joins)\n * and the link reports the mismatch; on a net the pads only share the net.\n * A composite is never validated against the lone pad a wire lands on: that\n * finds the composite's own matching pad and passes the wire that is wrong\n * (a cell's + lead on the board's BAT- pad). Two ground pads on a net share it without a link; as\n * conductors of two composites they still pair.\n */\nfunction lift(a: Candidate[], b: Candidate[], onNet: boolean, joined: (la: string, lb: string) => boolean = () => true): { fa: InterfaceDef; fb: InterfaceDef } | undefined {\n let best: { fa: InterfaceDef; fb: InterfaceDef } | undefined;\n let bestSize = 0;\n for (const x of a) {\n for (const y of b) {\n if (x.size + y.size <= bestSize || isComposite(x.iface) !== isComposite(y.iface)) continue;\n // two composites pair only when a conductor other than ground joins them: on a board, a part's\n // LED supply and a regulator's output may both reach the other part, but only their grounds meet\n if (isComposite(x.iface) && !x.live.some((la) => y.live.some((lb) => joined(la, lb)))) continue;\n if (onNet && !isComposite(x.iface) && isGround(x.iface) && isGround(y.iface)) continue;\n // passive terminals (a resistor's, a capacitor's) on a net only share it: they pair only through an explicit conductor\n if (onNet && isPassive(x.iface) && isPassive(y.iface)) continue;\n if (!matchProtocols(x.iface, y.iface).compatible) continue;\n best = { fa: x.iface, fb: y.iface };\n bestSize = x.size + y.size;\n }\n }\n if (best || onNet) return best;\n if (isComposite(a[0].iface) === isComposite(b[0].iface)) return { fa: a[0].iface, fb: b[0].iface };\n return { fa: a[a.length - 1].iface, fb: b[b.length - 1].iface };\n}\n\n/** Root-relative endpoint for an interface owned at `ownerPath`: through an export when one exists. */\nfunction endpointFor(def: ModuleDef, ownerPath: string[], owner: ModuleDef, iface: InterfaceDef, lookup: ModuleLookup): ResolvedEndpoint {\n if (ownerPath.length > 1) {\n const top = def.children?.find((c) => c.id === ownerPath[0]);\n const topDef = top ? lookup(top.moduleDefId) : undefined;\n for (const ex of topDef ? resolveExports(topDef, lookup) : []) {\n try {\n const r = resolveEndpoint(def, { child: ownerPath[0], interfaceId: ex.id }, lookup);\n if (r.owner === owner && r.iface.id === iface.id && pathKey(r.ownerPath) === pathKey(ownerPath)) return r;\n } catch {\n /* unresolvable export: skip */\n }\n }\n }\n return { path: formatPath(ownerPath, iface.id), owner, iface, ownerPath };\n}\n\nconst targetFor = (end: ResolvedEndpoint) => {\n const [child] = end.ownerPath;\n const interfaceId = end.path.slice(end.path.indexOf(\":\") + 1);\n const below = end.ownerPath.length > 1 && !end.path.startsWith(`${child}:`) ? `${end.ownerPath.slice(1).join(\"/\")}:${end.iface.id}` : interfaceId;\n return { child, interfaceId: below };\n};\n\n/**\n * Functional links derived from the connector links and harnesses of `def`.\n * Pass `stored` to reuse results from validateLinks.\n */\nexport function deriveLinks(def: ModuleDef, lookup: ModuleLookup, stored: LinkResult[] = validateLinks(def, lookup)): LinkResult[] {\n const edges = new Map<string, Edge[]>();\n const terminals = new Map<string, Terminal>();\n const order: string[] = [];\n const addEdge = (x: string, y: string, e: Omit<Edge, \"to\">) => {\n edges.set(x, [...(edges.get(x) ?? []), { to: y, ...e }]);\n edges.set(y, [...(edges.get(y) ?? []), { to: x, ...e }]);\n };\n\n // 1. mated positions of stored connector links\n for (const r of stored) {\n if (r.protocol !== \"connector\" || r.state === \"incompatible\") continue;\n for (const p of positionPairs(r.link, r.a, r.b)) {\n const na = nodeFor(r.a, p.a, lookup);\n const nb = nodeFor(r.b, p.b, lookup);\n if (!na || !nb) continue;\n for (const n of [na, nb]) {\n if (n.terminal && !terminals.has(n.key)) {\n terminals.set(n.key, n.terminal);\n order.push(n.key);\n }\n }\n addEdge(na.key, nb.key, { link: r.link.id });\n }\n }\n\n // 1b. net memberships: each pin is joined to its net's node\n const rails = new Set<string>();\n const hasVoltage = (iface: InterfaceDef) => Boolean(iface.parameters?.some((p) => p.id === \"voltage\"));\n const terminalFor = (end: ResolvedEndpoint) => {\n const key = `${pathKey(end.ownerPath)}#${end.iface.id}`;\n if (!terminals.has(key)) {\n terminals.set(key, { key, owner: end.owner, ownerPath: end.ownerPath, leaf: end.iface });\n order.push(key);\n }\n return key;\n };\n // a child's net behind its net port: one node, joined to every pin the port reaches inside the child\n const nestedNets = new Map<string, InterfaceDef>();\n // port nodes whose nested net is a rail (a design voltage or a supply or ground pin inside)\n const railPorts = new Set<string>();\n const portNode = (port: ResolvedEndpoint) => {\n const node = `net#${physicalPath(port)}`;\n if (edges.has(node)) return node;\n edges.set(node, []);\n const reached = netPortReach(port, lookup);\n for (const n of reached.nets) nestedNets.set(n.path, n.iface);\n if (reached.nets.some((n) => hasVoltage(n.iface)) || reached.members.some((m) => isPower(m.end.iface))) {\n railPorts.add(node);\n for (const n of reached.nets) rails.add(n.path);\n }\n for (const m of reached.members) addEdge(node, terminalFor(m.end), { link: m.link, net: m.through![m.through!.length - 1], inner: true });\n return node;\n };\n for (const r of stored) {\n if (r.protocol !== NET_PROTOCOL || r.state === \"incompatible\") continue;\n const ends = membershipEnds(r);\n if (\"port\" in ends) {\n // a pin linked straight to a child's net port\n const node = portNode(ends.port);\n if (isPower(ends.member.iface)) rails.add(physicalPath(ends.port));\n addEdge(terminalFor(ends.member), node, { link: r.link.id, net: physicalPath(ends.port) });\n continue;\n }\n const { net, member } = ends;\n if (member.netPort) {\n // the parent's net and the child's net behind the port are one conductor: a rail on either side is a rail on both\n const node = portNode(member);\n if (hasVoltage(net.iface) || railPorts.has(node)) rails.add(net.iface.id);\n addEdge(`net#${net.iface.id}`, node, { link: r.link.id, net: net.iface.id });\n continue;\n }\n if (isPower(member.iface) || hasVoltage(net.iface)) rails.add(net.iface.id);\n addEdge(terminalFor(member), `net#${net.iface.id}`, { link: r.link.id, net: net.iface.id });\n }\n\n // 2. conductors inside harness children\n for (const ref of def.children ?? []) {\n const h = lookup(ref.moduleDefId);\n if (h?.kind !== \"harness\") continue;\n for (const link of h.links ?? []) {\n if (!(\"self\" in link.a) || !(\"self\" in link.b)) continue;\n const ia = h.interfaces.find((i) => i.id === link.a.interfaceId);\n const ib = h.interfaces.find((i) => i.id === link.b.interfaceId);\n if (!ia || !ib) continue;\n const ra: ResolvedEndpoint = { path: formatPath([ref.id], ia.id), owner: h, iface: ia, ownerPath: [ref.id] };\n const rb: ResolvedEndpoint = { path: formatPath([ref.id], ib.id), owner: h, iface: ib, ownerPath: [ref.id] };\n for (const p of positionPairs(link, ra, rb)) {\n addEdge(`${ref.id}#${ia.id}/${p.a}`, `${ref.id}#${ib.id}/${p.b}`, { harness: ref.id });\n }\n }\n }\n\n // 3. walk from each terminal through non-terminal nodes to the terminals it reaches\n interface Pair {\n a: Terminal;\n b: Terminal;\n links: Set<string>;\n harnesses: Set<string>;\n nets: Set<string>;\n }\n const pairs = new Map<string, Pair>();\n for (const start of order) {\n // `outside`: the conductor so far runs through something of this module, not only a child's own net\n const walk = (node: string, seen: Set<string>, links: Set<string>, harnesses: Set<string>, nets: Set<string>, outside: boolean) => {\n for (const e of edges.get(node) ?? []) {\n if (seen.has(e.to)) continue;\n const nextLinks = e.link ? new Set([...links, e.link]) : links;\n const nextHarnesses = e.harness ? new Set([...harnesses, e.harness]) : harnesses;\n const nextNets = e.net ? new Set([...nets, e.net]) : nets;\n const nextOutside = outside || !e.inner;\n const t = terminals.get(e.to);\n if (t) {\n // two pins on a child's own net pair in the child's check, not here\n if (!nextOutside) continue;\n let a = terminals.get(start)!;\n let b = t;\n if (pathKey(a.ownerPath) === pathKey(b.ownerPath)) {\n // the walk never pairs a part with itself, except a part supplying\n // itself through a board net (an on-chip regulator's output to its core)\n if (!nextNets.size || !selfSupply(a.leaf, b.leaf)) continue;\n if (!isPowerOutput(a.leaf)) [a, b] = [b, a];\n }\n // over a rail only power pins pair; a logic pin tied to it is a strap\n if ([...nextNets].some((n) => rails.has(n)) && !(isPower(a.leaf) && isPower(b.leaf))) continue;\n const key = [start, e.to].sort().join(\"|\");\n if (!pairs.has(key)) pairs.set(key, { a, b, links: nextLinks, harnesses: nextHarnesses, nets: nextNets });\n continue;\n }\n walk(e.to, new Set([...seen, e.to]), nextLinks, nextHarnesses, nextNets, nextOutside);\n }\n };\n walk(start, new Set([start]), new Set(), new Set(), new Set(), false);\n }\n\n // 4. group by module pair, lift pads to functional interfaces, validate\n const byModules = new Map<string, Pair[]>();\n for (const p of pairs.values()) {\n const fwd = `${pathKey(p.a.ownerPath)}|${pathKey(p.b.ownerPath)}`;\n const rev = `${pathKey(p.b.ownerPath)}|${pathKey(p.a.ownerPath)}`;\n if (fwd !== rev && byModules.has(rev)) byModules.get(rev)!.push({ ...p, a: p.b, b: p.a });\n else byModules.set(fwd, [...(byModules.get(fwd) ?? []), p]);\n }\n\n const out: LinkResult[] = [];\n for (const group of byModules.values()) {\n const carriedA = new Set(group.map((p) => p.a.leaf.id));\n const carriedB = new Set(group.map((p) => p.b.leaf.id));\n const functional = new Map<string, { fa: InterfaceDef; fb: InterfaceDef; pairs: Pair[] }>();\n const wires = new Set(group.map((p) => `${p.a.leaf.id}|${p.b.leaf.id}`));\n const joined = (la: string, lb: string) => wires.has(`${la}|${lb}`);\n for (const p of group) {\n const lifted = lift(liftCandidates(p.a.owner, p.a.leaf, carriedA), liftCandidates(p.b.owner, p.b.leaf, carriedB), p.nets.size > 0, joined);\n if (!lifted) continue;\n const { fa, fb } = lifted;\n const k = `${fa.id}|${fb.id}`;\n const entry = functional.get(k) ?? { fa, fb, pairs: [] };\n entry.pairs.push(p);\n functional.set(k, entry);\n }\n for (const { fa, fb, pairs: wires } of functional.values()) {\n const { a: ta, b: tb } = wires[0];\n const a = endpointFor(def, ta.ownerPath, ta.owner, fa, lookup);\n const b = endpointFor(def, tb.ownerPath, tb.owner, fb, lookup);\n const via = [...new Set(wires.flatMap((w) => [...w.links]))].sort();\n const harnesses = [...new Set(wires.flatMap((w) => [...w.harnesses]))].sort();\n const nets = [...new Set(wires.flatMap((w) => [...w.nets]))].sort();\n const link: InterfaceLink = {\n id: `${via.join(\"+\")}~${fa.id}~${fb.id}`,\n name: `${fa.name ?? fa.id} ↔ ${fb.name ?? fb.id}`,\n a: targetFor(a),\n b: targetFor(b),\n ...(harnesses.length ? { harness: harnesses[0] } : {}),\n };\n const result = { ...validateResolved(link, atRail(def, nets, a, nestedNets), atRail(def, nets, b, nestedNets)), a, b };\n const wired: LinkChildResult[] = wires\n .filter((w) => w.a.leaf.id !== fa.id || w.b.leaf.id !== fb.id)\n .map((w) => ({\n a: { slotId: slotOf(fa, w.a.leaf.id), leafId: w.a.leaf.id, pin: pinOf(w.a.leaf) },\n b: { slotId: slotOf(fb, w.b.leaf.id), leafId: w.b.leaf.id, pin: pinOf(w.b.leaf) },\n method: \"wired\",\n locked: false,\n }));\n const problems = [...wiringProblems(result, wired), ...(isComposite(fa) ? missingConductors(result, fa, fb, wired) : [])];\n // slots the 1:1 slot pairing leaves open (a second VLED pin, an exposed pad beside GND, VIN and\n // VINA on one rail against one VBAT slot) are complete when a conductor (a wire or a board net)\n // joins every pad of the slot to the other side of the link\n const unresolved = result.unresolvedSlots.filter((u) => !reachedByConductor(u, fa, fb, a, b, wired));\n const state = problems.length ? \"incompatible\" : result.state === \"partial\" && !unresolved.length && !result.diagnostics.some((d) => d.severity !== \"info\") ? \"configured\" : result.state;\n out.push({\n ...result,\n unresolvedSlots: unresolved,\n state,\n children: wired.length ? wired : result.children,\n diagnostics: [...problems, ...result.diagnostics],\n derived: { via, harnesses, ...(nets.length ? { nets } : {}) },\n });\n }\n }\n return out;\n}\n\nconst isPower = (i: InterfaceDef) => i.protocols.some((p) => p.type === \"power\");\nconst isPassive = (i: InterfaceDef) => i.protocols.length > 0 && i.protocols.every((p) => p.type === \"passive\");\n\n/**\n * A supply output on a rail whose net states a design voltage, as the board\n * runs it: its voltage narrowed to the rail's when the rail lies inside the\n * output's own range (outside it, the output keeps its range and the link\n * fails as it should). Used for validation only.\n */\nfunction atRail(def: ModuleDef, nets: string[], end: ResolvedEndpoint, nested: Map<string, InterfaceDef> = new Map()): ResolvedEndpoint {\n if (!isPowerOutput(end.iface)) return end;\n const own = end.iface.parameters?.find((p) => p.id === \"voltage\");\n const ownRange = own && getEffectiveRange(own);\n if (!own || !ownRange) return end;\n // this module's own nets first, then the children's nets behind net ports\n const ordered = [...nets.filter((id) => !nested.has(id)), ...nets.filter((id) => nested.has(id))];\n for (const id of ordered) {\n const net = def.interfaces.find((i) => i.id === id && isNet(i)) ?? nested.get(id);\n const v = net?.parameters?.find((p) => p.id === \"voltage\");\n const rail = v && getEffectiveRange(v);\n if (!rail || rail[0] < ownRange[0] || rail[1] > ownRange[1]) continue;\n // the composite and the output leaves it binds, all at the rail's voltage (validation slices the owner by id)\n const bound = new Set([end.iface.id, ...(end.iface.profiles ?? []).flatMap((pr) => Object.values(pr.bindings).flat().filter((x): x is string => typeof x === \"string\"))]);\n const narrow = (i: InterfaceDef): InterfaceDef =>\n bound.has(i.id) && isPowerOutput(i) && i.parameters?.some((p) => p.id === \"voltage\")\n ? { ...i, parameters: i.parameters.map((p) => (p.id === \"voltage\" ? { ...p, value: v!.value ?? (rail[0] + rail[1]) / 2, range: rail as [number, number] } : p)) }\n : i;\n const owner = { ...end.owner, interfaces: end.owner.interfaces.map(narrow) };\n return { ...end, owner, iface: owner.interfaces.find((i) => i.id === end.iface.id)! };\n }\n return end;\n}\nconst isGround = (i: InterfaceDef) => i.protocols.some((p) => p.type === \"power\" && p.roles.includes(\"ground\"));\nconst isPowerOutput = (i: InterfaceDef) => i.protocols.some((p) => p.type === \"power\" && p.roles.includes(\"output\"));\nconst isPowerInput = (i: InterfaceDef) => i.protocols.some((p) => p.type === \"power\" && p.roles.includes(\"input\"));\nconst selfSupply = (x: InterfaceDef, y: InterfaceDef) => (isPowerOutput(x) && isPowerInput(y)) || (isPowerOutput(y) && isPowerInput(x));\n\nconst pinOf = (leaf: InterfaceDef) => (leaf.pin === undefined ? undefined : String(leaf.pin));\n\nfunction slotOf(composite: InterfaceDef, leafId: string): string | undefined {\n return Object.entries(slotBindings(composite)).find(([, id]) => id === leafId)?.[0];\n}\n\n/** A `module:slot` the slot pairing left open, all of whose pads reach the other end of the link over a conductor. */\nfunction reachedByConductor(slot: string, fa: InterfaceDef, fb: InterfaceDef, a: ResolvedEndpoint, b: ResolvedEndpoint, wired: LinkChildResult[]): boolean {\n const [moduleId, slotId] = [slot.slice(0, slot.lastIndexOf(\":\")), slot.slice(slot.lastIndexOf(\":\") + 1)];\n const sides = [\n { owner: a.owner, iface: fa, reached: new Set(wired.map((w) => w.a.leafId)) },\n { owner: b.owner, iface: fb, reached: new Set(wired.map((w) => w.b.leafId)) },\n ].filter((x) => x.owner.id === moduleId);\n return sides.some(({ iface, reached }) => {\n const bound = iface.profiles?.[0]?.bindings[slotId];\n const leaves = (Array.isArray(bound) ? bound : bound ? [bound] : []).filter((l): l is string => typeof l === \"string\");\n return leaves.length > 0 && leaves.every((l) => reached.has(l));\n });\n}\n\n/** Conductors inside a composite must land where the protocol pairing expects. */\nfunction wiringProblems(result: LinkResult, wired: LinkChildResult[]): Diagnostic[] {\n if (result.state === \"incompatible\") return [];\n const expected = new Map(result.children.filter((c) => c.method === \"protocol\").map((c) => [c.a.leafId, c.b.leafId]));\n // what each pad reaches: one counterpart through a conductor, every pad of a net through the net\n // (two supply pins on one net are one conductor, so either is the pairing the protocol expects)\n const reaches = new Map<string, Set<string>>();\n for (const w of wired) reaches.set(w.a.leafId, (reaches.get(w.a.leafId) ?? new Set()).add(w.b.leafId));\n const out: Diagnostic[] = [];\n for (const w of wired) {\n const want = expected.get(w.a.leafId);\n if (want && want !== w.b.leafId && !reaches.get(w.a.leafId)!.has(want)) {\n out.push({\n severity: \"error\",\n code: \"harness_wiring\",\n message: `${w.a.leafId} is wired to ${w.b.leafId}, but ${result.protocol} pairs it with ${want}`,\n refs: [result.a.path, result.b.path],\n });\n }\n }\n return out;\n}\n\n/**\n * A composite lifted over conductors needs one for each required pairing its\n * protocol expects. A required pad that reaches the other module only outside\n * the counterpart composite (SDA landed on an interrupt pin) leaves the bus\n * incomplete.\n */\nfunction missingConductors(result: LinkResult, fa: InterfaceDef, fb: InterfaceDef, wired: LinkChildResult[]): Diagnostic[] {\n if (result.state === \"incompatible\") return [];\n const wiredA = new Set(wired.map((w) => w.a.leafId));\n const wiredB = new Set(wired.map((w) => w.b.leafId));\n const required = (iface: InterfaceDef, slot?: string) => iface.slots?.find((s) => s.id === slot)?.required ?? false;\n const out: Diagnostic[] = [];\n for (const c of result.children) {\n if (c.method !== \"protocol\" || (wiredA.has(c.a.leafId) && wiredB.has(c.b.leafId))) continue;\n if (!required(fa, c.a.slotId) && !required(fb, c.b.slotId)) continue;\n const slot = c.a.slotId ?? c.b.slotId ?? c.a.leafId;\n out.push({\n severity: \"error\",\n code: \"bus_incomplete\",\n message: `${result.protocol} ${slot}: ${result.a.path} ${c.a.leafId} and ${result.b.path} ${c.b.leafId} are not wired to each other`,\n refs: [result.a.path, result.b.path],\n });\n }\n return out;\n}\n\n/** Stored links plus the links derived from them. */\nexport function systemLinks(def: ModuleDef, lookup: ModuleLookup): LinkResult[] {\n const stored = validateLinks(def, lookup);\n return [...stored, ...deriveLinks(def, lookup, stored)];\n}\n","/**\n * Board nets in the view model (PB-823; UHD docs/boards-and-nets.md).\n *\n * A net is a `Net` interface on the board itself (protocol `net`, not\n * exposed), joined to each pin on it by a stored membership link. Drawing a\n * line per membership would draw a star of N lines per net, most of them to\n * the same component; drawing every pair would be worse. Instead:\n *\n * - each net is a junction node (`:<net>`; `board:<net>` when the board is\n * expanded in place);\n * - each component on the net gets one port for it, named for the net, and\n * one grouped line to the junction whose children are its pins on the net;\n * - a ground net (a ground pin on it and no supply pin) is drawn as ground\n * symbols at its members, like any ground link, unless GND wires are on;\n * - the functional links UHD derives over the nets (an I2C bus, a supply to\n * its loads) are listed by name, and their state is carried by the grouped\n * lines they run over, so a `bus_incomplete` or `harness_wiring` finding\n * on one turns those lines red, as it does for a cable's lanes.\n */\nimport type { InterfaceDef, ModuleDef } from \"@uhd/types/index.js\";\nimport type { LinkResult, ModuleLookup } from \"@uhd/system/index.js\";\nimport { isNet } from \"@uhd/protocols/net.js\";\nimport { isNetMembership, netVoltageRange } from \"@uhd/system/nets.js\";\nimport { slotBindings } from \"@uhd/system/connectors.js\";\nimport type { LinkState, ViewChildPort, ViewDerived, ViewLink, ViewNode, ViewPort } from \"./types\";\n\nconst RANK: Record<LinkState, number> = { incompatible: 3, partial: 2, unconfigured: 1, configured: 0 };\nconst worst = (states: LinkState[]): LinkState => states.reduce<LinkState>((w, s) => (RANK[s] > RANK[w] ? s : w), \"configured\");\n\nconst hasPower = (i: InterfaceDef, role?: string) => i.protocols.some((p) => p.type === \"power\" && (!role || p.roles.includes(role)));\nconst isGroundPin = (i: InterfaceDef) => hasPower(i, \"ground\");\nconst isSupplyPin = (i: InterfaceDef) => hasPower(i, \"input\") || hasPower(i, \"output\");\n\n/** Node id of a net: the canonical path of the net interface (`:<net>`, or `board:<net>` inside an expanded board). */\nexport const netNodeId = (prefix: string, net: string) => `${prefix.replace(/\\/$/, \"\")}:${net}`;\n\n/** Port id on a component for its connection to a net. */\nexport const netPortId = (net: string) => `net:${net}`;\n\nconst fmtV = (r: [number, number]) => (r[0] === r[1] ? `${r[0]} V` : `${r[0]}–${r[1]} V`);\n\n/**\n * Label of a grouped membership line: the pin's name, or the distinct names\n * of several (\"VDD/VDDIO\"), or the first and how many others (\"IOVDD +3\").\n */\nexport function pinsLabel(names: string[]): string {\n const counts = new Map<string, number>();\n for (const n of names) counts.set(n, (counts.get(n) ?? 0) + 1);\n const distinct = [...counts.keys()];\n if (distinct.length === 1) return distinct[0];\n if (distinct.length === 2) return distinct.join(\"/\");\n return `${distinct[0]} +${distinct.length - 1}`;\n}\n\nexport interface LevelNets {\n /** Junction nodes (ground nets left out unless `grounds`). */\n nodes: ViewNode[];\n /** One grouped line per component and net. */\n links: ViewLink[];\n /** Ports to add to the component nodes, by node id. */\n ports: Map<string, ViewPort[]>;\n derived: ViewDerived[];\n /** Membership link id (prefixed) → grouped line id. */\n owners: Map<string, string>;\n /** Derived link id (prefixed) → grouped line ids it runs over. */\n derivedOwners: Map<string, string[]>;\n}\n\n/**\n * The nets of `def` drawn at a level (`prefix` \"\" for the level module itself,\n * `<child>/` for a board expanded in place). `results` are the module's stored\n * link results, `derived` the links UHD derives from them.\n */\nexport function levelNets(\n def: ModuleDef,\n results: LinkResult[],\n derived: LinkResult[],\n lookup: ModuleLookup,\n prefix: string,\n opts: { grounds: boolean; parent?: string },\n): LevelNets {\n const out: LevelNets = { nodes: [], links: [], ports: new Map(), derived: [], owners: new Map(), derivedOwners: new Map() };\n const nets = def.interfaces.filter(isNet);\n if (!nets.length) return out;\n const memberships = results.filter(isNetMembership);\n const childName = (id: string) => {\n const ref = def.children?.find((c) => c.id === id);\n return (ref?.name ?? (ref ? lookup(ref.moduleDefId)?.name : undefined) ?? id).toUpperCase();\n };\n\n for (const net of nets) {\n const mine = memberships.filter((r) => [r.a, r.b].some((e) => e.iface === net && e.ownerPath.length === 0));\n const members = mine.map((r) => {\n const pinEnd = r.a.iface === net ? r.link.b : r.link.a;\n const pin = r.a.iface === net ? r.b : r.a;\n return { r, child: \"child\" in pinEnd ? pinEnd.child : \"\", pin: pin.iface };\n });\n const pins = members.map((m) => m.pin);\n const ground = pins.some(isGroundPin) && !pins.some(isSupplyPin);\n const rail = pins.some((p) => hasPower(p)) || Boolean(net.parameters?.some((p) => p.id === \"voltage\"));\n const over = derived.filter((d) => d.derived?.nets?.includes(net.id));\n const leaf = pins.map((p) => p.protocols[0]?.type).find((t) => t && t !== \"passive\" && t !== \"custom\");\n const signal = ground ? \"ground\" : rail ? \"power\" : (over.find((d) => d.protocol !== \"power\")?.protocol ?? leaf ?? \"custom\");\n const range = netVoltageRange(net);\n const nodeId = netNodeId(prefix, net.id);\n const children = [...new Set(members.map((m) => m.child))];\n\n if (!ground || opts.grounds) {\n out.nodes.push({\n id: nodeId,\n label: (net.name ?? net.id).toUpperCase(),\n icon: ground ? \"arrow-down-to-line\" : \"git-commit-horizontal\",\n kind: \"net\",\n ...(opts.parent ? { parent: opts.parent } : {}),\n ports: children.map((c) => ({ id: c, name: childName(c), domain: \"electrical\", protocol: signal, roles: [], children: [] })),\n shape: \"pill\",\n status: \"configured\",\n childCount: 0,\n description: `Net ${net.name ?? net.id}: ${pins.length} pin${pins.length === 1 ? \"\" : \"s\"}${range ? `, ${fmtV(range)}` : \"\"}`,\n net: { id: net.id, name: net.name ?? net.id, signal, ...(range ? { voltage: fmtV(range) } : {}), ground, pins: pins.length },\n });\n }\n\n for (const child of children) {\n const group = members.filter((m) => m.child === child);\n const nodeOfChild = prefix + child;\n const portId = netPortId(net.id);\n const pinPorts: ViewChildPort[] = group.map((m) => ({\n slotId: m.pin.id,\n name: m.pin.name ?? m.pin.id,\n leafId: m.pin.id,\n ...(m.pin.pin !== undefined ? { pin: String(m.pin.pin) } : {}),\n }));\n const list = out.ports.get(nodeOfChild) ?? [];\n list.push({ id: portId, name: net.name ?? net.id, domain: \"electrical\", protocol: signal, roles: [], children: pinPorts });\n out.ports.set(nodeOfChild, list);\n\n const id = `${prefix}${net.id}.${child}`;\n const memberIds = group.map((m) => prefix + m.r.link.id);\n const state = worst(group.map((m) => m.r.state as LinkState));\n out.links.push({\n id,\n linkId: id,\n alsoIds: memberIds,\n source: { node: nodeOfChild, port: portId },\n target: { node: nodeId, port: child },\n name: pinsLabel(group.map((m) => m.pin.name ?? m.pin.id)),\n domain: \"electrical\",\n protocol: signal,\n state,\n children: group.map((m) => ({\n id: prefix + m.r.link.id,\n label: m.pin.name ?? m.pin.id,\n a: m.pin.id,\n b: net.name ?? net.id,\n ...(m.pin.pin !== undefined ? { aPin: String(m.pin.pin) } : {}),\n state: m.r.state as LinkState,\n })),\n ...(group.length > 1\n ? {\n lanes: group.map((m, i) => ({\n id: `${id}#${i}`,\n name: (m.pin.name ?? m.pin.id).toUpperCase(),\n domain: \"electrical\",\n protocol: signal,\n state: m.r.state as LinkState,\n children: [],\n conductors: [`${id}#c${i}`],\n })),\n conductors: group.map((m, i) => ({\n id: `${id}#c${i}`,\n label: String(m.pin.pin ?? m.pin.name ?? m.pin.id).toUpperCase(),\n protocol: signal,\n domain: \"electrical\",\n state: m.r.state as LinkState,\n })),\n }\n : {}),\n ...(ground ? { ground: true } : {}),\n net: { id: net.id, name: net.name ?? net.id },\n diagnostics: group.flatMap((m) => m.r.diagnostics.map((d) => d.message)),\n });\n for (const m of memberIds) out.owners.set(m, id);\n }\n }\n\n // functional links over the nets, by name, carried by the grouped lines they run over\n for (const d of derived) {\n if (!d.derived?.nets?.length) continue;\n // the lines it runs over, and every line carrying a pin of either end: a bus whose SDA landed on\n // another net shows that line too, where a line of its own would be missing\n const pinsOf = (e: LinkResult[\"a\"]) => new Set([e.iface.id, ...Object.values(slotBindings(e.iface))]);\n const carrying = [d.a, d.b].flatMap((e) => {\n const pins = pinsOf(e);\n return out.links.filter((l) => l.source.node === prefix + (e.ownerPath[0] ?? \"\") && l.children.some((c) => pins.has(c.a))).map((l) => l.id);\n });\n const via = [...new Set([...d.derived.via.map((v) => out.owners.get(prefix + v)).filter((x): x is string => Boolean(x)), ...carrying])];\n const id = prefix + d.link.id;\n out.derivedOwners.set(id, via);\n const end = (e: LinkResult[\"a\"]) => ({ node: prefix + (e.ownerPath[0] ?? \"\"), iface: e.path.slice(e.path.indexOf(\":\") + 1) });\n out.derived.push({\n id,\n name: d.link.name ?? d.link.id,\n protocol: d.protocol,\n state: d.state as LinkState,\n a: end(d.a),\n b: end(d.b),\n nets: d.derived.nets.map((n) => netNodeId(prefix, n)),\n via,\n children: d.children.map((c) => ({ a: c.a.slotId ?? c.a.leafId, aPin: c.a.pin, b: c.b.slotId ?? c.b.leafId, bPin: c.b.pin })),\n diagnostics: d.diagnostics.map((x) => x.message),\n });\n // the lines it runs over carry its state, as a cable's lanes carry the links derived through it\n for (const line of out.links.filter((l) => via.includes(l.id))) {\n if (RANK[d.state as LinkState] > RANK[line.state]) line.state = d.state as LinkState;\n for (const x of d.diagnostics) if (!line.diagnostics.includes(x.message)) line.diagnostics.push(x.message);\n }\n }\n return out;\n}\n","/**\n * Adapter: UHD system ModuleDef → neutral view model.\n *\n * A level shows the children of one module. Children that have children of\n * their own are drawn expanded in place when listed in `expanded` (their\n * boundary ports are exports, joined to the inner ports by pass-through\n * lines); otherwise they are drawn as a single card with boundary ports.\n * Harness children (kind \"harness\") become harness nodes, and every link\n * they carry is drawn in two segments through them. System diagnostics\n * (checkSystem) are overlaid onto link state for DRC colouring.\n */\nimport type { ChildLink, InterfaceDef, InterfaceLink, ModuleDef } from \"@uhd/types/index.js\";\nimport {\n boundaryInterfaces,\n resolveExports,\n validateLinks,\n type LinkResult,\n type ModuleLookup,\n type ResolvedEndpoint,\n} from \"@uhd/system/index.js\";\nimport { deriveLinks } from \"@uhd/system/derive.js\";\nimport type { SystemDiagnostic } from \"@uhd/system/checks.js\";\nimport { isConnector } from \"@uhd/protocols/connector.js\";\nimport { isNetMembership } from \"@uhd/system/nets.js\";\nimport { levelNets, type LevelNets } from \"./nets\";\nimport { isPlaceholder } from \"../source/tolerant\";\nimport type {\n LinkState,\n ViewChildPort,\n ViewConductor,\n ViewLane,\n ViewLink,\n ViewModel,\n ViewNode,\n ViewPort,\n} from \"./types\";\n\n/**\n * UHD taxonomy paths (UHD docs/taxonomy.md) and their icons, matched by whole\n * segments in the definition's category order, before the words below:\n * `actuator.motor_controller` (an ESC) is not under `actuator.motor`.\n */\nconst TAXONOMY_ICONS: [string, string][] = [\n [\"actuator.motor_controller\", \"zap\"],\n [\"actuator.motor\", \"rotate-cw\"],\n [\"mechanical.propeller\", \"fan\"],\n [\"microcontroller.flight_controller\", \"cpu\"],\n [\"power.battery\", \"battery-full\"],\n [\"connectivity.wireless.video\", \"video\"],\n [\"sensor.gnss\", \"satellite\"],\n [\"mechanical.structure\", \"hexagon\"],\n [\"component.passive.capacitor\", \"battery-medium\"],\n];\n\nconst underPath = (path: string, root: string) => path === root || path.startsWith(`${root}.`);\n\n/** Words in categories and tags (strap before battery: a battery strap is a strap). */\nconst CATEGORY_ICONS: Record<string, string> = {\n \"flight-controller\": \"cpu\",\n esc: \"zap\",\n motor: \"rotate-cw\",\n propeller: \"fan\",\n strap: \"link\",\n battery: \"battery-full\",\n receiver: \"radio\",\n video: \"video\",\n gnss: \"satellite\",\n structure: \"hexagon\",\n capacitor: \"battery-medium\",\n};\n\nfunction iconFor(def: ModuleDef): string {\n if (def.display?.icon) return def.display.icon;\n for (const path of def.categories ?? []) for (const [root, icon] of TAXONOMY_ICONS) if (underPath(path, root)) return icon;\n const words = [...(def.categories ?? []), ...(def.tags ?? [])].map((w) => w.toLowerCase());\n for (const word of words) {\n for (const [key, icon] of Object.entries(CATEGORY_ICONS)) {\n if (word.includes(key)) return icon;\n }\n }\n if (/esc/i.test(def.name)) return \"zap\";\n if (/battery strap|strap/i.test(def.name)) return \"link\";\n if (/battery|lipo/i.test(def.name)) return \"battery-full\";\n if (/capacitor/i.test(def.name)) return \"battery-medium\";\n if (/receiver|elrs/i.test(def.name)) return \"radio\";\n if (/gnss|gps/i.test(def.name)) return \"satellite\";\n if (/motor/i.test(def.name)) return \"rotate-cw\";\n if (/prop/i.test(def.name)) return \"fan\";\n if (/air unit|camera|video/i.test(def.name)) return \"video\";\n if (/flight controller/i.test(def.name)) return \"cpu\";\n return \"box\";\n}\n\nfunction shapeFor(def: ModuleDef): ViewNode[\"shape\"] {\n if (def.kind === \"harness\") return \"pill\";\n if (def.display?.shape === \"circle\") return \"circle\";\n // a motor controller (taxonomy actuator.motor_controller) is not a motor\n const categories = (def.categories ?? []).filter((c) => !underPath(c, \"actuator.motor_controller\"));\n return /motor|propeller|\\bprop\\b/i.test(`${def.name} ${categories.join(\" \")} ${(def.tags ?? []).join(\" \")}`) &&\n !def.children?.length\n ? \"circle\"\n : \"rect\";\n}\n\nfunction childPorts(owner: ModuleDef | undefined, iface: InterfaceDef): ViewChildPort[] {\n if (!iface.slots?.length) return [];\n const profile = iface.profiles?.[0];\n return iface.slots.map((slot) => {\n const bound = profile?.bindings[slot.id];\n const leafId = typeof bound === \"string\" ? bound : Array.isArray(bound) ? bound[0] : undefined;\n const leaf = leafId ? owner?.interfaces.find((i) => i.id === leafId) : undefined;\n return {\n slotId: slot.id,\n name: leaf?.name ?? slot.id.toUpperCase(),\n leafId,\n pin: leaf?.pin !== undefined ? String(leaf.pin) : undefined,\n };\n });\n}\n\nexport function toPort(iface: InterfaceDef, owner: ModuleDef, exported?: ViewPort[\"exported\"]): ViewPort {\n return {\n id: iface.id,\n name: iface.name ?? iface.id,\n domain: iface.domain,\n protocol: iface.protocols[0]?.type ?? \"custom\",\n roles: iface.protocols[0]?.roles ?? [],\n children: childPorts(owner, iface),\n ...(exported ? { exported } : {}),\n };\n}\n\nfunction portsOf(def: ModuleDef, lookup: ModuleLookup): ViewPort[] {\n const own = boundaryInterfaces(def, lookup);\n const exports = new Map(\n (def.exports?.length || def.kind === \"group\" ? resolveExports(def, lookup) : []).map((e) => [e.id, e]),\n );\n return own.map((iface) => {\n const ex = exports.get(iface.id);\n if (!ex) return toPort(iface, def);\n // a net port (UHD 0.3.0) exports the module's own net: no child behind it to draw a pass-through to\n return \"child\" in ex.from ? toPort(iface, ex.childDef, { child: ex.from.child, interfaceId: ex.from.interfaceId }) : toPort(iface, def);\n });\n}\n\nconst isGround = (r: LinkResult) =>\n [r.a.iface, r.b.iface].every((i) => i.protocols.some((p) => p.type === \"power\" && p.roles.includes(\"ground\")));\n\nconst RANK: Record<LinkState, number> = { incompatible: 3, partial: 2, unconfigured: 1, configured: 0 };\n\nfunction worst(states: LinkState[]): LinkState {\n return states.reduce<LinkState>((w, s) => (RANK[s] > RANK[w] ? s : w), \"configured\");\n}\n\n/** Link ids whose child links are stored overrides. */\ntype Overrides = Record<string, ChildLink[]>;\n\nfunction toLinks(r: LinkResult, prefix: string, harnessNode: string | undefined, manual: boolean): ViewLink[] {\n const endpoint = (end: typeof r.link.a) =>\n \"child\" in end\n ? { node: prefix + end.child, port: end.interfaceId }\n : { node: prefix.replace(/\\/$/, \"\"), port: end.interfaceId };\n const linkId = prefix + r.link.id;\n const base: Omit<ViewLink, \"id\" | \"source\" | \"target\"> = {\n linkId,\n name: r.link.name ?? r.link.id,\n domain: r.a.iface.domain,\n protocol: r.protocol,\n state: r.state,\n children: r.children.map((c, i) => ({\n id: `${linkId}#${i}`,\n label: (c.a.slotId ?? c.a.leafId).toUpperCase(),\n a: c.a.slotId ?? c.a.leafId,\n b: c.b.slotId ?? c.b.leafId,\n aPin: c.a.pin,\n bPin: c.b.pin,\n state: r.state,\n })),\n ...(isGround(r) ? { ground: true } : {}),\n ...(manual ? { manual: true } : {}),\n diagnostics: [...r.diagnostics.map((d) => d.message), ...r.unresolvedSlots.map((s) => `unresolved slot ${s}`)],\n };\n const source = endpoint(r.link.a);\n const target = endpoint(r.link.b);\n // ground returns stay ground symbols at their ports rather than routing through the harness\n if (!harnessNode || isGround(r)) return [{ ...base, id: linkId, source, target }];\n return [\n { ...base, id: linkId, source, target: { node: harnessNode, port: `${r.link.id}:a` }, harness: harnessNode, segment: \"a\" },\n { ...base, id: `${linkId}~b`, source: { node: harnessNode, port: `${r.link.id}:b` }, target, harness: harnessNode, segment: \"b\" },\n ];\n}\n\n/** \"UART5 (DJI)\" → \"UART5\", \"10V/12V BEC\" → \"10V/12V\": a lane label short enough for the canvas. */\nconst shortName = (name: string) => name.split(/\\s[(—-]|\\s(?=[A-Z][a-z])/)[0].trim();\n\nfunction leafProtocol(iface: InterfaceDef | undefined): string {\n const p = iface?.protocols[0];\n if (!p) return \"custom\";\n if (p.type === \"power\" && p.roles.includes(\"ground\")) return \"ground\";\n return p.type;\n}\n\n/**\n * Signal type of a lane or conductor (signal classification): what the link it\n * belongs to carries (I2C, UART, power…), except that a ground is a ground.\n * Leaves alone are not enough: I2C's SCL and SDA are declared as digital lines.\n */\nfunction signalOf(linkProtocol: string, leaf?: InterfaceDef): string {\n return leafProtocol(leaf) === \"ground\" ? \"ground\" : linkProtocol;\n}\n\n/** The leaf interface behind one position of a resolved connector end. */\nfunction positionLeaf(end: ResolvedEndpoint, slot: string): InterfaceDef | undefined {\n const composed = end.composed?.[slot];\n if (composed) return composed.iface;\n const bound = end.iface.profiles?.[0]?.bindings[slot];\n const id = Array.isArray(bound) ? bound[0] : bound;\n return id ? end.owner.interfaces.find((i) => i.id === id) : undefined;\n}\n\nfunction laneOf(r: LinkResult): ViewLane {\n const names = [r.a.iface.name ?? r.a.iface.id, r.b.iface.name ?? r.b.iface.id].map(shortName);\n // a bundle is named for what it is (\"UART\", \"I2C\"), not which instance (\"UART1\"): it opens to show its signals\n const shortest = names.sort((x, y) => x.length - y.length)[0].toUpperCase();\n const name = r.children.length > 1 ? shortest.replace(/(?<=[A-Z])\\d+$/, \"\") : shortest;\n const leafOf = (id?: string) => r.a.owner.interfaces.find((x) => x.id === id);\n return {\n id: r.link.id,\n name,\n domain: r.a.iface.domain,\n protocol: signalOf(r.protocol, r.a.iface),\n state: STATE_OF(r),\n children:\n r.children.length > 1\n ? r.children.map((c, i) => ({\n id: `${r.link.id}#${i}`,\n name: (c.a.slotId ?? c.a.leafId).replace(/^.*_/, \"\").toUpperCase(),\n domain: r.a.iface.domain,\n protocol: signalOf(r.protocol, leafOf(c.a.leafId)),\n state: STATE_OF(r),\n children: [],\n }))\n : [],\n };\n}\n\nconst STATE_OF = (r: LinkResult): LinkState => r.state as LinkState;\n\nexport interface LevelLinks {\n links: ViewLink[];\n /** Harness children drawn as regions on links, not as nodes. */\n regionHarnesses: Set<string>;\n /** Stored or derived link id → the view link that draws it (for diagnostics). */\n owners: Map<string, string>;\n /** Every link UHD derives at this level (through cables and over nets). */\n derived: LinkResult[];\n}\n\n/**\n * The links of one level (PB-803/805). A harness with exactly two connector\n * ends becomes one link from part to part with the harness as a region along\n * it; its lanes are the links derived through its conductors and its\n * conductors are the mated positions. Logical links that name a harness get\n * the same region. Anything else keeps its own line.\n */\nexport function levelLinks(\n def: ModuleDef,\n results: LinkResult[],\n lookup: ModuleLookup,\n prefix: string,\n overrides: Overrides | undefined,\n): LevelLinks {\n const derived = deriveLinks(def, lookup, results);\n const links: ViewLink[] = [];\n const consumed = new Set<string>();\n const regionHarnesses = new Set<string>();\n const owners = new Map<string, string>();\n const tabbed = new Set<string>();\n\n for (const ref of def.children ?? []) {\n const h = lookup(ref.moduleDefId);\n if (h?.kind !== \"harness\") continue;\n const ends = results.filter((r) => r.protocol === \"connector\" && [r.a, r.b].some((e) => e.owner === h && e.ownerPath[0] === ref.id));\n if (ends.length !== 2) continue;\n const part = (r: LinkResult) => (r.a.owner === h && r.a.ownerPath[0] === ref.id ? { end: r.link.b, res: r.b, first: false } : { end: r.link.a, res: r.a, first: true });\n const [r1, r2] = ends;\n const p1 = part(r1);\n const p2 = part(r2);\n const via = new Set([r1.link.id, r2.link.id]);\n const carried = derived.filter((d) => d.derived!.via.some((v) => via.has(v)));\n const lanes = carried.map(laneOf);\n const conductors: ViewConductor[] = r1.children.map((c, i) => {\n const slot = p1.first ? c.a.slotId : c.b.slotId;\n const leaf = slot ? positionLeaf(p1.res, slot) : undefined;\n const label = p1.res.iface.slots?.find((x) => x.id === slot)?.label ?? leaf?.name ?? slot ?? String(i + 1);\n // the derived link this conductor belongs to decides its DRC state\n const owner = leaf\n ? carried.find((d) => [d.a.iface.id, d.b.iface.id].includes(leaf.id) || d.children.some((ch) => ch.a.leafId === leaf.id || ch.b.leafId === leaf.id))\n : undefined;\n const id = `${r1.link.id}#${slot ?? i}`;\n if (owner && leaf) {\n // group the conductor under its lane, and under the lane's child when it carries one\n const lane = lanes.find((l) => l.id === owner.link.id)!;\n (lane.conductors ??= []).push(id);\n const k = owner.children.findIndex((ch) => ch.a.leafId === leaf.id || ch.b.leafId === leaf.id);\n if (k >= 0 && lane.children[k]) (lane.children[k].conductors ??= []).push(id);\n }\n return {\n id,\n label: label.toUpperCase(),\n protocol: owner ? signalOf(owner.protocol, leaf) : leafProtocol(leaf),\n domain: leaf?.domain ?? r1.a.iface.domain,\n state: owner ? STATE_OF(owner) : STATE_OF(r1),\n };\n });\n const states = [r1, r2, ...carried].map(STATE_OF);\n const state = states.reduce<LinkState>((w, x) => (RANK[x] > RANK[w] ? x : w), \"configured\");\n const protocols = [...new Set(lanes.map((l) => l.protocol))];\n const endpoint = (end: InterfaceLink[\"a\"]) => (\"child\" in end ? { node: prefix + end.child, port: end.interfaceId } : { node: prefix.replace(/\\/$/, \"\"), port: end.interfaceId });\n const id = prefix + r1.link.id;\n links.push({\n id,\n linkId: id,\n alsoIds: [prefix + r2.link.id],\n source: endpoint(p1.end),\n target: endpoint(p2.end),\n name: `${lanes.length} LINK${lanes.length === 1 ? \"\" : \"S\"}`,\n domain: r1.a.iface.domain,\n // the cable reads as the signal it carries (UART, I2C…), or as power when it only carries supply and return\n protocol: protocols.find((p) => p !== \"power\" && p !== \"ground\") ?? (protocols.includes(\"power\") || protocols.includes(\"ground\") ? \"power\" : protocols[0] ?? \"custom\"),\n state,\n children: lanes.map((l) => ({ id: l.id, label: l.name, a: l.name, b: l.name, state: l.state })),\n lanes,\n conductors,\n run: { id: prefix + ref.id, defId: h.id, name: (ref.name ?? h.name).toUpperCase(), icon: h.display?.icon ?? \"cable\", physical: true, tab: true },\n diagnostics: [...r1.diagnostics, ...r2.diagnostics, ...carried.flatMap((d) => d.diagnostics)].map((d) => d.message),\n });\n consumed.add(r1.link.id).add(r2.link.id);\n regionHarnesses.add(ref.id);\n for (const x of [r1, r2, ...carried]) owners.set(prefix + x.link.id, id);\n }\n\n for (const r of results) {\n // net memberships are drawn grouped, per component and net (./nets.ts)\n if (consumed.has(r.link.id) || isNetMembership(r)) continue;\n const harnessRef = r.link.harness ? def.children?.find((c) => c.id === r.link.harness) : undefined;\n const harnessDef = harnessRef ? lookup(harnessRef.moduleDefId) : undefined;\n const [view] = toLinks(r, prefix, undefined, Boolean(prefix === \"\" && overrides?.[r.link.id]));\n if (r.children.length > 1) {\n const leafOf = (id?: string) => r.a.owner.interfaces.find((x) => x.id === id);\n view.lanes = r.children.map((c, i) => ({\n id: `${view.id}#${i}`,\n name: (c.a.slotId ?? c.a.leafId).replace(/^.*_/, \"\").toUpperCase(),\n domain: r.a.iface.domain,\n protocol: signalOf(r.protocol, leafOf(c.a.leafId)),\n state: STATE_OF(r),\n children: [],\n conductors: [`${view.id}#c${i}`],\n }));\n view.conductors = r.children.map((c, i) => ({\n id: `${view.id}#c${i}`,\n label: (c.a.pin ?? c.a.slotId ?? c.a.leafId).toUpperCase(),\n protocol: signalOf(r.protocol, leafOf(c.a.leafId)),\n domain: r.a.iface.domain,\n state: STATE_OF(r),\n }));\n }\n if (harnessRef && harnessDef?.kind === \"harness\") {\n view.run = {\n id: prefix + harnessRef.id,\n defId: harnessDef.id,\n name: (harnessRef.name ?? harnessDef.name).toUpperCase(),\n icon: harnessDef.display?.icon ?? \"cable\",\n physical: false,\n tab: !tabbed.has(harnessRef.id),\n };\n tabbed.add(harnessRef.id);\n regionHarnesses.add(harnessRef.id);\n }\n owners.set(prefix + r.link.id, view.id);\n links.push(view);\n }\n return { links, regionHarnesses, owners, derived };\n}\n\n/**\n * Carry a check result on a link down to what is drawn inside it, so expanded\n * lanes and ribbon conductors follow the DRC classification too: a finding on\n * the link itself applies to all of them, one on a link derived through a\n * cable only to that lane (and its conductors).\n */\nfunction overlayChildren(link: ViewLink, refId: string, state: LinkState) {\n const bump = (x: { state: LinkState }) => {\n if (RANK[state] > RANK[x.state]) x.state = state;\n };\n const all = (ls: ViewLane[]): ViewLane[] => ls.flatMap((l) => [l, ...all(l.children)]);\n const direct = link.linkId === refId || link.alsoIds?.includes(refId) || !link.run?.physical;\n const hit = direct ? all(link.lanes ?? []) : all((link.lanes ?? []).filter((l) => l.id === refId));\n hit.forEach(bump);\n const conductorIds = new Set(hit.flatMap((l) => l.conductors ?? []));\n for (const c of link.conductors ?? []) if (direct || conductorIds.has(c.id)) bump(c);\n}\n\nexport interface BuildOptions {\n /** Child ids (at this level) drawn expanded in place. */\n expanded: Set<string>;\n /** Stored child-link overrides keyed by link id (top level). */\n overrides?: Overrides;\n /**\n * System diagnostics to overlay on link state. Refs are relative to the\n * root; findings of a board checked on its own (see App) carry its path\n * (`link:board/<id>`), so they overlay when that board is drilled into.\n */\n diagnostics?: SystemDiagnostic[];\n /** Draw ground nets as junctions with wires (GND wires on) rather than as ground symbols. */\n grounds?: boolean;\n}\n\n/** Apply child-link overrides to a module's stored links. */\nexport function withOverrides(def: ModuleDef, overrides: Overrides | undefined): ModuleDef {\n if (!overrides || !Object.keys(overrides).length) return def;\n return {\n ...def,\n links: (def.links ?? []).map((l: InterfaceLink) => (overrides[l.id] ? { ...l, childLinks: overrides[l.id] } : l)),\n };\n}\n\n/** Descend `drill` child ids from the root to find the module shown at this level. */\nexport function levelModule(root: ModuleDef, drill: string[], lookup: ModuleLookup): { def: ModuleDef; path: ViewModel[\"path\"] } {\n let def = root;\n const path: ViewModel[\"path\"] = [{ id: \"\", label: root.name }];\n for (const childId of drill) {\n const ref = def.children?.find((c) => c.id === childId);\n const next = ref ? lookup(ref.moduleDefId) : undefined;\n if (!ref || !next) break;\n path.push({ id: path.length > 1 ? `${path[path.length - 1].id}/${childId}` : childId, label: ref.name ?? next.name });\n def = next;\n }\n return { def, path };\n}\n\nexport function buildView(root: ModuleDef, lookup: ModuleLookup, drill: string[], opts: BuildOptions): ViewModel {\n const { def: rawLevel, path } = levelModule(root, drill, lookup);\n const level = drill.length === 0 ? withOverrides(rawLevel, opts.overrides) : rawLevel;\n const nodes: ViewNode[] = [];\n const links: ViewLink[] = [];\n\n const nodeFor = (id: string, name: string | undefined, def: ModuleDef, parent?: string, expanded = false): ViewNode => ({\n id,\n label: (name ?? def.name).toUpperCase(),\n icon: iconFor(def),\n kind: def.kind ?? \"module\",\n ...(parent ? { parent } : {}),\n ...(expanded ? { expanded } : {}),\n // a harness shows its connector ends (PB-805); carried logical links add their own pairs\n ports: def.kind === \"harness\" ? def.interfaces.filter(isConnector).map((i) => toPort(i, def)) : portsOf(def, lookup),\n shape: expanded ? \"rect\" : shapeFor(def),\n status: \"configured\",\n defId: def.id,\n manufacturer: def.manufacturer,\n partNumber: def.part_number,\n description: def.description,\n category: def.categories?.[0],\n childCount: def.kind === \"harness\" ? 0 : (def.children?.length ?? 0),\n ...(isPlaceholder(def) ? { missing: true } : {}),\n });\n\n /** Harness ports: one in/out pair per carried link. */\n const addHarnessPorts = (node: ViewNode, results: LinkResult[]) => {\n for (const r of results) {\n if (r.link.harness !== node.id.split(\"/\").pop() || isGround(r)) continue;\n for (const side of [\"a\", \"b\"] as const) {\n node.ports.push({\n id: `${r.link.id}:${side}`,\n name: r.link.name ?? r.link.id,\n domain: r.a.iface.domain,\n protocol: r.protocol,\n roles: [],\n children: [],\n });\n }\n }\n };\n\n // Sheet ports: the level module's own boundary, drawn at the canvas edges.\n if (drill.length > 0) {\n for (const port of portsOf(level, lookup)) {\n nodes.push({\n id: `@${port.id}`,\n label: port.name.toUpperCase(),\n icon: \"arrow-right-left\",\n kind: \"module\",\n ports: [{ ...port }],\n shape: \"rect\",\n status: \"configured\",\n childCount: 0,\n sheetPort: true,\n });\n if (port.exported) {\n links.push({\n id: `@${port.id}->${port.exported.child}`,\n linkId: `@${port.id}`,\n source: { node: `@${port.id}`, port: port.id },\n target: { node: port.exported.child, port: port.exported.interfaceId },\n name: port.name,\n domain: port.domain,\n protocol: port.protocol,\n state: \"configured\",\n children: [],\n passThrough: true,\n diagnostics: [],\n });\n }\n }\n }\n\n const levelResults = validateLinks(level, lookup);\n const top = levelLinks(level, levelResults, lookup, \"\", opts.overrides);\n const owners = new Map(top.owners);\n const grounds = opts.grounds ?? false;\n // board nets: junction nodes and grouped membership lines (./nets.ts)\n const netLevels: LevelNets[] = [levelNets(level, levelResults, top.derived, lookup, \"\", { grounds })];\n /** Link-scoped compositions (PB-805) are ports on their child for as long as the link exists. */\n const addComposedPorts = (results: LinkResult[], prefix: string) => {\n for (const r of results) {\n for (const [end, resolved] of [[r.link.a, r.a], [r.link.b, r.b]] as const) {\n if (!(\"child\" in end) || !end.compose) continue;\n const node = nodes.find((n) => n.id === prefix + end.child);\n if (!node || node.ports.some((p) => p.id === end.interfaceId)) continue;\n node.ports.push({\n ...toPort(resolved.iface, resolved.owner),\n name: resolved.iface.name ?? end.interfaceId,\n children: Object.entries(resolved.composed ?? {}).map(([slotId, c]) => ({\n slotId,\n name: c.iface.name ?? c.iface.id,\n leafId: c.iface.id,\n pin: c.iface.pin !== undefined ? String(c.iface.pin) : undefined,\n })),\n });\n }\n }\n };\n\n for (const ref of level.children ?? []) {\n const def = lookup(ref.moduleDefId);\n if (!def) continue;\n const expanded = opts.expanded.has(ref.id) && (def.children?.length ?? 0) > 0 && def.kind !== \"harness\";\n if (def.kind === \"harness\" && top.regionHarnesses.has(ref.id)) continue;\n const node = nodeFor(ref.id, ref.name, def, undefined, expanded);\n if (def.kind === \"harness\") addHarnessPorts(node, levelResults);\n nodes.push(node);\n if (!expanded) continue;\n\n const innerResults = validateLinks(def, lookup);\n const innerLinks = levelLinks(def, innerResults, lookup, `${ref.id}/`, undefined);\n for (const [k, v] of innerLinks.owners) owners.set(k, v);\n netLevels.push(levelNets(def, innerResults, innerLinks.derived, lookup, `${ref.id}/`, { grounds, parent: ref.id }));\n for (const inner of def.children ?? []) {\n const innerDef = lookup(inner.moduleDefId);\n if (!innerDef) continue;\n if (innerDef.kind === \"harness\" && innerLinks.regionHarnesses.has(inner.id)) continue;\n const innerNode = nodeFor(`${ref.id}/${inner.id}`, inner.name, innerDef, ref.id);\n if (innerDef.kind === \"harness\") addHarnessPorts(innerNode, innerResults);\n nodes.push(innerNode);\n }\n addComposedPorts(innerResults, `${ref.id}/`);\n links.push(...innerLinks.links);\n\n // pass-through lines from each boundary export to the child port it exposes\n const exports = def.exports?.length || def.kind === \"group\" ? resolveExports(def, lookup) : [];\n for (const ex of exports) {\n // a net port's net is drawn as the sub-module's own junction, joined by its memberships\n if (!(\"child\" in ex.from)) continue;\n links.push({\n id: `${ref.id}:${ex.id}`,\n linkId: `${ref.id}:${ex.id}`,\n source: { node: ref.id, port: ex.id },\n target: { node: `${ref.id}/${ex.from.child}`, port: ex.from.interfaceId },\n name: ex.name ?? ex.id,\n domain: ex.iface.domain,\n protocol: ex.iface.protocols[0]?.type ?? \"custom\",\n state: \"configured\",\n children: [],\n passThrough: true,\n diagnostics: [],\n });\n }\n }\n\n addComposedPorts(levelResults, \"\");\n links.push(...top.links);\n\n const derived: ViewModel[\"derived\"] = [];\n const derivedOwners = new Map<string, string[]>();\n for (const n of netLevels) {\n nodes.push(...n.nodes);\n links.push(...n.links);\n derived.push(...n.derived);\n for (const [k, v] of n.owners) owners.set(k, v);\n for (const [k, v] of n.derivedOwners) derivedOwners.set(k, v);\n for (const [nodeId, ports] of n.ports) {\n const node = nodes.find((x) => x.id === nodeId);\n if (node) node.ports.push(...ports.filter((p) => !node.ports.some((q) => q.id === p.id)));\n }\n }\n\n // overlay system diagnostics on the links of this level: errors → incompatible, warnings → partial\n const levelPrefix = drill.length ? `${drill.join(\"/\")}/` : \"\";\n for (const d of opts.diagnostics ?? []) {\n if (d.severity === \"info\") continue;\n const state: LinkState = d.severity === \"error\" ? \"incompatible\" : \"partial\";\n for (const ref of d.refs) {\n if (!ref.startsWith(\"link:\") || !ref.startsWith(`link:${levelPrefix}`)) continue;\n const id = ref.slice(5 + levelPrefix.length);\n for (const x of derived.filter((x) => x.id === id)) {\n if (RANK[state] > RANK[x.state]) x.state = state;\n if (!x.diagnostics.includes(d.message)) x.diagnostics.push(d.message);\n }\n const targets = derivedOwners.get(id) ?? [owners.get(id) ?? id];\n for (const link of links.filter((l) => targets.includes(l.linkId))) {\n if (RANK[state] > RANK[link.state]) link.state = state;\n if (!link.diagnostics.includes(d.message)) link.diagnostics.push(d.message);\n overlayChildren(link, id, state);\n }\n }\n }\n\n // node status = worst state of the links touching it\n for (const node of nodes) {\n const touching = links.filter(\n (l) => !l.passThrough && (l.source.node === node.id || l.target.node === node.id || l.source.node.startsWith(`${node.id}/`) || l.target.node.startsWith(`${node.id}/`)),\n );\n node.status = touching.length ? worst(touching.map((l) => l.state)) : \"unconfigured\";\n }\n\n return { path, nodes, links, derived };\n}\n","/**\n * Orthogonal link routing with filleted corners (design decision D3).\n * Pure geometry: no React.\n */\n\nexport type Side = \"left\" | \"right\" | \"top\" | \"bottom\";\nexport type Pt = [number, number];\n\nconst STUB = 18;\n\nconst DIR: Record<Side, Pt> = {\n left: [-1, 0],\n right: [1, 0],\n top: [0, -1],\n bottom: [0, 1],\n};\n\nfunction stub([x, y]: Pt, side: Side, len = STUB): Pt {\n const [dx, dy] = DIR[side];\n return [x + dx * len, y + dy * len];\n}\n\nconst horizontal = (s: Side) => s === \"left\" || s === \"right\";\n\n/** Remove duplicate and collinear points. */\nexport function simplify(points: Pt[]): Pt[] {\n const out: Pt[] = [];\n for (const p of points) {\n const last = out[out.length - 1];\n if (last && Math.abs(last[0] - p[0]) < 0.5 && Math.abs(last[1] - p[1]) < 0.5) continue;\n out.push(p);\n while (out.length >= 3) {\n const [a, b, c] = out.slice(-3);\n const collinear =\n (Math.abs(a[0] - b[0]) < 0.5 && Math.abs(b[0] - c[0]) < 0.5) ||\n (Math.abs(a[1] - b[1]) < 0.5 && Math.abs(b[1] - c[1]) < 0.5);\n if (!collinear) break;\n out.splice(out.length - 2, 1);\n }\n }\n return out;\n}\n\n/** Insert elbows so every segment between consecutive points is axis-aligned. */\nfunction orthogonalize(points: Pt[], startHorizontal: boolean): Pt[] {\n const out: Pt[] = [points[0]];\n let wasHorizontal = startHorizontal;\n for (let i = 1; i < points.length; i++) {\n const [px, py] = out[out.length - 1];\n const [x, y] = points[i];\n if (Math.abs(px - x) > 0.5 && Math.abs(py - y) > 0.5) {\n // continue in the current direction first, then turn\n out.push(wasHorizontal ? [x, py] : [px, y]);\n }\n out.push([x, y]);\n const [ax, ay] = out[out.length - 2];\n wasHorizontal = Math.abs(ay - y) < 0.5 && Math.abs(ax - x) > 0.5;\n }\n return out;\n}\n\n/**\n * Route from a port on `sourceSide` to a port on `targetSide`. Waypoints, when\n * given, are visited in order; otherwise a 1–2 elbow Manhattan route is used.\n */\nexport function route(\n source: Pt,\n sourceSide: Side,\n target: Pt,\n targetSide: Side,\n waypoints: Pt[] = [],\n): Pt[] {\n const s1 = stub(source, sourceSide);\n const t1 = stub(target, targetSide);\n let middle: Pt[];\n\n if (waypoints.length > 0) {\n middle = waypoints;\n } else if (horizontal(sourceSide) && horizontal(targetSide)) {\n const mx = (s1[0] + t1[0]) / 2;\n middle = [[mx, s1[1]], [mx, t1[1]]];\n } else if (!horizontal(sourceSide) && !horizontal(targetSide)) {\n const my = (s1[1] + t1[1]) / 2;\n middle = [[s1[0], my], [t1[0], my]];\n } else if (horizontal(sourceSide)) {\n middle = [[t1[0], s1[1]]];\n } else {\n middle = [[s1[0], t1[1]]];\n }\n\n const pts = orthogonalize([source, s1, ...middle, t1], horizontal(sourceSide));\n // final approach must arrive along the target side's axis\n const last = pts[pts.length - 1];\n const [tx, ty] = target;\n if (horizontal(targetSide) && Math.abs(last[1] - ty) > 0.5) pts.push([last[0], ty]);\n if (!horizontal(targetSide) && Math.abs(last[0] - tx) > 0.5) pts.push([tx, last[1]]);\n pts.push(target);\n return simplify(pts);\n}\n\n/** SVG path through `points` with quadratic fillets of radius `r` (or per-corner radii). */\nexport function filletPath(points: Pt[], r: number | number[]): string {\n if (points.length < 2) return \"\";\n let d = `M${points[0][0]},${points[0][1]}`;\n for (let i = 1; i < points.length - 1; i++) {\n const [ax, ay] = points[i - 1];\n const [bx, by] = points[i];\n const [cx, cy] = points[i + 1];\n const l1 = Math.hypot(bx - ax, by - ay);\n const l2 = Math.hypot(cx - bx, cy - by);\n const radius = Math.max(0, Math.min(Array.isArray(r) ? r[i - 1] : r, l1 / 2, l2 / 2));\n const p1x = bx - ((bx - ax) / l1) * radius;\n const p1y = by - ((by - ay) / l1) * radius;\n const p2x = bx + ((cx - bx) / l2) * radius;\n const p2y = by + ((cy - by) / l2) * radius;\n d += ` L${p1x},${p1y} Q${bx},${by} ${p2x},${p2y}`;\n }\n const [ex, ey] = points[points.length - 1];\n return `${d} L${ex},${ey}`;\n}\n\nexport function length(points: Pt[]): number {\n let total = 0;\n for (let i = 1; i < points.length; i++) {\n total += Math.hypot(points[i][0] - points[i - 1][0], points[i][1] - points[i - 1][1]);\n }\n return total;\n}\n\n/** Point at fraction `t` (0..1) along the polyline. */\nexport function pointAt(points: Pt[], t: number): Pt {\n const target = length(points) * Math.min(1, Math.max(0, t));\n let walked = 0;\n for (let i = 1; i < points.length; i++) {\n const [ax, ay] = points[i - 1];\n const [bx, by] = points[i];\n const seg = Math.hypot(bx - ax, by - ay);\n if (walked + seg >= target && seg > 0) {\n const f = (target - walked) / seg;\n return [ax + (bx - ax) * f, ay + (by - ay) * f];\n }\n walked += seg;\n }\n return points[points.length - 1];\n}\n\n/** Fraction along the path of the middle of its longest segment (default label spot). */\nexport function longestSegmentMid(points: Pt[]): number {\n const total = length(points) || 1;\n let best = 0;\n let bestMid = 0.5;\n let walked = 0;\n for (let i = 1; i < points.length; i++) {\n const seg = Math.hypot(points[i][0] - points[i - 1][0], points[i][1] - points[i - 1][1]);\n if (seg > best) {\n best = seg;\n bestMid = (walked + seg / 2) / total;\n }\n walked += seg;\n }\n return bestMid;\n}\n\n/**\n * Offset an orthogonal polyline sideways by `d` (positive = left of travel\n * direction in screen space). Returns the points and concentric fillet radii.\n */\nexport function offsetPolyline(points: Pt[], d: number, r: number): { points: Pt[]; radii: number[] } {\n const pts = simplify(points);\n if (pts.length < 2 || d === 0) return { points: pts, radii: pts.map(() => r) };\n const normals: Pt[] = [];\n for (let i = 1; i < pts.length; i++) {\n const dx = pts[i][0] - pts[i - 1][0];\n const dy = pts[i][1] - pts[i - 1][1];\n const len = Math.hypot(dx, dy) || 1;\n normals.push([dy / len, -dx / len]);\n }\n const out: Pt[] = [];\n const radii: number[] = [];\n out.push([pts[0][0] + normals[0][0] * d, pts[0][1] + normals[0][1] * d]);\n for (let i = 1; i < pts.length - 1; i++) {\n const n1 = normals[i - 1];\n const n2 = normals[i];\n // mitred corner: exact for any turn angle (orthogonal corners reduce to n1 + n2)\n const k = d / (1 + n1[0] * n2[0] + n1[1] * n2[1]);\n out.push([pts[i][0] + (n1[0] + n2[0]) * k, pts[i][1] + (n1[1] + n2[1]) * k]);\n // turn direction: cross of incoming and outgoing direction vectors\n const din: Pt = [pts[i][0] - pts[i - 1][0], pts[i][1] - pts[i - 1][1]];\n const dout: Pt = [pts[i + 1][0] - pts[i][0], pts[i + 1][1] - pts[i][1]];\n const cross = Math.sign(din[0] * dout[1] - din[1] * dout[0]);\n // left-of-travel offsets sit on the outside of a right (clockwise) turn; the\n // fillet is a tangent length, so it scales with tan(half the turn) to stay concentric\n const cos = (din[0] * dout[0] + din[1] * dout[1]) / ((Math.hypot(...din) * Math.hypot(...dout)) || 1);\n const half = Math.tan(Math.acos(Math.max(-1, Math.min(1, cos))) / 2);\n radii.push(Math.max(2, r + cross * d * half));\n }\n const n = normals[normals.length - 1];\n const last = pts[pts.length - 1];\n out.push([last[0] + n[0] * d, last[1] + n[1] * d]);\n return { points: out, radii };\n}\n","/**\n * Grid router (PB-803, design D12): orthogonal routes on the 16 px grid.\n *\n * A* over grid cells with a direction in the state. It avoids module cards,\n * penalises bends and crossings, and keeps parallel runs one grid step apart\n * by charging for cells another route already runs along. Pinned waypoints\n * (dragged by the user, saved in the display file) are visited in order; the\n * bends it chooses itself are the automatic waypoints.\n */\nimport type { Pt, Side } from \"../canvas/routing\";\nimport { simplify } from \"../canvas/routing\";\n\nexport const GRID = 16;\n\nexport interface Rect {\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\nconst DIRS: Pt[] = [[1, 0], [0, 1], [-1, 0], [0, -1]];\nconst SIDE_DIR: Record<Side, number> = { right: 0, bottom: 1, left: 2, top: 3 };\n\nconst COST = { step: 1, bend: 4, parallel: 12, cross: 3 };\n\nexport const snap = (v: number) => Math.round(v / GRID) * GRID;\n\nclass Heap {\n private a: { k: number; v: number }[] = [];\n push(k: number, v: number) {\n const a = this.a;\n a.push({ k, v });\n let i = a.length - 1;\n while (i > 0) {\n const p = (i - 1) >> 1;\n if (a[p].k <= a[i].k) break;\n [a[p], a[i]] = [a[i], a[p]];\n i = p;\n }\n }\n pop(): number | undefined {\n const a = this.a;\n if (!a.length) return undefined;\n const top = a[0].v;\n const last = a.pop()!;\n if (a.length) {\n a[0] = last;\n let i = 0;\n for (;;) {\n const l = 2 * i + 1;\n const r = l + 1;\n let m = i;\n if (l < a.length && a[l].k < a[m].k) m = l;\n if (r < a.length && a[r].k < a[m].k) m = r;\n if (m === i) break;\n [a[m], a[i]] = [a[i], a[m]];\n i = m;\n }\n }\n return top;\n }\n get size() {\n return this.a.length;\n }\n}\n\nexport class GridRouter {\n private x0: number;\n private y0: number;\n private W: number;\n private H: number;\n private blocked: Uint8Array;\n /** Cells used by earlier routes: bit 1 horizontal run, bit 2 vertical run. */\n private used: Uint8Array;\n /** Search state, allocated once and reused: a state is valid when its stamp is the current search's. */\n private g: Float64Array;\n private prev: Int32Array;\n private stamp: Uint32Array;\n private gen = 0;\n private thorough: boolean;\n\n /**\n * `thorough`: a search that runs out of its budget is retried over the whole grid (off while\n * dragging, where a frame cannot wait for it).\n */\n constructor(obstacles: Rect[], extra: Pt[] = [], margin = 12, thorough = true) {\n this.thorough = thorough;\n // a level with nothing on it (a new system with no modules yet) still has a grid: one cell at the origin\n const xs = [...obstacles.flatMap((b) => [b.x, b.x + b.w]), ...extra.map((p) => p[0]), ...(obstacles.length || extra.length ? [] : [0])];\n const ys = [...obstacles.flatMap((b) => [b.y, b.y + b.h]), ...extra.map((p) => p[1]), ...(obstacles.length || extra.length ? [] : [0])];\n this.x0 = Math.floor(Math.min(...xs) / GRID) - margin;\n this.y0 = Math.floor(Math.min(...ys) / GRID) - margin;\n this.W = Math.ceil(Math.max(...xs) / GRID) + margin - this.x0 + 1;\n this.H = Math.ceil(Math.max(...ys) / GRID) + margin - this.y0 + 1;\n this.blocked = new Uint8Array(this.W * this.H);\n this.used = new Uint8Array(this.W * this.H);\n this.g = new Float64Array(this.W * this.H * 4);\n this.prev = new Int32Array(this.W * this.H * 4);\n this.stamp = new Uint32Array(this.W * this.H * 4);\n for (const b of obstacles) {\n // a cell is blocked when its point lies inside the card (edges included, so routes keep off outlines)\n for (let gx = Math.ceil(b.x / GRID); gx <= Math.floor((b.x + b.w) / GRID); gx++) {\n for (let gy = Math.ceil(b.y / GRID); gy <= Math.floor((b.y + b.h) / GRID); gy++) {\n const i = this.idx(gx, gy);\n if (i >= 0) this.blocked[i] = 1;\n }\n }\n }\n }\n\n private idx(gx: number, gy: number): number {\n const x = gx - this.x0;\n const y = gy - this.y0;\n return x < 0 || y < 0 || x >= this.W || y >= this.H ? -1 : y * this.W + x;\n }\n\n /**\n * Route from a port (on `fromSide` of its card) to another port, through\n * `pins` in order. Returns the polyline in canvas coordinates. With\n * `within`, the route stays inside that rectangle (a link between two\n * modules of a container expanded in place never leaves the container);\n * where no such route exists it is routed without the limit.\n */\n route(from: Pt, fromSide: Side, to: Pt, toSide: Side, pins: Pt[] = [], within?: Rect): Pt[] {\n if (within) {\n const region = { x0: Math.ceil(within.x / GRID), y0: Math.ceil(within.y / GRID), x1: Math.floor((within.x + within.w) / GRID), y1: Math.floor((within.y + within.h) / GRID) };\n this.region = region;\n try {\n const inside = this.routeOnce(from, fromSide, to, toSide, pins, true);\n if (inside) return inside;\n } finally {\n this.region = undefined;\n }\n }\n return this.routeOnce(from, fromSide, to, toSide, pins, false)!;\n }\n\n /** The cells a search may use, in grid coordinates (a container's inside), when a route is kept within one. */\n private region: { x0: number; y0: number; x1: number; y1: number } | undefined;\n\n /** One routing attempt; `strict` gives up (undefined, nothing marked) where a leg finds no way instead of jogging straight. */\n private routeOnce(from: Pt, fromSide: Side, to: Pt, toSide: Side, pins: Pt[], strict: boolean): Pt[] | undefined {\n const d0 = SIDE_DIR[fromSide];\n const dEnd = SIDE_DIR[toSide];\n const s: Pt = [snap(from[0]) / GRID + DIRS[d0][0], snap(from[1]) / GRID + DIRS[d0][1]];\n const t: Pt = [snap(to[0]) / GRID + DIRS[dEnd][0], snap(to[1]) / GRID + DIRS[dEnd][1]];\n const stops: Pt[] = [...pins.map((p) => [snap(p[0]) / GRID, snap(p[1]) / GRID] as Pt), t];\n let cells: Pt[] = [s];\n let dir = d0;\n for (let k = 0; k < stops.length; k++) {\n const last = k === stops.length - 1;\n // arrive at the end cell heading into the target port\n const arrive = last ? (dEnd + 2) % 4 : -1;\n // a bounded search first (keeps drags at frame rate); unless mid-drag, one that gives up gets the\n // whole grid, then may arrive from any side, before the route falls back to a straight jog\n const from = cells[cells.length - 1];\n const leg =\n this.search(from, dir, stops[k], arrive) ??\n (this.thorough ? this.search(from, dir, stops[k], arrive, Infinity) ?? (arrive >= 0 ? this.search(from, dir, stops[k], -1, Infinity) : undefined) : undefined);\n if (!leg) {\n if (strict) return undefined;\n cells.push(stops[k]);\n continue;\n }\n cells = cells.concat(leg.cells.slice(1));\n dir = leg.dir;\n }\n this.mark(cells);\n const pts: Pt[] = [from, ...cells.map(([gx, gy]) => [gx * GRID, gy * GRID] as Pt), to];\n return orthogonal(simplify(pts));\n }\n\n private search(start: Pt, startDir: number, goal: Pt, arriveDir: number, budget?: number): { cells: Pt[]; dir: number } | undefined {\n const { g, prev, stamp, region } = this;\n const gen = ++this.gen;\n const cost = (st: number) => (stamp[st] === gen ? g[st] : Infinity);\n const si = this.idx(start[0], start[1]);\n const gi = this.idx(goal[0], goal[1]);\n if (si < 0 || gi < 0) return undefined;\n const heap = new Heap();\n const h = (i: number) => Math.abs((i % this.W) - (gi % this.W)) + Math.abs(Math.floor(i / this.W) - Math.floor(gi / this.W));\n const s0 = si * 4 + startDir;\n g[s0] = 0;\n prev[s0] = -1;\n stamp[s0] = gen;\n heap.push(h(si), s0);\n let found = -1;\n let expanded = 0;\n // a search that has to wander this far is blocked (e.g. mid-drag, a card over a port): give up and jog\n const limit = budget ?? 6000 + 80 * (Math.abs(start[0] - goal[0]) + Math.abs(start[1] - goal[1]));\n while (heap.size && expanded < limit) {\n const st = heap.pop()!;\n expanded++;\n const cell = st >> 2;\n const dir = st & 3;\n if (cell === gi && (arriveDir < 0 || dir === arriveDir)) {\n found = st;\n break;\n }\n const cx = cell % this.W;\n const cy = Math.floor(cell / this.W);\n for (let nd = 0; nd < 4; nd++) {\n if (nd === (dir + 2) % 4) continue;\n const nx = cx + DIRS[nd][0];\n const ny = cy + DIRS[nd][1];\n if (nx < 0 || ny < 0 || nx >= this.W || ny >= this.H) continue;\n if (region && (nx + this.x0 < region.x0 || nx + this.x0 > region.x1 || ny + this.y0 < region.y0 || ny + this.y0 > region.y1)) continue;\n const ni = ny * this.W + nx;\n if (this.blocked[ni] && ni !== gi) continue;\n const horizontal = nd % 2 === 0;\n const u = this.used[ni];\n let c = COST.step + (nd !== dir ? COST.bend : 0);\n if (u) c += (horizontal ? u & 1 : u & 2) ? COST.parallel : COST.cross;\n const ns = ni * 4 + nd;\n const ng = g[st] + c;\n if (ng < cost(ns)) {\n g[ns] = ng;\n prev[ns] = st;\n stamp[ns] = gen;\n heap.push(ng + h(ni), ns);\n }\n }\n }\n if (found < 0) return undefined;\n const cells: Pt[] = [];\n for (let st = found; st >= 0; st = prev[st]) {\n const cell = st >> 2;\n cells.push([(cell % this.W) + this.x0, Math.floor(cell / this.W) + this.y0]);\n }\n cells.reverse();\n return { cells, dir: found & 3 };\n }\n\n /** Treat an existing route (canvas coordinates, axis-aligned) as occupied, as if it had just been routed. */\n occupy(points: Pt[]) {\n const cells = points.map(([x, y]) => [Math.round(x / GRID), Math.round(y / GRID)] as Pt);\n this.mark(cells.filter((c, i) => i === 0 || c[0] !== cells[i - 1][0] || c[1] !== cells[i - 1][1]));\n }\n\n private mark(cells: Pt[]) {\n for (let i = 1; i < cells.length; i++) {\n const [a, b] = [cells[i - 1], cells[i]];\n const horizontal = a[1] === b[1];\n const n = Math.max(Math.abs(b[0] - a[0]), Math.abs(b[1] - a[1]));\n for (let k = 0; k <= n; k++) {\n const x = a[0] + Math.sign(b[0] - a[0]) * k;\n const y = a[1] + Math.sign(b[1] - a[1]) * k;\n const idx = this.idx(x, y);\n if (idx >= 0) this.used[idx] |= horizontal ? 1 : 2;\n }\n }\n }\n}\n\n/** Make every segment axis-aligned (ports that sit off the grid get a short jog). */\nfunction orthogonal(points: Pt[]): Pt[] {\n const out: Pt[] = [points[0]];\n for (let i = 1; i < points.length; i++) {\n const [px, py] = out[out.length - 1];\n const [x, y] = points[i];\n if (Math.abs(px - x) > 0.5 && Math.abs(py - y) > 0.5) out.push([px, y]);\n out.push([x, y]);\n }\n return simplify(out);\n}\n","/**\n * Board-level layout (PB-873): a level with nets — a board's components and\n * the junctions of its nets — laid out the way a schematic sheet reads, as\n * layers with channels between them.\n *\n * - Components are clustered: a passive or discrete part (a decoupling\n * capacitor, a pull-up, a crystal) sits under the part it serves, named in\n * its label (\"U7 input\") or else the part it shares the most specific net\n * with; a connector or switch that serves one part only sits with it too.\n * - Clusters go in columns by function, from the taxonomy category:\n * connectors, power, the processor, then sensors and outputs. A part driven\n * only by another peripheral (the LEDs of an LED driver) goes one column\n * further out. A column too tall for a landscape sheet wraps.\n * - Within a column, clusters are ordered by barycentre sweeps and set at\n * the height of what they connect to, as close as the gaps allow, so lines\n * between columns run level and cross less.\n * - Junctions go in the channels between columns, each in the channel\n * between the parts it joins, level with them; a channel holds one or more\n * lanes of junctions and is as wide as its lines need.\n *\n * Same input, same output; nothing overlaps.\n */\nimport { GRID } from \"./router\";\n\nexport interface BoardNode {\n id: string;\n w: number;\n h: number;\n /** A net junction (placed after the components). */\n net?: boolean;\n /** Taxonomy category (\"power.regulator\", \"component.passive.capacitor\"). */\n category?: string;\n label?: string;\n /** A junction that is one tap of a rail drawn in several places: the rail's id (taps.ts). */\n tapOf?: string;\n /** A card's height once one side holds this many ports (cards grow to fit their ports). */\n heightFor?: (perSide: number) => number;\n /** Ports on lines that do not go to a junction (a sheet port's, a direct link's): either side. */\n otherPorts?: number;\n}\n\nexport interface Rect {\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\nexport type FunctionGroup = \"io\" | \"power\" | \"mcu\" | \"sensor\" | \"output\" | \"other\";\nconst GROUP_ORDER: FunctionGroup[] = [\"io\", \"power\", \"mcu\", \"sensor\", \"output\", \"other\"];\n/** Column of each group: sensors and outputs share the column after the processor. */\nconst GROUP_COLUMN: Record<FunctionGroup, number> = { io: 0, power: 1, mcu: 2, sensor: 3, output: 3, other: 3 };\n\n/** Card spacing inside a cluster, and between clusters in a column. */\nconst GAP_IN_X = 96;\nconst GAP_IN_Y = 64;\nconst GAP_CLUSTER = 112;\n/** Junction lanes: the gap between junctions in a lane, and between lanes. */\nconst HUB_GAP_Y = 32;\nconst LANE_GAP = 96;\n/** How far a junction may be pushed down its lane before the channel opens another. */\nconst LANE_PUSH = 480;\n/** Room between a column and the junction lanes beside it: a base, and a grid track per few lines. */\nconst CHANNEL_PAD = 80;\nconst STEP = GRID;\n/** A column shorter than this never wraps. */\nconst WRAP_MIN = 1600;\n\n/** A passive or discrete part: placed with the part it serves rather than in a group of its own. */\nexport function isSatellite(category?: string): boolean {\n return !!category && /^component\\.(passive|discrete)\\b/.test(category);\n}\n\n/** The function group of a component, from its category. */\nexport function functionGroup(category?: string): FunctionGroup {\n const c = category ?? \"\";\n if (/^(connector|interconnect)\\b|^component\\.(switch|protection|button)\\b|^mechanical\\.connector/.test(c)) return \"io\";\n if (/^power\\b|^energy\\b|^battery\\b/.test(c)) return \"power\";\n if (/^(microcontroller|processor|compute|fpga|soc)\\b|^component\\.(mcu|processor)\\b/.test(c)) return \"mcu\";\n if (/^sensor\\b/.test(c)) return \"sensor\";\n if (/^(actuator|display|lighting|audio|communication|radio|motor)\\b|^component\\.(display|led|ic|driver|audio)\\b/.test(c)) return \"output\";\n return \"other\";\n}\n\nconst natural = (a: string, b: string) => a.localeCompare(b, undefined, { numeric: true });\nconst snapUp = (v: number) => Math.ceil(v / STEP) * STEP;\nconst snapTo = (v: number) => Math.round(v / STEP) * STEP;\n\nconst words = (s: string) =>\n s\n .toUpperCase()\n .split(/[^A-Z0-9+-]+/)\n .filter((w) => w.length >= 3 && !GENERIC.has(w));\n/** Words too common in part names to say which part a passive serves. */\nconst GENERIC = new Set([\"THE\", \"AND\", \"FOR\", \"PULL-UP\", \"PULL-DOWN\", \"PULL\", \"BULK\", \"BYPASS\", \"INPUT\", \"OUTPUT\", \"SERIES\", \"UPPER\", \"LOWER\", \"TOP\", \"BOTTOM\", \"PAD\", \"PADS\", \"LOAD\", \"SENSE\", \"DIVIDER\", \"MODULE\"]);\n\n/** Whether `boxes` overlap once each is grown by its own padding. */\nexport function hits(a: Rect, b: Rect, padA = 0, padB = 0): boolean {\n return a.x - padA < b.x + b.w + padB && b.x - padB < a.x + a.w + padA && a.y - padA < b.y + b.h + padB && b.y - padB < a.y + a.h + padA;\n}\n\n/** Search offsets, cheapest first: a vertical move costs less than a sideways one. */\nlet OFFSETS: [number, number][] | undefined;\nfunction offsets(): [number, number][] {\n if (OFFSETS) return OFFSETS;\n const out: [number, number, number][] = [];\n const R = 90;\n for (let i = -R; i <= R; i++) for (let j = -R; j <= R; j++) out.push([i * STEP, j * STEP, Math.abs(i) * 1.25 + Math.abs(j) + (i < 0 ? 0.01 : 0) + (j < 0 ? 0.005 : 0)]);\n out.sort((a, b) => a[2] - b[2]);\n OFFSETS = out.map(([x, y]) => [x, y]);\n return OFFSETS;\n}\n\n/**\n * The free top-left position nearest `ideal` (a centre) for a box of size w×h,\n * clear of every obstacle by the paddings. Falls back to below everything.\n */\nexport function freeSpot(ideal: [number, number], w: number, h: number, obstacles: Rect[], pad: { x: number; y: number } = { x: 36, y: 18 }): { x: number; y: number } {\n const x0 = Math.round((ideal[0] - w / 2) / STEP) * STEP;\n const y0 = Math.round((ideal[1] - h / 2) / STEP) * STEP;\n const clear = (x: number, y: number) =>\n obstacles.every((o) => !(x - pad.x < o.x + o.w && o.x < x + w + pad.x && y - pad.y < o.y + o.h && o.y < y + h + pad.y));\n for (const [dx, dy] of offsets()) if (clear(x0 + dx, y0 + dy)) return { x: x0 + dx, y: y0 + dy };\n const bottom = Math.max(0, ...obstacles.map((o) => o.y + o.h));\n return { x: x0, y: bottom + 2 * pad.y };\n}\n\n/**\n * Isotonic placement: tops for boxes in a fixed order, each at least `gap`\n * below the one before, as close to its ideal top as that allows (least\n * squares, pool-adjacent-violators).\n */\nexport function pack(ideal: number[], heights: number[], gap: number): number[] {\n // z_i = y_i − (the room the boxes above take); z must not decrease\n const offset: number[] = [];\n let acc = 0;\n for (let i = 0; i < ideal.length; i++) {\n offset.push(acc);\n acc += heights[i] + gap;\n }\n const blocks: { sum: number; n: number }[] = [];\n for (let i = 0; i < ideal.length; i++) {\n blocks.push({ sum: ideal[i] - offset[i], n: 1 });\n while (blocks.length > 1 && blocks[blocks.length - 2].sum / blocks[blocks.length - 2].n > blocks[blocks.length - 1].sum / blocks[blocks.length - 1].n) {\n const b = blocks.pop()!;\n blocks[blocks.length - 1].sum += b.sum;\n blocks[blocks.length - 1].n += b.n;\n }\n }\n const out: number[] = [];\n for (const b of blocks) for (let k = 0; k < b.n; k++) out.push(snapTo(b.sum / b.n + offset[out.length]));\n // snapping can close a gap by a step: open it again\n for (let i = 1; i < out.length; i++) out[i] = Math.max(out[i], out[i - 1] + snapUp(heights[i - 1]) + gap);\n return out;\n}\n\n/** What the layout and the rail taps share: the clusters of a board level. */\nexport interface BoardClusters {\n /** Cluster (its anchor's id) of each component. */\n clusterOf: Map<string, string>;\n /** Members of each cluster: the anchor first, then its satellites in reading order. */\n clusters: Map<string, string[]>;\n /** Function group of each cluster. */\n group: Map<string, FunctionGroup>;\n /** Component members of each junction. */\n members: Map<string, string[]>;\n /** Component ↔ component lines (two-member nets of their own). */\n direct: [string, string][];\n}\n\n/** Cluster a board level's components: each passive with the part it serves, a dedicated connector with its part. */\nexport function boardClusters(nodes: BoardNode[], edges: [string, string][]): BoardClusters {\n const byId = new Map(nodes.map((n) => [n.id, n]));\n const comps = nodes.filter((n) => !n.net).sort((a, b) => natural(a.id, b.id));\n\n // nets as member sets; component ↔ component lines count as two-member nets\n const memberSets = new Map<string, Set<string>>();\n const direct: [string, string][] = [];\n for (const [a, b] of edges) {\n const na = byId.get(a);\n const nb = byId.get(b);\n if (!na || !nb || a === b) continue;\n if (na.net && !nb.net) memberSets.set(a, (memberSets.get(a) ?? new Set()).add(b));\n else if (nb.net && !na.net) memberSets.set(b, (memberSets.get(b) ?? new Set()).add(a));\n else if (!na.net && !nb.net) direct.push([a, b]);\n }\n const members = new Map([...memberSets].map(([k, s]) => [k, [...s].sort(natural)]));\n const nets: string[][] = [...members.values(), ...direct];\n const affinity = affinities(nets);\n\n const satellite = (n: BoardNode) => isSatellite(n.category);\n const anchors = comps.filter((n) => !satellite(n));\n const group = new Map<string, FunctionGroup>(anchors.map((n) => [n.id, functionGroup(n.category)]));\n const rank = (id: string) => GROUP_ORDER.indexOf(group.get(id) ?? \"other\");\n const parentOf = new Map<string, string>();\n for (const s of comps.filter(satellite)) {\n const label = (s.label ?? \"\").toUpperCase();\n // 1. a designator named in the label (\"U7 INPUT\", \"Y1 LOAD XL1\")\n const named = comps.filter((o) => o !== s && new RegExp(`(^|[^A-Z0-9])${o.id.toUpperCase().replace(/[^A-Z0-9]/g, \"\")}([^A-Z0-9]|$)`).test(label));\n // 2. an anchor whose name shares a distinctive word (\"LED DRIVER VCC\" → \"LED DRIVER\")\n const own = new Set(words(label));\n const worded = anchors\n .map((o) => ({ o, n: words(o.label ?? \"\").filter((w) => own.has(w)).length }))\n .filter((x) => x.n > 0)\n .sort((a, b) => b.n - a.n || rank(a.o.id) - rank(b.o.id) || natural(a.o.id, b.o.id));\n // 3. the component sharing the most specific nets (ties: the processor first)\n const aff = [...(affinity.get(s.id) ?? new Map<string, number>())].sort((a, b) => b[1] - a[1] || (group.has(a[0]) ? rank(a[0]) : 9) - (group.has(b[0]) ? rank(b[0]) : 9) || natural(a[0], b[0]));\n const pick = named[0]?.id ?? worded[0]?.o.id ?? aff[0]?.[0];\n if (pick) parentOf.set(s.id, pick);\n }\n // follow satellite → satellite chains to an anchor; a satellite with none becomes an anchor of its own\n const anchorOf = (id: string): string => {\n const seen = new Set<string>();\n let cur = id;\n while (parentOf.has(cur) && !seen.has(cur)) {\n seen.add(cur);\n cur = parentOf.get(cur)!;\n }\n return seen.has(cur) || !group.has(cur) ? id : cur;\n };\n // a connector or switch dedicated to one part (an LRA's pads, the SWD pads, a button) sits with\n // that part: every specific net it is on (three members or fewer) goes to the same cluster\n for (const n of anchors) {\n if (group.get(n.id) !== \"io\") continue;\n const targets = new Set<string>();\n for (const set of nets) if (set.includes(n.id) && set.length <= 3) for (const o of set) if (o !== n.id) targets.add(anchorOf(o));\n targets.delete(n.id);\n const [only] = targets;\n if (targets.size === 1 && group.has(only) && group.get(only) !== \"io\") {\n parentOf.set(n.id, only);\n group.delete(n.id);\n }\n }\n const sats = new Map<string, string[]>();\n for (const n of comps) {\n const a = satellite(n) || !group.has(n.id) ? anchorOf(n.id) : n.id;\n if (!group.has(a)) group.set(a, \"other\");\n if (a !== n.id) sats.set(a, [...(sats.get(a) ?? []), n.id]);\n else if (!sats.has(a)) sats.set(a, []);\n }\n const clusters = new Map<string, string[]>();\n const clusterOf = new Map<string, string>();\n for (const [a, list] of sats) {\n // satellites listed by what they hang from (Y1's load caps beside Y1), then by id\n const chain = (id: string): string[] => (parentOf.has(id) && parentOf.get(id) !== a && list.includes(parentOf.get(id)!) ? [...chain(parentOf.get(id)!), id] : [id]);\n list.sort((x, y) => {\n const cx = chain(x);\n const cy = chain(y);\n return natural(cx[0], cy[0]) || cx.length - cy.length || natural(x, y);\n });\n clusters.set(a, [a, ...list]);\n for (const id of [a, ...list]) clusterOf.set(id, a);\n }\n return { clusterOf, clusters, group, members, direct };\n}\n\n/** Affinity between components: a net of n members adds 1/(n−1) to each pair (a rail says little). */\nfunction affinities(nets: string[][]): Map<string, Map<string, number>> {\n const affinity = new Map<string, Map<string, number>>();\n const add = (a: string, b: string, w: number) => {\n const m = affinity.get(a) ?? new Map<string, number>();\n m.set(b, (m.get(b) ?? 0) + w);\n affinity.set(a, m);\n };\n for (const set of nets) {\n if (set.length < 2) continue;\n const w = 1 / (set.length - 1);\n for (let i = 0; i < set.length; i++)\n for (let j = i + 1; j < set.length; j++) {\n add(set[i], set[j], w);\n add(set[j], set[i], w);\n }\n }\n return affinity;\n}\n\ninterface Cluster {\n id: string;\n col: number;\n w: number;\n h: number;\n /** Offsets of each card inside the cluster. */\n cards: Record<string, { x: number; y: number }>;\n}\n\n/**\n * Top-left positions by node id for a board level. `edges` are the lines\n * drawn between nodes (component ↔ junction, or component ↔ component).\n */\nexport function boardLayout(nodes: BoardNode[], edges: [string, string][]): Record<string, { x: number; y: number }> {\n if (!nodes.length) return {};\n const byId = new Map(nodes.map((n) => [n.id, n]));\n const hubs = nodes.filter((n) => n.net).sort((a, b) => natural(a.id, b.id));\n const { clusterOf, clusters, group, members, direct } = boardClusters(nodes, edges);\n const hubMembers = (id: string) => members.get(id) ?? [];\n\n // ---- cluster shapes: the anchor on top, its satellites in up to two stacks below it ----\n // (left and right: a satellite goes on the side its junctions are, so its lines leave the cluster\n // without crossing the other stack; before the sides are known, alternately)\n const shapeCluster = (c: Cluster, side?: (id: string) => \"L\" | \"R\", order?: (id: string) => number) => {\n const [a, ...sats] = clusters.get(c.id)!;\n const an = byId.get(a)!;\n const cards: Record<string, { x: number; y: number }> = {};\n if (!sats.length) {\n cards[a] = { x: 0, y: 0 };\n Object.assign(c, { w: an.w, h: an.h, cards });\n return;\n }\n let L = sats.filter((id, i) => (side ? side(id) === \"L\" : i % 2 === 1));\n let R = sats.filter((id) => !L.includes(id));\n if (order) {\n L = L.slice().sort((x, y) => order(x) - order(y));\n R = R.slice().sort((x, y) => order(x) - order(y));\n }\n const stackW = (ids: string[]) => (ids.length ? Math.max(...ids.map((id) => byId.get(id)!.w)) : 0);\n const wl = stackW(L);\n const wr = stackW(R);\n const both = wl && wr;\n const gridW = wl + wr + (both ? GAP_IN_X : 0);\n const w = Math.max(an.w, gridW);\n cards[a] = { x: snapTo((w - an.w) / 2), y: 0 };\n const x0 = snapTo((w - gridW) / 2);\n let h = an.h;\n for (const [ids, x, sw] of [\n [L, x0, wl],\n [R, x0 + (wl ? wl + GAP_IN_X : 0), wr],\n ] as [string[], number, number][]) {\n let y = snapUp(an.h + GAP_IN_Y);\n for (const id of ids) {\n const n = byId.get(id)!;\n // a stack's cards line up on the cluster's outer edge (the side their lines leave from)\n cards[id] = { x: snapTo(ids === L ? x : x + sw - n.w), y };\n y = snapUp(y + n.h + GAP_IN_Y);\n h = Math.max(h, y - GAP_IN_Y);\n }\n }\n Object.assign(c, { w, h, cards });\n };\n const shapes: Cluster[] = [...clusters.keys()].map((id) => {\n const c: Cluster = { id, col: 0, w: 0, h: 0, cards: {} };\n shapeCluster(c);\n return c;\n });\n const shapeOf = new Map(shapes.map((c) => [c.id, c]));\n\n // cluster ↔ cluster weights, from the nets (each junction's members) and the direct lines\n // (a rail's taps count as the one net they are: what a rail joins belongs near its source, if weakly)\n const merged = new Map<string, Set<string>>();\n for (const [hub, list] of members) {\n const key = byId.get(hub)?.tapOf ?? hub;\n merged.set(key, new Set([...(merged.get(key) ?? []), ...list]));\n }\n const clusterWeights = (nets: string[][]) => {\n const out = new Map<string, Map<string, number>>();\n for (const [a, m] of affinities(nets)) {\n const ca = clusterOf.get(a);\n if (!ca) continue;\n for (const [b, w] of m) {\n const cb = clusterOf.get(b);\n if (!cb || ca === cb) continue;\n const row = out.get(ca) ?? new Map<string, number>();\n row.set(cb, (row.get(cb) ?? 0) + w);\n out.set(ca, row);\n }\n }\n return out;\n };\n const cw = clusterWeights([...[...merged.values()].map((x) => [...x]), ...direct]);\n // the lines actually drawn (a rail's taps stay within their cluster), for who drives whom\n const drawnCw = clusterWeights([...members.values(), ...direct]);\n\n // ---- columns: by function; a peripheral driven only by another peripheral one column further out ----\n const hasMcu = shapes.some((c) => group.get(c.id) === \"mcu\");\n for (const c of shapes) c.col = hasMcu ? GROUP_COLUMN[group.get(c.id)!] : GROUP_ORDER.indexOf(group.get(c.id)!);\n if (hasMcu) {\n for (let round = 0; round < 3; round++) {\n for (const c of shapes) {\n if (c.col < 3) continue;\n const ns = [...(drawnCw.get(c.id) ?? [])].map(([o]) => shapeOf.get(o)!);\n if (!ns.length || ns.some((o) => o.col < 3)) continue;\n // only to peripherals: beside the one it hangs from (the most connected)\n const best = [...(drawnCw.get(c.id) ?? [])].sort((a, b) => b[1] - a[1] || natural(a[0], b[0]))[0][0];\n const driver = shapeOf.get(best)!;\n // the driver itself answers to the processor or the power stage (two peripherals joined only to each other stay put)\n const driven = [...(drawnCw.get(driver.id) ?? [])].some(([o]) => shapeOf.get(o)!.col < 3);\n if (driven && driver.col >= c.col) c.col = driver.col + 1;\n }\n }\n }\n const used = [...new Set(shapes.map((c) => c.col))].sort((a, b) => a - b);\n for (const c of shapes) c.col = used.indexOf(c.col);\n\n // wrap a column taller than a landscape sheet allows into several\n const area = shapes.reduce((s, c) => s + (c.w + 2 * CHANNEL_PAD + 160) * (c.h + GAP_CLUSTER), 0);\n // (never below a screen's worth: a short column stays one column)\n const maxH = Math.max(Math.max(...shapes.map((c) => c.h)), Math.sqrt(area / 1.6), WRAP_MIN);\n const byCol: Cluster[][] = used.map((_, i) => shapes.filter((c) => c.col === i).sort((a, b) => b.h * b.w - a.h * a.w || natural(a.id, b.id)));\n const columns: Cluster[][] = [];\n for (const col of byCol) {\n const total = col.reduce((s, c) => s + c.h + GAP_CLUSTER, -GAP_CLUSTER);\n const n = Math.max(1, Math.ceil(total / maxH));\n const per = Math.ceil(col.length / n);\n for (let k = 0; k < n; k++) if (col.slice(k * per, k * per + per).length) columns.push(col.slice(k * per, k * per + per));\n }\n columns.forEach((col, i) => col.forEach((c) => (c.col = i)));\n\n const colOf = (id: string) => shapeOf.get(clusterOf.get(id)!)!.col;\n\n // ---- junctions: a channel each (channel k lies right of column k; −1 left of the first) ----\n const channelHubs = new Map<number, BoardNode[]>();\n const lastCol = columns.length - 1;\n const load = new Map<number, number>();\n const ordered = hubs.slice().sort((a, b) => hubMembers(b.id).length - hubMembers(a.id).length || natural(a.id, b.id));\n for (const hub of ordered) {\n const m = hubMembers(hub.id).filter((id) => clusterOf.has(id));\n let ch: number;\n if (!m.length) ch = lastCol;\n else {\n const cols = m.map(colOf).sort((a, b) => a - b);\n const lo = cols[0];\n const hi = cols[cols.length - 1];\n if (lo === hi) {\n // all in one column: the side with less in it already (the outer side of the edge columns last)\n const sides = [lo - 1, lo].filter((k) => k >= 0 && k < lastCol);\n const pool = sides.length ? sides : [lo === 0 ? 0 : lo - 1];\n ch = pool.sort((a, b) => (load.get(a) ?? 0) - (load.get(b) ?? 0) || b - a)[0];\n if (lastCol === 0) ch = 0;\n } else {\n // the channel with as many members on either side as it can have\n let best = lo;\n let score = Infinity;\n for (let k = lo; k < hi; k++) {\n const s = cols.reduce((t, c) => t + Math.abs(c - (k + 0.5)), 0);\n if (s < score - 1e-9) [best, score] = [k, s];\n }\n ch = best;\n }\n }\n channelHubs.set(ch, [...(channelHubs.get(ch) ?? []), hub]);\n load.set(ch, (load.get(ch) ?? 0) + 1);\n }\n\n // a junction is as tall as the ports on its busier side need (members left of its channel on its left)\n const hubH = new Map<string, number>();\n for (const [ch, list] of channelHubs)\n for (const h of list) {\n const m = hubMembers(h.id).filter((id) => clusterOf.has(id));\n const left = m.filter((id) => colOf(id) <= ch).length;\n hubH.set(h.id, Math.max(h.h, (Math.max(left, m.length - left) + 1) * STEP));\n }\n const H = (h: BoardNode) => hubH.get(h.id) ?? h.h;\n\n // cards as tall as their busier side will be (junctions left of their column on the left)\n for (const n of nodes) {\n if (n.net || !n.heightFor || !clusterOf.has(n.id)) continue;\n const chs = [...channelHubs].flatMap(([ch, list]) => list.filter((h) => hubMembers(h.id).includes(n.id)).map(() => ch));\n const l = chs.filter((ch) => ch < colOf(n.id)).length;\n const h = n.heightFor(Math.max(l, chs.length - l) + (n.otherPorts ?? 0) + 1);\n if (h > n.h) byId.set(n.id, { ...n, h });\n }\n for (const c of shapes) shapeCluster(c);\n\n // satellites to the side of the channel their junctions are in (the side with fewer, for one with none)\n const hubsOf = new Map<string, string[]>();\n for (const [ch, list] of channelHubs) for (const h of list) for (const m of hubMembers(h.id)) hubsOf.set(m, [...(hubsOf.get(m) ?? []), h.id]);\n const channelOf = new Map<string, number>();\n for (const [ch, list] of channelHubs) for (const h of list) channelOf.set(h.id, ch);\n const sideOf = new Map<string, \"L\" | \"R\">();\n for (const c of shapes) {\n const sats = clusters.get(c.id)!.slice(1);\n let nl = 0;\n let nr = 0;\n for (const id of sats) {\n const chs = (hubsOf.get(id) ?? []).map((h) => channelOf.get(h)!);\n const l = chs.filter((ch) => ch < c.col).length;\n const r = chs.length - l;\n const side = l > r || (l === r && !chs.length && nl < nr) ? \"L\" : \"R\";\n sideOf.set(id, side);\n if (side === \"L\") nl++;\n else nr++;\n }\n shapeCluster(c, (id) => sideOf.get(id)!);\n }\n\n // each junction hangs off its smallest member card (the LED, not its driver): the cluster of that card\n // is given room down the side of the junction's channel for it, so a channel's junctions fit one lane\n const demand = new Map<string, { L: number; R: number }>();\n for (const [ch, list] of channelHubs)\n for (const h of list) {\n const m = hubMembers(h.id).filter((id) => clusterOf.has(id));\n if (!m.length) continue;\n const owner = m.slice().sort((a, b) => byId.get(a)!.h - byId.get(b)!.h || natural(a, b))[0];\n const c = clusterOf.get(owner)!;\n const d = demand.get(c) ?? { L: 0, R: 0 };\n d[ch < colOf(owner) ? \"L\" : \"R\"] += H(h) + HUB_GAP_Y;\n demand.set(c, d);\n }\n const slot = (c: Cluster) => snapUp(Math.max(c.h, demand.get(c.id)?.L ?? 0, demand.get(c.id)?.R ?? 0));\n\n // ---- heights: barycentre sweeps, then each column packed toward the height of what it joins ----\n // (`top` is the top of a cluster's slot: its cards sit in the middle of it)\n const top = new Map<string, number>();\n const mid = (c: Cluster) => top.get(c.id)! + slot(c) / 2;\n for (const col of columns) {\n const total = col.reduce((s, c) => s + slot(c) + GAP_CLUSTER, -GAP_CLUSTER);\n let y = snapTo((maxH - total) / 2);\n for (const c of col) {\n top.set(c.id, y);\n y += slot(c) + GAP_CLUSTER;\n }\n }\n const sweepOrder = columns.map((_, i) => i).sort((a, b) => columns[b].reduce((s, c) => s + slot(c), 0) - columns[a].reduce((s, c) => s + slot(c), 0));\n for (let sweep = 0; sweep < 8; sweep++) {\n // the tallest column first: the others line up with it\n for (const i of sweep === 0 ? sweepOrder.slice(1) : sweepOrder) {\n const col = columns[i];\n const key = new Map<string, number>();\n for (const c of col) {\n let s = 0;\n let n = 0;\n for (const [o, w] of cw.get(c.id) ?? []) {\n const oc = shapeOf.get(o)!;\n if (oc.col === c.col) continue;\n // nearer columns pull harder\n const k = w / Math.abs(oc.col - c.col);\n s += mid(oc) * k;\n n += k;\n }\n key.set(c.id, n ? s / n : NaN);\n }\n // a cluster joined to nothing in another column (a cell's pads on a tapped rail) goes last, packed\n const last = Math.max(0, ...col.map((c) => key.get(c.id)!).filter((k) => !Number.isNaN(k)));\n for (const c of col) if (Number.isNaN(key.get(c.id)!)) key.set(c.id, last + 1);\n col.sort((a, b) => key.get(a.id)! - key.get(b.id)! || natural(a.id, b.id));\n const ys = pack(col.map((c) => key.get(c.id)! - slot(c) / 2), col.map(slot), GAP_CLUSTER);\n col.forEach((c, k) => top.set(c.id, ys[k]));\n }\n }\n\n // card positions without x yet: x comes once the channels are sized\n const cardY = new Map<string, number>();\n const cardMidY = (id: string) => cardY.get(id)! + byId.get(id)!.h / 2;\n const setCardY = () => {\n for (const c of shapes) for (const [id, o] of Object.entries(c.cards)) cardY.set(id, top.get(c.id)! + snapTo((slot(c) - c.h) / 2) + o.y);\n };\n setCardY();\n\n // lanes: junctions in order of the height of what they join; a new lane where one would be pushed far\n interface Lane {\n hubs: BoardNode[];\n ideal: number[];\n }\n // a junction's height: where the lines to it run shortest. A card's port can sit anywhere along its\n // side, so each member is the span of its card, and the best height is the one nearest every span\n // (ties: nearest the weighted mean of their middles)\n const hubIdeal = (h: BoardNode) => {\n const m = hubMembers(h.id).filter((id) => cardY.has(id));\n if (!m.length) return maxH / 2;\n const spans = m.map((id) => {\n const t = cardY.get(id)!;\n const bh = byId.get(id)!.h;\n const inset = Math.min(32, bh / 2);\n return [t + inset, t + bh - inset] as [number, number];\n });\n const cost = (y: number) => spans.reduce((s, [a, b]) => s + (y < a ? a - y : y > b ? y - b : 0), 0);\n // the middles weighted toward the small cards (an LED's junction sits by the LED, not its driver's middle)\n const wt = (id: string) => 1 / byId.get(id)!.h ** 2;\n const mean = m.reduce((s, id) => s + cardMidY(id) * wt(id), 0) / m.reduce((s, id) => s + wt(id), 0);\n let best = mean;\n let bc = cost(mean);\n for (const y of spans.flat()) {\n const c = cost(y);\n if (c < bc - 1e-6 || (Math.abs(c - bc) < 1e-6 && Math.abs(y - mean) < Math.abs(best - mean))) [best, bc] = [y, c];\n }\n // within the best range, as near the mean as it allows\n const lo = Math.min(...spans.flat().filter((y) => Math.abs(cost(y) - bc) < 1e-6), best);\n const hi = Math.max(...spans.flat().filter((y) => Math.abs(cost(y) - bc) < 1e-6), best);\n return Math.max(lo, Math.min(hi, mean));\n };\n const makeLanes = () => {\n const channelLanes = new Map<number, Lane[]>();\n for (const [ch, list] of channelHubs) {\n const sorted = list.slice().sort((a, b) => hubIdeal(a) - hubIdeal(b) || natural(a.id, b.id));\n const lanes: Lane[] = [];\n const bottoms: number[] = [];\n for (const h of sorted) {\n const ideal = hubIdeal(h) - H(h) / 2;\n let pick = -1;\n let push = Infinity;\n bottoms.forEach((b, i) => {\n const p = Math.max(0, b + HUB_GAP_Y - ideal);\n if (p < push - 1e-9) [pick, push] = [i, p];\n });\n // lanes side by side cross each other's lines: a second one only where one lane would push far\n if (pick < 0 || (push > LANE_PUSH && lanes.length < 3)) {\n lanes.push({ hubs: [], ideal: [] });\n bottoms.push(-Infinity);\n pick = lanes.length - 1;\n }\n lanes[pick].hubs.push(h);\n lanes[pick].ideal.push(ideal);\n bottoms[pick] = Math.max(bottoms[pick] + HUB_GAP_Y, ideal) + H(h);\n }\n channelLanes.set(ch, lanes);\n }\n return channelLanes;\n };\n\n // place the junctions once, then order each satellite stack by the height of its junctions, and again\n let channelLanes = makeLanes();\n const hubMid = new Map<string, number>();\n for (const lanes of channelLanes.values())\n for (const lane of lanes) {\n const ys = pack(lane.ideal, lane.hubs.map(H), HUB_GAP_Y);\n lane.hubs.forEach((h, i) => hubMid.set(h.id, ys[i] + H(h) / 2));\n }\n const satKey = (id: string) => {\n const hs = (hubsOf.get(id) ?? []).filter((h) => hubMid.has(h));\n return hs.length ? hs.reduce((t, h) => t + hubMid.get(h)!, 0) / hs.length : cardMidY(id);\n };\n for (const c of shapes) if (clusters.get(c.id)!.length > 2) shapeCluster(c, (id) => sideOf.get(id)!, satKey);\n setCardY();\n channelLanes = makeLanes();\n\n // lines into each side of a channel: room for their vertical runs\n const sideLines = (ch: number, side: \"left\" | \"right\") => {\n let n = 0;\n for (const h of channelHubs.get(ch) ?? []) for (const m of hubMembers(h.id)) if (clusterOf.has(m) && (side === \"left\" ? colOf(m) <= ch : colOf(m) > ch)) n++;\n return n;\n };\n const pad = (n: number) => snapUp(CHANNEL_PAD + Math.min(320, n * 8));\n\n // ---- x: columns and channels left to right ----\n const out: Record<string, { x: number; y: number }> = {};\n let x = 0;\n const place = (ch: number) => {\n const lanes = channelLanes.get(ch) ?? [];\n if (!lanes.length) {\n x += ch < 0 || ch >= lastCol ? 0 : snapUp(2 * CHANNEL_PAD + 64);\n return;\n }\n x += pad(sideLines(ch, \"left\"));\n for (const lane of lanes) {\n const w = Math.max(...lane.hubs.map((h) => h.w));\n const ys = pack(lane.ideal, lane.hubs.map(H), HUB_GAP_Y);\n lane.hubs.forEach((h, i) => (out[h.id] = { x: snapTo(x + (w - h.w) / 2), y: ys[i] }));\n x += w + LANE_GAP;\n }\n x += pad(sideLines(ch, \"right\")) - LANE_GAP;\n };\n place(-1);\n columns.forEach((col, i) => {\n const w = Math.max(...col.map((c) => c.w));\n for (const c of col) {\n const cx = snapTo(x + (w - c.w) / 2);\n for (const [id, o] of Object.entries(c.cards)) out[id] = { x: cx + o.x, y: cardY.get(id)! };\n }\n x = snapUp(x + w);\n place(i);\n });\n\n const all = Object.values(out);\n const minX = Math.min(...all.map((p) => p.x));\n const minY = Math.min(...all.map((p) => p.y));\n for (const p of all) {\n p.x -= minX;\n p.y -= minY;\n }\n return out;\n}\n","/**\n * Rail taps (PB-873): a supply rail drawn the way a schematic draws it.\n *\n * A rail joins most of a board (a 3V3 rail reaches 15–20 parts). Drawn as one\n * junction it pulls a line from every corner of the sheet. Drawn as a net\n * label at each place it is used, it reads at a glance: here the rail is\n * split into taps, one per cluster of parts (a part and the passives that\n * serve it, board-layout.ts), each joined only to the members of its cluster.\n * The taps carry the net's name and colour; the one with the most members\n * keeps the net's id, the others are `<net>~<cluster>` with `tapOf` set.\n *\n * Only the drawing changes: the inspector, the hierarchy and the findings\n * read the level's view model, where the net is one node.\n */\nimport type { ViewLink, ViewModel, ViewNode } from \"../model/types\";\nimport { boardClusters, functionGroup, type BoardNode } from \"./board-layout\";\n\n/** A power net with at least this many members is drawn as taps. */\nexport const RAIL_TAP_MIN = 5;\n\nconst GROUP_RANK = [\"power\", \"io\", \"mcu\", \"sensor\", \"output\", \"other\"];\nconst natural = (a: string, b: string) => a.localeCompare(b, undefined, { numeric: true });\n\nexport function tapRails(vm: ViewModel): ViewModel {\n const top = vm.nodes.filter((n) => !n.parent && !n.sheetPort);\n const rails = top.filter((n) => n.kind === \"net\" && n.net && !n.net.ground && n.net.signal === \"power\");\n if (!rails.length) return vm;\n const ids = new Set(top.map((n) => n.id));\n const lines = vm.links.filter((l) => !l.passThrough && !l.ground && ids.has(l.source.node) && ids.has(l.target.node));\n const nodes: BoardNode[] = top.map((n) => ({ id: n.id, w: 0, h: 0, net: n.kind === \"net\", category: n.category, label: n.label }));\n const { clusterOf } = boardClusters(\n nodes,\n lines.map((l) => [l.source.node, l.target.node]),\n );\n const byId = new Map(top.map((n) => [n.id, n]));\n\n const retarget = new Map<string, string>();\n const replaced = new Map<string, ViewNode[]>();\n for (const rail of rails) {\n const own = lines.filter((l) => l.target.node === rail.id && clusterOf.has(l.source.node));\n if (own.length < RAIL_TAP_MIN) continue;\n const groups = new Map<string, ViewLink[]>();\n for (const l of own) {\n const c = clusterOf.get(l.source.node)!;\n groups.set(c, [...(groups.get(c) ?? []), l]);\n }\n if (groups.size < 2) continue;\n const rank = (c: string) => GROUP_RANK.indexOf(functionGroup(byId.get(c)?.category));\n const order = [...groups.keys()].sort((a, b) => groups.get(b)!.length - groups.get(a)!.length || rank(a) - rank(b) || natural(a, b));\n const taps: ViewNode[] = order.map((c, i) => {\n const ports = new Set(groups.get(c)!.map((l) => l.target.port));\n const id = i === 0 ? rail.id : `${rail.id}~${c}`;\n for (const l of groups.get(c)!) retarget.set(l.id, id);\n return { ...rail, id, ports: rail.ports.filter((p) => ports.has(p.id)), ...(i === 0 ? {} : { tapOf: rail.id }) };\n });\n // the net's own ports with no line here (a member drawn elsewhere) stay on the main junction\n const kept = new Set(taps.flatMap((t) => t.ports.map((p) => p.id)));\n taps[0] = { ...taps[0], ports: [...taps[0].ports, ...rail.ports.filter((p) => !kept.has(p.id))] };\n replaced.set(rail.id, taps);\n }\n if (!replaced.size) return vm;\n return {\n ...vm,\n nodes: vm.nodes.flatMap((n) => replaced.get(n.id) ?? [n]),\n links: vm.links.map((l) => (retarget.has(l.id) ? { ...l, target: { ...l.target, node: retarget.get(l.id)! } } : l)),\n };\n}\n\n/** The node a selection names for a drawn node: a tap's net. */\nexport const selectionId = (node: ViewNode | undefined, id: string) => node?.tapOf ?? id;\n","/**\n * What a module card's body holds (its icon, its title and the chips that\n * count its unlinked interfaces by protocol) and how much height that needs.\n *\n * The layout grows a card to fit its body between the labels of the ports\n * on its top and bottom edges; the card then draws only the chips that fit\n * and folds the rest into \"+N\". Sizes follow `.module-body`, `.module-title`\n * and `.port-group` in styles/app.css.\n */\nimport type { PortGroup } from \"./layout\";\nimport type { Side } from \"../canvas/routing\";\n\nconst BORDER = 2;\nconst PAD_X = 34;\nconst ICON = 22;\nconst GAP = 7;\nconst TITLE_LINE = 13;\nconst TITLE_CHAR = 6.4;\n/** Room kept above and below the body: a port label's row on an edge with labelled ports, else a margin. */\nconst EDGE = 8;\nconst LABEL_ROW = 20;\n/** A side label: its offset from the edge, its width per character (8 px type), and the gap kept beside it. */\nconst LABEL_OFFSET = 9;\nconst LABEL_CHAR = 4.9;\nconst LABEL_GAP = 4;\nconst CHIP_H = 14;\nconst CHIP_GAP = 3;\nconst CHIP_CHAR = 4.9;\nconst CHIP_PAD = 12;\n/** Chips shown before the rest fold into \"+N\". */\nexport const MAX_CHIPS = 4;\n/** Chip rows a card grows for; more chips fold into \"+N\". */\nexport const MAX_CHIP_ROWS = 3;\n\nexport interface CardInsets {\n top: number;\n bottom: number;\n left: number;\n right: number;\n}\n\n/** A port's label as the card draws it: the name without its parenthesised or dashed qualifier. */\nexport function portLabelText(name: string): string {\n return name.replace(/\\s*\\(.*?\\)/g, \"\").replace(/\\s+[—–-]\\s+.*$/, \"\");\n}\n\n/** How wide a label on a card's left or right edge may run before it is cut with an ellipsis. */\nexport function sideLabelWidth(cardWidth: number): number {\n return Math.max(40, cardWidth / 2 - 54);\n}\n\n/** A card's width with nothing to fit, and the widest it grows to for its labels. */\nexport const CARD_W = 170;\nexport const CARD_W_MAX = 272;\n\n/** The widest a label on a card's top or bottom edge runs (its share of the edge, when that is less). */\nexport const TOP_LABEL_MAX = 160;\n\n/** A label's width as drawn (8 px type). */\nexport const labelWidth = (name: string): number => Math.ceil(portLabelText(name).length * LABEL_CHAR);\n\n/**\n * The width a card takes so the labels of its linked interfaces fit beside\n * its body: as wide as the longest needs (two may face each other across the\n * card), from the plain width up to `CARD_W_MAX`. A longer label is cut with\n * an ellipsis and says its whole name on hover.\n */\nexport function cardWidth(labels: readonly string[]): number {\n const widest = Math.max(0, ...labels.map(labelWidth));\n // the inverse of sideLabelWidth, with a pixel to spare for the ellipsis rule\n const need = 2 * (widest + 1 + 54);\n return Math.min(CARD_W_MAX, Math.max(CARD_W, need));\n}\n\n/** A label is drawn short: it does not fit `width`, or the card leaves out the name's qualifier. */\nexport function labelIsCut(name: string, width: number): boolean {\n return portLabelText(name) !== name || labelWidth(name) > width;\n}\n\n/**\n * Room the body keeps clear of the port labels: a label row on the top and\n * bottom edges that have labelled ports, and on the left and right as wide\n * as that edge's longest label.\n */\nexport function cardInsets(labels: { side: Side; name: string }[], cardWidth: number): CardInsets {\n const has = (side: Side) => labels.some((l) => l.side === side);\n const across = (side: Side) => {\n const widest = Math.max(0, ...labels.filter((l) => l.side === side).map((l) => portLabelText(l.name).length * LABEL_CHAR));\n return widest ? Math.max(PAD_X, LABEL_OFFSET + Math.min(sideLabelWidth(cardWidth), widest) + LABEL_GAP) : PAD_X;\n };\n return { top: has(\"top\") ? LABEL_ROW : EDGE, bottom: has(\"bottom\") ? LABEL_ROW : EDGE, left: across(\"left\"), right: across(\"right\") };\n}\n\nexport function chipText(g: PortGroup): string {\n return `${g.protocol.replace(/_/g, \" \").toUpperCase()} ×${g.count}`;\n}\n\nconst chipWidth = (text: string) => text.length * CHIP_CHAR + CHIP_PAD;\n\n/** Rows the chips wrap to in a body `width` wide (flex-wrap, centred). */\nfunction chipRows(texts: string[], width: number): number {\n let rows = 0;\n let used = Infinity;\n for (const t of texts) {\n const w = Math.min(chipWidth(t), width);\n if (used + CHIP_GAP + w > width) {\n rows++;\n used = w;\n } else used += CHIP_GAP + w;\n }\n return rows;\n}\n\nfunction titleLines(title: string, bodyWidth: number): number {\n const perLine = Math.max(6, Math.floor(bodyWidth / TITLE_CHAR));\n return Math.min(3, Math.max(1, Math.ceil(title.length / perLine)));\n}\n\n/** The chips in the order drawn: the first few groups, then \"+N\" for the interfaces of the rest. */\nfunction chipsFor(groups: PortGroup[], shown: number): { shown: PortGroup[]; rest: number; texts: string[] } {\n const list = groups.slice(0, shown);\n const rest = groups.slice(shown).reduce((n, g) => n + g.count, 0);\n return { shown: list, rest, texts: [...list.map(chipText), ...(rest > 0 ? [`+${rest}`] : [])] };\n}\n\nconst rowsHeight = (rows: number) => (rows > 0 ? GAP + rows * CHIP_H + (rows - 1) * CHIP_GAP : 0);\n\n/** The height a card needs for its body, with up to MAX_CHIP_ROWS rows of chips. */\nexport function cardHeight(title: string, width: number, groups: PortGroup[], insets: CardInsets): number {\n const body = width - insets.left - insets.right;\n const rows = groups.length ? Math.min(MAX_CHIP_ROWS, chipRows(chipsFor(groups, MAX_CHIPS).texts, body)) : 0;\n return 2 * BORDER + insets.top + insets.bottom + ICON + GAP + titleLines(title, body) * TITLE_LINE + rowsHeight(rows);\n}\n\n/**\n * The chips a card of this size draws: as many groups as fit its free rows,\n * the rest counted in \"+N\". A card with no room for a row draws none.\n */\nexport function fitChips(title: string, box: { w: number; h: number }, groups: PortGroup[], insets: CardInsets): { shown: PortGroup[]; rest: number } {\n if (!groups.length) return { shown: [], rest: 0 };\n const body = box.w - insets.left - insets.right;\n const free = box.h - 2 * BORDER - insets.top - insets.bottom - ICON - GAP - titleLines(title, body) * TITLE_LINE;\n let rows = 0;\n while (rows < MAX_CHIP_ROWS && rowsHeight(rows + 1) <= free) rows++;\n if (rows === 0) return { shown: [], rest: 0 };\n for (let k = Math.min(MAX_CHIPS, groups.length); k >= 0; k--) {\n const c = chipsFor(groups, k);\n if (chipRows(c.texts, body) <= rows) return { shown: c.shown, rest: c.rest };\n }\n return { shown: [], rest: 0 };\n}\n","/**\n * Geometry along a routed link (PB-803): positions by arc length, sub-paths,\n * lanes that fan out of the centre line, and harness regions traced around\n * whatever runs through them. Pure functions, no React.\n */\nimport { filletPath, offsetPolyline, type Pt } from \"./routing\";\n\nexport const RUN = 24; // length of one fan\nexport const LANE_PITCH = 16;\nexport const RIBBON_PITCH = 6;\nconst RADIUS = 12;\n\nexport function lengths(points: Pt[]): number[] {\n const out = [0];\n for (let i = 1; i < points.length; i++) out.push(out[i - 1] + Math.hypot(points[i][0] - points[i - 1][0], points[i][1] - points[i - 1][1]));\n return out;\n}\n\nexport const totalLength = (points: Pt[]) => lengths(points).at(-1) ?? 0;\n\n/** Point and unit direction at arc length `s`. */\nexport function at(points: Pt[], s: number): { p: Pt; d: Pt } {\n const L = lengths(points);\n const t = Math.max(0, Math.min(L[L.length - 1], s));\n for (let i = 1; i < points.length; i++) {\n if (L[i] >= t || i === points.length - 1) {\n const seg = L[i] - L[i - 1] || 1;\n const f = (t - L[i - 1]) / seg;\n const [a, b] = [points[i - 1], points[i]];\n return { p: [a[0] + (b[0] - a[0]) * f, a[1] + (b[1] - a[1]) * f], d: [(b[0] - a[0]) / seg, (b[1] - a[1]) / seg] };\n }\n }\n return { p: points[0], d: [1, 0] };\n}\n\n/** The polyline between arc lengths s0 and s1. */\nexport function subpath(points: Pt[], s0: number, s1: number): Pt[] {\n const L = lengths(points);\n const out: Pt[] = [at(points, s0).p];\n for (let i = 1; i < points.length - 1; i++) if (L[i] > s0 && L[i] < s1) out.push(points[i]);\n out.push(at(points, s1).p);\n return out;\n}\n\n/** Arc length of the point on the polyline nearest to `q`. */\nexport function project(points: Pt[], q: Pt): number {\n const L = lengths(points);\n let best = { d: Infinity, s: 0 };\n for (let i = 1; i < points.length; i++) {\n const [a, b] = [points[i - 1], points[i]];\n const vx = b[0] - a[0];\n const vy = b[1] - a[1];\n const len2 = vx * vx + vy * vy || 1;\n const f = Math.max(0, Math.min(1, ((q[0] - a[0]) * vx + (q[1] - a[1]) * vy) / len2));\n const px = a[0] + vx * f;\n const py = a[1] + vy * f;\n const d = Math.hypot(q[0] - px, q[1] - py);\n if (d < best.d) best = { d, s: L[i - 1] + f * Math.sqrt(len2) };\n }\n return best.s;\n}\n\nconst add = (a: Pt, b: Pt, k = 1): Pt => [a[0] + b[0] * k, a[1] + b[1] * k];\nconst normal = (d: Pt): Pt => [d[1], -d[0]]; // left of travel, as offsetPolyline\n\nexport function densify(points: Pt[], step = 3): Pt[] {\n const out: Pt[] = [];\n for (let i = 1; i < points.length; i++) {\n const [a, b] = [points[i - 1], points[i]];\n const n = Math.max(1, Math.ceil(Math.hypot(b[0] - a[0], b[1] - a[1]) / step));\n for (let k = 0; k < n; k++) out.push([a[0] + ((b[0] - a[0]) * k) / n, a[1] + ((b[1] - a[1]) * k) / n]);\n }\n if (points.length) out.push(points[points.length - 1]);\n return out;\n}\n\n/** Offsets for n lanes centred on the line. */\nexport const offsets = (n: number, pitch: number) => Array.from({ length: n }, (_, i) => (i - (n - 1) / 2) * pitch);\n\n/** Fillet radius for the centre line of a ribbon `width` wide, so its inner conductor still turns round. */\nexport const ribbonRadius = (width: number) => Math.max(RADIUS, width / 2 + 6);\n\n/** Stroke points of a ribbon (parallel conductors at a fixed pitch) along the whole route. */\nexport function ribbon(points: Pt[], n: number, radius = RADIUS): { d: string; samples: Pt[] }[] {\n return offsets(n, RIBBON_PITCH).map((o) => {\n const off = offsetPolyline(points, o, radius);\n return { d: filletPath(off.points, off.radii), samples: densify(off.points) };\n });\n}\n\n/**\n * The straight stretches of a route as arc-length intervals, each kept `clear`\n * of the corners at its ends (and `end` of the route's own ends).\n */\nexport function straights(points: Pt[], clear: number, end = 0): [number, number][] {\n const L = lengths(points);\n const out: [number, number][] = [];\n for (let i = 1; i < points.length; i++) {\n const a = L[i - 1] + (i > 1 ? clear : end);\n const b = L[i] - (i < points.length - 1 ? clear : end);\n if (b >= a) out.push([a, b]);\n }\n return out;\n}\n\n/**\n * The nearest arc length to `s` that sits on a straight stretch, clear of the\n * bends (handles and toggles never sit in a corner). Where no stretch is long\n * enough, the middle of the longest segment.\n */\nexport function clearOfBends(points: Pt[], s: number, clear: number, end = 0): number {\n const iv = straights(points, clear, end);\n if (!iv.length) {\n const L = lengths(points);\n let best = 1;\n for (let i = 2; i < points.length; i++) if (L[i] - L[i - 1] > L[best] - L[best - 1]) best = i;\n return (L[best - 1] + L[best]) / 2;\n }\n let out = s;\n let dist = Infinity;\n for (const [a, b] of iv) {\n const c = Math.max(a, Math.min(b, s));\n if (Math.abs(c - s) < dist) {\n dist = Math.abs(c - s);\n out = c;\n }\n }\n return out;\n}\n\n/** The straight stretch (with `clear` at its corners) that contains arc length `s`. */\nexport function stretchAt(points: Pt[], s: number, clear: number, end = 0): [number, number] {\n const L = lengths(points);\n for (let i = 1; i < points.length; i++) {\n if (s <= L[i] + 0.5 || i === points.length - 1) return [L[i - 1] + (i > 1 ? clear : end), L[i] - (i < points.length - 1 ? clear : end)];\n }\n return [0, L[L.length - 1]];\n}\n\n/**\n * Turn short S-jogs (a sidestep between two runs in the same direction,\n * shorter than `min`) into a gentle diagonal: a wide ribbon cannot take two\n * right angles in less than its own width without its conductors crossing.\n */\nexport function easeJogs(points: Pt[], min: number): Pt[] {\n let pts = points.map((p) => [...p] as Pt);\n for (let guard = 0; guard < 16; guard++) {\n let changed = false;\n for (let i = 1; i < pts.length - 2; i++) {\n const [a, b, c, e] = [pts[i - 1], pts[i], pts[i + 1], pts[i + 2]];\n const j = Math.hypot(c[0] - b[0], c[1] - b[1]);\n const lin = Math.hypot(b[0] - a[0], b[1] - a[1]);\n const lout = Math.hypot(e[0] - c[0], e[1] - c[1]);\n if (j >= min || j < 0.5 || !lin || !lout) continue;\n const din: Pt = [(b[0] - a[0]) / lin, (b[1] - a[1]) / lin];\n const dout: Pt = [(e[0] - c[0]) / lout, (e[1] - c[1]) / lout];\n if (din[0] * dout[0] + din[1] * dout[1] < 0.99) continue; // not an S-jog\n // leave the first and last runs (the port stubs) a little straight\n const k = Math.min(Math.max(min, 2 * j), lin - (i === 1 ? 10 : 2), lout - (i + 2 === pts.length - 1 ? 10 : 2));\n if (k < j / 2) continue;\n pts = [...pts.slice(0, i), add(b, din, -k), add(c, dout, k), ...pts.slice(i + 2)];\n changed = true;\n break;\n }\n if (!changed) break;\n }\n return pts;\n}\n\n/**\n * A closed outline around every sample (dilated by `pad`), traced on a 2 px\n * raster and smoothed: the harness region, tight to what runs through it.\n */\nexport function regionOutline(samples: Pt[], pad: number): string {\n if (!samples.length) return \"\";\n const C = 2;\n const xs = samples.map((p) => p[0]);\n const ys = samples.map((p) => p[1]);\n const x0 = Math.min(...xs) - pad - 4;\n const y0 = Math.min(...ys) - pad - 4;\n const W = Math.ceil((Math.max(...xs) + pad + 4 - x0) / C);\n const H = Math.ceil((Math.max(...ys) + pad + 4 - y0) / C);\n const grid = new Uint8Array(W * H);\n const r = Math.ceil(pad / C);\n const disc: [number, number][] = [];\n for (let dx = -r; dx <= r; dx++) for (let dy = -r; dy <= r; dy++) if (dx * dx + dy * dy <= r * r) disc.push([dx, dy]);\n for (const [x, y] of samples) {\n const cx = Math.round((x - x0) / C);\n const cy = Math.round((y - y0) / C);\n for (const [dx, dy] of disc) {\n const X = cx + dx;\n const Y = cy + dy;\n if (X >= 0 && Y >= 0 && X < W && Y < H) grid[Y * W + X] = 1;\n }\n }\n let start = -1;\n for (let i = 0; i < grid.length && start < 0; i++) if (grid[i]) start = i;\n if (start < 0) return \"\";\n const nb: [number, number][] = [[-1, 0], [-1, -1], [0, -1], [1, -1], [1, 0], [1, 1], [0, 1], [-1, 1]];\n const filled = (x: number, y: number) => x >= 0 && y >= 0 && x < W && y < H && grid[y * W + x] === 1;\n let cur: [number, number] = [start % W, Math.floor(start / W)];\n const first = cur;\n let back = 0;\n const contour: Pt[] = [cur];\n for (let guard = 0; guard < W * H * 4; guard++) {\n let moved = false;\n for (let k = 0; k < 8; k++) {\n const d = (back + 1 + k) % 8;\n const nx = cur[0] + nb[d][0];\n const ny = cur[1] + nb[d][1];\n if (filled(nx, ny)) {\n back = (d + 4) % 8;\n cur = [nx, ny];\n moved = true;\n break;\n }\n }\n if (!moved || (cur[0] === first[0] && cur[1] === first[1] && contour.length > 2)) break;\n contour.push(cur);\n }\n let poly: Pt[] = contour.filter((_, i) => i % 2 === 0).map(([x, y]) => [x0 + (x + 0.5) * C, y0 + (y + 0.5) * C]);\n for (let it = 0; it < 3; it++) {\n const next: Pt[] = [];\n for (let i = 0; i < poly.length; i++) {\n const p = poly[i];\n const q = poly[(i + 1) % poly.length];\n next.push([0.75 * p[0] + 0.25 * q[0], 0.75 * p[1] + 0.25 * q[1]], [0.25 * p[0] + 0.75 * q[0], 0.25 * p[1] + 0.75 * q[1]]);\n }\n poly = next;\n }\n return \"M\" + poly.filter((_, i) => i % 2 === 0).map((p) => `${p[0].toFixed(1)},${p[1].toFixed(1)}`).join(\"L\") + \"Z\";\n}\n\n/** A stretch of a line at a constant offset from the centre line, between arc lengths a and b. */\nexport interface Plateau {\n o: number;\n a: number;\n b: number;\n}\n\n/**\n * A line that steps between offsets from the centre line: it runs each\n * plateau parallel to the route and curves smoothly from one to the next over\n * the gap between them (b of one to a of the next). Consecutive plateaus at\n * the same offset join straight through. The building block of every\n * breakout: a lane leaving its parent line, and a conductor stepping out\n * level by level.\n */\nexport function stepped(points: Pt[], plateaus: Plateau[], radius = RADIUS): { d: string; samples: Pt[] } {\n const ps: Plateau[] = [];\n for (const p of plateaus) {\n const last = ps[ps.length - 1];\n if (last && Math.abs(last.o - p.o) < 0.01) last.b = Math.max(last.b, p.b);\n else ps.push({ ...p });\n }\n const pointAt = (s: number, o: number): Pt => {\n const { p, d } = at(points, s);\n return add(p, normal(d), o);\n };\n let d = \"\";\n const samples: Pt[] = [];\n let end: Pt | undefined;\n ps.forEach((p, i) => {\n const sub = p.b - p.a > 0.5 ? offsetPolyline(subpath(points, p.a, p.b), p.o, radius) : undefined;\n const start = sub ? sub.points[0] : pointAt(p.a, p.o);\n if (i === 0) d = `M${start[0]},${start[1]}`;\n else if (end) {\n const q = ps[i - 1];\n const h = Math.max(1, (p.a - q.b) / 2);\n d += ` C${add(end, at(points, q.b).d, h).join(\",\")} ${add(start, at(points, p.a).d, -h).join(\",\")} ${start[0]},${start[1]}`;\n samples.push(...densify([end, start]));\n }\n if (sub) {\n d += filletPath(sub.points, sub.radii).replace(/^M[^L]*/, \"\");\n samples.push(...densify(sub.points));\n end = sub.points[sub.points.length - 1];\n } else end = start;\n });\n return { d, samples };\n}\n","/**\n * Module-level layout (PB-1007): the default for a level of modules (no\n * nets), which used to be one long row. The cards go in a grid shaped like\n * a screen, each next to what it connects to:\n *\n * - the grid has about as many columns as a 16:10 screen holds for the\n * level's cards, so no level is a strip;\n * - the hub (the card with the most links: a flight controller, a processor)\n * starts in the middle, and the others are added in order of how strongly\n * they join what is placed, each at the free cell that suits it best;\n * - then cards swap cells while that lowers the cost: link length, links that\n * bend (neither in a row nor a column), lines crossing, lines that a card\n * sits in the way of, and, mildly, the reading order of a block diagram\n * (connectors and power left of the processor, what it drives right of it);\n * - empty rows and columns go, and each column is as wide, and each row as\n * tall, as its largest card, with room between them for the lines and\n * their labels.\n *\n * Same input, same output: every choice breaks ties by id.\n *\n * `fixed` cards keep their places (top-left, as saved); a `seed` (each card's\n * centre in an earlier layout) starts the grid from that arrangement instead\n * (a tidy keeps what the person laid out where it can).\n */\nimport { freeSpot, functionGroup, hits } from \"./board-layout\";\nimport { GRID } from \"./router\";\n\nexport interface GridNode {\n id: string;\n w: number;\n h: number;\n category?: string;\n}\n\nexport interface GridOptions {\n /** Cards that stay where they are: top-left positions. */\n fixed?: Record<string, { x: number; y: number }>;\n /** Where each card's centre was: the starting arrangement. */\n seed?: Record<string, { x: number; y: number }>;\n /** Width over height to aim for (default 1.6). */\n aspect?: number;\n}\n\n/** Room between columns (lines and their labels run there) and between rows. */\nexport const GRID_GAP_X = 192;\nexport const GRID_GAP_Y = 128;\n\nconst natural = (a: string, b: string) => a.localeCompare(b, undefined, { numeric: true });\nconst snapUp = (v: number) => Math.ceil(v / GRID) * GRID;\nconst snapTo = (v: number) => Math.round(v / GRID) * GRID;\n\n/** Reading order of a block diagram: what feeds the processor left of it (−1), what it drives right (+1). */\nfunction flowSide(category?: string): number {\n const g = functionGroup(category);\n return g === \"power\" || g === \"io\" ? -1 : g === \"sensor\" || g === \"output\" ? 1 : 0;\n}\n\ninterface Edge {\n a: number;\n b: number;\n w: number;\n}\n\n/**\n * Top-left positions by id for a level of modules. `edges` are the lines\n * between cards (one entry per line; several between two cards weigh more,\n * though less than that many).\n */\nexport function gridLayout(nodes: GridNode[], edges: [string, string][], opts: GridOptions = {}): Record<string, { x: number; y: number }> {\n // cards linked to nothing (a consumable, an adhesive pad, a seal) go in rows under the block, out of the lines' way\n const linked = new Set(edges.filter(([a, b]) => a !== b).flat());\n const loose = nodes.filter((n) => !linked.has(n.id) && !opts.fixed?.[n.id]).sort((a, b) => natural(a.id, b.id));\n if (!loose.length || loose.length === nodes.length) return gridCore(nodes, edges, opts);\n const out = gridCore(\n nodes.filter((n) => !loose.includes(n)),\n edges,\n opts,\n );\n const placed = nodes.filter((n) => out[n.id]).map((n) => ({ ...out[n.id], w: n.w, h: n.h }));\n const left = Math.min(...placed.map((b) => b.x));\n const right = Math.max(...placed.map((b) => b.x + b.w));\n let y = snapUp(Math.max(...placed.map((b) => b.y + b.h)) + GRID_GAP_Y);\n // as many to a row as fit under the block (three at least)\n const gap = GRID_GAP_X / 2;\n const rows: GridNode[][] = [];\n let row: GridNode[] = [];\n let width = 0;\n for (const n of loose) {\n if (row.length >= 3 && width + gap + n.w > right - left) {\n rows.push(row);\n row = [];\n width = 0;\n }\n width += (row.length ? gap : 0) + n.w;\n row.push(n);\n }\n if (row.length) rows.push(row);\n for (const r of rows) {\n const w = r.reduce((s, n) => s + n.w, 0) + gap * (r.length - 1);\n let x = snapTo(left + (right - left - w) / 2);\n for (const n of r) {\n out[n.id] = { x, y };\n x = snapUp(x + n.w + gap);\n }\n y = snapUp(y + Math.max(...r.map((n) => n.h)) + GRID_GAP_Y / 2);\n }\n return out;\n}\n\nfunction gridCore(nodes: GridNode[], edges: [string, string][], opts: GridOptions = {}): Record<string, { x: number; y: number }> {\n const out: Record<string, { x: number; y: number }> = {};\n if (!nodes.length) return out;\n const list = nodes.slice().sort((a, b) => natural(a.id, b.id));\n const index = new Map(list.map((n, i) => [n.id, i]));\n const n = list.length;\n const fixed = opts.fixed ?? {};\n\n // links between two cards, weighted 1 + ln(count)\n const pairCount = new Map<string, number>();\n for (const [a, b] of edges) {\n const i = index.get(a);\n const j = index.get(b);\n if (i === undefined || j === undefined || i === j) continue;\n const key = i < j ? `${i},${j}` : `${j},${i}`;\n pairCount.set(key, (pairCount.get(key) ?? 0) + 1);\n }\n const E: Edge[] = [...pairCount]\n .sort((x, y) => natural(x[0], y[0]))\n .map(([k, c]) => {\n const [a, b] = k.split(\",\").map(Number);\n return { a, b, w: 1 + Math.log(c) };\n });\n const incident: number[][] = list.map(() => []);\n E.forEach((e, k) => {\n incident[e.a].push(k);\n incident[e.b].push(k);\n });\n const degree = list.map((_, i) => incident[i].reduce((s, k) => s + E[k].w, 0));\n\n // the grid: about as many columns as a screen's shape holds for these cards\n const avgW = list.reduce((s, x) => s + x.w, 0) / n + GRID_GAP_X;\n const avgH = list.reduce((s, x) => s + x.h, 0) / n + GRID_GAP_Y;\n const aspect = opts.aspect ?? 1.6;\n let cols = Math.max(1, Math.min(n, Math.round(Math.sqrt((n * aspect * avgH) / avgW))));\n // two or three cards sit side by side\n if (n <= 3) cols = n;\n let rows = Math.ceil(n / cols);\n // a little room to move: one spare cell at least, beyond a handful of cards\n if (n > 4 && cols * rows === n) cols++;\n rows = Math.ceil(n / cols);\n const cells = cols * rows;\n const cW = avgW;\n const cH = avgH;\n\n const cellOf = new Int32Array(n).fill(-1);\n const at = new Int32Array(cells).fill(-1);\n const put = (i: number, c: number) => {\n cellOf[i] = c;\n at[c] = i;\n };\n const cx = (c: number) => c % cols;\n const cy = (c: number) => Math.floor(c / cols);\n\n // ---- cost ----\n const mcu = list.map((x) => functionGroup(x.category) === \"mcu\");\n const side = list.map((x) => flowSide(x.category));\n const edgeCost = (e: Edge): number => {\n const ca = cellOf[e.a];\n const cb = cellOf[e.b];\n if (ca < 0 || cb < 0) return 0;\n const dx = Math.abs(cx(ca) - cx(cb));\n const dy = Math.abs(cy(ca) - cy(cb));\n let c = e.w * (dx * cW + dy * cH);\n // a line that must bend (neither in a row nor a column)\n if (dx && dy) c += e.w * 0.35 * Math.min(dx * cW, dy * cH);\n // cards in the way of a straight line\n if (!dx || !dy) {\n const steps = Math.max(dx, dy);\n const sx = Math.sign(cx(cb) - cx(ca));\n const sy = Math.sign(cy(cb) - cy(ca));\n for (let k = 1; k < steps; k++) if (at[(cy(ca) + sy * k) * cols + cx(ca) + sx * k] >= 0) c += e.w * cW;\n }\n // reading order around a processor\n for (const [m, o] of [[e.a, e.b], [e.b, e.a]] as const) {\n if (!mcu[m] || !side[o]) continue;\n const d = cx(cellOf[o]) - cx(cellOf[m]);\n if (Math.sign(d) !== side[o]) c += e.w * 0.3 * cW;\n }\n return c;\n };\n // straight centre-to-centre lines of two links cross (links that share a card never count)\n const crosses = (e: Edge, f: Edge): boolean => {\n if (e.a === f.a || e.a === f.b || e.b === f.a || e.b === f.b) return false;\n const p = [cellOf[e.a], cellOf[e.b], cellOf[f.a], cellOf[f.b]];\n if (p.some((c) => c < 0)) return false;\n const P = p.map((c) => [cx(c) * cW, cy(c) * cH]);\n const d = (o: number[], q: number[], r: number[]) => (q[0] - o[0]) * (r[1] - o[1]) - (q[1] - o[1]) * (r[0] - o[0]);\n const d1 = d(P[2], P[3], P[0]);\n const d2 = d(P[2], P[3], P[1]);\n const d3 = d(P[0], P[1], P[2]);\n const d4 = d(P[0], P[1], P[3]);\n return ((d1 > 0 && d2 < 0) || (d1 < 0 && d2 > 0)) && ((d3 > 0 && d4 < 0) || (d3 < 0 && d4 > 0));\n };\n const CROSS = 0.9 * cW;\n /** The part of the cost that changes when the cards in `moved` (and the cells `cellsTouched`) change. */\n const localCost = (moved: number[], cellsTouched: number[]): number => {\n const mine = new Set<number>();\n for (const i of moved) if (i >= 0) for (const k of incident[i]) mine.add(k);\n let c = 0;\n for (const k of mine) c += edgeCost(E[k]);\n for (const k of mine)\n for (let f = 0; f < E.length; f++) {\n if (f === k || (mine.has(f) && f < k)) continue;\n if (crosses(E[k], E[f])) c += CROSS * Math.min(E[k].w, E[f].w);\n }\n // other links whose straight line passes the touched cells\n for (let f = 0; f < E.length; f++) {\n if (mine.has(f)) continue;\n const e = E[f];\n const ca = cellOf[e.a];\n const cb = cellOf[e.b];\n if (ca < 0 || cb < 0) continue;\n if (cx(ca) !== cx(cb) && cy(ca) !== cy(cb)) continue;\n for (const t of cellsTouched) {\n const tx = cx(t);\n const ty = cy(t);\n const between =\n (cy(ca) === cy(cb) && ty === cy(ca) && tx > Math.min(cx(ca), cx(cb)) && tx < Math.max(cx(ca), cx(cb))) ||\n (cx(ca) === cx(cb) && tx === cx(ca) && ty > Math.min(cy(ca), cy(cb)) && ty < Math.max(cy(ca), cy(cb)));\n if (between && at[t] >= 0) c += e.w * cW;\n }\n }\n // a card joined to nothing stays near the middle rather than at a far corner\n for (const i of moved) if (i >= 0 && !incident[i].length) c += 0.05 * (Math.abs(cx(cellOf[i]) - (cols - 1) / 2) * cW + Math.abs(cy(cellOf[i]) - (rows - 1) / 2) * cH);\n return c;\n };\n\n // ---- fixed cards: the cell nearest where they are, on a grid anchored on the first of them ----\n const fixedIds = Object.keys(fixed).filter((id) => index.has(id)).sort(natural);\n const locked = new Uint8Array(n);\n const order = list.map((_, i) => i).sort((a, b) => degree[b] - degree[a] || Number(mcu[b]) - Number(mcu[a]) || natural(list[a].id, list[b].id));\n if (fixedIds.length) {\n const centre = (id: string) => ({ x: fixed[id].x + list[index.get(id)!].w / 2, y: fixed[id].y + list[index.get(id)!].h / 2 });\n const a = centre(fixedIds[0]);\n const startX = Math.floor((cols - 1) / 2);\n const startY = Math.floor((rows - 1) / 2);\n for (const id of fixedIds) {\n const p = centre(id);\n const gx = Math.max(0, Math.min(cols - 1, startX + Math.round((p.x - a.x) / cW)));\n const gy = Math.max(0, Math.min(rows - 1, startY + Math.round((p.y - a.y) / cH)));\n // the nearest free cell to that\n let best = -1;\n let bd = Infinity;\n for (let c = 0; c < cells; c++) {\n if (at[c] >= 0) continue;\n const d = Math.abs(cx(c) - gx) + Math.abs(cy(c) - gy);\n if (d < bd) [best, bd] = [c, d];\n }\n if (best >= 0) {\n put(index.get(id)!, best);\n locked[index.get(id)!] = 1;\n }\n }\n }\n\n // ---- the starting arrangement ----\n const free = () => [...Array(cells).keys()].filter((c) => at[c] < 0);\n if (opts.seed && list.some((x) => opts.seed![x.id])) {\n // rows by height, then columns by x, as they were\n const seeded = order.filter((i) => cellOf[i] < 0).sort((a, b) => (opts.seed![list[a].id]?.y ?? Infinity) - (opts.seed![list[b].id]?.y ?? Infinity) || natural(list[a].id, list[b].id));\n const slots = free();\n const byRow = new Map<number, number[]>();\n for (const c of slots) byRow.set(cy(c), [...(byRow.get(cy(c)) ?? []), c]);\n let k = 0;\n for (const r of [...byRow.keys()].sort((a, b) => a - b)) {\n const row = byRow.get(r)!;\n const take = seeded.slice(k, k + row.length).sort((a, b) => (opts.seed![list[a].id]?.x ?? Infinity) - (opts.seed![list[b].id]?.x ?? Infinity) || natural(list[a].id, list[b].id));\n take.forEach((i, j) => put(i, row[j]));\n k += take.length;\n }\n } else {\n // the hub in the middle, then each card at the best free cell, strongest joined first\n const placed = new Set<number>(order.filter((i) => cellOf[i] >= 0));\n const weightTo = (i: number) => incident[i].reduce((s, k) => s + (placed.has(E[k].a === i ? E[k].b : E[k].a) ? E[k].w : 0), 0);\n while (placed.size < n) {\n let pick = -1;\n let best = -Infinity;\n for (const i of order) {\n if (placed.has(i)) continue;\n const w = weightTo(i);\n if (w > best) [pick, best] = [i, w];\n }\n if (!placed.size || best <= 0) {\n // nothing placed it joins: the middle (the hub), or the free cell nearest the middle\n const mid = Math.floor((rows - 1) / 2) * cols + Math.floor((cols - 1) / 2);\n const c = free().sort((a, b) => Math.abs(cx(a) - cx(mid)) + Math.abs(cy(a) - cy(mid)) - (Math.abs(cx(b) - cx(mid)) + Math.abs(cy(b) - cy(mid))) || a - b)[0];\n put(pick, c);\n } else {\n let bc = -1;\n let bv = Infinity;\n for (const c of free()) {\n put(pick, c);\n const v = localCost([pick], [c]);\n at[c] = -1;\n cellOf[pick] = -1;\n if (v < bv - 1e-9) [bc, bv] = [c, v];\n }\n put(pick, bc);\n }\n placed.add(pick);\n }\n }\n\n // ---- swaps (and moves to empty cells) while they help ----\n for (let pass = 0; pass < 24; pass++) {\n let improved = false;\n for (let c1 = 0; c1 < cells; c1++)\n for (let c2 = c1 + 1; c2 < cells; c2++) {\n const i = at[c1];\n const j = at[c2];\n if (i < 0 && j < 0) continue;\n if ((i >= 0 && locked[i]) || (j >= 0 && locked[j])) continue;\n const before = localCost([i, j], [c1, c2]);\n at[c1] = j;\n at[c2] = i;\n if (i >= 0) cellOf[i] = c2;\n if (j >= 0) cellOf[j] = c1;\n const after = localCost([i, j], [c1, c2]);\n if (after < before - 1e-6) improved = true;\n else {\n at[c1] = i;\n at[c2] = j;\n if (i >= 0) cellOf[i] = c1;\n if (j >= 0) cellOf[j] = c2;\n }\n }\n if (!improved) break;\n }\n\n // ---- positions: empty rows and columns dropped, each column as wide and each row as tall as its largest card ----\n const usedCols = [...new Set([...cellOf].map(cx))].sort((a, b) => a - b);\n const usedRows = [...new Set([...cellOf].map(cy))].sort((a, b) => a - b);\n const colW = usedCols.map((c) => Math.max(...list.filter((_, i) => cx(cellOf[i]) === c).map((x) => x.w)));\n const rowH = usedRows.map((r) => Math.max(...list.filter((_, i) => cy(cellOf[i]) === r).map((x) => x.h)));\n const colX: number[] = [];\n let x = 0;\n colW.forEach((w) => {\n colX.push(x);\n x = snapUp(x + w + GRID_GAP_X);\n });\n const rowY: number[] = [];\n let y = 0;\n rowH.forEach((h) => {\n rowY.push(y);\n y = snapUp(y + h + GRID_GAP_Y);\n });\n list.forEach((node, i) => {\n const ci = usedCols.indexOf(cx(cellOf[i]));\n const ri = usedRows.indexOf(cy(cellOf[i]));\n out[node.id] = { x: snapTo(colX[ci] + (colW[ci] - node.w) / 2), y: snapTo(rowY[ri] + (rowH[ri] - node.h) / 2) };\n });\n\n // fixed cards where they were: the grid moved so the first sits there, then each where it was\n if (fixedIds.length) {\n const first = fixedIds[0];\n const dx = fixed[first].x - out[first].x;\n const dy = fixed[first].y - out[first].y;\n for (const id of Object.keys(out)) out[id] = { x: out[id].x + dx, y: out[id].y + dy };\n for (const id of fixedIds) out[id] = { ...fixed[id] };\n // a card the move put on a fixed one goes to the nearest free spot\n const settled = fixedIds.map((id) => ({ ...out[id], w: list[index.get(id)!].w, h: list[index.get(id)!].h }));\n for (const i of order) {\n const node = list[i];\n if (locked[i]) continue;\n const b = { ...out[node.id], w: node.w, h: node.h };\n if (settled.some((o) => hits(b, o, GRID_GAP_Y / 4))) {\n const spot = freeSpot([b.x + b.w / 2, b.y + b.h / 2], b.w, b.h, settled, { x: GRID_GAP_X / 2, y: GRID_GAP_Y / 2 });\n out[node.id] = spot;\n b.x = spot.x;\n b.y = spot.y;\n }\n settled.push(b);\n }\n }\n return out;\n}\n","/**\n * Layout: node boxes, port placement, and link routes for one level.\n * Layout data lives outside UHD (design D3, D6); a level can ship a hand\n * layout (from the bundle's display hints) and the user's drags override it.\n */\nimport { CARD_W, cardHeight, cardInsets, cardWidth } from \"./card-body\";\nimport type { ViewLink, ViewModel, ViewNode, ViewPort } from \"../model/types\";\nimport { route, type Pt, type Side } from \"../canvas/routing\";\nimport { GridRouter, GRID, snap } from \"./router\";\nimport { at, clearOfBends, lengths } from \"../canvas/geometry\";\nimport type { LinkLayout } from \"../api\";\nimport { boardLayout, freeSpot, hits } from \"./board-layout\";\nimport { gridLayout } from \"./module-layout\";\n\n/** Distance kept between a corner and anything placed on a link (handles, toggles). */\nexport const BEND_CLEAR = 28;\n/** How far a link keeps its label from a corner (LinkEdge: the corner radius, half a toggle, 4 px). */\nconst LABEL_CLEAR = 24;\n\nexport interface Box {\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\n/** A link's hand layout: part of the host contract (src/api.ts). */\nexport type { LinkLayout };\n\nexport interface LevelLayout {\n /** Top-level nodes: absolute. Nodes inside a container: relative to it. */\n nodes: Record<string, Partial<Box>>;\n /** Port side overrides keyed \"node|port\". */\n ports?: Record<string, Side>;\n links?: Record<string, LinkLayout>;\n}\n\nexport interface PlacedPort {\n node: string;\n port: ViewPort;\n side: Side;\n /** Absolute position on the node outline. */\n x: number;\n y: number;\n /** Colour key: the link that decides this port's classification colour. */\n links: ViewLink[];\n}\n\nexport interface PortGroup {\n protocol: string;\n domain: string;\n count: number;\n}\n\nexport interface ComputedLayout {\n boxes: Record<string, Box>;\n ports: Record<string, PlacedPort>;\n /** Unlinked ports summarised per node (design D6: \"UART ×4\"). */\n groups: Record<string, PortGroup[]>;\n routes: Record<string, Pt[]>;\n /** Label anchor per link (absent: route too short to label). */\n labels: Record<string, Pt>;\n /** Label + toggle position as an arc length along the route. */\n labelAt: Record<string, number>;\n /** Harness region span along the route (arc lengths), for links that run through one. */\n runs: Record<string, [number, number]>;\n /** Pinned waypoints per link, and the automatic ones (the router's own bends). */\n pins: Record<string, Pt[]>;\n bends: Record<string, Pt[]>;\n /** Links whose label (and expansion point) the user or the display file placed. */\n labelFixed: Record<string, boolean>;\n /** The display file's and the user's label and tab placement per link, merged. */\n edits: Record<string, LinkLayout>;\n}\n\nexport const portKey = (node: string, port: string) => `${node}|${port}`;\n\nconst PORT_PITCH = 22;\n\n/** A card's size before it is placed: as wide as the labels of its linked interfaces (`labels`) need. */\nfunction defaultSize(node: ViewNode, visiblePorts: number, labels: readonly string[] = []): { w: number; h: number } {\n if (node.sheetPort) return { w: 150, h: 30 };\n if (node.kind === \"harness\") return { w: 150, h: Math.max(30, 14 + (visiblePorts / 2) * 16) };\n // a net junction: as wide as its name, as tall as its busiest side needs (grown once ports have sides)\n if (node.kind === \"net\") return { w: Math.max(64, node.label.length * 8 + 40), h: 32 };\n if (node.shape === \"circle\") return /prop/i.test(node.label) ? { w: 60, h: 60 } : { w: 78, h: 78 };\n const perSide = Math.ceil(visiblePorts / 2);\n return { w: labels.length ? cardWidth(labels) : CARD_W, h: Math.max(84, 40 + perSide * PORT_PITCH) };\n}\n\nfunction center(b: Box): Pt {\n return [b.x + b.w / 2, b.y + b.h / 2];\n}\n\nfunction sideFacing(from: Box, to: Pt): Side {\n const [cx, cy] = center(from);\n const dx = to[0] - cx;\n const dy = to[1] - cy;\n // normalise by the box aspect so wide boxes prefer top/bottom less eagerly\n const nx = dx / (from.w / 2 + 40);\n const ny = dy / (from.h / 2 + 40);\n if (Math.abs(nx) >= Math.abs(ny)) return dx >= 0 ? \"right\" : \"left\";\n return dy >= 0 ? \"bottom\" : \"top\";\n}\n\n/** How an automatic layout starts (PB-1007): cards that keep their places, and an earlier arrangement to keep. */\nexport interface ArrangeOptions {\n /** Top-level cards that stay where they are (top-left). */\n fixed?: Record<string, { x: number; y: number }>;\n /** Each top-level card's centre in an earlier layout: the arrangement to start from. */\n seed?: Record<string, { x: number; y: number }>;\n /** The old default (one row), for comparing against. */\n legacy?: boolean;\n}\n\n/**\n * Auto layout for levels without a hand layout: modules in a grid shaped like\n * a screen, each beside what it connects to (module-layout.ts), and each sheet\n * port (the drilled-into module's boundary) on the canvas edge nearest the\n * child it exposes, stacked beside it. A level with nets is laid out as a\n * board (board-layout.ts).\n */\nfunction autoPositions(vm: ViewModel, sizes: Record<string, { w: number; h: number }>, opts: ArrangeOptions = {}): Record<string, Box> {\n const top = vm.nodes.filter((n) => !n.parent && !n.sheetPort);\n const sheets = vm.nodes.filter((n) => n.sheetPort);\n if (top.some((n) => n.kind === \"net\")) {\n const boxes = netPositions(vm, top, sheets, sizes);\n for (const [id, p] of Object.entries(opts.fixed ?? {})) if (boxes[id]) Object.assign(boxes[id], p);\n return boxes;\n }\n if (opts.legacy) return rowPositions(vm, sizes);\n const ids = new Set(top.map((n) => n.id));\n const topOf = (id: string) => (ids.has(id) ? id : [...ids].find((t) => id.startsWith(`${t}/`)));\n const edges: [string, string][] = [];\n for (const l of vm.links) {\n if (l.passThrough || l.ground) continue;\n const a = topOf(l.source.node);\n const b = topOf(l.target.node);\n if (a && b && a !== b) edges.push([a, b]);\n }\n // a block with no category (a concept's placeholder) gets the role its links give it: one that mostly\n // supplies power feeds from the left, and the busiest block is the hub, so the reading order still holds\n const lines = vm.links.filter((l) => !l.passThrough && !l.ground);\n const busiest = top\n .map((n) => ({ id: n.id, k: lines.filter((l) => topOf(l.source.node) === n.id || topOf(l.target.node) === n.id).length }))\n .sort((a, b) => b.k - a.k || a.id.localeCompare(b.id))[0]?.id;\n const hasHub = top.some((n) => /^(microcontroller|processor|compute|fpga|soc)\\b/.test(n.category ?? \"\"));\n const roleOf = (n: ViewNode): string | undefined => {\n if (n.category) return n.category;\n if (!hasHub && n.id === busiest) return \"microcontroller\";\n const mine = lines.filter((l) => topOf(l.source.node) === n.id || topOf(l.target.node) === n.id);\n return mine.length && mine.filter((l) => l.domain === \"power\" || /power/i.test(l.protocol)).length * 2 > mine.length ? \"power\" : undefined;\n };\n const at = gridLayout(\n top.map((n) => ({ id: n.id, ...sizes[n.id], category: roleOf(n) })),\n edges,\n { fixed: opts.fixed, seed: opts.seed },\n );\n const x0 = sheets.length ? 400 : 60;\n const y0 = 100;\n const boxes: Record<string, Box> = {};\n const fixed = opts.fixed ?? {};\n for (const n of top) boxes[n.id] = fixed[n.id] ? { ...fixed[n.id], ...sizes[n.id] } : { x: at[n.id].x + (Object.keys(fixed).length ? 0 : x0), y: at[n.id].y + (Object.keys(fixed).length ? 0 : y0), ...sizes[n.id] };\n placeSheets(boxes, sheets, sizes, y0);\n return boxes;\n}\n\n/** The layout before PB-1007: modules in one centred row (kept to measure against). */\nfunction rowPositions(vm: ViewModel, sizes: Record<string, { w: number; h: number }>): Record<string, Box> {\n const boxes: Record<string, Box> = {};\n const top = vm.nodes.filter((n) => !n.parent && !n.sheetPort);\n const sheets = vm.nodes.filter((n) => n.sheetPort);\n const gapX = 300;\n const rowY = 140;\n let x = sheets.length ? 460 : 60;\n for (const n of top) {\n const s = sizes[n.id];\n boxes[n.id] = { x, y: rowY, ...s };\n x += s.w + gapX;\n }\n const rowRight = x - gapX;\n const mid = (sheets.length ? 460 : 60) + (rowRight - (sheets.length ? 460 : 60)) / 2;\n const columns: Record<\"left\" | \"right\", ViewNode[]> = { left: [], right: [] };\n for (const sheet of sheets) {\n const child = sheet.ports[0]?.exported?.child;\n const b = child ? boxes[child] : undefined;\n columns[b && b.x + b.w / 2 > mid ? \"right\" : \"left\"].push(sheet);\n }\n const rowH = Math.max(...top.map((n) => sizes[n.id].h), 100);\n for (const side of [\"left\", \"right\"] as const) {\n const col = columns[side];\n const pitch = 54;\n const y0 = rowY + rowH / 2 - ((col.length - 1) * pitch) / 2;\n col.forEach((n, i) => {\n const s = sizes[n.id];\n boxes[n.id] = { x: side === \"left\" ? 60 : rowRight + 180, y: y0 + i * pitch, ...s };\n });\n }\n return boxes;\n}\n\n/**\n * A level with nets (a board): components grouped by function and junctions\n * beside what they join (board-layout.ts), and each sheet port on the left\n * or right edge level with the child it exposes.\n */\nfunction netPositions(vm: ViewModel, top: ViewNode[], sheets: ViewNode[], sizes: Record<string, { w: number; h: number }>): Record<string, Box> {\n const ids = new Set(top.map((n) => n.id));\n const edges = vm.links\n .filter((l) => !l.passThrough && !l.ground && ids.has(l.source.node) && ids.has(l.target.node))\n .map((l) => [l.source.node, l.target.node] as [string, string]);\n const degree = new Map<string, number>();\n for (const [a, b] of edges) for (const id of [a, b]) degree.set(id, (degree.get(id) ?? 0) + 1);\n // a junction grows to fit its ports once they have sides: lay it out at the size it will likely have\n const planned = (n: ViewNode) => (n.kind === \"net\" ? { w: sizes[n.id].w, h: Math.max(sizes[n.id].h, (Math.ceil((degree.get(n.id) ?? 0) / 2) + 1) * GRID) } : sizes[n.id]);\n const grows = (n: ViewNode) => n.kind !== \"net\" && n.shape !== \"circle\";\n const isNet = new Set(top.filter((n) => n.kind === \"net\").map((n) => n.id));\n const otherPorts = (id: string) =>\n new Set(\n vm.links\n .filter((l) => !l.ground && (l.source.node === id || l.target.node === id) && !isNet.has(l.source.node) && !isNet.has(l.target.node))\n .map((l) => (l.source.node === id ? l.source.port : l.target.port)),\n ).size;\n const at = boardLayout(\n top.map((n) => ({\n id: n.id,\n ...planned(n),\n net: n.kind === \"net\",\n ...(n.tapOf ? { tapOf: n.tapOf } : {}),\n category: n.category,\n label: n.label,\n ...(grows(n) ? { heightFor: (k: number) => Math.ceil((44 + k * PORT_PITCH) / GRID) * GRID, otherPorts: otherPorts(n.id) } : {}),\n })),\n edges,\n );\n const x0 = sheets.length ? 400 : 60;\n const y0 = 100;\n const boxes: Record<string, Box> = {};\n for (const n of top) boxes[n.id] = { x: at[n.id].x + x0, y: at[n.id].y + y0, ...sizes[n.id] };\n placeSheets(boxes, sheets, sizes, y0);\n return boxes;\n}\n\n/** Sheet ports (the drilled-into module's boundary) in a column on the left or right edge, level with the child each exposes. */\nfunction placeSheets(boxes: Record<string, Box>, sheets: ViewNode[], sizes: Record<string, { w: number; h: number }>, y0: number) {\n const placed = Object.values(boxes);\n if (!sheets.length || !placed.length) return;\n const minX = Math.min(...placed.map((b) => b.x));\n const maxX = Math.max(...placed.map((b) => b.x + b.w));\n const mid = (minX + maxX) / 2;\n const columns: Record<\"left\" | \"right\", { node: ViewNode; y: number }[]> = { left: [], right: [] };\n for (const sheet of sheets) {\n const b = boxes[sheet.ports[0]?.exported?.child ?? \"\"];\n const side = b && b.x + b.w / 2 > mid ? \"right\" : \"left\";\n columns[side].push({ node: sheet, y: b ? b.y + b.h / 2 - sizes[sheet.id].h / 2 : y0 });\n }\n for (const side of [\"left\", \"right\"] as const) {\n let last = -Infinity;\n for (const { node, y } of columns[side].sort((a, b) => a.y - b.y)) {\n const s = sizes[node.id];\n const top = Math.max(y, last + 54);\n boxes[node.id] = { x: side === \"left\" ? minX - 340 : maxX + 180, y: top, ...s };\n last = top;\n }\n }\n}\n\n/**\n * Positions for the nodes a hand layout does not name (a part added since\n * the layout was saved, or the junctions of a layout that placed only the\n * components): each at the free spot nearest the nodes it is linked to,\n * sheet ports on the edges. Top-level nodes only; absolute.\n */\nfunction fillMissing(vm: ViewModel, hand: LevelLayout, sizes: Record<string, { w: number; h: number }>): Record<string, Box> {\n const top = vm.nodes.filter((n) => !n.parent);\n const missing = top.filter((n) => !hand.nodes[n.id] || hand.nodes[n.id].x === undefined || hand.nodes[n.id].y === undefined);\n if (!missing.length) return {};\n const boxes: Record<string, Box> = {};\n for (const n of top) if (!missing.includes(n)) boxes[n.id] = { x: hand.nodes[n.id].x!, y: hand.nodes[n.id].y!, ...sizes[n.id] };\n const known = Object.values(boxes);\n const right = known.length ? Math.max(...known.map((b) => b.x + b.w)) : 60;\n const bottom = known.length ? Math.max(...known.map((b) => b.y + b.h)) : 60;\n const neighbours = (id: string) =>\n vm.links\n .filter((l) => !l.passThrough && !l.ground && (l.source.node === id || l.target.node === id))\n .map((l) => (l.source.node === id ? l.target.node : l.source.node))\n .map((o) => o.split(\"/\")[0])\n .filter((o) => boxes[o]);\n const out: Record<string, Box> = {};\n // most-connected first, so a junction lands among its members before a lone part takes the spot\n const order = missing.filter((n) => !n.sheetPort).sort((a, b) => neighbours(b.id).length - neighbours(a.id).length || a.id.localeCompare(b.id));\n for (const n of order) {\n const ns = neighbours(n.id);\n const s = sizes[n.id];\n const ideal: [number, number] = ns.length\n ? [ns.reduce((t, o) => t + boxes[o].x + boxes[o].w / 2, 0) / ns.length, ns.reduce((t, o) => t + boxes[o].y + boxes[o].h / 2, 0) / ns.length]\n : [right + 120 + s.w / 2, bottom + 80];\n const at = freeSpot(ideal, s.w, s.h, Object.values(boxes), { x: 40, y: 24 });\n boxes[n.id] = out[n.id] = { ...at, ...s };\n }\n const sheets = missing.filter((n) => n.sheetPort);\n if (sheets.length) {\n const withSheets: Record<string, Box> = { ...boxes };\n placeSheets(withSheets, sheets, sizes, 100);\n for (const n of sheets) out[n.id] = withSheets[n.id];\n }\n return out;\n}\n\n/** Room kept inside a container expanded in place: left and right of its modules, under its label, and below them (where its links run). */\nconst CONTAINER_PAD = { left: 48, top: 64, right: 48, bottom: 48 };\n\n/**\n * A module expanded in place whose children the display file does not place\n * (PB-897): the children are laid out as their own level would be (a row, or\n * a board's clusters and junctions), inside the container, and the container\n * takes the size that holds them with room for their links. Deepest\n * containers first, so one that holds another is laid out around its size.\n * Returns the children's positions relative to their container; `sizes` gets\n * the containers' sizes. A container the display file sizes, or whose\n * children it places, is left as it says.\n */\nfunction containerLayouts(vm: ViewModel, hand: LevelLayout | undefined, sizes: Record<string, { w: number; h: number }>, arrange: ArrangeOptions = {}): Record<string, { x: number; y: number }> {\n const rel: Record<string, { x: number; y: number }> = {};\n const depth = (id: string) => {\n let d = 0;\n for (let n = vm.nodes.find((x) => x.id === id); n?.parent; n = vm.nodes.find((x) => x.id === n!.parent)) d++;\n return d;\n };\n const containers = vm.nodes.filter((n) => n.expanded).sort((a, b) => depth(b.id) - depth(a.id));\n for (const c of containers) {\n const kids = vm.nodes.filter((n) => n.parent === c.id);\n if (!kids.length) continue;\n const placed = (n: ViewNode) => hand?.nodes[n.id]?.x !== undefined && hand?.nodes[n.id]?.y !== undefined;\n const missing = kids.filter((n) => !placed(n));\n if (!missing.length) continue;\n const ids = new Set(kids.map((k) => k.id));\n if (missing.length === kids.length) {\n // none placed: the level's own automatic layout, moved into the container\n const sub: ViewModel = { ...vm, nodes: kids.map((k) => ({ ...k, parent: undefined })), links: vm.links.filter((l) => ids.has(l.source.node) && ids.has(l.target.node)) };\n const at = autoPositions(sub, sizes, { legacy: arrange.legacy });\n const minX = Math.min(...kids.map((k) => at[k.id].x));\n const minY = Math.min(...kids.map((k) => at[k.id].y));\n for (const k of kids) rel[k.id] = { x: snap(at[k.id].x - minX + CONTAINER_PAD.left), y: snap(at[k.id].y - minY + CONTAINER_PAD.top) };\n } else {\n // some placed (a part added since the layout was saved): the others at the free spot nearest what they are linked to\n const boxes: Record<string, Box> = {};\n for (const k of kids) if (placed(k)) boxes[k.id] = { x: hand!.nodes[k.id].x!, y: hand!.nodes[k.id].y!, ...sizes[k.id] };\n const neighbours = (id: string) =>\n vm.links\n .filter((l) => !l.ground && (l.source.node === id || l.target.node === id))\n .map((l) => (l.source.node === id ? l.target.node : l.source.node))\n .filter((o) => boxes[o]);\n for (const k of missing.sort((a, b) => neighbours(b.id).length - neighbours(a.id).length || a.id.localeCompare(b.id))) {\n const ns = neighbours(k.id);\n const known = Object.values(boxes);\n const s = sizes[k.id];\n const ideal: [number, number] = ns.length\n ? [ns.reduce((t, o) => t + boxes[o].x + boxes[o].w / 2, 0) / ns.length, ns.reduce((t, o) => t + boxes[o].y + boxes[o].h / 2, 0) / ns.length]\n : [Math.max(...known.map((b) => b.x + b.w)) + 80 + s.w / 2, CONTAINER_PAD.top + s.h / 2];\n const spot = freeSpot(ideal, s.w, s.h, known, { x: 40, y: 24 });\n // never left of, or above, the container's own padding\n const at = { x: Math.max(CONTAINER_PAD.left, spot.x), y: Math.max(CONTAINER_PAD.top, spot.y) };\n boxes[k.id] = { ...at, ...s };\n rel[k.id] = { x: snap(at.x), y: snap(at.y) };\n }\n }\n if (hand?.nodes[c.id]?.w) continue;\n const right = Math.max(...kids.map((k) => (rel[k.id]?.x ?? hand?.nodes[k.id]?.x ?? 0) + sizes[k.id].w));\n const bottom = Math.max(...kids.map((k) => (rel[k.id]?.y ?? hand?.nodes[k.id]?.y ?? 0) + sizes[k.id].h));\n const up = (v: number) => Math.ceil(v / GRID) * GRID;\n sizes[c.id] = { w: up(Math.max(sizes[c.id].w, right + CONTAINER_PAD.right)), h: up(Math.max(sizes[c.id].h, bottom + CONTAINER_PAD.bottom)) };\n }\n return rel;\n}\n\n/** The container (a module expanded in place) that holds both ends of a link, if one does: the innermost. */\nfunction sharedContainer(vm: ViewModel, byId: Map<string, ViewNode>, a: string, b: string): ViewNode | undefined {\n const chain = (id: string) => {\n const out: string[] = [];\n const self = byId.get(id);\n // a container's own boundary port is on its outline: the line from it inward is inside it\n if (self?.expanded) out.push(id);\n for (let p = self?.parent; p; p = byId.get(p)?.parent) out.push(p);\n return out;\n };\n const inB = new Set(chain(b));\n const id = chain(a).find((x) => inB.has(x));\n return id ? byId.get(id) : undefined;\n}\n\n/** Nearest free grid position between lo and hi (exclusive) on one side of a card. */\nfunction gridSlot(v: number, lo: number, hi: number, used: Map<string, Set<number>>, key: string): number {\n const taken = used.get(key) ?? new Set<number>();\n used.set(key, taken);\n const base = snap(v);\n for (let k = 0; k < 64; k++) {\n for (const c of k === 0 ? [base] : [base + k * GRID, base - k * GRID]) {\n if (c > lo && c < hi && !taken.has(c)) {\n taken.add(c);\n return c;\n }\n }\n }\n return v;\n}\n\n/**\n * A drag in progress: only the links touching what moves are rerouted, around\n * the routes the other links already have; everything is rerouted once the\n * drag ends. Keeps dragging a module or a waypoint at frame rate.\n */\nexport interface LiveLayout {\n previous: ComputedLayout;\n /** Nodes being dragged (their children move with them). */\n nodes?: Set<string>;\n /** Links whose waypoints are being dragged. */\n links?: Set<string>;\n}\n\nfunction linkedPortsOf(vm: ViewModel): Map<string, ViewLink[]> {\n const linkedPorts = new Map<string, ViewLink[]>();\n for (const link of vm.links) {\n for (const end of [link.source, link.target]) {\n const key = portKey(end.node, end.port);\n linkedPorts.set(key, [...(linkedPorts.get(key) ?? []), link]);\n }\n }\n return linkedPorts;\n}\n\n/** Each card's size before it is placed (a hand size wins), and the cards that grew wider than plain for their labels. */\nfunction baseSizes(vm: ViewModel, hand: LevelLayout | undefined, linkedPorts = linkedPortsOf(vm)) {\n const sizes: Record<string, { w: number; h: number }> = {};\n const up = (v: number) => Math.ceil(v / GRID) * GRID;\n /** Cards that grew wider than the plain card for their labels, with the plain width. */\n const grown = new Map<string, number>();\n for (const node of vm.nodes) {\n const linked = node.ports.filter((p) => linkedPorts.has(portKey(node.id, p.id)));\n const hand0 = hand?.nodes[node.id];\n // a card is as wide as the labels of its linked interfaces need, up to a limit (card-body.ts)\n const d = defaultSize(node, linked.length, linked.map((p) => p.name));\n const plain = defaultSize(node, linked.length);\n sizes[node.id] = { w: up(hand0?.w ?? d.w), h: up(hand0?.h ?? d.h) };\n if (!hand0?.w && sizes[node.id].w > up(plain.w)) grown.set(node.id, up(plain.w));\n }\n return { sizes, grown };\n}\n\n/**\n * The automatic layout of a level as a hand layout (PB-1007, for a host that\n * writes it to the display file): top-level nodes absolute, nodes inside an\n * expanded module relative to it. `fixed` cards keep their places; a `seed`\n * keeps an earlier arrangement where it can.\n */\nexport function arrangeLevel(vm: ViewModel, opts: ArrangeOptions = {}, keepSizes?: LevelLayout): LevelLayout {\n // sizes set by hand (`keepSizes`) are kept; the places are all new\n const sized: LevelLayout | undefined = keepSizes && {\n nodes: Object.fromEntries(Object.entries(keepSizes.nodes).flatMap(([id, n]) => (n.w !== undefined || n.h !== undefined ? [[id, { ...(n.w !== undefined ? { w: n.w } : {}), ...(n.h !== undefined ? { h: n.h } : {}) }]] : []))),\n };\n const { sizes } = baseSizes(vm, sized);\n const inner = containerLayouts(vm, sized, sizes, opts);\n const boxes = autoPositions(vm, sizes, opts);\n const nodes: LevelLayout[\"nodes\"] = {};\n for (const n of vm.nodes) {\n if (n.tapOf) continue;\n const p = n.parent ? inner[n.id] : boxes[n.id];\n if (p) nodes[n.id] = { x: snap(p.x), y: snap(p.y) };\n }\n return { nodes };\n}\n\nexport function computeLayout(\n vm: ViewModel,\n hand: LevelLayout | undefined,\n overrides: Record<string, { x: number; y: number }>,\n showGrounds: boolean,\n linkOverrides?: Record<string, LinkLayout>,\n live?: LiveLayout,\n arrange?: ArrangeOptions,\n): ComputedLayout {\n const linkedPorts = linkedPortsOf(vm);\n const up = (v: number) => Math.ceil(v / GRID) * GRID;\n const { sizes, grown } = baseSizes(vm, hand, linkedPorts);\n // a level the display file lays out placed its cards for the plain width: there a card grows only\n // into the room its neighbours on the right leave (three grid steps stay clear for the lines between them)\n if (hand) {\n for (const [id, plain] of grown) {\n const at = hand.nodes[id];\n const node = vm.nodes.find((n) => n.id === id)!;\n if (at?.x === undefined || at.y === undefined) continue;\n let room = Infinity;\n for (const other of vm.nodes) {\n const o = hand.nodes[other.id];\n if (other.id === id || other.parent !== node.parent || o?.x === undefined || o.y === undefined) continue;\n const oh = sizes[other.id].h;\n const apart = o.y >= at.y + sizes[id].h + GRID || o.y + oh + GRID <= at.y;\n if (!apart && o.x >= at.x + plain) room = Math.min(room, o.x - 3 * GRID - at.x);\n }\n sizes[id].w = Math.max(plain, Math.min(sizes[id].w, Math.floor(room / GRID) * GRID));\n }\n }\n\n // modules expanded in place: their children's places inside them, and the size that holds them\n const collapsed: Record<string, { w: number; h: number }> = {};\n for (const n of vm.nodes) if (n.expanded) collapsed[n.id] = { ...sizes[n.id] };\n const inner = containerLayouts(vm, hand, sizes, arrange);\n\n // positions (absolute)\n const auto = hand ? fillMissing(vm, hand, sizes) : autoPositions(vm, sizes, arrange);\n // a hand layout places the cards for their collapsed sizes: one that grew when expanded in place\n // makes room, moving the cards beside and below it by what it grew (not the ones the user dragged)\n const shift: Record<string, { x: number; y: number }> = {};\n if (hand) {\n for (const c of vm.nodes.filter((n) => n.expanded && !n.parent && !hand.nodes[n.id]?.w)) {\n const at = hand.nodes[c.id] ?? auto[c.id];\n if (at?.x === undefined || at?.y === undefined) continue;\n const was = collapsed[c.id];\n const grewX = sizes[c.id].w - was.w;\n const grewY = sizes[c.id].h - was.h;\n if (grewX <= 0 && grewY <= 0) continue;\n for (const n of vm.nodes) {\n if (n === c || n.parent || overrides[n.id]) continue;\n const p = hand.nodes[n.id] ?? auto[n.id];\n if (p?.x === undefined || p?.y === undefined) continue;\n const s = (shift[n.id] ??= { x: 0, y: 0 });\n // beside it (overlapping its rows) and to its right: pushed right; below it: pushed down\n const rows = p.y < at.y! + sizes[c.id].h && p.y + sizes[n.id].h > at.y!;\n if (grewX > 0 && rows && p.x >= at.x! + was.w) s.x += grewX;\n else if (grewY > 0 && p.y >= at.y! + was.h && p.x < at.x! + sizes[c.id].w && p.x + sizes[n.id].w > at.x!) s.y += grewY;\n }\n }\n }\n const boxes: Record<string, Box> = {};\n const place = (node: ViewNode) => {\n if (boxes[node.id]) return;\n const own = hand?.nodes[node.id];\n const size = sizes[node.id];\n let x = (own?.x ?? inner[node.id]?.x ?? auto[node.id]?.x ?? 0) + (shift[node.id]?.x ?? 0);\n let y = (own?.y ?? inner[node.id]?.y ?? auto[node.id]?.y ?? 0) + (shift[node.id]?.y ?? 0);\n if (node.parent) {\n const parent = vm.nodes.find((n) => n.id === node.parent)!;\n place(parent);\n const p = boxes[parent.id];\n x += p.x;\n y += p.y;\n }\n const o = overrides[node.id];\n if (o) {\n x = o.x;\n y = o.y;\n }\n if (node.parent) {\n // a module stays inside its container: it grows to the right and down, never to the left or above its label\n const p = boxes[node.parent];\n x = Math.max(x, p.x + GRID);\n y = Math.max(y, p.y + 2 * GRID);\n }\n boxes[node.id] = { x: snap(x), y: snap(y), ...size };\n };\n // containers without a hand size wrap their children\n for (const node of vm.nodes) place(node);\n const kidsOf = (id: string) => vm.nodes.filter((n) => n.parent === id);\n const wrapContainers = () => {\n // a size the display file gives is the least it draws at: it still holds its children (PB-1007)\n for (const node of vm.nodes.filter((n) => n.expanded)) {\n const kids = vm.nodes.filter((n) => n.parent === node.id).map((n) => boxes[n.id]);\n if (!kids.length) continue;\n const b = boxes[node.id];\n const maxX = Math.max(...kids.map((k) => k.x + k.w));\n const maxY = Math.max(...kids.map((k) => k.y + k.h));\n // a container laid out here keeps room for its links around its modules; one the display file lays out keeps its tighter wrap\n const laid = kidsOf(node.id).some((k) => inner[k.id]);\n b.w = Math.ceil(Math.max(b.w, maxX - b.x + (laid ? CONTAINER_PAD.right : 28)) / GRID) * GRID;\n b.h = Math.ceil(Math.max(b.h, maxY - b.y + (laid ? CONTAINER_PAD.bottom : 24)) / GRID) * GRID;\n }\n };\n wrapContainers();\n\n // port sides\n const ports: Record<string, PlacedPort> = {};\n const groups: Record<string, PortGroup[]> = {};\n const bySide = new Map<string, { key: string; order: number }[]>();\n\n for (const node of vm.nodes) {\n const box = boxes[node.id];\n const hidden = new Map<string, PortGroup>();\n for (const port of node.ports) {\n const key = portKey(node.id, port.id);\n const links = linkedPorts.get(key);\n if (!links) {\n const g = hidden.get(port.protocol) ?? { protocol: port.protocol, domain: port.domain, count: 0 };\n g.count++;\n hidden.set(port.protocol, g);\n continue;\n }\n // counterpart: prefer an external (non pass-through) link for boundary ports\n const external = links.find((l) => !l.passThrough) ?? links[0];\n const other = external.source.node === node.id && external.source.port === port.id ? external.target : external.source;\n const otherBox = boxes[other.node];\n const target: Pt = otherBox ? [...center(otherBox)] : [...center(box)];\n const inside = otherBox && node.expanded && other.node.startsWith(`${node.id}/`);\n if (node.parent && other.node === node.parent) {\n const parentPort = ports[portKey(other.node, other.port)];\n if (parentPort) {\n const [cx, cy] = center(box);\n const far = 400;\n const out: Record<Side, Pt> = { left: [cx - far, cy], right: [cx + far, cy], top: [cx, cy - far], bottom: [cx, cy + far] };\n target[0] = out[parentPort.side][0];\n target[1] = out[parentPort.side][1];\n }\n }\n // a line to or from a net junction leaves its card sideways, toward the junction's channel (a schematic's pins)\n const otherNode = vm.nodes.find((n) => n.id === other.node);\n const sideways = !node.parent && !node.expanded && !otherNode?.expanded && (node.kind === \"net\" || otherNode?.kind === \"net\");\n let side = hand?.ports?.[key] ?? (sideways ? (target[0] >= center(box)[0] ? \"right\" : \"left\") : sideFacing(box, target));\n if (node.sheetPort && !hand?.ports?.[key]) side = target[0] >= center(box)[0] ? \"right\" : \"left\";\n if (!hand?.ports?.[key] && inside) {\n // boundary port with only an inner counterpart: face outward on the nearest edge\n side = sideFacing(box, [target[0] + (target[0] - center(box)[0]) * 4, target[1] + (target[1] - center(box)[1]) * 4]);\n }\n ports[key] = { node: node.id, port, side, x: 0, y: 0, links };\n const sk = `${node.id}|${side}`;\n const order = side === \"left\" || side === \"right\" ? target[1] : target[0];\n bySide.set(sk, [...(bySide.get(sk) ?? []), { key, order }]);\n }\n groups[node.id] = [...hidden.values()].sort((a, b) => b.count - a.count);\n }\n\n // grow cards (without a hand-set height) so the busiest side fits its ports\n const sideCount = new Map<string, number>();\n for (const [sk, entries] of bySide) {\n const nodeId = sk.slice(0, sk.lastIndexOf(\"|\"));\n const side = sk.slice(sk.lastIndexOf(\"|\") + 1);\n if (side === \"left\" || side === \"right\") sideCount.set(nodeId, Math.max(sideCount.get(nodeId) ?? 0, entries.length));\n }\n for (const [nodeId, count] of sideCount) {\n const node = vm.nodes.find((n) => n.id === nodeId)!;\n if (hand?.nodes[nodeId]?.h || node.shape === \"circle\" || node.sheetPort || node.expanded || node.kind === \"harness\" || node.kind === \"net\") continue;\n boxes[nodeId].h = Math.ceil(Math.max(boxes[nodeId].h, 44 + count * PORT_PITCH) / GRID) * GRID;\n }\n // grow module cards (without a hand-set height) so the body (icon, title, protocol chips) clears the\n // labels of the ports on the top and bottom edges; a container then still wraps its grown children\n let grew = false;\n const labelsOf = new Map<string, { side: Side; name: string }[]>();\n for (const p of Object.values(ports)) labelsOf.set(p.node, [...(labelsOf.get(p.node) ?? []), { side: p.side, name: p.port.name }]);\n for (const node of vm.nodes) {\n if (hand?.nodes[node.id]?.h || node.shape === \"circle\" || node.sheetPort || node.expanded || node.kind === \"harness\" || node.kind === \"net\") continue;\n const b = boxes[node.id];\n const need = Math.ceil(cardHeight(node.label, b.w, groups[node.id] ?? [], cardInsets(labelsOf.get(node.id) ?? [], b.w)) / GRID) * GRID;\n if (need > b.h) {\n b.h = need;\n grew = true;\n }\n }\n if (grew) wrapContainers();\n // a junction keeps one grid step between its ports on every side\n for (const [sk, entries] of bySide) {\n const nodeId = sk.slice(0, sk.lastIndexOf(\"|\"));\n const side = sk.slice(sk.lastIndexOf(\"|\") + 1);\n const node = vm.nodes.find((n) => n.id === nodeId)!;\n if (node.kind !== \"net\" || hand?.nodes[nodeId]) continue;\n const need = (entries.length + 1) * GRID;\n if (side === \"left\" || side === \"right\") boxes[nodeId].h = Math.max(boxes[nodeId].h, need);\n else boxes[nodeId].w = Math.max(boxes[nodeId].w, need + 32);\n }\n\n // a grown junction placed automatically moves to the nearest spot where it overlaps nothing\n for (const node of vm.nodes) {\n if (node.kind !== \"net\" || node.parent || hand?.nodes[node.id]?.x !== undefined || overrides[node.id]) continue;\n const b = boxes[node.id];\n const others = vm.nodes.filter((n) => n !== node && !n.expanded && !n.parent).map((n) => boxes[n.id]);\n if (!others.some((o) => hits(b, o, 8))) continue;\n // ports get their positions below, from the box\n const at = freeSpot([b.x + b.w / 2, b.y + b.h / 2], b.w, b.h, others, { x: 24, y: 12 });\n b.x = at.x;\n b.y = at.y;\n }\n\n const counterpartOf = (key: string): Pt | undefined => {\n const p = ports[key];\n const link = p.links.find((l) => !l.passThrough) ?? p.links[0];\n const self = link.source.node === p.node && link.source.port === p.port.id;\n const other = ports[portKey(self ? link.target.node : link.source.node, self ? link.target.port : link.source.port)];\n return other ? [other.x, other.y] : undefined;\n };\n\n // distribute along each side, ordered by counterpart position; the second\n // pass re-orders by where the counterpart ports actually landed\n let used = new Map<string, Set<number>>();\n for (let pass = 0; pass < 2; pass++) {\n used = new Map();\n for (const [sk, entries] of bySide) {\n if (pass === 1) {\n for (const e of entries) {\n const c = counterpartOf(e.key);\n const side = ports[e.key].side;\n if (c) e.order = side === \"left\" || side === \"right\" ? c[1] : c[0];\n }\n }\n const [nodeId, side] = [sk.slice(0, sk.lastIndexOf(\"|\")), sk.slice(sk.lastIndexOf(\"|\") + 1) as Side];\n const box = boxes[nodeId];\n const node = vm.nodes.find((n) => n.id === nodeId)!;\n entries.sort((a, b) => a.order - b.order);\n const n = entries.length;\n entries.forEach(({ key }, i) => {\n const f = (i + 1) / (n + 1);\n const p = ports[key];\n if (node.shape === \"circle\") {\n const r = box.w / 2;\n const [cx, cy] = center(box);\n const spread = Math.min(0.9, 0.35 * n); // radians around the side's midpoint\n const base = { right: 0, bottom: Math.PI / 2, left: Math.PI, top: -Math.PI / 2 }[side];\n const angle = base + (n === 1 ? 0 : (f - 0.5) * 2 * spread);\n p.x = cx + Math.cos(angle) * r;\n p.y = cy + Math.sin(angle) * r;\n } else if (side === \"left\" || side === \"right\") {\n const harness = node.kind === \"harness\" || node.kind === \"net\";\n const inset = node.expanded ? 34 : harness ? 4 : 28;\n p.x = side === \"left\" ? box.x : box.x + box.w;\n p.y = gridSlot(box.y + inset + (box.h - inset - (harness ? 4 : 12)) * f, box.y, box.y + box.h, used, `${nodeId}|${side}`);\n } else {\n p.x = gridSlot(box.x + 16 + (box.w - 32) * f, box.x, box.x + box.w, used, `${nodeId}|${side}`);\n p.y = side === \"top\" ? box.y : box.y + box.h;\n }\n });\n }\n }\n\n // routes: the grid router, shortest links first, through any pinned waypoints\n const routes: Record<string, Pt[]> = {};\n const pins: Record<string, Pt[]> = {};\n const bends: Record<string, Pt[]> = {};\n const byId = new Map(vm.nodes.map((n) => [n.id, n]));\n /** Where a link between two modules of one container may run: inside it, under its label and off its outline. */\n const regionOf = (link: ViewLink): Box | undefined => {\n const c = sharedContainer(vm, byId, link.source.node, link.target.node);\n const b = c && boxes[c.id];\n return b ? { x: b.x + GRID, y: b.y + 2 * GRID, w: b.w - 2 * GRID, h: b.h - 3 * GRID } : undefined;\n };\n const obstacleNodes = vm.nodes.filter((n) => !n.expanded);\n const obstacles = obstacleNodes.map((n) => boxes[n.id]);\n const router = new GridRouter(obstacles, Object.values(ports).map((p) => [p.x, p.y] as Pt), 12, !live);\n const todo = vm.links\n .filter((link) => !(link.ground && !showGrounds))\n .map((link) => ({ link, a: ports[portKey(link.source.node, link.source.port)], b: ports[portKey(link.target.node, link.target.port)] }))\n .filter((x) => x.a && x.b)\n .sort((x, y) => Math.abs(x.a.x - x.b.x) + Math.abs(x.a.y - x.b.y) - (Math.abs(y.a.x - y.b.x) + Math.abs(y.a.y - y.b.y)));\n // live drag: keep the routes of links that nothing moved, and route the rest around them\n const moves = (node: string) => [...(live?.nodes ?? [])].some((m) => node === m || node.startsWith(`${m}/`));\n const affected = (link: ViewLink) =>\n !live || !live.previous.routes[link.id] || live.links?.has(link.linkId) || moves(link.source.node) || moves(link.target.node);\n for (const { link } of todo) {\n if (affected(link)) continue;\n routes[link.id] = live!.previous.routes[link.id];\n pins[link.id] = live!.previous.pins[link.id] ?? [];\n bends[link.id] = live!.previous.bends[link.id] ?? [];\n if (!link.passThrough) router.occupy(routes[link.id]);\n }\n for (const { link, a, b } of todo) {\n if (!affected(link)) continue;\n let sa = a.side;\n const fromContainer = vm.nodes.find((n) => n.id === link.source.node)?.expanded;\n if (link.passThrough && fromContainer) {\n sa = ({ left: \"right\", right: \"left\", top: \"bottom\", bottom: \"top\" } as const)[sa];\n }\n const wp = linkOverrides?.[link.id]?.waypoints ?? hand?.links?.[link.id]?.waypoints ?? [];\n pins[link.id] = wp;\n // a pass-through line (a container's boundary inward, a sheet port to its child) runs the plain way,\n // unless that would cross a card it does not end at (a sheet port's line across a board): then it\n // goes round the cards like the rest\n if (link.passThrough) {\n const plain = route([a.x, a.y], sa, [b.x, b.y], b.side, wp);\n const ends = new Set([link.source.node, link.target.node]);\n // a line from a container's boundary inward too: round the cards it does not end at, and inside the container\n routes[link.id] = !crossesCards(plain, obstacleNodes.filter((n) => !ends.has(n.id)).map((n) => boxes[n.id])) ? plain : router.route([a.x, a.y], sa, [b.x, b.y], b.side, wp, regionOf(link));\n } else routes[link.id] = router.route([a.x, a.y], sa, [b.x, b.y], b.side, wp, regionOf(link));\n const pts = routes[link.id];\n // automatic waypoints: every interior corner that is not a pin\n bends[link.id] = pts.slice(1, -1).filter((p) => !wp.some((w) => Math.abs(w[0] - p[0]) < 1 && Math.abs(w[1] - p[1]) < 1));\n }\n\n // harness regions: the middle of the route, clear of the port stubs\n const runs: Record<string, [number, number]> = {};\n for (const link of vm.links) {\n const pts = routes[link.id];\n if (!link.run || !pts) continue;\n const L = lengths(pts).at(-1)!;\n const inset = Math.min(56, L * 0.18);\n // the harness ends (connector handles) sit on straight stretches, never in a bend\n const a = clearOfBends(pts, inset, BEND_CLEAR, 12);\n const b = clearOfBends(pts, L - inset, BEND_CLEAR, 12);\n runs[link.id] = b - a >= 24 ? [a, b] : [inset, L - inset];\n }\n\n const labelAt = placeLabels(vm, routes, boxes, hand, linkOverrides, runs);\n const labels: Record<string, Pt> = Object.fromEntries(Object.entries(labelAt).map(([id, s]) => [id, at(routes[id], s).p]));\n const labelFixed = Object.fromEntries(vm.links.map((l) => [l.id, (linkOverrides?.[l.id]?.labelT ?? hand?.links?.[l.id]?.labelT) !== undefined]));\n const edits = Object.fromEntries(vm.links.map((l) => [l.id, { ...hand?.links?.[l.id], ...linkOverrides?.[l.id] }]));\n return { boxes, ports, groups, routes, labels, labelAt, runs, pins, bends, labelFixed, edits };\n}\n\n/** Whether an axis-aligned polyline runs through any of `cards` (inside them, not along an edge). */\nfunction crossesCards(pts: Pt[], cards: Box[]): boolean {\n for (let i = 1; i < pts.length; i++) {\n const [x0, x1] = [Math.min(pts[i - 1][0], pts[i][0]), Math.max(pts[i - 1][0], pts[i][0])];\n const [y0, y1] = [Math.min(pts[i - 1][1], pts[i][1]), Math.max(pts[i - 1][1], pts[i][1])];\n if (cards.some((b) => x1 > b.x + 1 && x0 < b.x + b.w - 1 && y1 > b.y + 1 && y0 < b.y + b.h - 1)) return true;\n }\n return false;\n}\n\nconst CANDIDATES = [0.5, 0.35, 0.65, 0.22, 0.78, 0.12, 0.88];\n\nfunction labelSize(link: ViewLink): { w: number; h: number } {\n return { w: link.name.length * 5.6 + (link.children.length > 1 ? 44 : 16), h: 16 };\n}\n\n/** Whether a link opens into lanes (its label carries the +/− toggle, so it is always drawn). */\nconst opens = (link: ViewLink) => (link.lanes?.length ?? 0) > 1 || link.children.length > 1;\n\n/**\n * Choose a label spot per link, as an arc length along its route. The label\n * reads along the line (design D13): above a horizontal stretch, turned\n * beside a vertical one. Candidates are spots along every straight stretch\n * long enough for the text, horizontal ones first; each is scored by what\n * the text would cover: a card or another label (never), other lines (as\n * few as possible). A label with no clear spot is left off (the line still\n * names itself in the inspector and on hover); a link that opens into lanes\n * keeps its label, as that is where its toggle is. A label made only of a\n * pin number (a resistor's \"1\") says nothing on the sheet and is left off.\n * Routes shorter than 70 px (e.g. prop-on-shaft) stay unlabelled.\n */\nfunction placeLabels(\n vm: ViewModel,\n routes: Record<string, Pt[]>,\n boxes: Record<string, Box>,\n hand: LevelLayout | undefined,\n linkOverrides: Record<string, LinkLayout> | undefined,\n runs: Record<string, [number, number]>,\n): Record<string, number> {\n const placed: Box[] = [];\n const out: Record<string, number> = {};\n const cards = [\n ...vm.nodes.filter((n) => !n.expanded).map((n) => boxes[n.id]),\n ...vm.nodes.filter((n) => n.expanded).map((n) => ({ ...boxes[n.id], h: 26 })),\n ];\n const overlaps = (a: Box, b: Box, pad = 3) =>\n a.x < b.x + b.w + pad && b.x < a.x + a.w + pad && a.y < b.y + b.h + pad && b.y < a.y + a.h + pad;\n // every drawn segment, for counting the lines a label would sit on\n const segs: { id: string; a: Pt; b: Pt }[] = [];\n for (const link of vm.links) {\n const pts = routes[link.id];\n if (pts) for (let i = 1; i < pts.length; i++) segs.push({ id: link.id, a: pts[i - 1], b: pts[i] });\n }\n const crossing = (r: Box, own: string) =>\n segs.filter(\n (s) => s.id !== own && Math.max(s.a[0], s.b[0]) > r.x && Math.min(s.a[0], s.b[0]) < r.x + r.w && Math.max(s.a[1], s.b[1]) > r.y && Math.min(s.a[1], s.b[1]) < r.y + r.h,\n ).length;\n /**\n * The text's box for a label asked for at arc length `s` along `pts`: where the link draws it (moved\n * off the bends onto a straight stretch, as LinkEdge does), above a horizontal stretch or right of a\n * vertical one. Returns the arc length it lands at too.\n */\n const rectAt = (pts: Pt[], s0: number, w: number): { rect: Box; vertical: boolean; s: number } => {\n const s = clearOfBends(pts, s0, LABEL_CLEAR, 12);\n const { p, d } = at(pts, s);\n const vertical = Math.abs(d[1]) > Math.abs(d[0]);\n // the drawn tab: text plus its padding and border, a few px off the line\n return vertical ? { rect: { x: p[0] + 2, y: p[1] - w / 2, w: 22, h: w }, vertical, s } : { rect: { x: p[0] - w / 2, y: p[1] - 22, w, h: 20 }, vertical, s };\n };\n\n const ordered = [...vm.links].sort((a, b) => Number(opens(b)) - Number(opens(a)) || b.children.length - a.children.length || a.id.localeCompare(b.id));\n for (const link of ordered) {\n const pts = routes[link.id];\n if (!pts || link.passThrough || link.segment === \"b\") continue;\n const L = pathLength(pts);\n if (L < 70) continue;\n const fixed = linkOverrides?.[link.id]?.labelT ?? hand?.links?.[link.id]?.labelT;\n const keep = opens(link);\n if (fixed === undefined && !keep && /^\\d+$/.test(link.name.trim())) continue;\n const size = labelSize(link);\n const [lo, hi] = runs[link.id] ?? [0, L];\n const within = (t: number) => (lo + (hi - lo) * t) / L;\n // fractions of the route: the given one, or the classic spots plus the middle of every straight stretch the text fits on\n const tries: number[] = [];\n if (fixed !== undefined) tries.push(fixed);\n else {\n let walked = 0;\n const stretches: { mid: number; len: number }[] = [];\n for (let i = 1; i < pts.length; i++) {\n const len = Math.hypot(pts[i][0] - pts[i - 1][0], pts[i][1] - pts[i - 1][1]);\n if (len >= size.w + 2 * BEND_CLEAR) stretches.push({ mid: walked + len / 2, len });\n walked += len;\n }\n stretches.sort((a, b) => b.len - a.len);\n for (const st of stretches) for (const f of [0, -0.25, 0.25]) tries.push((st.mid + f * (st.len - size.w - 2 * BEND_CLEAR)) / L);\n tries.push(longestMid(pts), ...CANDIDATES.map(within));\n }\n let best: { at: number; score: number; rect: Box } | undefined;\n for (const t of tries) {\n const { rect, vertical, s } = rectAt(pts, t * L, size.w);\n const hard = cards.filter((b) => overlaps(rect, b, 0)).length + placed.filter((b) => overlaps(rect, b)).length;\n const score = hard * 100 + crossing(rect, link.id) * 2 + (vertical ? 1 : 0);\n if (!best || score < best.score) best = { at: fixed !== undefined ? t * L : s, score, rect };\n if (score === 0) break;\n }\n if (!best || (best.score >= 100 && fixed === undefined && !keep)) continue;\n out[link.id] = best.at;\n placed.push(best.rect);\n }\n return out;\n}\n\nfunction pathLength(pts: Pt[]): number {\n let n = 0;\n for (let i = 1; i < pts.length; i++) n += Math.hypot(pts[i][0] - pts[i - 1][0], pts[i][1] - pts[i - 1][1]);\n return n;\n}\n\nfunction pointAlong(pts: Pt[], t: number): Pt {\n const target = pathLength(pts) * t;\n let walked = 0;\n for (let i = 1; i < pts.length; i++) {\n const seg = Math.hypot(pts[i][0] - pts[i - 1][0], pts[i][1] - pts[i - 1][1]);\n if (walked + seg >= target && seg > 0) {\n const f = (target - walked) / seg;\n return [pts[i - 1][0] + (pts[i][0] - pts[i - 1][0]) * f, pts[i - 1][1] + (pts[i][1] - pts[i - 1][1]) * f];\n }\n walked += seg;\n }\n return pts[pts.length - 1];\n}\n\nfunction longestMid(pts: Pt[]): number {\n const total = pathLength(pts) || 1;\n let best = 0;\n let mid = 0.5;\n let walked = 0;\n for (let i = 1; i < pts.length; i++) {\n const seg = Math.hypot(pts[i][0] - pts[i - 1][0], pts[i][1] - pts[i - 1][1]);\n if (seg > best) {\n best = seg;\n mid = (walked + seg / 2) / total;\n }\n walked += seg;\n }\n return mid;\n}\n","/**\n * Layout quality (PB-1007): numbers that say whether a diagram reads, measured\n * on what the viewer draws (the boxes, and the routes the grid router gives\n * the links), so an agent can check a layout without looking at it.\n *\n * - crossings: places where two links' lines cross;\n * - overlaps: pairs of boxes that overlap (a card and a junction, two cards);\n * - aspect: the drawing's width over its height (a screen is about 1.6);\n * - strip: the most cards one straight line, across or down, passes through\n * (a long row or column of parts; a tidy level of twenty cards has 4 or 5);\n * - underCards: links whose line runs under a card it does not end at;\n * - length: the total length of the lines, in diagram units.\n *\n * `findings` turns them into what to fix, with the thresholds below.\n */\nimport type { ViewModel } from \"../model/types\";\nimport type { Pt } from \"../canvas/routing\";\nimport type { Box, ComputedLayout } from \"./layout\";\n\nexport interface LayoutMetrics {\n /** Cards on the level: modules, components and harnesses (not junctions, sheet ports or open containers). */\n cards: number;\n /** Boundary ports drawn (the exports of the module this level shows). */\n boundary: number;\n /** Lines drawn. */\n links: number;\n crossings: number;\n overlaps: number;\n /** Width over height of the drawing (0 when it is empty). */\n aspect: number;\n width: number;\n height: number;\n strip: number;\n /** Whether the strip runs across (a row) or down (a column). */\n stripAxis: \"row\" | \"column\";\n /** The cards of the strip, in order. */\n stripCards: string[];\n underCards: number;\n length: number;\n /** The overlapping pairs and the links under cards, by id. */\n detail: { overlaps: [string, string][]; underCards: { link: string; card: string }[] };\n}\n\nexport interface LayoutFinding {\n severity: \"warning\" | \"info\";\n code: \"strip\" | \"crossings\" | \"overlaps\" | \"under-cards\" | \"aspect\";\n message: string;\n}\n\n/**\n * What `findings` flags. A row or column of up to `strip(cards)` cards is\n * fine (a row of a grid shaped like a screen: 6 for up to 16 cards, then\n * one and a half times the square root of the count); more reads as a strip.\n */\nexport const LAYOUT_LIMITS = {\n strip: (cards: number) => Math.max(6, Math.ceil(1.5 * Math.sqrt(cards))),\n /** Crossings allowed: a few, and more on a level with many lines. */\n crossings: (links: number) => Math.max(3, Math.ceil(links / 8)),\n /** Aspect ratios outside this range read as a strip too. */\n aspect: [1 / 3, 3] as [number, number],\n};\n\nconst ancestorOf = (a: string, b: string) => b.startsWith(`${a}/`);\n\n/** Whether two boxes overlap by more than a hairline. */\nfunction overlap(a: Box, b: Box): boolean {\n return a.x < b.x + b.w - 1 && b.x < a.x + a.w - 1 && a.y < b.y + b.h - 1 && b.y < a.y + a.h - 1;\n}\n\ninterface Seg {\n link: string;\n a: Pt;\n b: Pt;\n}\n\nfunction segments(id: string, pts: Pt[]): Seg[] {\n const out: Seg[] = [];\n for (let i = 1; i < pts.length; i++) if (pts[i - 1][0] !== pts[i][0] || pts[i - 1][1] !== pts[i][1]) out.push({ link: id, a: pts[i - 1], b: pts[i] });\n return out;\n}\n\n/** Whether a horizontal and a vertical segment cross inside both (not at an end, not touching). */\nfunction cross(s: Seg, t: Seg): boolean {\n const h = (x: Seg) => Math.abs(x.a[1] - x.b[1]) < 0.5;\n const v = (x: Seg) => Math.abs(x.a[0] - x.b[0]) < 0.5;\n let H: Seg;\n let V: Seg;\n if (h(s) && v(t)) [H, V] = [s, t];\n else if (v(s) && h(t)) [H, V] = [t, s];\n else return obliqueCross(s, t);\n const y = H.a[1];\n const x = V.a[0];\n const [x0, x1] = [Math.min(H.a[0], H.b[0]), Math.max(H.a[0], H.b[0])];\n const [y0, y1] = [Math.min(V.a[1], V.b[1]), Math.max(V.a[1], V.b[1])];\n return x > x0 + 0.5 && x < x1 - 0.5 && y > y0 + 0.5 && y < y1 - 0.5;\n}\n\n/** A crossing of two segments when either is not axis-aligned (pass-through lines drawn straight). */\nfunction obliqueCross(s: Seg, t: Seg): boolean {\n const d = (p: Pt, q: Pt, r: Pt) => (q[0] - p[0]) * (r[1] - p[1]) - (q[1] - p[1]) * (r[0] - p[0]);\n const d1 = d(t.a, t.b, s.a);\n const d2 = d(t.a, t.b, s.b);\n const d3 = d(s.a, s.b, t.a);\n const d4 = d(s.a, s.b, t.b);\n return ((d1 > 0 && d2 < 0) || (d1 < 0 && d2 > 0)) && ((d3 > 0 && d4 < 0) || (d3 < 0 && d4 > 0));\n}\n\n/** Whether a segment runs through the inside of a box (not along its edge). */\nfunction through(s: Seg, b: Box): boolean {\n const [x0, x1] = [Math.min(s.a[0], s.b[0]), Math.max(s.a[0], s.b[0])];\n const [y0, y1] = [Math.min(s.a[1], s.b[1]), Math.max(s.a[1], s.b[1])];\n return x1 > b.x + 2 && x0 < b.x + b.w - 2 && y1 > b.y + 2 && y0 < b.y + b.h - 2;\n}\n\n/**\n * The most boxes one line along an axis passes through, and which: a sweep\n * over the boxes' extents on the other axis.\n */\nfunction stab(boxes: { id: string; b: Box }[], axis: \"row\" | \"column\"): string[] {\n const lo = (x: { b: Box }) => (axis === \"row\" ? x.b.y : x.b.x);\n const hi = (x: { b: Box }) => (axis === \"row\" ? x.b.y + x.b.h : x.b.x + x.b.w);\n const along = (x: { b: Box }) => (axis === \"row\" ? x.b.x : x.b.y);\n let best: string[] = [];\n // the line through the middle of an overlap of extents: try each box's centre and edges (inset a little)\n const tries = [...new Set(boxes.flatMap((x) => [lo(x) + 4, (lo(x) + hi(x)) / 2, hi(x) - 4]))].sort((a, b) => a - b);\n for (const at of tries) {\n const hit = boxes.filter((x) => lo(x) <= at && hi(x) >= at);\n if (hit.length > best.length) best = hit.sort((a, b) => along(a) - along(b)).map((x) => x.id);\n }\n return best;\n}\n\n/** Measure a level as the viewer lays it out. `vm` is what is drawn (after rail taps). */\nexport function measureLayout(vm: ViewModel, layout: ComputedLayout): LayoutMetrics {\n const byId = new Map(vm.nodes.map((n) => [n.id, n]));\n const drawn = vm.nodes.filter((n) => layout.boxes[n.id]);\n const isCard = (id: string) => {\n const n = byId.get(id);\n return !!n && n.kind !== \"net\" && !n.sheetPort && !n.expanded;\n };\n const cards = drawn.filter((n) => isCard(n.id)).map((n) => ({ id: n.id, b: layout.boxes[n.id] }));\n\n // overlaps: any two boxes, except a container and what it holds\n const overlaps: [string, string][] = [];\n for (let i = 0; i < drawn.length; i++)\n for (let j = i + 1; j < drawn.length; j++) {\n const a = drawn[i].id;\n const b = drawn[j].id;\n if (ancestorOf(a, b) || ancestorOf(b, a)) continue;\n if (overlap(layout.boxes[a], layout.boxes[b])) overlaps.push([a, b].sort() as [string, string]);\n }\n\n // lines\n const routed = vm.links.filter((l) => layout.routes[l.id]?.length);\n const segs = routed.flatMap((l) => segments(l.id, layout.routes[l.id]));\n let crossings = 0;\n for (let i = 0; i < segs.length; i++)\n for (let j = i + 1; j < segs.length; j++) if (segs[i].link !== segs[j].link && cross(segs[i], segs[j])) crossings++;\n\n const under: { link: string; card: string }[] = [];\n for (const l of routed) {\n const ends = [l.source.node, l.target.node];\n const mine = (id: string) => ends.some((e) => e === id || ancestorOf(id, e) || ancestorOf(e, id));\n const own = segments(l.id, layout.routes[l.id]);\n for (const c of cards) {\n if (mine(c.id)) continue;\n if (own.some((s) => through(s, c.b))) under.push({ link: l.id, card: c.id });\n }\n }\n\n let length = 0;\n for (const s of segs) length += Math.hypot(s.b[0] - s.a[0], s.b[1] - s.a[1]);\n\n const all = drawn.map((n) => layout.boxes[n.id]);\n const minX = all.length ? Math.min(...all.map((b) => b.x)) : 0;\n const minY = all.length ? Math.min(...all.map((b) => b.y)) : 0;\n const width = all.length ? Math.max(...all.map((b) => b.x + b.w)) - minX : 0;\n const height = all.length ? Math.max(...all.map((b) => b.y + b.h)) - minY : 0;\n\n // the strip counts the level's boundary ports too (a drilled-into module's exports, drawn in a column at the edge)\n const sheets = drawn.filter((n) => n.sheetPort).map((n) => ({ id: n.id, b: layout.boxes[n.id] }));\n const row = stab([...cards, ...sheets], \"row\");\n const column = stab([...cards, ...sheets], \"column\");\n const [strip, stripAxis] = column.length > row.length ? [column, \"column\" as const] : [row, \"row\" as const];\n\n return {\n cards: cards.length,\n boundary: sheets.length,\n links: routed.length,\n crossings,\n overlaps: overlaps.length,\n aspect: height ? Math.round((width / height) * 100) / 100 : 0,\n width: Math.round(width),\n height: Math.round(height),\n strip: strip.length,\n stripAxis,\n stripCards: strip,\n underCards: new Set(under.map((u) => u.link)).size,\n length: Math.round(length),\n detail: { overlaps, underCards: under },\n };\n}\n\n/** What a level's layout needs fixed, worst first. */\nexport function layoutFindings(m: LayoutMetrics, limits: typeof LAYOUT_LIMITS = LAYOUT_LIMITS): LayoutFinding[] {\n const out: LayoutFinding[] = [];\n if (m.overlaps) out.push({ severity: \"warning\", code: \"overlaps\", message: `${m.overlaps} pair${m.overlaps === 1 ? \"\" : \"s\"} of boxes overlap (${m.detail.overlaps.slice(0, 3).map((p) => p.join(\" / \")).join(\", \")}${m.overlaps > 3 ? \", …\" : \"\"})` });\n const strip = limits.strip(m.cards + (m.boundary ?? 0));\n const ports = m.stripCards.filter((id) => id.startsWith(\"@\")).length * 2 > m.stripCards.length;\n if (m.strip > strip)\n out.push({\n severity: \"warning\",\n code: \"strip\",\n message: `${m.strip} cards in one ${m.stripAxis} (${m.stripCards.slice(0, 4).join(\", \")}${m.strip > 4 ? \", …\" : \"\"}): more than ${strip} reads as a strip; ${ports ? \"most are the level's boundary ports: export fewer, grouped interfaces from this module (composites) rather than one per signal\" : \"arrange them in a block around what they connect to\"}`,\n });\n const [lo, hi] = limits.aspect;\n if (m.cards > 3 && m.aspect && (m.aspect < lo || m.aspect > hi)) out.push({ severity: \"warning\", code: \"aspect\", message: `the drawing is ${m.aspect > 1 ? `${m.aspect}× as wide as it is tall` : `${Math.round(100 / m.aspect) / 100}× as tall as it is wide`}: aim for a screen's shape (about 1.6)` });\n const allowed = limits.crossings(m.links);\n if (m.crossings > allowed) out.push({ severity: \"warning\", code: \"crossings\", message: `${m.crossings} line crossings (up to ${allowed} is fine for ${m.links} lines): move cards next to what they connect to` });\n if (m.underCards) out.push({ severity: \"info\", code: \"under-cards\", message: `${m.underCards} line${m.underCards === 1 ? \" runs\" : \"s run\"} under a card (${m.detail.underCards.slice(0, 2).map((u) => `${u.link} under ${u.card}`).join(\", \")}${m.detail.underCards.length > 2 ? \", …\" : \"\"})` });\n return out;\n}\n","/**\n * Headless layout (PB-1007): the viewer's diagram layout without a browser,\n * for hosts that check or write a project's layout (`protoboard layout`).\n *\n * import { diagramLevels, measureLevel, proposeLevel } from \"@deltarobotics/uhd-viewer/headless\";\n *\n * Everything here computes what the viewer would draw for a level: the same\n * model (`buildView`, rail taps), the same layout and routes\n * (`computeLayout`), from the bundle and its display hints. No React, no DOM.\n */\nimport type { UhdBundle } from \"@uhd/types/bundle.js\";\nimport type { ModuleDef } from \"@uhd/types/index.js\";\nimport type { ModuleLookup } from \"@uhd/system/index.js\";\nimport { sourceFromBundle, type DisplayConfig } from \"./source/source\";\nimport { buildView, levelModule } from \"./model/from-uhd\";\nimport { tapRails } from \"./layout/taps\";\nimport { arrangeLevel, computeLayout, type ComputedLayout, type LevelLayout } from \"./layout/layout\";\nimport { layoutFindings, measureLayout, LAYOUT_LIMITS, type LayoutFinding, type LayoutMetrics } from \"./layout/metrics\";\nimport type { ViewModel } from \"./model/types\";\n\nexport { LAYOUT_LIMITS, layoutFindings, measureLayout };\nexport type { LayoutFinding, LayoutMetrics, LevelLayout };\n\n/** A level of the diagram: the inside of one module, keyed by its instance path (\"\" = the top level). */\nexport interface DiagramLevel {\n level: string;\n /** The module's name. */\n label: string;\n /** The level holds a board's nets (laid out as a schematic sheet, board-layout.ts). */\n board: boolean;\n}\n\n/** A level layout with the nodes the layout step must not move (PB-1007; the viewer ignores the list). */\nexport type PinnedLevelLayout = LevelLayout & { pinned?: string[] };\n\ninterface Loaded {\n system: ModuleDef;\n lookup: ModuleLookup;\n display: DisplayConfig;\n}\n\nfunction load(bundle: UhdBundle): Loaded {\n const src = sourceFromBundle(bundle, \"bundle.json\");\n const nominal = src.scenarios[0];\n return { system: nominal.system, lookup: nominal.lookup, display: src.display };\n}\n\n/** Every level of the diagram, top first: the top level and the inside of every module that has modules in it. */\nexport function diagramLevels(bundle: UhdBundle, maxDepth = 4): DiagramLevel[] {\n const { system, lookup } = load(bundle);\n const out: DiagramLevel[] = [];\n const walk = (def: ModuleDef, path: string[], label: string) => {\n const children = def.children ?? [];\n if (!children.length) return;\n const board = (def.interfaces ?? []).some((i) => (i as { protocol?: { type?: string } }).protocol?.type === \"Net\" || (i as { kind?: string }).kind === \"net\");\n out.push({ level: path.join(\"/\"), label, board: board || isBoardLevel(system, lookup, path) });\n if (path.length >= maxDepth) return;\n for (const c of children) {\n const next = lookup(c.moduleDefId);\n if (!next || next.kind === \"harness\") continue;\n walk(next, [...path, c.id], c.name ?? next.name);\n }\n };\n walk(system, [], system.name);\n return out;\n}\n\n/** Whether a level draws net junctions (a board): what the viewer's own view model says. */\nfunction isBoardLevel(system: ModuleDef, lookup: ModuleLookup, drill: string[]): boolean {\n try {\n return buildView(system, lookup, drill, { expanded: new Set() }).nodes.some((n) => n.kind === \"net\");\n } catch {\n return false;\n }\n}\n\nexport interface LevelOptions {\n /** The level's layout to use: the display file's when undefined; null for none (the automatic layout). */\n layout?: LevelLayout | null;\n /** Modules drawn expanded in place (default: the display file's `diagram.expanded`). */\n expanded?: string[];\n /** Lay a level without a layout out the way the viewer did before PB-1007 (one row), to compare. */\n legacy?: boolean;\n}\n\nexport interface MeasuredLevel {\n level: string;\n /** Whether the layout measured is a saved one (from the display file or given). */\n saved: boolean;\n metrics: LayoutMetrics;\n findings: LayoutFinding[];\n /** What the viewer draws: the model and the computed layout. */\n view: ViewModel;\n layout: ComputedLayout;\n}\n\n/** The display hints of a bundle: its `display`, as the viewer reads it. */\nexport function displayOf(bundle: UhdBundle): DisplayConfig {\n return (bundle.display ?? {}) as DisplayConfig;\n}\n\n/** Lay a level out as the viewer would, and measure it. */\nexport function measureLevel(bundle: UhdBundle, level: string, opts: LevelOptions = {}): MeasuredLevel {\n const { system, lookup, display } = load(bundle);\n const drill = level ? level.split(\"/\") : [];\n const known = levelModule(system, drill, lookup);\n if (known.path.length !== drill.length + 1) throw new Error(`no level \"${level}\" (levels are instance paths of modules with modules inside)`);\n const expanded = new Set(opts.expanded ?? display.diagram?.expanded ?? []);\n const vm = tapRails(buildView(system, lookup, drill, { expanded }));\n const hand = opts.layout === null ? undefined : (opts.layout ?? display.diagram?.layouts?.[level]);\n const layout = computeLayout(vm, hand, {}, false, undefined, undefined, { legacy: opts.legacy });\n const metrics = measureLayout(vm, layout);\n return { level, saved: !!hand, metrics, findings: layoutFindings(metrics), view: vm, layout };\n}\n\n/**\n * A display-file level that holds a computed layout: every node's position\n * (top-level nodes absolute, nodes inside an expanded module relative to\n * it), as the viewer writes them.\n */\nexport function levelLayoutOf(vm: ViewModel, layout: ComputedLayout): LevelLayout {\n const nodes: LevelLayout[\"nodes\"] = {};\n const byId = new Map(vm.nodes.map((n) => [n.id, n]));\n for (const n of [...vm.nodes].sort((a, b) => a.id.localeCompare(b.id))) {\n const b = layout.boxes[n.id];\n if (!b) continue;\n // a rail's taps are drawn from the net: they are placed again from it, never saved\n if (n.tapOf) continue;\n const p = n.parent ? layout.boxes[n.parent] : undefined;\n nodes[n.id] = p && byId.get(n.parent!) ? { x: b.x - p.x, y: b.y - p.y } : { x: b.x, y: b.y };\n // a module expanded in place keeps the size it was laid out at (else the viewer takes the layout as made\n // for its collapsed card, and moves what is beside and below it)\n if (n.expanded) Object.assign(nodes[n.id], { w: b.w, h: b.h });\n }\n return { nodes };\n}\n\nexport interface ProposeOptions extends LevelOptions {\n /**\n * \"default\": the level laid out afresh (the viewer's automatic layout);\n * \"tidy\": the saved layout's arrangement kept as the starting point, and\n * what reads badly (strips, overlaps, crossings) fixed.\n */\n mode?: \"default\" | \"tidy\";\n /** Nodes that keep their saved positions (added to the level's own `pinned`). */\n pinned?: string[];\n}\n\nexport interface Proposal {\n level: string;\n /** The level as it is drawn now. */\n before: MeasuredLevel;\n /** The level with the proposed layout. */\n after: MeasuredLevel;\n /** What to write to `diagram.layouts[level]`. */\n layout: PinnedLevelLayout;\n /** Whether the proposal reads clearly better than what is there (`readsBetter`). */\n better: boolean;\n}\n\n/**\n * A layout for a level: afresh, or tidied from the saved one; pinned nodes\n * keep their saved positions. Links whose ends moved lose their saved\n * waypoints (they were drawn for the old places); labels and tabs stay.\n */\nexport function proposeLevel(bundle: UhdBundle, level: string, opts: ProposeOptions = {}): Proposal {\n const before = measureLevel(bundle, level, opts);\n const saved: PinnedLevelLayout | undefined = opts.layout === null ? undefined : (opts.layout ?? (displayOf(bundle).diagram?.layouts?.[level] as PinnedLevelLayout | undefined));\n const pinned = [...new Set([...(saved?.pinned ?? []), ...(opts.pinned ?? [])])].filter((id) => saved?.nodes[id]?.x !== undefined).sort();\n const fixed: Record<string, { x: number; y: number }> = {};\n for (const id of pinned) fixed[id] = { x: saved!.nodes[id].x!, y: saved!.nodes[id].y! };\n // the starting arrangement: for a tidy, where the cards are drawn now\n const seed = opts.mode === \"tidy\" ? Object.fromEntries(Object.entries(before.layout.boxes).map(([id, b]) => [id, { x: b.x + b.w / 2, y: b.y + b.h / 2 }])) : undefined;\n // a tidy keeps the sizes set by hand; a fresh layout gives every card its own size again\n const keepSizes = opts.mode === \"tidy\" ? saved : undefined;\n const fresh = arrangeLevel(before.view, { fixed, seed }, keepSizes);\n // the arrangement as a hand layout, laid out once more so the saved positions are exactly what is drawn\n const draft = measureLevel(bundle, level, { ...opts, layout: { ...fresh, ...(keepSizes?.ports ? { ports: keepSizes.ports } : {}) } });\n const layout: PinnedLevelLayout = levelLayoutOf(draft.view, draft.layout);\n for (const id of pinned) layout.nodes[id] = { ...fixed[id] };\n // sizes and port sides set by hand stay; waypoints only where neither end moved\n if (keepSizes) for (const [id, n] of Object.entries(saved?.nodes ?? {})) if (layout.nodes[id] && (n.w !== undefined || n.h !== undefined)) layout.nodes[id] = { ...layout.nodes[id], ...(n.w !== undefined ? { w: n.w } : {}), ...(n.h !== undefined ? { h: n.h } : {}) };\n if (keepSizes?.ports) layout.ports = { ...keepSizes.ports };\n const moved = (id: string) => !pinned.includes(id.split(\"/\")[0]);\n const links: NonNullable<LevelLayout[\"links\"]> = {};\n for (const [id, l] of Object.entries(saved?.links ?? {})) {\n const link = before.view.links.find((x) => x.id === id);\n const keep = link && !moved(link.source.node) && !moved(link.target.node);\n const { waypoints, ...rest } = l;\n const next = keep && waypoints ? { ...rest, waypoints } : rest;\n if (Object.keys(next).length) links[id] = next;\n }\n if (Object.keys(links).length) layout.links = links;\n if (pinned.length) layout.pinned = pinned;\n const refined = before.view.nodes.some((n) => n.kind === \"net\") ? layout : refine(bundle, level, opts, layout, pinned);\n const after = measureLevel(bundle, level, { ...opts, layout: refined });\n return { level, before, after, layout: refined, better: readsBetter(after.metrics, before.metrics) };\n}\n\n/** Swaps tried at most when refining a level (the same count every run: the result does not depend on the machine). */\nexport const REFINE_BUDGET = 120;\n/** Levels with more cards than this keep the grid's arrangement (each try routes the whole level). */\nexport const REFINE_MAX_CARDS = 16;\n\n/**\n * Refine a proposed layout on what the viewer actually draws: swap two\n * cards' places (centre for centre) while that lowers the routed crossings,\n * overlaps or line length (`reads`), up to REFINE_BUDGET tries. Pinned cards\n * stay. Deterministic: pairs in id order, the first improvement taken.\n */\nfunction refine(bundle: UhdBundle, level: string, opts: LevelOptions, start: PinnedLevelLayout, pinned: string[]): PinnedLevelLayout {\n const ids = Object.keys(start.nodes)\n .filter((id) => !id.includes(\"/\") && !pinned.includes(id))\n .sort();\n if (ids.length < 3 || ids.length > REFINE_MAX_CARDS) return start;\n let best = start;\n let m = measureLevel(bundle, level, { ...opts, layout: best });\n let score = reads(m.metrics);\n let tries = 0;\n let improved = true;\n while (improved && tries < REFINE_BUDGET) {\n improved = false;\n for (let i = 0; i < ids.length && tries < REFINE_BUDGET; i++)\n for (let j = i + 1; j < ids.length && tries < REFINE_BUDGET; j++) {\n const a = m.layout.boxes[ids[i]];\n const b = m.layout.boxes[ids[j]];\n if (!a || !b) continue;\n const snap = (v: number) => Math.round(v / 16) * 16;\n const nodes = { ...best.nodes };\n nodes[ids[i]] = { ...nodes[ids[i]], x: snap(b.x + b.w / 2 - a.w / 2), y: snap(b.y + b.h / 2 - a.h / 2) };\n nodes[ids[j]] = { ...nodes[ids[j]], x: snap(a.x + a.w / 2 - b.w / 2), y: snap(a.y + a.h / 2 - b.h / 2) };\n const next: PinnedLevelLayout = { ...best, nodes };\n tries++;\n const nm = measureLevel(bundle, level, { ...opts, layout: next });\n const ns = reads(nm.metrics);\n if (ns < score - 1e-6) {\n best = next;\n m = nm;\n score = ns;\n improved = true;\n }\n }\n }\n return best;\n}\n\n\n\n/**\n * Whether layout `a` reads clearly better than `b`: fewer problems (warnings,\n * then overlaps, the strip's excess, crossings, lines under cards), or as\n * few and lines a quarter shorter. A layout with nothing to fix is not\n * replaced for a few pixels of line.\n */\nexport function readsBetter(a: LayoutMetrics, b: LayoutMetrics): boolean {\n const problems = (m: LayoutMetrics) => [\n layoutFindings(m).filter((x) => x.severity === \"warning\").length,\n m.overlaps,\n Math.max(0, m.strip - LAYOUT_LIMITS.strip(m.cards + m.boundary)),\n m.crossings,\n m.underCards,\n ];\n const pa = problems(a);\n const pb = problems(b);\n for (let i = 0; i < pa.length; i++) if (pa[i] !== pb[i]) return pa[i] < pb[i];\n return a.length < 0.75 * b.length;\n}\n\n/** A score for comparing two layouts of one level: lower reads better. */\nexport function reads(m: LayoutMetrics): number {\n const f = layoutFindings(m).filter((x) => x.severity === \"warning\").length;\n return f * 1e9 + m.overlaps * 1e7 + Math.max(0, m.strip - LAYOUT_LIMITS.strip(m.cards + m.boundary)) * 1e6 + m.crossings * 1e4 + m.underCards * 1e3 + m.length / 100;\n}\n"],"mappings":"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"}
|