Ship Sprint 0 CAD foundations so findings, KiCad hierarchy, BOM match, eval, and optional PCB ingest have a stable contract.

Extend Finding with rule_id/net/pins, flatten multi-sheet .kicad_sch, flag MPN mismatches, score simple_project, and parse .kicad_pcb without running layout DRC.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-10 21:54:37 +02:00
co-authored by Cursor
parent d31c04ba86
commit e4fd6c3849
29 changed files with 1995 additions and 46 deletions
@@ -46,6 +46,7 @@ import {
deleteProject,
uploadBom,
uploadNetlist,
uploadPcb,
uploadDatasheet,
startPipeline,
checkLibrary,
@@ -548,6 +549,7 @@ export function CreateProjectDialog({
const [name, setName] = useState("");
const [bomFile, setBomFile] = useState<File | null>(null);
const [netlistFile, setNetlistFile] = useState<File | null>(null);
const [pcbFile, setPcbFile] = useState<File | null>(null);
const [netlistNetCount, setNetlistNetCount] = useState<number | null>(null);
const [netlistError, setNetlistError] = useState<string | null>(null);
@@ -1879,6 +1881,10 @@ export function CreateProjectDialog({
setProgress("Uploading netlist...");
await uploadNetlist(project.id, netlistFile!);
}
if (pcbFile) {
setProgress("Uploading PCB...");
await uploadPcb(project.id, pcbFile);
}
} catch (uploadErr) {
if (!projectAlreadyExists) {
try {
@@ -2112,6 +2118,19 @@ export function CreateProjectDialog({
)}
</div>
</div>
<div className="space-y-1.5">
<FileUploadZone
label="PCB (.kicad_pcb, optional)"
accept=".kicad_pcb"
files={pcbFile ? [pcbFile] : []}
onFilesChange={(files) => setPcbFile(files[0] ?? null)}
/>
<p className="text-[11px] text-muted-foreground leading-tight px-1">
Optional. Layout checks (trace width, 3W, placement mm) stay
off until a board is present. Schema review still runs
without it.
</p>
</div>
</div>
)}