Skip to the content
PCBKitNew board
2 layers60 × 40 mmTest4.routed, the printed circuit board in 3D

It combines deterministic EDA analysis, native KiCad tooling, structured engineering knowledge, multi-plane design graphs, vector retrieval, and controlled execution to provide an AI-assisted hardware engineering…

Size
60 × 40 mm
Copper layers
2
Thickness
1.6 mm
Parts
31
Nets
97
Pads
177
Tracks, vias
244, 37
Pours
6
Routed
Yes
KiCad
KiCad 10.0 (file 20260206)
Created
20 Oct 2026
Updated
20 Oct 2026

Overview

Test4.routed is an open-source printed circuit board by pginfinitylab-ai, from the pginfinitylab-ai/forge repository on GitHub. It is a 2-layer board of 60 × 40 mm with 31 parts on 97 nets, routed with 244 tracks and 37 vias.

It is built around the STM32F407VGT6, AP2112K-3.3TRG1 and FTSH-105-01-L-DV-K, with the TL3342F160QG and USB4125-GF-A among its other parts. Its parts include 16 capacitors, 4 resistors, 2 ICs, 2 connectors and 1 diode. It belongs with the STM32 boards of this library.

Main components

5

README

README.md

UST Forge

UST Forge — Design · Simulate · Build

DESIGN · SIMULATE · BUILD — AI-Powered, End-to-End Product Engineering

UST Forge (formerly CircuitMind) is an engineering-grade AI-powered, end-to-end product engineering platform covering Electronics · Firmware · Mechanical · Simulation · Validation, designed to operate alongside KiCad 10.x, ngspice, Renode, FreeCAD, and Freerouting.

Using the application? The end-user guide for hardware engineers is in docs/user-guide/ (PDF: CircuitMind-User-Guide.pdf).

It combines deterministic EDA analysis, native KiCad tooling, structured engineering knowledge, multi-plane design graphs, vector retrieval, and controlled execution to provide an AI-assisted hardware engineering environment.

The primary design principle is:

AI may reason about the design, but engineering facts must come from deterministic sources.

UST Forge therefore separates:

  • Deterministic engineering facts — KiCad, netlists, BOMs, DRC/ERC, coordinates, project files
  • Canonical design representation — PostgreSQL-backed EDM graph
  • Engineering knowledge — Qdrant vector knowledge base
  • Reasoning — AI/LLM layer
  • Execution — controlled KCAA execution bridge
  • Verification — deterministic re-validation before accepting changes

Contents

Part I — Overview

Part II — Core Capabilities

Part III — Technology Selection and Benchmarks

Part IV — Installation and Configuration

Part V — Operation

Part VI — Reference


Part I — Overview

1 Project Overview

CircuitMind is composed of two primary applications:

text
CircuitMind
├── frontend/
│   └── React + Vite + Tailwind engineering workstation
│
└── backend/
    └── FastAPI + PostgreSQL + KiCad integration

Backend

The backend provides:

  • Native KiCad project analysis
  • KiCad CLI integration
  • DRC/ERC execution
  • Schematic extraction
  • PCB analysis
  • BOM/netlist extraction
  • Canonical EDM graph construction
  • Deterministic engineering calculations
  • Design Synchronization Manager (DSM)
  • Qdrant knowledge retrieval
  • KCAA execution bridge
  • REST API for the frontend

Frontend

The frontend provides the engineering workstation interface:

  • Project management
  • Schematic visualization
  • PCB visualization
  • Verification results
  • Active findings
  • Cross-probing
  • Design state
  • Engineering calculations
  • Knowledge retrieval
  • AI-assisted engineering workflows

1.1 Example Design Prompts

UST Forge allows designing complete boards starting from natural-language engineering requirements. You can paste these directly into the Design Pipeline (Stage 1 — Requirements > Describe tab):

Example 1: 12V to 5V Step-Down Buck Converter Power Supply
text
Design a 12V to 5V step-down buck converter power supply capable of supplying 1A continuous output current. 
Input requirements:
- Nominal input voltage: 12V DC (acceptable range 9V to 16V).
- Protection: Reverse polarity protection diode, over-current fuse, and input TVS surge diode.

Output requirements:
- Output voltage: 5V DC at 1A continuous.
- Delivery interface: Power-only USB-C receptacle output (sink/source advertisement via CC pins).
- Diagnostics: Power indicator LED with series resistor, and an output test point.

PCB & Mechanical requirements:
- PCB stackup: 2 layers.
- Board dimensions: 50 mm width by 40 mm height.
- Mounting: 4x M3 mounting holes (3.2 mm diameter).
- Operating temperature range: -20°C to 70°C.
Example 2: STM32 Microcontroller Board (USB-C 5V Input)
text
Design an STM32 microcontroller board powered from a 5V USB-C input.
Power requirements:
- Input: 5V DC via USB-C receptacle (4.75V to 5.5V VBUS).
- Regulation: 3.3V low-dropout regulator (AP2112K-3.3 or equivalent) with 100mA continuous load capability.

Microcontroller requirements:
- MCU: STM32F407 MCU (LQFP-100) operating at 3.3V.
- Clock: 8 MHz HSE crystal oscillator with 27 pF load capacitors.
- Power integrity: 6x 100 nF VDD decoupling capacitors, 1x 4.7 µF bulk capacitor, and 2x 2.2 µF VCAP capacitors.
- Boot & Control: 10 kΩ BOOT0 pull-down resistor, tactile reset push button connected to NRST.

Interfaces & Diagnostics:
- Debug: Standard 5-pin SWD debug header (3V3, SWDIO, SWCLK, NRST, GND).
- User interface: User status LED connected to GPIO with a current-limiting resistor.

PCB & Mechanical requirements:
- PCB stackup: 2 layers.
- Board dimensions: 60 mm width by 40 mm height.
- Mounting: 4x M3 mounting holes (3.2 mm diameter).

See docs/EXAMPLE_PROMPTS.md for full stage-by-stage pipeline outcomes and engineering calculation details.


2 Design Philosophy

CircuitMind is intentionally designed to avoid treating an LLM as the source of truth.

2.1 Engineering Truth Hierarchy

CircuitMind follows this general hierarchy:

text
KiCad Project Files
        │
        ▼
Native KiCad CLI / Parsers
        │
        ▼
Deterministic Engineering Facts
        │
        ▼
Canonical EDM Graph
        │
        ├──────────────► Deterministic Calculation Engine
        │
        ├──────────────► Verification Engine
        │
        └──────────────► Retrieval / Knowledge Layer
                                  │
                                  ▼
                             AI Reasoning
                                  │
                                  ▼
                              ChangeSet
                                  │
                                  ▼

The AI layer can propose, explain, compare, and reason.

It should not invent:

  • Component identity
  • Net connectivity
  • Pin connectivity
  • PCB coordinates
  • DRC/ERC violations
  • BOM information
  • Design-rule results
  • Electrical measurements

Those facts must originate from deterministic engineering sources.

2.2 Safety Principles

CircuitMind follows several safety principles.

Principle 1 — Deterministic facts before reasoning

Use native EDA data before asking an LLM to infer design relationships.

Principle 2 — No regex-based identity reconstruction

Do not infer electrical identity solely from human-readable error descriptions.

Principle 3 — Design state must be known

Use DSM hashes and project state checks to detect stale information.

Principle 4 — Changes must be explicit

Represent modifications as ChangeSets rather than implicit AI mutations.

Principle 5 — Verify after modification

A successful file modification does not mean the engineering change is correct.

Run deterministic verification after changes.

Principle 6 — Preserve evidence

Engineering findings should retain their source and supporting evidence wherever practical.

2.3 In One Sentence

CircuitMind is evolving toward a platform where:

KiCad provides the facts. The EDM graph provides the structure. Deterministic engines provide the calculations. Qdrant provides engineering knowledge. AI provides reasoning. DSM provides state integrity. KCAA provides controlled execution. Verification provides evidence.

The objective is not simply to build an AI chatbot for electronics.

The objective is to build an engineering system in which AI reasoning is constrained by deterministic design facts, explicit evidence, controlled execution, and repeatable verification.


3 System Status

CircuitMind is an active engineering-development project. Some subsystems are production-oriented while others remain experimental.

backend/app/main.py imports cleanly. Run pytest from the repository root for the hermetic suite (1018 tests collected; live-service tests are marked and skipped unless configured — see §22).

3.1 Readiness

