gokul/usb3-sd-hub

Engineering draft: four-layer, computer-powered USB 3 hub with one USB-C host socket, two USB-C and two USB-A accessory sockets, and a full-size SD slot. Board and three schematic previews are available. Routing and production checks are incomplete; not fabrication ready.

Version
0.1.5
License
MIT
Stars
0

TOOL-ISSUES.md

PCBPCB preview for TOOL-ISSUES.md
SchematicSchematic preview for TOOL-ISSUES.md
# Tool findings and reproduction history

Current board build: tscircuit 0.0.2911. The historical cases below retain their original versions; they are not all claimed to remain unfixed in the current SDK. Board routing and electrical qualification are separate unfinished engineering work, not newly discovered tscircuit bugs.

## Current slot-rotation reproduction — already tracked

A pill-shaped NPTH inside a component rotated 90/270 degrees moves to the rotated position but keeps its unrotated shape when the hole has no explicit rotation. The retained eight-case reproduction compares parent-only and explicit hole rotations; Circuit JSON schema validation alone accepts both. This would orient a USB locating slot incorrectly in manufacturing output. The board passes its known component rotation explicitly to each affected hole.

This is already covered by [core PR 4343, Apply own and parent rotation to rect, oval and pill holes](https://github.com/tscircuit/core/pull/4343), found during duplicate checking. Do not file a duplicate or present it as a new contribution. Evidence: `verification/issues/repro-parent-slot.tsx` and `parent-slot-rotation-repro.json`.

No new issue or PR was filed. The remaining-net preflight guard, unfinished routing, source courtyard fixes, disk-space interruption and assembly choices are not listed as new bugs.

## Historical evidence

### Earlier confirmed tool issues

The original import/schema reproductions use CLI 0.1.2293 and tscircuit 0.0.2821. The additional fiducial-to-Gerber reproduction uses current tscircuit 0.0.2823, core 0.0.2128 and circuit-json-to-gerber 0.0.111. These are an evidence bundle, not filed GitHub issues or PRs. Searches of open and closed issues / PRs were performed; related work is identified below. Maintainers should still check for duplicates immediately before filing.

The board has since been rebuilt with tscircuit 0.0.2825 / core 0.0.2129 / circuit-json 0.0.526. Its current placement and complete three-sheet schematic snapshots have zero invalid records with the disclosed compatibility adapters. Historical reproduction versions and failures below are retained as evidence; they are not current board validation counts.

## 1. Accept legacy model `at` coordinates in KiCad footprint imports

**Repository:** tscircuit/kicad-to-circuit-json. The installed standalone converter is 0.0.142; the reproduction uses the current CLI import path.

**Trigger:** Convert the retained KiCad USB3_A_Molex_48393-001 footprint, which includes a legacy `(model ... (at (xyz ...)))` declaration.

**Observed:** The CLI exits with `model encountered unsupported child token "at"`. The same footprint converts when only the model-position keyword is normalized from `at` to `offset`.

**Expected:** Accept the valid legacy model coordinates or ignore unsupported 3D placement metadata with a useful warning while preserving the electrical footprint.

**User impact:** A USB connector footprint import fails entirely even though its pads and holes are usable. Manual source normalization is required.

**Evidence:** `verification/issues/UsbA-legacy.kicad_mod`, `UsbA-normalized.kicad_mod`, and `legacy-convert.log`.

**Reproduce:** `tsci convert verification/issues/UsbA-legacy.kicad_mod -o /tmp/UsbA.tsx`, then repeat with the normalized file. No PCB design or routing is necessary to reproduce it.

The exact unsupported-token search did not identify a matching issue. This is a verified legacy-format compatibility limitation; it is not claimed to support every KiCad format.

## 2. Omit unsupported `height` from generated pill plated-hole TSX

**Repository:** tscircuit/circuit-json-to-tscircuit.

**Trigger:** Convert the normalized connector footprint containing oval plated mounting holes. The CLI emits `shape="pill"`, `outerHeight`, `outerWidth`, `holeHeight`, `holeWidth`, and an extra `height` property.

**Observed:** Strict TypeScript checking rejects the emitted JSX: `Property 'height' does not exist on type 'PillPlatedHoleProps'`. Removing only `height` resolves this specific diagnostic. The generator on the repository's main branch also still emits this property in `lib/generate-footprint-tsx/convert-plated-holes.ts`.

**Expected:** Generated TSX should satisfy the current public component prop types; pill plated holes already have explicit outer/hole dimensions.

**User impact:** An ordinary imported USB socket produces code that fails type checking, requiring manual edits before use in a typed circuit project.

**Evidence:** `verification/issues/UsbA-generated-current.tsx` is freshly generated, without the project workaround. `repro-pill.tsx` isolates the emitted element; `tsconfig.json` and `pill-typecheck.log` show the diagnostic.

**Reproduce:** Run `tsci convert verification/issues/UsbA-normalized.kicad_mod -n UsbAConverted -o /tmp/UsbAConverted.tsx`. From this project, run `bun x tsc -p verification/issues/tsconfig.json --noEmit`. Removing `height` from the isolated JSX should make that type check pass.

**Related work:** [PR 39: Add support for rectangular and pill-shaped PCB holes](https://github.com/tscircuit/circuit-json-to-tscircuit/pull/39), [PR 41: Support extra plated-hole variants](https://github.com/tscircuit/circuit-json-to-tscircuit/pull/41), and [PR 59: Rotated pill SMT-pad conversion](https://github.com/tscircuit/circuit-json-to-tscircuit/pull/59). These concern related shapes; none is presented as proof that the extra generated property is fixed. [Current generator source](https://github.com/tscircuit/circuit-json-to-tscircuit/blob/main/lib/generate-footprint-tsx/convert-plated-holes.ts) is the relevant implementation.

## 3. Board-level fiducial / silkscreen records fail current Circuit JSON validation

**Repository:** tscircuit/core, with a schema-contract decision also needed in tscircuit/circuit-json. Tested with tscircuit 0.0.2821, core 0.0.2125 and the current published circuit-json 0.0.525.

**Trigger:** Render a board containing just a normal `fiducial` and a board-level `silkscreentext`, with schematic and routing disabled. No imported parts or hub design is involved.

**Observed:** The generated `pcb_smtpad` and `pcb_silkscreen_text` records contain `pcb_component_id: null`; the current published schemas reject both. The validator reports `Expected string, received null` for that field. The current main-branch SMT-pad schema allows an omitted owner but still rejects null; the silkscreen schema requires an owner string, so its correct board-level representation needs an explicit contract decision.

**User impact:** Standard board decoration / assembly primitives produce exported JSON that strict Circuit JSON consumers cannot parse, even though PCB previews can render them. In this board, the three fiducial pads and four board-level text records contribute seven failures.

**Evidence:** `verification/issues/schema-repro.tsx`, `schema-board-primitives.log` and `schema-primitives-repro.circuit.json`. Run the reproduction with Bun and circuit-json 0.0.525 installed. It prints the failing records and the individual schema diagnostics.

**Duplicate / prior-work status:** The board-level silkscreen case is already explicitly mentioned, but deliberately left unresolved, in [core issue 2843](https://github.com/tscircuit/core/issues/2843). This is not presented as a newly discovered silkscreen problem. A matching fiducial-specific report was not identified by the searches. A contribution should extend the existing owner-ID investigation, agree on the intended schema, and avoid opening a duplicate for the known silkscreen case. [SMT-pad schema](https://github.com/tscircuit/circuit-json/blob/main/src/pcb/pcb_smtpad.ts), [silkscreen schema](https://github.com/tscircuit/circuit-json/blob/main/src/pcb/pcb_silkscreen_text.ts).

## Already tracked schema bugs reproduced in this build

- [core issue 2841](https://github.com/tscircuit/core/issues/2841): `display_offset_x/y` are generated as numbers where the current schema expects strings. Reproduced on a single resistor in a group, and on 229 component / 33 group records in this draft. These are existing tracked defects, not new issue candidates.
- [core issue 2845](https://github.com/tscircuit/core/issues/2845): a group emits `anchor_alignment: null`, which its schema rejects. The same small reproduction demonstrates it. This is also already tracked.

`schema-offsets-and-anchor.log` and `schema-offsets-repro.circuit.json` preserve the reproduction. Overall, 269 of the 7,446 records in the final placement-only output fail `any_circuit_element.safeParse()` with published circuit-json 0.0.525. Some records have multiple invalid fields; counts should not be added as if they were distinct records. TypeScript success and zero placement DRC errors do not establish valid exported JSON. This is the historical, unmodified reproduction. The current board uses explicit group anchors, actual DNP feature-owner components, and a scoped conversion of numeric display offsets to millimetre strings after native placement. The compatibility module is disclosed in design/pcb-position-compatibility.ts; it changes metadata only. Current placement passes circuit-json 0.0.526 with zero invalid records. These upstream defects are not claimed to be fixed upstream.

## 4. Open the solder mask over native fiducial targets in Gerber exports

**Repository:** tscircuit/core; generated fiducial semantics should also be checked against circuit-json-to-gerber. Tested with tscircuit 0.0.2823, core 0.0.2128, circuit-json-to-gerber 0.0.111.

**Trigger:** Render one 1 mm fiducial with 0.5 mm soldermask pullback, owned by a DNP chip on an otherwise empty 10 x 10 mm board. Export the generated Circuit JSON as Gerbers. Owner IDs are valid, so this is independent of issue 3.

**Observed:** The circular copper pad has `is_covered_with_solder_mask: true` and `soldermask_margin: 0.5`, and no standalone mask opening. F_Cu has one flash. F_Mask defines a 2 mm circular aperture but has zero draw/flash operations. F_Paste has zero flashes. The target is covered with mask despite the declared pullback.

**Expected:** A fiducial exposes its optical copper target through a 2 mm mask opening, with no solder paste. Defining an unused aperture is insufficient.

**User impact:** Assembly optical alignment targets are hidden in exported manufacturing files, even though a copper target appears in the PCB preview.

**Evidence:** `verification/issues/repro-fiducial-mask.tsx`, its Circuit JSON and Gerber archive, `fiducial-repro-F_Mask.gbr`, and `fiducial-mask-proof.json`. The reduced reproduction does not contain the hub, routing, schematic layout overrides or imported components.

**Reproduce:** Run `bun verification/issues/repro-fiducial-mask.tsx` from this package, then `tsci export repro-fiducial-mask.circuit.json --format gerbers -o repro-fiducial-gerbers.zip`. Inspect F_Mask rather than only the PCB preview.

**Board workaround verified:** Each target has an explicit circular `pcbsoldermaskopening` with radius 1 mm. The board export now includes aperture D77, diameter 2.000000 mm, and three flashes at the fiducial coordinates. This addresses mask exposure in this draft; routing remains incomplete.

**Related work / duplicate check:** Search found no exact missing-mask-flash issue in core. [Core PR 4214](https://github.com/tscircuit/core/pull/4214) addresses fiducial courtyards, and [circuit-json-to-kicad issue 372](https://github.com/tscircuit/circuit-json-to-kicad/issues/372) concerns unwanted paste/clearance in KiCad export. These are related, distinct findings, not proof that the native Gerber mask case is fixed. Recheck duplicates before filing.

## Excluded observations

### Already known differential-pair diagnostic integration

The current capacity-autorouter 0.0.969 upstream TX trial returns `solved: true` with two length-matched traces, while its native post-processor reports `no-valid-candidate` for coupled rerouting. The returned paths fail this board's 2 mm uncoupled-length requirement; the independent conservative distance check proves approximately 20.445 mm continuously separated on each path. This result is rejected. The original input, native result, measured checks and diagram are retained in `verification/routing-input.srj.json.gz`, `native-pair-candidate.json`, `routing-check.json` and `usb-pair-diagnostic.png`.

[Autorouter PR 2753](https://github.com/tscircuit/tscircuit-autorouter/pull/2753) already proposes exposing these post-processing diagnostics while retaining best-effort output. Its API state was checked: closed, unmerged. [Length-matching solver PR 43](https://github.com/tscircuit/length-matching-solver/pull/43) defines the best-effort route-plus-errors contract. This is an existing integration concern with a current downstream example, not a new issue candidate. No duplicate issue or replacement PR has been filed, and native completion is not presented as successful USB routing.

The schematic group adapter also fills generated null group ownership from the actual enclosing subcircuit. This is disclosed in `design/schematic-group-compatibility.ts`; no unrelated owner ID is invented and no validation result is hidden.

Slow or unfinished autorouting is not presented as a verified upstream bug. Incomplete configuration, the power budget, part qualification, schematic review and approximate CAD bodies are design/release blockers. No speculative NaN, routing or hardware defect has been included as a confirmed tool issue.

No GitHub issue or PR has been filed. Future contributions must follow the handbook, recheck duplicates, use the requested commit name `up`, and open new PRs as drafts.