SubsystemReadinessStateDescription
KiCad 10 Headless DRC/ERC100%LIVEExecutes kicad-cli ERC/DRC, parses JSON violations into findings, computes verification deltas
Smart Verification Cache90%LIVEDRC/ERC are skipped while every schematic sheet, the board, the .kicad_pro, any .kicad_dru and the kicad-cli install are unchanged and the last result was usable; the status shows STALE as soon as one of them changes, and Run Full Verification always reruns (§5.1). Pipeline stages run their own checks every time
PCB Layer SVG Visualizer100%LIVEGenerates multi-layer SVG visualization with coordinate crosshair support
Schematic Vector Visualizer100%LIVEMulti-sheet SVG export via KiCad CLI with calibrated reticle overlay for cross-probing
BOM & Netlist Extraction90%LIVENative BOM/netlist extraction via kicad-cli and a real s-expression parser, feeds the EDM graph hydration pipeline
5-Plane Canonical EDM Graph40%LIVE/WIPOnly LOGICAL and PHYSICAL planes are populated; INTENT, FUNCTIONAL, and VERIFICATION planes are not yet implemented
Visual IR → KiCad schematic (§6)BetaLIVE/HYBRIDImage/PDF schematic → components, pins, geometry-proven connection suggestions → engineer review → ERC-gated KCAA build verified by netlist read-back. Op-amp polarity and unnamed parts always need an engineer (§6.6)
Visual retrieval (ColQwen) indexing (§6.7, §13.5)BetaLIVE/OPTIONALRendered pages are embedded through vLLM /pooling (chat request; server needs --chat-template deploy/colqwen/chat_template.jinja) into Qdrant, observable per job and never fatal. R@1 92.9 vs 64.3 for OCR text on a 14-query schematic test (§11.4); evidence only
Deterministic Calculation Engine85%LIVE/HYBRIDBuck (with TPS54360 support parts), voltage-divider, inductor/capacitor sizing, MLCC DC-bias derating, LDO dissipation, boost sizing, IPC-2152 trace width, tolerance, thermal and op-amp headroom math, wired into the design pipeline's component resolver and contract; RS-485 and other interface topologies are not yet implemented
Design Sync Manager (DSM)75%LIVESHA-256 multi-file hashing used for cache invalidation across PCB/schematic/EDM; gating is hash-equality, not a rich dependency gate
Qdrant Engineering Knowledge80%LIVE/HYBRIDFull upload → PDF extraction → embedding → indexing → semantic search → delete pipeline is implemented and wired; documents are now Global (org-wide library) or Project-private, with global docs applyable per-project
KCAA Safe Execution Sandbox55%EXPERIMENTALSandbox clone/commit, MCP stdio driver, and LLM-driven repair-loop orchestrator exist with a full /api/repair/* session lifecycle
Design Pipeline (Requirements → Gate 3 release)BetaLIVE/HYBRIDStages 0–8 with gates G0–G5: requirements, architecture, components validated against the KiCad libraries, contract with a connectivity plan, schematic synthesis and verification (ERC, ngspice DC operating point), placement, Freerouting routing with ground plane, DRC repair loop, and the Gate 3 release package. The D9 end-to-end run released both reference boards (12 V→5 V buck, STM32F407) on real KiCad 10 (docs/D9_PC_RESULTS.md); routing is not yet repeatable on every run
Firmware Simulation (STM32F4-Discovery, Renode)BetaLIVE/HYBRIDEditable architecture canvas, Simulation Bench with pin bindings, Renode runs replayed on the canvas (LED, button, UART), firmware build worker on a fixed skeleton, AI-written firmware and tests the engineer reviews, bench bindings checked against the KiCad netlist (docs/simulation-spike.md); one target, Windows-verified
Mechanical Stage (board 3D, enclosure, fit, GM) (§9A)BetaLIVE/HYBRIDkicad-cli STEP/GLB export with a model-status manifest, enclosure intent in the contract, deterministic two-piece case generated by headless FreeCAD, box + exact fit tiers, gate GM and enclosure files in the Gate 3 release
Reference Library & AI Design Comparison100%LIVEArchitecture > Reference Library runs an LLM-graded, RAG-grounded functional/physical block comparison of the live design against a chosen reference document, utilizing multi-modal VLM circuit graph extraction and evidence fusion.
Remote Project Access (ZIP Upload/Download)70%LIVEUpload a ZIP of a KiCad project over HTTP to open it on a server the browser isn't running on, and download the live project folder back as a ZIP (see §19); no authentication yet

Readiness percentages represent the current development state and are not production-readiness certifications.

3.2 Database and Tests at a Glance

  • Schema: managed by Alembic (head a6c8e0f2b4d5); the application only verifies at startup that the database is at head (§14.3).
  • Tests: 1018 collected; the hermetic suite passes without KiCad, KCAA, a GPU or torch. Live suites are opt-in (§22).
  • Benchmarks: component detection, text extraction, page retrieval and VLM verification were measured and are reported in Part III (§11) together with their limits.

3.3 Current Development Priorities

  1. Repeatable D9 routing: the same commit must release both reference boards on every run (docs/D9_PC_RESULTS.md)
  2. EDM graph completion (FUNCTIONAL and VERIFICATION planes; INTENT holds only the contract's rails today)
  3. KCAA sandbox hardening (§13.4, §10)
  4. Authentication in front of the API, before remote access (§19) is exposed beyond a trusted LAN
  5. Per-session/per-user project isolation (there is currently one global active project shared by every connected client)
  6. ChangeSet validation and end-to-end verification workflows
  7. AI-assisted engineering workflows beyond the current Reference Library comparison (§7.2) and generic Engineering Audit
  8. Detector quality on KiCad-rendered schematics (§11.3): the model was trained on hand-drawn circuit images, so a KiCad-style training set is the highest-value improvement for Visual IR
  9. Validate visual retrieval on a larger set (datasheets and more schematics) before any rank fusion with text (§11.4)
  10. Hybrid lexical + dense text retrieval for datasheet lookups (§11.2, §11.6)

4 Architecture

4.1 System Architecture

text
                         ┌───────────────────────┐
                         │   CircuitMind UI      │
                         │ React / Vite /        │
                         │ Tailwind              │
                         └───────────┬───────────┘
                                     │
                                     │ REST API
                                     ▼
                         ┌───────────────────────┐
                         │    FastAPI Backend    │
                         └───────────┬───────────┘
                                     │
              ┌──────────────────────┼──────────────────────┐
              │                      │                      │
              ▼                      ▼                      ▼
       ┌─────────────┐       ┌─────────────┐       ┌──────────────┐
       │ KiCad CLI   │       │ PostgreSQL  │       │   Qdrant     │
       │              │       │             │       │              │
       │ DRC/ERC      │       │ Canonical   │       │ Engineering  │
       │ BOM         │       │ EDM Graph   │       │ Knowledge    │
       │ Netlist     │       │             │       │              │
       │ SVG         │       │             │       │              │
       └──────┬──────┘       └─────────────┘       └──────────────┘
              │

4.2 Architectural Boundaries

KiCad 10.x

CircuitMind targets KiCad 10.x.

The live verification and export pipeline relies on KiCad 10.x CLI functionality, including:

  • Headless DRC
  • Headless ERC
  • BOM generation
  • Netlist generation
  • Schematic SVG export
  • PCB visualization/export workflows

Older KiCad versions are not currently supported by the v6 verification pipeline.


Read-Heavy and Non-Destructive Operation

CircuitMind is intentionally conservative when interacting with design files.

Analysis operations should be read-only.

AI-generated modifications are represented as proposed ChangeSets rather than immediately modifying the KiCad project.

The intended workflow is:

text
AI Proposal
     │
     ▼
ChangeSet
     │
     ▼
DSM Preconditions
     │
     ▼
Controlled Execution
     │
     ▼
KiCad Re-analysis
     │
     ▼
DRC/ERC Verification

Direct uncontrolled modification of the user's KiCad project is intentionally avoided.


Deterministic Source of Truth

CircuitMind does not use textual descriptions from DRC/ERC messages as the primary identity of design objects.

For example, a description such as:

text
Symbol R3 [R1206_10K_1%_0.25W_100PPM]

is not sufficient to uniquely identify the electrical context of a component.

Component identity, connectivity, pins, nets, coordinates, and relationships should instead be derived from:

  • KiCad project data
  • Native KiCad parsers
  • Netlists
  • BOM data
  • PCB data
  • DRC/ERC structured output
  • Deterministic graph relationships

This prevents fragile regex-based reverse engineering of engineering relationships.

4.3 Canonical EDM Graph

CircuitMind uses a canonical Engineering Design Model (EDM) to represent the hardware design independently from individual UI representations.

The graph is intended to represent multiple engineering planes, including:

  1. Component Plane
  2. Connectivity / Net Plane
  3. Physical / PCB Plane
  4. Requirement / Specification Plane
  5. Verification / Evidence Plane

Conceptually:

text
                 ┌─────────────────┐
                 │   Requirements  │
                 └────────┬────────┘
                          │
                          ▼
┌────────────┐     ┌──────────────┐     ┌─────────────┐
│ Components │────►│ Canonical EDM│◄────│   Nets      │
└────────────┘     │    Graph     │     └─────────────┘
                   └──────┬───────┘
                          │
             ┌────────────┼────────────┐
             ▼            ▼            ▼
         Physical     Verification   Evidence
           PCB          DRC/ERC      Knowledge

The database currently uses composite identity structures such as:

text
(project_id, entity_id)

to prevent collisions between entities belonging to different projects.

4.4 Design Synchronization Manager

The Design Synchronization Manager (DSM) protects against reasoning against stale design data.

DSM tracks project state using SHA-256 hashes across relevant project files.

Conceptually:

text
Project Files
     │
     ▼
SHA-256 Hashing
     │
     ▼
Current Design State
     │
     ├── unchanged ──► cached verification may be reused
     │
     └── changed ────► re-analysis required

The DSM is also used as a pre-condition gate before controlled design mutations.

A proposed ChangeSet should not execute if the underlying design state has changed unexpectedly.


Part II — Core Capabilities

5 Verification and Cross-Probing

5.1 Verification

CircuitMind integrates with the KiCad CLI for deterministic verification.

Typical verification flow:

text
KiCad Project
      │
      ▼
kicad-cli
      │
      ├── DRC
      ├── ERC
      ├── BOM
      ├── Netlist
      └── SVG
      │
      ▼
Structured Results
      │
      ▼
CircuitMind Verification Model
      │
      ▼
Frontend Findings
Smart Verification Cache

The verification cache uses file hashes to avoid unnecessary DRC/ERC execution (dsm.get_verification_keys). A result depends on two keys: every schematic sheet plus the .kicad_pro, and the board plus the .kicad_pro and any .kicad_dru. Local UI state (.kicad_prl) and KiCad backups do not count.

Conceptually:

text
Project Hash
     │
     ├── unchanged ──► reuse previous verification
     │
     └── changed ────► execute KiCad verification

A result of ERR, UNKNOWN or a missing tool is never reused. Run all tests reuses a current result; Run Full Verification (DRC/ERC) on the Verification dashboard always reruns (POST /api/tests/run-all?force=true).

5.2 Interactive Cross-Probing

CircuitMind supports cross-probing between verification findings and visual design representations.

Example workflow:

  1. Open Verification.
  2. Select an active finding.
  3. Select View in PCB Canvas.
  4. CircuitMind switches to the PCB visualization.
  5. The violation coordinate is projected onto the canvas.
  6. A visual reticle identifies the relevant location.

This allows deterministic coordinates from KiCad verification output to be connected directly to the visual engineering workstation.


6 Visual IR Pipeline

The Visual IR pipeline turns a schematic image or PDF into a structured, reviewable graph — components, pins, wires, junctions, connection evidence and coordinates — and, after an engineer reviews it, builds a KiCad schematic through KCAA that is checked by netlist read-back.

6.1 Principles

  • Never fabricate connectivity. A net exists only if an engineer accepted evidence for it.
  • The VLM and ColQwen produce evidence, not authority. Only services/visual_ir/decisions.py writes ENGINEER_OVERRIDE, and only from an explicit human action.
  • Re-extraction is reconciliation, not a reset. Engineer decisions follow matched parts; unmatched ones become ORPHANED (re-bind or discard).
  • KCAA is the only writer of .kicad_sch. Pin numbers and names come only from KCAA get_symbol_pins.
  • Exact read-back. An export is accepted only when the topology read back from KiCad equals the approved connections.
  • Honest uncertainty. Anything that cannot be proven is UNPLACED or SUGGESTED with a reason code, never silently promoted.

6.2 Pipeline Stages

Every stage is persisted as a VisualJobStage row (status, timing, error, model versions), so a job can be inspected, retried or cancelled. Stages 4–7 run once per page. Order (services/visual_extraction.py):

OrderStageWhat it does
1ingestRegister the PDF/image and its pages
2analyzeRoute each page by content type (VECTOR, RASTER, VECTOR_MIXED): does it carry usable vector drawings and a text layer?
3renderRender pages at 300 DPI; optionally index them for visual retrieval (§6.7)
4objectsYOLO component detection; text from the PDF text layer, or — when the vector text is empty (stroked/outlined text, as in the multichannel fixture) — PyMuPDF OCR (get_textpage_ocr, Tesseract, 300 DPI); YOLO text boxes are cropped and OCR'd
5associateGlobally consistent text↔component assignment (Hungarian); references, values and net labels are matched in separate passes
6wiresWires and junctions from vector drawings and/or raster masks, merged by confidence
7vlmVLM circuit description — evidence only
8normalizeNormalized coordinates and statuses
9symbols, pinsSymbol resolution (exact part-number match only), pin hydration and geometry
10connectivityStrict/loose net graph, ConnectionSuggestion rows, dangling-end evidence
11graphsVisual circuit graphs for the inspector

6.3 Symbols, Pins and Placement

  • Symbol: resolved from the KCAA symbol index by exact part number. There is no fuzzy fallback; no match means NEEDS_SYMBOL.
  • Pins: numbers and names come from KCAA only. Pin positions come from the .kicad_sym geometry (parsed by symbols/geometry.py) mapped onto the detection box, then cross-checked against the KCAA pin set. The detection box covers the symbol body; pins lie outside it, so the scale is taken from the body.
  • Orientation is fitted from the wire ends; when two orientations are indistinguishable (an op-amp flipped vertically swaps +/−) the fit reports ambiguity instead of guessing.
  • Auto-placement rule (placement.py): a part is PLACED only if all four hold — detector confidence ≥ place_min_confidence (0.5), box inside the page, aspect ratio within place_aspect_tolerance (±35 %) of the symbol body, and overlap with other detections ≤ place_max_overlap (0.3). Otherwise it is UNPLACED with a reason code: NEEDS_SYMBOL, LOW_CONFIDENCE, BBOX_OUT_OF_PAGE, BAD_ASPECT, OVERLAP or NO_BBOX. VLM-only components are always UNPLACED / NO_BBOX.

Thresholds live in VisualIRSettings (database columns with the defaults above). There is no Settings control or API for them yet; change them in the database.

6.4 Connectivity Evidence

  • Wires are graph-chained and break at junctions and T-points; KiCad junction dots are classified (DETERMINISTIC_JUNCTION, LIKELY_JUNCTION, LIKELY_CROSSING, AMBIGUOUS); a wire that merely crosses at a node is not joined.
  • The resolver builds a strict graph (exact, unambiguous, continuous evidence → GEOMETRY_CONFIRMED) and a loose graph (SUGGESTED).
  • A wire end that touches no pin is stored as a VisualDanglingEndpoint (NO_PIN_IN_TOLERANCE, AMBIGUOUS_PIN, OFF_PAGE) rather than dropped.
  • Nothing in this stage creates a net. Suggestions are only evidence for the review queue.

6.5 Review, Reconciliation and Export

  1. Review (inspector): wire/junction/dangling overlays, drag-to-draw placement, an UNPLACED tray with reason codes, assign-symbol, add-pin, net naming, accept/reject suggestions (also batch-accept of geometry-confirmed ones), manual pin-to-pin connections, re-bind or discard of orphaned decisions.
  2. Reconcile on re-extract: matching in normalized units (reconcile_component_proximity 0.04, reconcile_pin_proximity 0.02); each endpoint of an orphaned connection is re-pointed independently, and an ORPHANED connection heals to APPROVED automatically when both ends match again. A .cmi snapshot/restore keeps the review state with the project.
  3. Export gate (exporter/erc_lite.py): errors block the export — floating pins, single-pin nets, duplicate references, UNPLACED or NEEDS_SYMBOL parts, missing references, shorted rails. Only PLACED, symbol-resolved parts and APPROVED + ENGINEER_OVERRIDE connections are exported.
  4. Build (exporter/export_job.py, kicad_builder.py): a scratch folder through KCAA; positions come from a page→mm scale derived from the symbol body, never from normalized values.
  5. Routing replay: a detected wire is reproduced with connect_points_with_wire only if its polyline is orthogonal, on the 1.27 mm grid and on real pin coordinates; the netlist is re-extracted after each wire, and a wire that shorts is deleted and replaced by connect_pins_with_wire. Each connection is tagged ROUTING_REPRODUCED or ROUTING_FALLBACK.
  6. Verify: exact topology read-back, then an uncached kicad-cli sch erc; only on success is the project schematic replaced (the previous file is kept as .bak) and the .net written by kicad-cli. The report (blockers, routing tags, topology diff, ERC) is stored on the job and shown in the inspector.

Main API (all under /api/visual-ir):

EndpointPurpose
POST /upload, POST /jobs, POST /jobs/{id}/runCreate and run a job
GET /jobs/{id}, /stages, /graph, /evidence, /irJob state, stage rows, the typed review graph
POST /jobs/{id}/re-extractRe-run with reconciliation
POST /jobs/{id}/components/{cid}/place, /symbol, /pinsPlace a part, assign a symbol, add a pin
POST /jobs/{id}/suggestions/{sid}/accept, /reject; /connections/batch-accept-geometry, /connections/manualCreate engineer decisions
POST /jobs/{id}/connections/{cid}/rebind, /disconnect; /nets/rename; /reset-decisionsMaintain decisions
POST /jobs/{id}/export/check, /export/kicad; GET /jobs/{id}/export/reportERC-lite preview, gated export (422 with the report when blocked or unverified), stored report

MVP note: the Visual IR screen no longer shows an export panel. The review workflow ends at an approved netlist (pins joined by accepted connections, grouped into named nets), shown in the right-hand pane. The export endpoints above and their tests are unchanged and still available through the API; the UI control returns when KiCad export is part of the supported workflow.

6.6 Known Limits (by design)

  • Op-amp polarity is never geometry-proven. A vertical flip is indistinguishable from the original, so +/− connections stay SUGGESTED until an engineer accepts them.
  • Unnamed parts are blocked. A part the detector or OCR cannot name has no reference and is blocked by ERC-lite until one is set.
  • Routing replay covers single-wire connections. Junction branches use KCAA's pin-to-pin routing.
  • The detector was trained on hand-drawn schematics (§11.3). On KiCad renders it still misses roughly 15 % of components, never labels potentiometers resistor-adjustable, and over-counts ICs; the engineer's UNPLACED tray is the safety net. It runs at its training size (1024 px).
  • The EDM-publish, compare and reference-publish endpoints answer 501 rather than returning invented data, and /conflicts returns an empty list: conflict detection is not implemented.

6.7 ColQwen Page Indexing

Visual retrieval is an optional part of the render stage. It is auxiliary evidence: nothing in connectivity depends on it.

text
ColQwenClient ──► ColQwenProvider ──► vLLM  POST /pooling   (task: token_embed, multi-vector)
      │
      └────────► VisualRetrievalService ──► Qdrant (multivector, MaxSim)
  • One implementation talks to ColQwen (services/colqwen_service.py); ColQwenClient adds a per-page timeout, a sync bridge and an honest result per page. There is no /embed or /retrieve.
  • A page is sent as a chat-style /pooling request (messages with an image_url). The vLLM server must be started with --chat-template deploy/colqwen/chat_template.jinja (§13.5); the client sends no template of its own. Sending the image in multi_modal_data is silently ignored by the server and gives every page the same placeholder-only vectors (§11.4).
  • Pages are downscaled to ≤ 0.7 MP before embedding (the reference server has max_model_len 1024); each page becomes about 694 vectors of 320 values.
  • The Qdrant client uses the per-page timeout (not the 5 s library default), because multivector upserts can be slow on a local disk.
  • Vectors carry the job_id. A job's old vectors are deleted immediately before it is indexed again.
  • Disabled means no ColQwen evidence at all, never placeholder embeddings. A failure or timeout is recorded and never fails the extraction; after the first failed page the remaining pages are skipped.
  • The outcome (DISABLED, SUCCESS, PARTIAL, FAILED, TIMEOUT) is stored on the render stage row (model_versions["colqwen"]) and shown in the inspector.
Setting (Settings page / AppSettings)DefaultMeaning
colqwen_enabledtrueMaster switch
colqwen_index_pagestrueIndex rendered pages during extraction
colqwen_timeout_ms30000Per-page timeout
colqwen_collection(null)Qdrant collection; null uses circuitmind_reference_visual

6.8 Verified Results

Run on page2_multichannel_sch.pdf with the real YOLO weights, real KCAA and real kicad-cli, no engineer action (this first run used the detector at 640 px; at the trained size 1024 px it finds many more parts — §11.3 — and the real-service acceptance tests still pass):

  • 24 components detected, about 19 auto-placed (the rest UNPLACED with reason codes)
  • 15 connection suggestions, 8 of them geometry-confirmed; 33 dangling wire ends; 0 approved nets

After an engineer-style review of the suggestions: the export succeeded with 15 connections, the topology read-back matched exactly, KiCad ERC ran and passed (14 non-blocking pin_not_connected notices), the .net was produced, and one replayed wire that shorted two nets was caught and rolled back. Decisions survived a re-extract with 0 orphaned.

The final check — opening the generated .kicad_sch in the KiCad GUI and running ERC — is a manual step.

6.9 Delivery Status

PackageScopeState
W0Foundation and honesty: Alembic baseline + migrations, no hardcoded toolchain paths, authority hygiene, hermetic testsDone
W1Pipeline end to end: symbols, pins, pin geometry, auto-placement rule, geometry-proven suggestions, dangling-wire evidenceDone
W2Reconciliation on re-extract, wire/junction/dangling overlays, re-bind / rename / add-pin / assign-symbol controlsDone
W3ERC-lite export gate, wire-routing replay with tags, KiCad ERC and report stored on the jobDone
W4Acceptance tests and a run on the multichannel schematic against real KCAA + KiCadDone (final KiCad GUI check is manual)
W5ColQwen: one implementation over /pooling, optional and observable page indexing, job-scoped cleanup, settingsDone (verified against the real server)

7 Engineering Knowledge

7.1 Knowledge Base (Qdrant)

Qdrant is intended to provide retrieval over engineering documentation.

Potential knowledge sources include:

text
Engineering Standards
        │
Manufacturer Datasheets
        │
Application Notes
        │
Internal Design Guidelines
        │
Test Specifications
        │
       PDFs
        │
        ▼
Document Ingestion
        │
        ▼
Chunking
        │
        ▼
Embeddings
        │
        ▼
Qdrant
        │

This pipeline is implemented and wired end-to-end: upload a PDF, it's chunked and embedded into Qdrant, and both semantic search and the AI Engineering Review draw on it. Knowledge documents are either Global (visible to every project — standards, generic datasheets) or Project-private (this project's own reference material); a global document can be applied to a project from the Knowledge view. See §7.2 for the Reference Library, which uses one chosen document for a targeted design comparison rather than open-ended retrieval.

7.2 Reference Library and AI Design Comparison

CircuitMind can compare the live design against one specific reference document (a reference design, EVM guide, or similar), distinct from the open-ended "Engineering Audit" AI review (§7.1) that retrieves across the whole knowledge base rather than one chosen document.

Knowledge document scope

Every document in the Knowledge view (datasheets, standards, app notes, reference designs) is one of:

  • Global — visible to every project, the shared org-wide library (e.g. a standard or a generic manufacturer datasheet).
  • Project-private — visible only to the project it was uploaded for (e.g. a project's own reference design).

A global document can be applied to the open project from the Knowledge view without duplicating the file or its Qdrant vectors; applying/un-applying just links/unlinks it.

Reference Library (Architecture view)

Architecture > Reference Library lists the open project's linked documents of type Reference Design or EVM Design (its own private ones, plus any applied global ones). "Add Reference" uploads a new project-private Reference Design directly from there.

Running a comparison

Selecting Run Comparison on a linked reference document runs a comprehensive evidence fusion pipeline:

  1. Visual Circuit Graph Extraction: For reference designs, VLM-powered extractors (ColQwen3.5) pre-process diagrams into a strict Reference Graph containing discrete components, net aliases, functional blocks, and qualitative physical rules (e.g. proximity/thermal claims).
  2. Evidence Fusion: A unified semantic search merges Qdrant Text RAG, visual embeddings, and the parsed Reference Graph into a highly-contextual knowledge payload scoped strictly to the chosen document.
  3. Live Design Gathering: Gathers deterministic live design facts, including components, nets, PCB footprints, and routing tracks directly from the native KiCad EDM graph.
  4. LLM Synthesis & Mapping: Both context sets are sent to the reasoning LLM with strict epistemological boundaries:
    • Perform semantic mapping (e.g., matching a reference U1 to a live U3).
    • Never invent specifications or live values not present in the facts.
    • Emit REVIEW instead of guessing when evidence is missing or ambiguous.
  5. Structured Results: Produces a persisted, block-by-block table split into Functional (topology/values) and Physical (placement/layout) results. Each row contains the status (PASS/WARNING/REVIEW), a note, and exact provenance pointers (evidence_ids) tracing back to the reference source.

Results persist per (project, document) pair and are cleared automatically if that document is later un-applied or deleted from a project.

Reviewing a Visual IR job without a project

A schematic PDF alone can be reviewed against a datasheet or a reference design from the Visual IR screen (Review against a reference or datasheet). GET /api/visual-ir/jobs/{id}/compare/documents lists the indexed reference/EVM designs, datasheets and application notes; POST /api/visual-ir/jobs/{id}/compare ({doc_id}) runs run_reference_comparison with the job's parts and engineer-approved nets as the design (job_design_facts, no layout, so physical rows are a layout checklist marked Not available (schematic only)); GET /api/visual-ir/jobs/{id}/comparison returns the stored Functional and Physical rows. Rows are stored under the key visual-ir-job:<id>, so the Architecture view of a project never shows them. The same tables component (components/ComparisonTable.tsx) is used in both places. LaTeX in datasheet text is shown as symbols (_plain).

Visual IR netlist as a reference, and the deterministic graph comparison

A Visual IR job becomes a reference design with Use as reference design (Visual IR, under Netlist (approved); API POST /api/visual-ir/jobs/{id}/publish-reference). It writes a global Reference Design document, a ReferenceExtractionRun and its ReferenceComponent/ReferenceNet rows (components that have a reference designator, nets from engineer-approved connections only) and links the document to the open project. Parts without a designator are skipped (skipped_unnamed_components in the response). A job can be published more than once.

Run Comparison then adds deterministic rows from services/visual_ir/comparison/anchor_matcher.py to the LLM rows, all as Functional results:

  • Parts are paired by designator (a drawing's IC2A pairs with the design's IC2), then by type and value. Values are compared by meaning (parse_value): 10k, 4k7, 100nF, 0.1uF and library part names such as R1206_10K_1%_0.25W_100PPM read as ohms or farads, so a plain value matches a library name; a real difference is reported with both values.
  • Nets are compared by connectivity, not by name: a reference net passes when all its pins sit on one net of the live design (live pin-to-net links come from the EDM PIN -> NET relationships, _net_connections). The two ends of a resistor, capacitor or inductor are interchangeable. A missing part makes the net WARNING ("cannot be checked completely"); pins split over several live nets are a REVIEW row naming where each pin is.

The Architecture view shows one Functional and one Physical table per reference document, with a pass/warning/review summary.

Current state (2026-10-06): step 1 above names ColQwen3.5 as the extractor, but nothing in the backend calls ColQwen page search today. The comparison's visual evidence comes from stored VisualEvidence rows of a Visual IR job (services/evidence_fusion.py), and the only production ColQwen call is the optional page indexing of §6.7, which is currently ineffective (§11.4).


8 Deterministic Calculation Engine

CircuitMind contains a deterministic calculation layer intended to keep engineering calculations independent from LLM reasoning.

Implemented and wired into the design pipeline's component resolver (feeds Architecture > Generate Components, with passing integration test coverage):

  • Buck converter sizing (duty cycle, inductor ripple, output capacitance)
  • Voltage-divider sizing with exhaustive E96-series search across tolerance corners
  • Inductor and capacitor sizing
  • Tolerance / worst-case analysis
  • Thermal analysis
  • Op-amp bias / headroom tracing (walks the EDM graph's pin→net→pin connectivity)

Not yet implemented:

  • IPC-2152 PCB trace/current-capacity sizing
  • Additional topologies (boost, LDO, RS-485, and others)

See §3 (System Readiness) for the current readiness percentage.

The intended architecture is:

text
Engineering Inputs
       │
       ▼
Deterministic Calculation
       │
       ├── Formula
       ├── Inputs
       ├── Assumptions
       └── Units
       │
       ▼
Result + Evidence

The AI layer can explain the calculation, but the calculation itself should be reproducible.


9 Requirements, Tests and Demo Data

9.1 Requirements View

The Requirements view (sidebar: Requirements) tracks the open project's engineering requirements and their verification status — the left-hand side of the Requirement → Implementation → Test → Status traceability chain described in §2's Engineering Truth Hierarchy.

What it shows

A table of requirements, each with:

  • ID — a stable identifier (REQ-001, ...), unique within the project.
  • Requirement — the description of what must be true.
  • Impl. — the component(s)/mechanism intended to satisfy it.
  • Test — which test case (§9.2) verifies it.
  • Status — Pass / Warning / Fail / Unknown, shown as an icon.

Below the table: coverage percentage and verified/partial/unverified counts, computed live from the current requirement statuses.

Filtering
  • Category (sidebar sub-items: All / Electrical / Functional / EMC/EMI / Mechanical / Environmental) — filters by the Category column; click the × on the active category chip to clear it.
  • Status (top-right pills: All / Passed / Unverified / Failed) — filters by verification status.
Getting requirements in

Click Upload CSV and select a CSV with these exact headers:

text
ID,Category,Description,Target_Implementation,Test_Method,Status
  • ID — required; rows with a blank ID are skipped. Uploading a CSV with an ID that already exists updates that requirement in place rather than duplicating it, so re-uploading a revised CSV is a safe way to update the set.
  • Category — free text; use Electrical, Functional, EMC/EMI, Mechanical, or Environmental to match the sidebar's filter categories (anything else still works, it just won't have a matching sidebar shortcut).
  • Status — one of Pass, Warning, Fail, Unknown (anything else is stored as Unknown). Leave it Unknown on upload — statuses are normally set by Run All Tests (§9.2) or the AI Engineering Audit, not hand-entered.

A ready-to-use example is at samples/requirements.csv (see §9.3).

9.2 Automated Test Cases

The Tests view (sidebar: Verification > Automated Tests) runs and tracks the test cases that verify requirements (§9.1) against the live design.

What it shows

A table of test cases: ID, Type (Functional / Performance / Stress / ...), Title & Setup, Expected Outcome, and Status (Pending / Passed / Failed). When a test's title/setup/expected text names a net or a RefDes pin N that has a simulated DC operating-point voltage (from a live Ngspice run), that measured value is shown inline next to the expectation.

Getting test cases in

Click Upload Test CSV and select a CSV with these exact headers:

text
ID,Type,Title,Setup,Expected,Status

Like Requirements, ID is required and re-uploading an existing ID updates that test case in place. Status on upload should normally be Pending — it's set by running the tests, not hand-entered.

A ready-to-use example is at samples/testcases.csv (see §9.3).

Running tests

Run All Tests evaluates every test case for the open project:

  1. If the project is open in Live Mode, it runs a real headless DRC/ERC pass (§5.1) and a real Ngspice DC operating-point simulation first, and stores the results.
  2. Any test whose title contains "DRC" is evaluated against the real DRC status from step 1 (Pass only if DRC is clean) — this is how samples/testcases.csv's TC-105 demonstrates a genuinely deterministic, KiCad-grounded result rather than a simulated one.
  3. Two specific legacy test IDs (TC-001, TC-002) and specific setup text (+12V, IC1 pin 3) are special-cased to look up particular net names (+12V, vbias) from an older demo board — this only matters if a CSV happens to reuse those exact IDs or phrases; the sample files intentionally avoid them.
  4. Every other test case falls back to a generic evaluation: it's marked Passed, and if its text names a net/pin with a simulated voltage, that value is shown in the result (actualResults) for reference. There is no physical bench in the loop — this reflects what the deterministic/simulated data supports, not a hardware test result.

A single test can also be run individually via its row's Run action, which marks it Passed directly (used for manually-verified test cases rather than the automated DRC/Ngspice-driven evaluation Run All Tests performs).

9.3 Demo Data

samples/requirements.csv and samples/testcases.csv are a small, generic example set (12V input rail, 3.3V regulator, CAN bus, reverse-polarity protection, DRC/ERC cleanliness, thermal, mechanical fit) for exercising the Requirements (§9.1) and Automated Tests (§9.2) workflows end-to-end on any opened project — they aren't tied to any specific board's actual net names, so every requirement/test uploads and displays correctly regardless of which project is open, though the DRC-titled test case (TC-105) and any Ngspice-matched net voltages will only reflect real project data once the project has KiCad files and (optionally) Ngspice available.

To try them:

  1. Open, import, or upload a project (§14.1, §19).
  2. Requirements view > Upload CSV > select samples/requirements.csv.
  3. Verification > Automated Tests > Upload Test CSV > select samples/testcases.csv.
  4. Click Run All Tests to populate real/simulated results, then revisit Requirements — a future enhancement could sync requirement status from its linked test's outcome, but today Run All Tests marks every requirement Pass directly (see routers/tests.py::run_all_tests) rather than deriving it per-requirement from its linked test's result.

9A Mechanical Stage (Enclosure)

The Mechanical tab sits beside the design pipeline. It becomes available once the board is routed (the session reached STAGE7_ROUTING, i.e. G3 passed) and has its own gate, GM. It never moves the session status and never rewinds it: every result records the hashes it was made from (PCB, board export, contract, enclosure spec, plan, clearance classes) and is shown stale when one changes.

One board frame. Every mechanical file uses millimetres with the origin at the lower-left corner of the board outline, +X right, +Y up and Z = 0 at the PCB bottom. kicad-cli writes STEP and GLB straight into it (--user-origin); FreeCAD's glTF (metres, Y up) is converted for the viewer.

Flow

  1. Export board 3D (worker job mechanical_export): kicad-cli writes board.step, board.glb and a render, and mechanical_manifest.json is built from the .kicad_pcb and the export (JSON Schema in backend/app/services/mechanical/schemas/). kicad-cli exits 0 when models are missing, so its warnings are counted: a part whose model is missing (or that has none) is UNVERIFIED, never PASS. Part heights are measured from the GLB, whose nodes kicad-cli names by reference designator.
  2. Enclosure intent: requirements in category enclosure (type, manufacturing method fdm / sla / cnc, max_length / max_width / max_height, connector_faces such as J2:right, mounting) become the contract's mechanical.enclosure block, inside the contract hash (editing one rewinds the session past Gate 2 like any requirement). A preflight checks the board against it: outline in the envelope, Z stack-up, mounting holes, connector faces, part-height limit, each with the measured value and the limit.
  3. Generate: an EnclosureSpec (two-piece rectangular case with a screwed lid: walls, clearances, standoffs, lid lip, screws, cutout overrides; ranges per manufacturing method) becomes a deterministic plan (enclosure_plan.py): standoffs at the mounting holes, lid bosses and through-screws, cutouts from the contract's connector faces, the committed connector_table.json, or draft cutouts for unknown edge connectors. The worker runs the versioned FreeCADCmd script (cad/enclosure_cad_v1.py), which builds base, lid and screws, places the board STEP, saves enclosure.FCStd and exports STEP / STL / 3MF per part and GLBs, then probes the solids to confirm the geometry matches the plan.
  4. Fit check: a fast box tier in Python and an exact FreeCAD tier (intersection volume and distToShape per placed model, lid closure, solid validity), against the engineer's editable clearance classes. Failing parts are red in the 3D view, unverified ones amber.
  5. Gate GM: blocked by any FAIL; every UNVERIFIED part needs a recorded waiver; approval stores the hashes. When the contract requests an enclosure, Gate 3 (G5) also requires a current GM approval (mechanical_gate; NOT_REQUIRED otherwise).
  6. Release: the GM-approved enclosure goes into the release zip under mechanical/ (FCStd, STEP, STL / 3MF, manifest, render, spec, plan, fit report, hashes.json); an existing candidate is amended on approval. The release history flags packages whose board, contract or enclosure changed. PCB-side suggestions (missing models, a connector recessed behind the wall, the part that sets the case height, parts in the standoff keep-out) are findings only.

AI drafts. "Describe the enclosure" turns one sentence into a draft spec with design decisions via LLMGateway.generate_structured; "Ask AI to fix" proposes a spec for the failing checks. Drafts are validated against the method ranges, keep their origin (llm, engineer, llm+engineer) and only take effect when the engineer accepts them; the AI can never change the checks or the clearance classes.

Tools. kicad-cli (KiCad 10) and FreeCAD 1.1 FreeCADCmd, both installed by the engineer and found by locators (FREECAD_CMD, FREECAD_PATH or PATH for FreeCAD; §13.3.1). Run the worker (python -m app.worker, or CIRCUITMIND_SIMULATION_WORKER=inprocess) for exports and CAD jobs. Status per milestone: docs/enclosure/STATUS.md.


10 KCAA Safe Execution

KCAA is intended to provide a controlled execution mechanism between AI-generated engineering actions and the local development environment.

The long-term execution model is:

text
AI
 │
 ▼
Proposed Action
 │
 ▼
Validation
 │
 ▼
Permission / Safety Gate
 │
 ▼
KCAA
 │
 ▼
Controlled Tool Execution
 │
 ▼
Result
 │
 ▼
Verification

The AI should not receive unrestricted filesystem or shell access merely because it is capable of generating commands.


Part III — Technology Selection and Benchmarks

11 Technology Selection and Benchmarks

This part records why each component of the extraction pipeline was chosen, and how well it actually works. Every number below was produced by a script in benchmarks/ and its raw output is committed in benchmarks/results/. Measurements were taken on 2026-10-06.

Read this first. The benchmarks are small, single-design measurements and they found real problems, not only confirmations. Two were fixed on 2026-10-06 and are kept in the record: ColQwen page indexing embedded only placeholder tokens (§11.4), and the detector ran at 640 px although it was trained at 1024 (§11.3). §11.6 lists what was decided and what is still open.

11.1 Method, Hardware and Ground Rules

ItemValue
MachineWindows 11, NVIDIA RTX 5070 (12 GB), Python 3.12.10
LibrariesPyMuPDF 1.28.2 (the version the backend pins), pymupdf4llm 1.28.2, Tesseract 5.5.0, Ultralytics 8.4.171 / torch 2.7.0+cu128, scikit-learn TF-IDF
ModelsYOLO26m best.pt; ColQwen athrael-soju/colqwen3.5-4.5B-v3 on vLLM 0.30.0 (--max-model-len 1024 --gpu-memory-utilization 0.85 --enforce-eager --limit-mm-per-prompt '{"image":1,"video":0}' --chat-template deploy/colqwen/chat_template.jinja); nomic-embed-text; VLM qwen3.5:9b-Q4_K_M on Ollama
Ground truthRead from source files, never from the extractor under test (the KiCad .kicad_sch, the dataset's label files, the datasheet's known page numbers)
DatasetWhat it isSize
D1 — TL07x datasheetTL072CD.pdf (TI), 40 lookup queries with ground-truth pages (pinouts, tables, graphs, schematics, package drawings)89 pages, 40 queries
D2 — KiCad schematicboard/test1 multichannel mixer: ground truth = every visible reference designator and field value in the KiCad source, resolved through the sheet hierarchy. Two renderings: a fresh kicad-cli PDF export (text layer present) and the project fixture multichannel_sch.pdf (text outlined, no text layer)5 pages, 114 designators, 69 values
D3 — CGHD test splitRoboflow cghd-zenodo-11-all v4, the detector's training distribution (hand-drawn circuits), held-out test split252 images, 20,172 instances, 56 classes present
D4 — Schematic page retrievalThe 5-page fixture multichannel_sch.pdf; 14 queries generated from the KiCad source (4 page descriptions, 10 designator queries) with ground-truth pages5 pages, 14 queries

Ground rules: sample sizes are shown next to the numbers; negative and disappointing results are kept; what was not measured is listed in §11.8.

11.2 Text Extraction — PyMuPDF vs pymupdf4llm vs Tesseract

Question. Where does the text of a schematic page come from, and what is it worth?

Schematic pages (D2) — recall of visible reference designators and values, 5 pages, 300 DPI for OCR:

Source PDFExtractorDesignators (of 114)Values (of 69)s / page
kicad-cli export (text layer)PyMuPDF text layer114 (100 %)69 (100 %)0.007
PyMuPDF OCR (get_textpage_ocr, what the pipeline uses)72 (63 %)42 (61 %)0.81
Tesseract, psm 11 (sparse text)81 (71 %)65 (94 %)1.12
Tesseract, psm 6 (block)68 (60 %)38 (55 %)1.18
pymupdf4llm0 (0 %)0 (0 %)0.51
Fixture multichannel_sch.pdf (text outlined)PyMuPDF text layer0 (0 %)0 (0 %)0.003
PyMuPDF OCR (pipeline)72 (63 %)49 (71 %)0.58
Tesseract, psm 1192 (81 %)41 (59 %)0.96
Tesseract, psm 677 (68 %)40 (58 %)0.89
pymupdf4llm3 (3 %)4 (6 %)0.99

Notes: multi-unit parts are plotted as IC2A, IC2B; IC2A counts as IC2. The fixture was exported earlier than the current source, so its recall is measured against the current source's designators (page i ↔ sheet i) and is indicative only.

Datasheet pages (D1) — extractor cost, and the downstream task that matters: lexical page retrieval (TF-IDF) over each extractor's text with the 40 queries:

Extractors / pageTotal (89 pp)Empty pagesTables foundR@1R@5R@10MRR
PyMuPDF get_text0.0080.7 s7—67.592.595.00.777
pymupdf4llm (Markdown)0.8777 s03765.092.595.00.771
Tesseract 200 DPI (psm 3)1.17104 s0—57.592.595.00.718

What this shows

  • A PDF text layer is exact when present (100 %/100 %) and roughly 100× cheaper than any OCR (0.007 s vs 0.6–1.2 s per page). It is the primary path; OCR is a fallback for pages without one (analyze routes by content type — §6.2).
  • OCR is not trustworthy enough to be authority. On pages without a text layer the best setting per page type recovers 71–81 % of designators and 71–94 % of values (the weakest settings 55–68 %), and no setting wins on both: psm 11 reads designators better on the fixture, the pipeline's OCR reads values better there, and psm 11 wins both on the text-layer render. This is why OCR output is evidence, why parts without a recovered reference are blocked until an engineer sets one (§6.6), and why reference designators are matched globally rather than trusted one by one (§6.2).
  • pymupdf4llm is the wrong tool for schematic pages. It turns a vector drawing into a picture region and keeps only the title block, so it recovers nothing from a page that PyMuPDF reads perfectly. On prose/table datasheet pages it is as good as plain text for retrieval (65.0 vs 67.5 R@1; with n = 40 the difference is noise), ~100× slower, and it does find tables (37) and read pages PyMuPDF left empty — a candidate for table-heavy datasheet ingestion, not adopted anywhere in the backend today.
  • On the datasheet, the three extractors reach the same R@5/R@10; only R@1 and MRR separate them, in the order text layer > pymupdf4llm > OCR.

11.3 Component Detection — YOLO

Model. best.pt: Ultralytics YOLO26m (21.9 M parameters, 42 MB), 57 classes, trained 150 epochs at 1024 px on the Roboflow CGHD export (1,767 train / 493 validation images). The weights embed the training-time validation metrics (best epoch: P 0.946, R 0.808, mAP50 0.833, mAP50-95 0.721).

Held-out test split (D3) — 252 images never used for training or model selection, imgsz 1024:

PrecisionRecallmAP50mAP50-95InferencePost-processPeak VRAM
0.9560.7970.8280.70814.5 ms3.9 ms978 MB

Per-class AP50 on the classes a schematic is built from: integrated_circuit 0.93, diode 0.91, inductor 0.91, transistor-bjt 0.90, capacitor-unpolarized 0.88, terminal 0.87, resistor 0.87, text 0.86, voltage-dc 0.84, junction 0.82, gnd 0.81, operational_amplifier 0.80, capacitor-polarized 0.77, crossover 0.73. Weak classes: xor 0.44, circuit-drawing 0.38, and mechanical, microphone, unknown at 0.00 (their instance counts were not examined).

The domain gap — KiCad-rendered schematics. D3 is hand-drawn circuits; CircuitMind feeds the detector KiCad renders. The only check available without labelled KiCad images is a count comparison against the KiCad source (5 pages; expected 47 R, 16 RV, 40 C, 5 IC; a count check, not a localisation-aware metric, so it can over-credit):

InputimgszComponents found (matched)Count recallCount precision
kicad-cli export640 (the old pipeline default)40 of 10837 %85 %
1024 (training size; now used)92 of 10885 %81 %
Fixture multichannel_sch.pdf64036 of 10833 %90 %
102492 of 10885 %77 %

What this shows

  • The model is a solid general detector on its own distribution (mAP50 0.83, 14 ms per page — detection is never the latency bottleneck).
  • The pipeline used to call the model at ultralytics' default 640 px, although it was trained at 1024. On KiCad pages that cost more than half of the recall (37 % → 85 %). Fixed on 2026-10-06: YoloClient now runs at the size recorded in the checkpoint (train_args.imgsz, overridable). On the fixture page page2_multichannel_sch.pdf (confidence 0.5) this changes component-like detections from 5 to 26 and total detections from 55 to 152; the real-service acceptance run (§6.8) still passes.
  • Potentiometers (RV) are never detected as resistor-adjustable (0 of 16 at either size) and ICs are over-counted (14–15 found for 5). Both likely reflect the hand-drawn training set; the highest-value upgrade is training data rendered from KiCad (§3.3). Until then, the review UI's UNPLACED tray and the placement thresholds (§6.3) are the safeguard — the detector's output is never trusted for connectivity.

11.4 Page Retrieval — Text vs ColQwen

Question. Does visual retrieval (ColQwen) find the right page better than text retrieval?

A defect found, and fixed

The first measurement (D1, the 89-page datasheet, 40 queries) gave ColQwen R@1 2.5 / R@10 35.0 — and the reason was not the model:

  • All 40 queries returned the identical ranking (pages 4, 7, 10, 13, 16, …), and in Qdrant all 89 page vectors were identical (each a 3 × 320 matrix). Re-indexing at another resolution gave the exact same metrics.
  • Cause: the indexing request sent the page as multi_modal_data, a field vLLM's /pooling completion request does not accept, so the server embedded only the three placeholder tokens <|vision_start|><|image_pad|><|vision_end|> and ignored the image. The project's earlier benchmark (2026-10-02; fused R@1 22.5) shows the same constant ranking: it measured this defect, not the model.
  • Fix (2026-10-06): pages are sent as a chat request (messages with an image_url). This vLLM 0.30.0 deployment cannot resolve the model's own chat template (unhashable type: 'dict', also logged as "Chat template warmup failed" at every start), so the server is started with a plain template file, --chat-template deploy/colqwen/chat_template.jinja (§13.5). After the fix a page embeds to 694 tokens × 320 and different pages get different vectors.
  • Regression test: test_the_embedding_depends_on_the_page_image (real-server, marked colqwen).

Historical result of the broken run (kept in benchmarks/results/retrieval_before_fix_placeholder_embeddings.json): ColQwen alone R@1 2.5 / R@5 20.0 / R@10 35.0 / MRR 0.115; RRF fusion with it cut text retrieval's R@1 from 47.5 to 22.5, which shows that rank fusion with an unvalidated retriever is dangerous.

Measurement with the fix (D4: 5-page schematic fixture, 14 queries)

The datasheet was not re-run (the 89-page benchmark is slow and the page-level question is better asked of schematics). Each system ranks the 5 pages for each query; chance for R@1 is 28.6 %.

SystemR@1R@3MRRNotes
Text: Tesseract OCR of the fixture + TF-IDF64.385.70.770What the pipeline has for this PDF (no text layer)
Text: PDF text layer of a fresh kicad-cli export + TF-IDF71.485.70.806Upper bound for text; the fixture itself has no text layer
ColQwen (production client, ≤ 0.7 MP pages)92.9100.00.9644.5 s per query, 7.8 s per page to index
Query type (n)OCR text R@1Text-layer R@1ColQwen R@1
Page descriptions (4), e.g. "power input connector and audio output jack"75.0100.0100.0
Designators (10), e.g. "R19 and RV6", "op-amp IC4"60.060.090.0

All 14 queries produced 14 different ColQwen rankings, and the 5 pages have 5 distinct embeddings.

What this shows

  • With the fix, visual retrieval works: on this fixture it beats both OCR-based and text-layer retrieval, including on designator queries, where the text is small and OCR is least reliable. It finds the one page out of five that contains the named parts, even though four of the five pages are near-identical channel strips.
  • This is n = 14 on 5 pages of one design, so it is an encouraging signal, not a general result. The text baselines use plain TF-IDF over designator tokens, which is a weak retriever for such queries (60 % even with a perfect text layer).
  • ColQwen is therefore a credible evidence source for locating schematic pages, and the cost (about 8 s per page to index) is small next to a full extraction. It stays evidence, not authority (§6.1), and rank fusion with text must not be introduced without a validation on a larger set.

11.5 VLM Candidate Verification

Question. Can a VLM look at a candidate page and tell whether it answers the query? Setup: for each query, the text retriever's top-5 pages (200 query–page pairs) are shown to qwen3.5:9b-Q4_K_M as images with a structured-JSON prompt (CONFIRMED / REJECTED / UNCERTAIN); pages are then re-ranked by the VLM's confidence. Same prompt and ordering rule as the original benchmark; temperature 0.

ReasoningVerdict precisionrecallfalse acceptancefalse rejectionuncertainLatency / verdict
Off (think: false)43.0 %97.6 %26.5 %0.5 %0 %5.3 s (2 requests in flight)
RankingR@1R@5R@10MRR
Text (dense; MRR over the top 10)47.582.592.50.624
Text → VLM re-rank, reasoning off65.082.592.50.735

What this shows

  • The VLM is a good filter and a poor judge: it almost never rejects the right page (0.5 % false rejection, 97.6 % recall) but accepts a lot of wrong ones (precision 43 %). Used to re-rank the top-5 it lifts R@1 from 47.5 % to 65.0 % (+17.5 points) and MRR from 0.624 to 0.735 without changing R@5/R@10, since it can only reorder candidates it is given.
  • A 43 %-precision verdict must never gate anything. That matches the pipeline's rule that the VLM produces evidence, not authority (§6.1): its output is displayed and used for ordering, and only an engineer creates connections.
  • Reasoning is a large cost, and its accuracy effect was not measured. With the model's default reasoning on, one verdict took 11.3 s in a single-request probe (1.5 s with reasoning off), and the five verdicts of the first benchmark query took about 6 minutes; the full run (≈ 4 hours) was abandoned. Every accuracy figure in this section is therefore for reasoning off.
  • The "text + ColQwen candidates → VLM" arm of the original benchmark was not repeated: its ColQwen candidates were the constant ranking of the broken run (§11.4).

11.6 What the Evidence Decided

DecisionEvidenceStatus
Read the PDF text layer first; use OCR only when there is none100 %/100 % recall at 0.007 s/page vs 71–81 %/71–94 % at 0.6–1.2 s/page (§11.2)In the pipeline
Treat OCR'd designators and values as evidence; block unnamed parts until an engineer names themBest OCR per page type recovers ≤ 81 % of designators and ≤ 94 % of values; no setting wins on both (§11.2)In the pipeline
Do not use pymupdf4llm for schematic pages0 of 114 designators recovered; keeps only the title block (§11.2)Decided; revisit only for datasheet-table ingestion
PyMuPDF for text, vector drawings and the OCR wrapperBest retrieval (R@1 67.5, MRR 0.777) at the lowest cost (§11.2)In the pipeline
YOLO26m for component boxes, never for connectivitymAP50 0.828 / P 0.956 / 14.5 ms; but 85 % count recall at best on KiCad renders, no potentiometer class (§11.3)In the pipeline, now at the trained size (1024 px, fixed 2026-10-06)
Engineer-gated review with UNPLACED reason codesDetector domain gap and OCR limits aboveIn the pipeline
ColQwen as page-level visual evidence, not in text rankingAfter the fix: R@1 92.9 vs 64.3 (OCR text) on 14 schematic queries; before it, a constant ranking and RRF cut R@1 47.5 → 22.5 (§11.4)Fixed 2026-10-06 (chat request + server-side --chat-template); validate on a larger set before any fusion
VLM as re-ranker/evidence, never a gate+17.5 pts R@1 but 43 % verdict precision (§11.5)In the pipeline
Lexical (TF-IDF) retrieval deserves a place next to dense retrieval for datasheet lookups67.5 vs 47.5 R@1 on the same queries (§11.2)Not adopted — a measured opportunity (hybrid retrieval was not tested)

11.7 Reproducing the Benchmarks

bash
# CPU only (needs PyMuPDF, pymupdf4llm, pytesseract + Tesseract, scikit-learn; KICAD_CLI_PATH or kicad-cli on PATH)
python benchmarks/bench_text_extraction.py

# needs the vLLM ColQwen server (started with --chat-template deploy/colqwen/chat_template.jinja) and Qdrant
COLQWEN_API_BASE_URL=http://localhost:8101 QDRANT_URL=http://localhost:6333 python benchmarks/bench_retrieval_schematic.py
# the 89-page datasheet version additionally needs Ollama (nomic-embed-text) and is slow
COLQWEN_API_BASE_URL=http://localhost:8101 QDRANT_URL=http://localhost:6333 python benchmarks/bench_retrieval.py

# stop the ColQwen container first (it holds ~10.7 of 12 GB): the VLM and YOLO need the GPU
python benchmarks/bench_vlm.py --think off          # `--think default` (reasoning on) takes hours
YOLO_DATASET_DIR=<path to the CGHD export> python benchmarks/bench_yolo.py

Inputs that are not in the repository and must be supplied locally: TL072CD.pdf (the TI datasheet), board/test1 (the KiCad source used as ground truth), the CGHD detector dataset (YOLO_DATASET_DIR) and the weights best.pt. Results land in benchmarks/results/*.json. retrieval_before_fix_placeholder_embeddings.json is the datasheet run that exposed the ColQwen defect (§11.4) and is kept as evidence; retrieval_schematic.json is the measurement after the fix.

11.8 Limits of This Evidence

  • Sample sizes are small: 40 queries on one datasheet; 5 schematic pages from one design (the four channel sheets share a layout, so they are not independent); 252 detector test images. Differences of a few points (for example 65.0 vs 67.5 R@1) are noise.
  • No labelled KiCad images exist for the detector, so the KiCad-render check counts components rather than scoring boxes, and the fixture PDF predates the current source.
  • Not measured: ColQwen on datasheets after the fix (only the 5-page schematic fixture was re-measured), the VLM's circuit-description accuracy (the vlm stage), wire/junction extraction accuracy against the source, and end-to-end connectivity beyond the single acceptance run in §6.8.
  • Latency is specific to this machine and to the models' state at the time (first-load effects, other GPU users).
  • The VLM runs at temperature 0 but is not guaranteed deterministic.

Part IV — Installation and Configuration

12 Infrastructure Requirements

Required

ComponentRequirement
OSWindows 10/11 64-bit, or Ubuntu 24.04 LTS 64-bit
KiCadKiCad 10.x
PythonPython 3.12+ 64-bit
Node.jsNode.js 20.x or 22.x
npmIncluded with Node.js
PostgreSQLPostgreSQL 15+
QdrantQdrant server
KCAAKCAA executable / MCP bridge — installed via the kicad_ai_assistant KiCad plugin, see §13.4

Sections 13–14 below give setup steps for both Windows and Ubuntu 24.04, including KCAA (§13.4), which is installed as a KiCad plugin and runs on both platforms.

Recommended service ports:

ServicePort
CircuitMind Backend8000
PostgreSQL5432
Qdrant HTTP6333
Qdrant gRPC6334

13 Supporting Services and Tools

13.1 PostgreSQL

CircuitMind uses PostgreSQL for the canonical EDM graph and application state.

A PostgreSQL instance may be provided by:

  • Local PostgreSQL installation
  • Company-managed PostgreSQL
  • Development VM
  • Approved container environment
  • Other PostgreSQL-compatible infrastructure
Windows
Example Docker setup

If Docker is permitted:

powershell
docker run -d `
  --name circuitmind-postgres `
  -e POSTGRES_USER=circuitmind `
  -e POSTGRES_PASSWORD=circuitmind `
  -e POSTGRES_DB=circuitmind `
  -p 5432:5432 `
  postgres:16-alpine
Verify PostgreSQL
powershell
psql -U circuitmind -h localhost -d circuitmind

If psql is not available in PATH, use the PostgreSQL installation directory or configure PostgreSQL client tools separately.

Ubuntu 24.04
Option A — Native package
bash
sudo apt update
sudo apt install -y postgresql postgresql-contrib
sudo systemctl enable --now postgresql

sudo -u postgres psql -c "CREATE USER circuitmind WITH PASSWORD 'circuitmind';"
sudo -u postgres psql -c "CREATE DATABASE circuitmind OWNER circuitmind;"
Option B — Docker
bash
sudo docker run -d \
  --name circuitmind-postgres \
  -e POSTGRES_USER=circuitmind \
  -e POSTGRES_PASSWORD=circuitmind \
  -e POSTGRES_DB=circuitmind \
  -p 5432:5432 \
  postgres:16-alpine
Verify PostgreSQL
bash
psql -U circuitmind -h localhost -d circuitmind

13.2 Qdrant

Qdrant is used for engineering knowledge retrieval, including:

  • Standards
  • Datasheets
  • Application notes
  • Engineering references
  • Internal documentation
  • Other approved engineering knowledge
  • Reference designs (see §7.2 — Reference Library)

CircuitMind communicates with Qdrant through HTTP on port 6333.

Windows
Option A — Standalone Windows Binary

Download the appropriate Qdrant Windows release and extract the executable.

powershell
.\qdrant.exe
Option B — Docker
powershell
docker run -d `
  --name circuitmind-qdrant `
  -p 6333:6333 `
  -p 6334:6334 `
  qdrant/qdrant

On company-managed machines where Docker is not approved, use the standalone Qdrant binary or an approved remote Qdrant instance.

Ubuntu 24.04
Option A — Standalone Linux binary

Download the appropriate Qdrant Linux release (qdrant-x86_64-unknown-linux-gnu.tar.gz or similar) and extract it:

bash
tar -xzf qdrant-x86_64-unknown-linux-gnu.tar.gz
./qdrant
Option B — Docker
bash
sudo docker run -d \
  --name circuitmind-qdrant \
  -p 6333:6333 \
  -p 6334:6334 \
  qdrant/qdrant
Verify Qdrant (both platforms)

Qdrant should then be available at:

text
http://localhost:6333
Embedding Model & Vector Dimension

The circuitmind_knowledge collection's vector size must match whatever embedding model EMBEDDING_MODEL (§14.2) is configured to use — different models produce different-sized vectors:

Embedding modelDimension
nomic-embed-text768
qwen3-embedding1024

CircuitMind handles this automatically: ensure_qdrant_collection (backend/app/services/vector_service.py) probes the configured model's actual output dimension on first use and recreates the collection if it doesn't match what's already there — so switching EMBEDDING_MODEL and restarting the backend is normally enough. Recreating the collection re-embeds nothing automatically, though, so existing Knowledge documents (§7.1) will need to be re-uploaded (or re-indexed) after switching models, since their old vectors are gone with the old collection.

To inspect or manually (re)create the collection instead of waiting for CircuitMind to do it on next use:

Check the current collection's vector size:

bash
curl http://localhost:6333/collections/circuitmind_knowledge

Manually create/reset it for a specific model (example: switching to nomic-embed-text, 768 dimensions). If the collection already exists with a different size, delete it first — this is the same delete-then-create sequence ensure_qdrant_collection runs automatically on a dimension mismatch:

Linux / macOS:

bash
curl -X DELETE http://localhost:6333/collections/circuitmind_knowledge

curl -X PUT http://localhost:6333/collections/circuitmind_knowledge \
  -H "Content-Type: application/json" \
  -d '{"vectors":{"size":768,"distance":"Cosine"}}'

Windows (Command Prompt):

cmd
curl -X PUT http://localhost:6333/collections/circuitmind_knowledge ^
  -H "Content-Type: application/json" ^
  -d "{\"vectors\":{\"size\":768,\"distance\":\"Cosine\"}}"

Windows (PowerShell):

powershell
curl.exe -X PUT http://localhost:6333/collections/circuitmind_knowledge `
  -H "Content-Type: application/json" `
  -d '{\"vectors\":{\"size\":768,\"distance\":\"Cosine\"}}'

This deletes any existing vectors in the collection (not the KnowledgeDocument rows in Postgres, which just become un-indexed) — only do this deliberately, and plan to re-upload documents afterward.

13.3 KiCad 10

CircuitMind expects KiCad 10.x to be installed.

Windows
powershell
& "C:\Program Files\KiCad\10.0\bin\kicad-cli.exe" --version

If KiCad is installed elsewhere, configure the path through KICAD_CLI_PATH / KICAD_APP_PATH (§14.2).

Ubuntu 24.04

KiCad 10.x is not yet in Ubuntu 24.04's default repositories at the time of writing — use the official KiCad PPA:

bash
sudo add-apt-repository ppa:kicad/kicad-10.0-releases
sudo apt update
sudo apt install -y kicad

kicad-cli --version

Expected output should identify a KiCad 10.x installation on either platform.

13.3.1 FreeCAD 1.1 (Mechanical stage, optional)

The Mechanical stage builds enclosures with FreeCAD's headless FreeCADCmd (FreeCAD 1.1). Install FreeCAD and point CircuitMind at it with FREECAD_PATH (the FreeCAD folder; its bin/ holds freecadcmd) or FREECAD_CMD (the executable itself); otherwise freecadcmd must be on PATH. CIRCUITMIND_CAD_TIMEOUT_S (default 600) limits one CAD job. Without FreeCAD the board export still works and CAD jobs end with a clear "FreeCAD is unavailable" error.

13.4 KCAA

KCAA (paul356/kcaa) provides the controlled execution bridge used by CircuitMind's repair sandbox (§10). It ships as a KiCad plugin (kicad_ai_assistant) whose setup script creates a Python virtual environment and installs the kcaa executable into it — it is not a single downloadable binary.

Step 1 — Clone the repository (optional)

Only needed to build the plugin from source or contribute. Skip this if installing the pre-built plugin from the Releases page.

bash
git clone https://github.com/paul356/kcaa.git
cd kcaa
Step 2 — Install the plugin into KiCad's plugin directory

Download kicad_ai_assistant.zip from the Releases page.

Ubuntu:

bash
KICAD_PLUGIN_DIR=~/.local/share/kicad/10.0/scripting/plugins
mkdir -p "$KICAD_PLUGIN_DIR"
unzip kicad_ai_assistant.zip -d "$KICAD_PLUGIN_DIR"

Windows (PowerShell):

powershell
$KICAD_PLUGIN_DIR = "$env:USERPROFILE\Documents\KiCad\10.0\scripting\plugins"
New-Item -ItemType Directory -Force -Path $KICAD_PLUGIN_DIR
Expand-Archive -Path kicad_ai_assistant.zip -DestinationPath $KICAD_PLUGIN_DIR

Or build from source (from the cloned kcaa repository root):

bash
make dist-plugin          # produces dist/kicad_ai_assistant.zip

# Ubuntu:
KICAD_PLUGIN_DIR=~/.local/share/kicad/10.0/scripting/plugins
mkdir -p "$KICAD_PLUGIN_DIR"
unzip dist/kicad_ai_assistant.zip -d "$KICAD_PLUGIN_DIR"
Step 3 — Create the plugin virtual environment (generates the kcaa executable)

Run the setup script from inside the installed plugin directory — it creates a .venv, installs kcaa from PyPI into it, and downloads the Freerouting JAR. uv installs the required Python version automatically. KiCad already provides the environment variables the script needs (KICAD_VERSION, KICAD*_DIR, etc.), so no .env file is needed for this step.

Ubuntu:

bash
cd ~/.local/share/kicad/10.0/scripting/plugins/kicad_ai_assistant
./setup_plugin.sh

Windows (PowerShell):

powershell
cd "$env:USERPROFILE\Documents\KiCad\10.0\scripting\plugins\kicad_ai_assistant"
.\setup_plugin.ps1

Windows (Command Prompt):

cmd
cd /d "%USERPROFILE%\Documents\KiCad\10.0\scripting\plugins\kicad_ai_assistant"
setup_plugin.bat
Step 4 — Point CircuitMind at the generated executable

The script installs kcaa inside the plugin's .venv. Set KCAA_PATH (§14.2) accordingly:

  • Ubuntu: ~/.local/share/kicad/10.0/scripting/plugins/kicad_ai_assistant/.venv/bin/kcaa
  • Windows: %USERPROFILE%\Documents\KiCad\10.0\scripting\plugins\kicad_ai_assistant\.venv\Scripts\kcaa.exe

Verify it runs:

bash
# Ubuntu
~/.local/share/kicad/10.0/scripting/plugins/kicad_ai_assistant/.venv/bin/kcaa --help
powershell
# Windows
& "$env:USERPROFILE\Documents\KiCad\10.0\scripting\plugins\kicad_ai_assistant\.venv\Scripts\kcaa.exe" --help

The actual location is configurable either way — CircuitMind should not assume every developer or deployment machine uses the same username, KiCad version, or filesystem layout.

13.5 ColQwen3.5 (Visual Embeddings)

CircuitMind uses athrael-soju/colqwen3.5-4.5B-v3 for visual page retrieval (Reference Library, Visual IR page indexing — §6.7). ColQwen is a multi-vector late-interaction model, not a chat model and not a single-vector embedder: it acts as a dedicated visual-evidence retrieval engine, and it is evidence only (measured quality in §11.4).

Ubuntu 24.04 and Windows (WSL2)

Run it with Docker and vLLM, which serves ColQwen3.5 natively and exposes the multi-vector POST /pooling endpoint (task token_embed). A vLLM server has no /embed and no /retrieve: a 404 on those paths in the server log means a client is calling the wrong API.

(Windows: install WSL2 with Ubuntu. Docker Desktop with the WSL2 backend supports GPU pass-through natively.)

bash
# 1. Install Docker and NVIDIA Container Toolkit (if not already installed)
sudo apt update
sudo apt install -y docker.io nvidia-container-toolkit
sudo systemctl restart docker

# 2. Start vLLM serving the ColQwen model on host port 8101
sudo docker run --gpus all \
    --name circuitmind-colqwen \
    -v ~/.cache/huggingface:/root/.cache/huggingface \
    -v ~/.cache/vllm:/root/.cache/vllm \
    -v "$PWD/deploy/colqwen:/templates:ro" \
    -p 8101:8000 \
    --ipc=host \
    vllm/vllm-openai:latest \
    --model athrael-soju/colqwen3.5-4.5B-v3 \
    --max-model-len 1024 \
    --gpu-memory-utilization 0.85 \
    --enforce-eager \
    --limit-mm-per-prompt '{"image":1,"video":0}' \
    --chat-template /templates/chat_template.jinja
  • --chat-template is required. Page images are sent as chat requests. This vLLM version cannot resolve the model's own (dict-valued) chat template: every start logs Chat template warmup failed ... unhashable type: 'dict' and an image request fails with 400 unhashable type: 'dict'. deploy/colqwen/chat_template.jinja is a plain Qwen turn template; mounting it and passing --chat-template fixes both. The client sends no template of its own (and reports this hint if the server rejects a page request).
  • Context window: image tokens scale with pixel count, so the client downscales every page to ≤ 0.7 MP before embedding (about 694 vectors per page). A 300 DPI A4 render does not fit a 1024-token window.
  • GPU memory: the model alone takes about 8.6 GiB, so a 12 GB card is nearly full, and the desktop and other programs take 1–1.5 GiB of it. --limit-mm-per-prompt '{"image":1,"video":0}' stops vLLM from profiling video input (ColQwen only embeds images), which cuts the peak by more than a gigabyte: 0.85 then leaves 1 GiB for the KV cache, whereas 0.90 without it needed about 10.8 GiB free and failed whenever another program held more than ~1.2 GiB (Free memory ... is less than desired GPU memory utilization). Close other GPU users first (Ollama models, a running YOLO job). On a 12 GB card the engine once died with CUDA error: unknown error during a request; restart the container if that happens.
  • Startup: --enforce-eager skips torch.compile and CUDA-graph capture, so the container is ready in about 3 minutes instead of 6–15; a ColQwen embedding is not latency-critical, so the eager-mode inference cost is irrelevant here. Wait for /v1/models to answer before running anything against it.
  • Reference deployment (the one measured in Part III): vLLM 0.30.0, RTX 5070 with 12 GB.
Windows: keeping Docker and the model cache on another drive

Docker Desktop keeps its WSL data disk (31 GB with the vLLM image) on C: by default, and a bind-mounted Hugging Face cache can be large (the model repository holds three 9 GB copies of the weights; only the root model.safetensors is needed).

  1. Docker data disk: quit Docker Desktop, wsl --shutdown, move %LOCALAPPDATA%\Docker\wsl to the target drive (for example D:\docker\wsl), unregister the stale distro with wsl --unregister docker-desktop, and set "CustomWslDistroDir": "D:\\docker\\wsl" in %APPDATA%\Docker\settings-store.json; then start Docker Desktop. (A directory junction does not work: WSL refuses disks behind a mount point.) Alternatively use Settings → Resources → Advanced → Disk image location.
  2. Model cache: download it once on the host and mount it into the container:
powershell
$env:HF_HUB_DISABLE_SYMLINKS_WARNING = "1"
python -c "from huggingface_hub import snapshot_download as d; d('athrael-soju/colqwen3.5-4.5B-v3', cache_dir=r'D:\docker\huggingface\hub', ignore_patterns=['v1/*','v2/*','results/*'])"
docker run -d --gpus all --name circuitmind-colqwen -e HF_HUB_OFFLINE=1 `
    -v "D:\docker\huggingface:/root/.cache/huggingface" -v "D:\docker\vllm-cache:/root/.cache/vllm" `
    -v "$PWD\deploy\colqwen:/templates:ro" `
    -p 8101:8000 --ipc=host vllm/vllm-openai:latest `
    --model athrael-soju/colqwen3.5-4.5B-v3 --max-model-len 1024 --gpu-memory-utilization 0.85 --enforce-eager `
    --limit-mm-per-prompt '{\"image\":1,\"video\":0}' --chat-template /templates/chat_template.jinja

On Windows the Hugging Face cache stores symlinks, which a Linux container cannot follow through a bind mount; replace the links in ...\snapshots\<rev> with hard links to the files in ...\blobs (same drive, no extra space) before starting the container.

  • HTTPS interception: if an antivirus (for example Avast Web/Mail Shield) re-signs HTTPS traffic, the host trusts it but the container does not, and a download started inside the container fails with CERTIFICATE_VERIFY_FAILED. Downloading on the host (above) avoids this; or export the interception root certificate and point REQUESTS_CA_BUNDLE / SSL_CERT_FILE at a bundle that includes it.
CircuitMind configuration

Do not overwrite your existing VLM_API_BASE_URL (reasoning engine). Configure the dedicated ColQwen endpoint in backend/.env:

dotenv
# Existing reasoning / VLM endpoint
VLM_API_BASE_URL=http://localhost:xxxx/v1
VLM_MODEL=<your-current-reasoning-model>

# Dedicated visual retrieval endpoint (vLLM serves multi-vector embeddings on /pooling)
COLQWEN_API_BASE_URL=http://localhost:8101
COLQWEN_MODEL=athrael-soju/colqwen3.5-4.5B-v3

CircuitMind configures the Qdrant visual index for 320-dimensional multi-vector embeddings (MaxSim late interaction). Visual IR indexing is switched from the Settings page (colqwen_enabled, colqwen_index_pages, colqwen_timeout_ms, colqwen_collection — §6.7).

Verify
bash
curl http://localhost:8101/v1/models
COLQWEN_API_BASE_URL=http://localhost:8101 QDRANT_URL=http://localhost:6333 \
    pytest backend/tests/integration/test_colqwen_real.py

The two tests embed real pages through /pooling, check that different pages get different embeddings, index one into a throwaway Qdrant collection, retrieve it, delete it by job, and drop the collection.


14 Backend

14.1 Installation

Windows

Open PowerShell and navigate to the backend:

powershell
cd backend
python -m venv .venv
.\.venv\Scripts\Activate.ps1

Install dependencies:

powershell
pip install -r requirements.txt
Ubuntu 24.04
bash
cd backend
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

If python3-venv or build tools (for psycopg2-binary) are missing:

bash
sudo apt install -y python3-venv python3-dev build-essential libpq-dev

If the repository has no requirements.txt yet, install the minimum set directly on either platform:

text
pip install fastapi uvicorn sqlmodel psycopg2-binary httpx qdrant-client pydantic

14.2 Environment Configuration

Create backend/.env. The variable names are the same on both platforms — only the path syntax differs.

Windows example
dotenv
# PostgreSQL
DATABASE_URL=postgresql://circuitmind:circuitmind@localhost:5432/circuitmind

# Qdrant
QDRANT_URL=http://localhost:6333

# KiCad
KICAD_APP_PATH=C:\Program Files\KiCad\10.0
KICAD_CLI_PATH=C:\Program Files\KiCad\10.0\bin\kicad-cli.exe

# KCAA (installed via the kicad_ai_assistant plugin, see §13.4)
KCAA_PATH=C:\Users\<USERNAME>\Documents\KiCad\10.0\scripting\plugins\kicad_ai_assistant\.venv\Scripts\kcaa.exe

# Ngspice
NGSPICE_PATH=C:\Users\<USERNAME>\ngspice\ngspice_fftw.exe

# AI Gateway (OpenAI-compatible — Ollama, vLLM, OpenAI, ...)
AI_PROVIDER=ollama
AI_BASE_URL=http://localhost:11434/v1
REASONING_MODEL=gemma4:26b
EMBEDDING_MODEL=nomic-embed-text
Ubuntu 24.04 example
dotenv
# PostgreSQL
DATABASE_URL=postgresql://circuitmind:circuitmind@localhost:5432/circuitmind

# Qdrant
QDRANT_URL=http://localhost:6333

# KiCad
KICAD_APP_PATH=/usr/share/kicad
KICAD_CLI_PATH=/usr/bin/kicad-cli

# KCAA (installed via the kicad_ai_assistant plugin, see §13.4)
KCAA_PATH=/home/<USERNAME>/.local/share/kicad/10.0/scripting/plugins/kicad_ai_assistant/.venv/bin/kcaa

# Ngspice
NGSPICE_PATH=/usr/bin/ngspice

# AI Gateway (OpenAI-compatible — Ollama, vLLM, OpenAI, ...)
AI_PROVIDER=ollama
AI_BASE_URL=http://localhost:11434/v1
REASONING_MODEL=gemma4:26b
EMBEDDING_MODEL=nomic-embed-text

These match the variables read by backend/app/core/config.py — if a variable is omitted, that file's built-in default is used instead (and today defaults to a Windows-shaped path), so set every path explicitly on Ubuntu rather than relying on defaults.

Important

Do not commit machine-specific .env files containing:

  • Passwords
  • API keys
  • Private paths
  • Credentials
  • Internal infrastructure addresses

Add .env to .gitignore if it is not already ignored.

14.3 Database Migrations

Schema changes are managed by Alembic (backend/alembic, run from backend/):

bash
alembic upgrade head          # apply
alembic current               # show the revision (head: a6c8e0f2b4d5)
  • At startup the application only checks that the database is at head; it no longer creates or alters tables itself.
  • Migrations are idempotent (they inspect before they add), so they are safe to run against a database created by an older build. Take a pg_dump before upgrading a database you care about.
  • CIRCUITMIND_DEV_SCHEMA=1 re-enables the old create_all schema sync for throwaway SQLite databases (the hermetic tests use this).

14.4 Starting the Backend

From the backend directory (same command on Windows PowerShell and Ubuntu's bash):

bash
uvicorn app.main:app --host 127.0.0.1 --port 8000 --reload

The API should then be available at:

text
http://127.0.0.1:8000

FastAPI documentation is typically available at:

text
http://127.0.0.1:8000/docs

Remote access (§19): 127.0.0.1 only accepts connections from the same machine. To reach CircuitMind from another machine on the network, bind to 0.0.0.0 instead — uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload — and set the frontend's VITE_API_BASE_URL (§15.2) to this machine's LAN address, not localhost. There is no authentication in front of the API yet (see §19) — only do this on a trusted network.


15 Frontend

15.1 Installation

Open a second PowerShell terminal:

powershell
cd frontend

Install dependencies:

powershell
npm install

15.2 Environment Configuration

Create frontend/.env.

Local-only example:

dotenv
VITE_API_BASE_URL=http://localhost:8000/api

Remote-access example (backend bound to 0.0.0.0, see §14.4) — use the server's actual LAN IP or hostname, never localhost, since a remote browser's localhost refers to itself, not the server:

dotenv
VITE_API_BASE_URL=http://192.168.1.50:8000/api

15.3 Starting the Frontend

Run:

bash
npm run dev

Vite will provide a local development URL, normally similar to:

text
http://localhost:5173

For remote access (§19), expose Vite on the network too:

bash
npm run dev -- --host 0.0.0.0

Open the displayed URL in a browser (substitute the server's LAN IP for localhost when connecting from another machine).


16 Quick Start

For an experienced developer, the minimum workflow is:

Windows

powershell
# 1. Start PostgreSQL
# 2. Start Qdrant
# 3. Verify KiCad 10 CLI

& "C:\Program Files\KiCad\10.0\bin\kicad-cli.exe" --version

# 4. Backend
cd backend
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
uvicorn app.main:app --host 127.0.0.1 --port 8000 --reload

# 5. Frontend - separate terminal
cd frontend
npm install
npm run dev

Ubuntu 24.04

bash
# 1. Start PostgreSQL
# 2. Start Qdrant
# 3. Verify KiCad 10 CLI

kicad-cli --version

# 4. Backend
cd backend
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn app.main:app --host 127.0.0.1 --port 8000 --reload

# 5. Frontend - separate terminal
cd frontend
npm install
npm run dev

Then open the Vite URL shown by the frontend development server.


Part V — Operation

17 Operating Modes

Changed: earlier builds had a Mock Mode / Live Mode toggle in Settings that showed hardcoded demo data when no project was open. That toggle, and all of the mock/demo data behind it, has been removed — every view is backed by real data from whichever project is currently open.

CircuitMind now has a single mode: a project is either open or it isn't.

No project open

The workstation shows an explicit "No project open" empty state instead of placeholder content. The Design/Inspection mode tabs and the Sync Graph indicator are hidden until a project is opened. Settings remains reachable regardless, so the AI Gateway, KCAA, and KiCad paths can be configured before opening anything.

A project is open

Opening, importing, or uploading a project (File menu: New / Open / Import / Upload ZIP — see §19) connects the workstation to:

  • PostgreSQL (EDM graph, requirements, findings, tests, decisions, ChangeSets)
  • KiCad CLI (DRC/ERC, SVG export, BOM/netlist)
  • Qdrant (engineering knowledge, Reference Library — §7.2)
  • KCAA, where configured (§13.4, §10)

There is currently only one active project at a time, shared by every client connected to the backend — opening a different project on one machine changes what every other connected browser sees.


18 Typical Engineering Workflow

A typical CircuitMind workflow is:

text
1. Select KiCad Project
          │
          ▼
2. Discover Project Files
          │
          ▼
3. Calculate Project Hash
          │
          ▼
4. Parse Deterministic Design Data
          │
          ├── Schematic
          ├── PCB
          ├── BOM
          └── Netlist
          │
          ▼
5. Build / Update EDM Graph
          │
          ▼
6. Run Verification
          │
          ├── DRC
          └── ERC

19 Remote Access — Project Upload and Download

CircuitMind was originally built as a local desktop-style tool: File > Open/Import and the filesystem browse dialog all read paths on the server's own disk — the same machine the browser was assumed to be running on. That assumption breaks the moment the browser is on a different machine, since a remote client has no way to hand the server a path to its own local files.

Uploading a project

File > Upload Project (ZIP)... lets a remote (or local) engineer get a KiCad project onto the server over HTTP instead of typing a path:

  1. Zip the KiCad project folder (either the files directly at the ZIP's root, or inside a single wrapping folder — both are handled; CircuitMind flattens one level automatically).
  2. Upload it via the File menu.
  3. The server extracts the ZIP (with zip-slip path-traversal protection and a 200 MB size cap), validates it contains at least one .kicad_pro/.kicad_sch/.kicad_pcb file, and stores it under backend/project_uploads/<name>_<id>/.
  4. The upload runs through the exact same import/activation path as File > Import KiCad Project — including writing the project's .cmi save file — so an uploaded project behaves identically to a locally-opened one from that point on.

Downloading a project

File > Download Project (ZIP) zips the active project's live server folder on demand and streams it back. Because KCAA merges and approved ChangeSets already write directly into that same folder (§10), whatever is downloaded reflects exactly what has been approved — no separate export step is needed after a merge.

Known limitations (by design, for now)

  • No authentication. The API has no login in front of it. Only use remote upload/download on a trusted network (§14.4's reminder when binding to 0.0.0.0).
  • One active project globally. CircuitMind does not yet have per-session/per-user project isolation — opening or uploading a project changes the active project for every client connected to the backend, exactly as opening a different local path always has.
  • No automatic cleanup. Uploaded project folders persist under backend/project_uploads/ until manually removed; there is currently no "delete project" action for uploaded or locally-opened projects.

See §20 (Troubleshooting) for common upload/download and remote-access connectivity issues.


20 Troubleshooting

KiCad CLI cannot be found

Windows:

powershell
Test-Path "C:\Program Files\KiCad\10.0\bin\kicad-cli.exe"
& "C:\Program Files\KiCad\10.0\bin\kicad-cli.exe" --version

Ubuntu:

bash
which kicad-cli
kicad-cli --version

If KiCad is installed elsewhere, update KICAD_CLI_PATH (§14.2).


PostgreSQL connection failure

Verify that PostgreSQL is running and listening on port 5432.

Check:

powershell
Test-NetConnection localhost -Port 5432

Then verify the configured connection string:

dotenv
DATABASE_URL=postgresql://circuitmind:circuitmind@localhost:5432/circuitmind

Qdrant connection failure

Check:

powershell
Test-NetConnection localhost -Port 6333

Then verify:

dotenv
QDRANT_URL=http://localhost:6333

KCAA cannot be executed

Confirm the kicad_ai_assistant plugin's setup script (§13.4 step 3) actually ran and created a .venv with kcaa installed in it before checking the path.

Windows:

powershell
Test-Path "$env:USERPROFILE\Documents\KiCad\10.0\scripting\plugins\kicad_ai_assistant\.venv\Scripts\kcaa.exe"
& "$env:USERPROFILE\Documents\KiCad\10.0\scripting\plugins\kicad_ai_assistant\.venv\Scripts\kcaa.exe" --help

Ubuntu:

bash
test -f ~/.local/share/kicad/10.0/scripting/plugins/kicad_ai_assistant/.venv/bin/kcaa && echo found
~/.local/share/kicad/10.0/scripting/plugins/kicad_ai_assistant/.venv/bin/kcaa --help

If the path doesn't exist, re-run setup_plugin.sh / setup_plugin.ps1 / setup_plugin.bat from inside the plugin directory (§13.4). If the executable is installed elsewhere, update KCAA_PATH (§14.2).


Backend cannot connect to the frontend

Verify that the backend is running:

text
http://127.0.0.1:8000/docs

Then verify:

dotenv
VITE_API_BASE_URL=http://localhost:8000/api

Restart the Vite development server after modifying .env.


CircuitMind loads on a remote machine, but nothing works (uploads fail, projects won't open)

This almost always means the frontend is still calling an API base URL the remote browser can't reach. A remote browser's localhost is itself, not the server.

  1. Confirm the backend is bound to 0.0.0.0, not 127.0.0.1 (§14.4).
  2. Confirm frontend/.env's VITE_API_BASE_URL (§15.2) points at the server's LAN IP or hostname, not localhost.
  3. Restart the Vite dev server after changing .env — it only reads it at startup.
  4. Check the browser's network tab for the actual request URL being called; if it still says localhost, the .env change wasn't picked up.

"No KiCad project found" when uploading a project ZIP

The uploaded ZIP must contain at least one .kicad_pro, .kicad_sch, or .kicad_pcb file, either at the ZIP's root or inside a single top-level folder (CircuitMind flattens one level automatically — see §19). Re-zip the project folder's contents directly if the structure is deeper than that.


"No project is open" when downloading a project ZIP

Open, import, or upload a project first (§19) — there is nothing to zip until a project is active.


Part VI — Reference

21 Project Structure

text
CircuitMind/
│
├── frontend/                    # React + Vite + Tailwind workstation
│   └── src/
│
├── backend/
│   ├── app/
│   │   ├── main.py
│   │   ├── routers/             # REST API (visual_ir.py, knowledge.py, design.py, ...)
│   │   ├── services/
│   │   │   ├── visual_extraction.py     # Visual IR pipeline orchestrator
│   │   │   ├── colqwen_service.py       # the one ColQwen implementation (/pooling -> Qdrant)
│   │   │   ├── kicad_locator.py         # toolchain path resolution (no hard-coded paths)
│   │   │   └── visual_ir/               # detection, association, wires, symbols, connectivity,
│   │   │                                #   decisions, reconcile, exporter, retrieval
│   │   └── models/              # SQLModel tables (incl. visual_ir.py)
│   ├── alembic/versions/        # schema migrations (production path)
│   ├── tests/                   # hermetic unit tests + marked integration tests
│   ├── requirements.txt
│   ├── requirements-visual-ir.txt   # Visual IR extras (numpy, opencv, tesseract bindings, ...)
│   ├── uploads/                 # Knowledge PDF uploads (§7.1, §7.2)
│   └── project_uploads/         # ZIP-uploaded KiCad projects (§19)
│
├── benchmarks/                  # reproducible technology-selection benchmarks (Part III)

The exact structure may evolve as the platform develops.


22 Testing

bash
pytest                      # from the repository root: the hermetic suite

The hermetic suite uses an in-memory SQLite database, an injected fake detector and an in-memory KCAA stand-in, so torch, ultralytics, KiCad and KCAA are not needed (347 tests collected). Tests that need live services are marked and skipped unless their environment is configured:

MarkerNeedsEnable with
integrationany live external service (KCAA, KiCad, Qdrant, Ollama, ColQwen)combined with the markers below
kcaaa KCAA executable and KiCadKCAA_PATH and KICAD_APP_PATH (or KICAD_INSTALL_PATH)
postgresa real PostgreSQL databaseCIRCUITMIND_TEST_POSTGRES_URL
gputorch / ultralytics and YOLO weightsYOLO_MODEL_PATH
colqwenthe vLLM ColQwen server and QdrantCOLQWEN_API_BASE_URL, QDRANT_URL

Notable suites:

  • backend/tests/unit/ — pipeline, geometry/placement, resolver/extractor, reconciliation, review actions, snapshots, export gate (ERC-lite, routing replay, verification), Alembic migrations, no-hardcoded-paths, ColQwen contract.
  • backend/tests/integration/test_w4_real_services.py — the multichannel fixture through the real YOLO weights, KCAA and kicad-cli.
  • backend/tests/integration/test_colqwen_real.py — the deployed ColQwen contract (/pooling → Qdrant).

Benchmarks (Part III) are separate from the test suite: they live in benchmarks/ and are run by hand (§11.7).


23 Roadmap and Non-Goals

23.1 Roadmap

Phase 1 — Deterministic Engineering Foundation
  • Native KiCad extraction
  • Reliable schematic parsing
  • Reliable PCB parsing
  • BOM/netlist integration
  • Canonical EDM graph
  • DRC/ERC evidence model
  • Design state management
  • Verification cache
Phase 2 — Engineering Intelligence
  • Engineering knowledge ingestion
  • Qdrant retrieval
  • Standards-aware reasoning
  • Datasheet-aware reasoning
  • Deterministic calculation engine
  • Requirement-to-design traceability
  • Design review automation
  • Failure-mode analysis support
Phase 3 — Controlled Autonomous Engineering
  • ChangeSet generation
  • KCAA execution
  • Automated design modifications
  • Pre-condition validation
  • Post-change verification
  • Autonomous engineering loops
  • Evidence-backed design decisions

Long-term objective:

text
Requirement
     │
     ▼
Engineering Analysis
     │
     ▼
Design Proposal
     │
     ▼
Implementation
     │
     ▼
Verification
     │
     ▼
Evidence
     │
     └──────────────► Engineering Decision

23.2 Non-Goals

CircuitMind is not intended to:

  • Replace KiCad
  • Replace qualified hardware engineers
  • Treat an LLM as an authoritative EDA parser
  • Modify designs without explicit control mechanisms
  • Hide engineering assumptions
  • Produce unsupported engineering claims
  • Use natural-language DRC descriptions as the canonical design database

CircuitMind is intended to augment engineering judgment with deterministic tooling, structured evidence, and AI reasoning.


24 License

Add the project's applicable license here.

For example:

text
Copyright © 2026 CircuitMind / UST
All rights reserved.

Replace this section with the actual repository license before public distribution.

Parts

31
QtyValueFootprintReferences
8100nFCapacitor_SMD:C_0805_2012MetricC5, C6, C7, C8, C9, C10, C12, C16
4MountingHoleMountingHole:MountingHole_3.2mm_M3H1, H2, H3, H4
31uFCapacitor_SMD:C_0805_2012MetricC1, C2, C13
22.2uFCapacitor_SMD:C_0805_2012MetricC14, C15
227pFCapacitor_SMD:C_0805_2012MetricC3, C4
25100ohmResistor_SMD:R_0603_1608MetricR1, R2
110000ohmResistor_SMD:R_0603_1608MetricR3
14.7uFCapacitor_SMD:C_0805_2012MetricC11
1604ohmResistor_SMD:R_0603_1608MetricR4
18MHzCrystal:Crystal_SMD_HC49-SDY1
1AP2112K-3.3TRG1Package_TO_SOT_SMD:SOT-23-5U1
1FTSH-105-01-L-DV-KConnector_PinHeader_1.27mm:PinHeader_2x05_P1.27mm_Vertical_SMDJ2
1STM32F407VGT6Package_QFP:LQFP-100_14x14mm_P0.5mmU2
1TL3342F160QGButton_Switch_SMD:SW_SPST_TL3342SW1
1USB4125-GF-AConnector_USB:USB_C_Receptacle_GCT_USB4125-xx-x-0190_6P_TopMnt_HorizontalJ1
1Vf=2.0VLED_SMD:LED_0603_1608MetricD1

Questions

How big is the Test4.routed PCB?

It measures 60 × 40 mm and has 2 copper layers, 1.6 mm thick.

What parts does the Test4.routed use?

31 parts, built around the STM32F407VGT6, AP2112K-3.3TRG1, FTSH-105-01-L-DV-K and TL3342F160QG. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.

Where can I download the Test4.routed KiCad files?

From the pginfinitylab-ai/forge repository on GitHub, at the commit this page was made from: the board is board/test4/circuitmind/stages/routing/724b68e5-6738-452f-9d6c-b16e911e2559/opt_ws/baseline/test4.routed.kicad_pcb. PCBKit opens the board in the browser, with nothing to install.

Can I use the Test4.routed design in my own project?

Its repository states no licence, so its author keeps all rights: ask pginfinitylab-ai before reusing the design.

More from pginfinitylab-ai/forge

2
  • 2 layers50 × 40 mmTest3, the printed circuit board in 3D

    Test3

    pginfinitylab-ai/forge

    It combines deterministic EDA analysis, native KiCad tooling, structured engineering knowledge, multi-plane design graphs, vector retrieval, and controlled execution to provide an AI-assisted hardware engineering…

    30 parts
  • 2 layers50 × 40 mmTest3, the printed circuit board in 3D

    Test3

    pginfinitylab-ai/forge

    It combines deterministic EDA analysis, native KiCad tooling, structured engineering knowledge, multi-plane design graphs, vector retrieval, and controlled execution to provide an AI-assisted hardware engineering…

    28 parts

Similar boards

  • 2 layersCoralC5-Motor, the printed circuit board in 3D

    CoralC5-Motor

    SmallCoral/c5-car

    用 KiCad 10 打开 CoralC5-Expansion.kicadpro。这是 Coral-C5 的单槽扩展板,顶部 J14 接核心板,左右 J9、J8 各一组 2×24 排针,下方放 RJ45 和 microSD,右侧放 ESP32-C3-MINI-1U。100×86mm 板框为本项目暂定尺寸。

    180 parts
  • 4 layers16.9 × 119.4 mmOrbit, the printed circuit board in 3D

    Orbit

    earthtojake/text-to-cad

    Design physical products with AI

    182 parts26kMIT
  • 6 layers85.9 × 77.5 mmFrob2354, the printed circuit board in 3D

    Frob2354

    tschak909/frob-modern

    The Frob, An Apple II Atari 2600 Development System, re-made as an RP2354 based device.

    80 parts8
  • 4 layers160 × 145 mmCarrier, the printed circuit board in 3D

    Carrier

    OrbitalCommons/gumstick

    Gumstick: ESP32 + iCE40UP5K FPGA module (v1 DF40 board-to-board, v2 M.2 gold-finger draft) and its programming carrier. KiCad 10.

    222 parts1MIT
  • 4 layers165 × 100 mmUsb scoring platform, the printed circuit board in 3D

    Usb scoring platform

    AndrewCraswell/agency

    Native KiCad engineering prototype, separate from the earlier ESP32/tscircuit board. Open usb-scoring-platform.kicadpro in KiCad 10; schematic and PCB are the editable source, with no generator required.

    224 partsMIT
  • 4 layers108 × 81 mmFoc dev board, the printed circuit board in 3D

    Foc dev board

    dganin-hw/bldc-foc

    Контроллер бесколлекторного мотора с FOC на STM32G431: своя силовая плата, плата энкодера AS5047P, печатный стенд и прошивка на C

    149 parts
  • 2 layers70 × 64 mmWindpcb, the printed circuit board in 3D

    Windpcb

    lindestad/wind-controller

    LINDESTAD simracing wind controller: ESP32-C3 Zephyr firmware, KiCad PCB and SimHub integration

    82 parts
  • 6 layers96 × 58 mmFujiNet Astrocade Rev0, the printed circuit board in 3D

    FujiNet Astrocade Rev0

    FujiNetWIFI/fujinet-hardware

    Schematics and design files for FujiNet hardware

    100 parts142