Files
periscope/docs/piano-pcb-review.md
T
michele 8f4ebc645c Share library/extracted for schematic and PCB review.
PCB AI skips a second PDF exam (pintable cache, pdf_path=None) and the report
gains a PCB exam section plus power-trace, thermal, via, Kelvin, and GND-stitch
checks grounded in board geometry and extracted specs.
2026-09-20 08:32:23 +02:00

239 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Piano — PCB review (esame AI + check deterministici)
Fonte di verità per **Periscope Layout review**. Non è un auto-placer.
**Delta vs revisione precedente:** lesame del board è **agentico come la pipeline schema** (datasheet + neighborhood + tool, findings ERROR/WARNING/INFO con **sempre** una `recommendation`). Restano i check numerici gated. Auto-placement / pack / write-back pcbnew restano **fuori**.
Prodotto: esaminare un `.kicad_pcb` già (parzialmente) sbrogliato — placement, routing, impedenze, lunghezze, decoupling, filtri, derating, compliance datasheet — e dire *cosa è sbagliato e come sistemarlo*. Non si spostano footprint e non si scrive rame.
Contratto rispetto a [`docs/piano-implementazione.md`](piano-implementazione.md):
| | Schema (già in produzione) | PCB review (questo piano) | Placement F2 pack (fuori) |
| --- | --- | --- | --- |
| Promessa | Lo schema rispetta il datasheet | Il **layout esistente** rispetta datasheet + geometria | Proporre xy nuovi |
| Metodo | Check deterministici + **review LLM per-IC** | Stesso spirito: check + **review LLM per-IC sul PCB** | Skeleton `placement_pack.json` |
| Trigger | BOM + netlist / `.kicad_sch` | + `.kicad_pcb` | PCB + `layout_rules` numerici |
| Output | Finding pin/net, derating, review | Finding mm / net / Z0 / skew / via EP / layout AI; `PE-PLC*` `PE-SI*` `PE-LAY*` `PE-Z0*` | Proposte xy |
| Job | `MODE=run` (`status`) | `MODE=pcb` (`pcb_status`) | `MODE=placement` (`placement_status`) |
Senza `.kicad_pcb` il progetto resta uno schema completo. Il report schema **non** si riempie di finding layout.
---
## 0. Postura: esame AI, non progettazione
Stesso spirito della Direct Datasheet Review: il modello legge datasheet + contesto del circuito **e** geometria del footprint/net, usa tool sul grafo, sottomette finding. Non progetta il board.
### Domains e functional Groups
Obbligatori come contesto dellesame (non come packing):
- **Domains** = isole sulle power net (`functional_groups.py` / `placement_plan.json`).
- **Groups** = IC + satelliti con `role_hint` (`decoupling`, `bulk`, `filter`, `crystal`, …).
Il job PCB **classifica** (riusa `build_placement_plan`) e passa domains/groups al reviewer e allinventory. Non propone coordinate.
La pipeline Placement (`POST …/placement/start`) resta topologia routing-first. F2 pack/export **parcheggiati**.
### Placement = verifica (deterministico + AI)
Misura ciò che è **già** sul board: distanza pad-cap, layer, via EP, keepout, crystal load caps. `placement_check` (`PE-PLC-001``004`) è il nucleo numerico. LAI copre note di layout del datasheet **senza mm strutturato** (citazione + `Unverified:` se la quote non verifica), sempre con recommendation.
### Routing = la stessa postura
Lunghezze, coppie, bus, Z0, pad-net vs schema. `si_check` (`PE-SI-001`) solo con `length_match` mm. LAI può flaggare crossing/loop evidenti **solo** se il contesto geometria lo mostra; niente 3W/IEC inventati.
### Findings (come parte 1 / schema)
Ogni finding PCB:
- `status`: **ERROR** | **WARNING** | **INFO**
- `recommendation` **obbligatoria** anche per INFO (cosa fare: spostare, allungare/accorciare, cambiare rating, verificare stackup, …)
- `rule_id` sui check automatici; review AI: `source=pcb_review`
- IDs `PCB-{designator}-{001}` per non collidere con lo schema
Normalization resta **downgrade-only**.
---
## 1. Job parallelo (riuso stack)
```
┌─ MODE=run → status → report.json (schema)
Project files ───┼─ MODE=placement → placement_status → placement_plan.json
└─ MODE=pcb → pcb_status → pcb_report.json
```
### Riuso
| Pezzo | Path | Ruolo PCB |
| --- | --- | --- |
| Workspace / SSE | `pipeline.py` | `PipelineWorkspace`, broker |
| Dispatch | `job_runner.py`, `pipeline_worker.py` | `MODE=pcb` |
| API | `routers/pipeline.py` | `pcb/start`, `cancel`, `events`, inventory |
| Meta | `projects.py` | `pcb_status`, `pcb_state`, `pcb_execution_name`, `pcb_cancel_requested` |
| Parser | `parsers_kicad_pcb.py` | `LayoutGraph` |
| Groups | `functional_groups.py` | domains + groups |
| Placement | `placement_check.py` | PE-PLC-* |
| SI | `si_check.py` | PE-SI-001 |
| Filtri | `filter_check.py` | contesto; proximity solo con mm |
| Derating | `derating.py` | Vop vs Vrated se entrambi noti |
| Impedenza | `impedance_traces.py` | inventory Z0; finding se target numerico |
| Review LLM | `services/validation.py` + prompt PCB | per-IC, stesso loop tool/`submit_review` |
| Cad bridge | `cad_bridge.py` | `target: pcb` |
| UI | report `finding-card`, sidebar, `types.ts`, `api.ts` | tab Layout, merge findings |
### Contratto job
- Non tocca `status` schema.
- Soft-cancel `pcb_cancel_requested`.
- Mutex vs analisi e vs placement (event log condiviso).
- SSE `pcb_step_update` / `pcb_complete` / `pcb_error` / `pcb_cancelled`.
- Locale: `local/pcb/{id}`.
- Heal zombie come placement.
- LLM: stesso provider DeepSeek della review schema; `ApiLogger` stage `pcb_review`; billing via `get_billing()` (NullBilling in OSS).
- Senza API key in test: skip AI, check deterministici restano.
### Stages
1. `ensure_graph``design_graph.json` o graph_build.
2. `parse_pcb``layout_graph.json` / `parse_kicad_pcb`. Fail → error.
3. `classify` — domains + groups (`build_placement_plan`); scrive `functional_groups.json` se manca.
4. `inventory` — tracce, bus, lunghezze, Z0 → `pcb_inventory.json`.
5. `checks` — deterministici fail-soft (`run_pcb_checks`).
6. `ai_review` — per-IC come schema, contesto layout + group/domain + inventory del vicinato.
7. `write_report``pcb_report.json`, cad-bridge, IDs `PCB-*`.
---
## 2. Ingressi
| Ingresso | Obbligatorio v1 |
| --- | --- |
| `.kicad_pcb` (`has_pcb`) | Sì |
| `design_graph.json` | Sì |
| `extracted/` + `layout_rules` / pintable | Per check numerici e AI |
| **Shared library** `library/extracted/{safe_mpn}.json` | **Unico** store schema+PCB. Deep exam PDF una volta (pipeline schema). |
| PDF datasheet | Solo per estrazione / review **schema**. PCB **non** riattacca il PDF. |
| Stackup nel PCB | Per Z0 e ampacity; skip se assente |
---
## 3. Check (deterministici) + AI
### 3.1 Inventario (non finding)
Net con rame: lunghezza, layer, width min/max, via, coppia, bus, Z0 se stackup. Domains/groups elencati.
### 3.2 Deterministici
| ID | Cosa | Gate |
| --- | --- | --- |
| `PE-LAY-001` | Pad net ≠ pin net schema | entrambi noti |
| `PE-LAY-002` | Ref schema senza footprint (skip `#PWR`) | graph + PCB |
| `PE-PLC-001``004` | decoupling / via / same_layer / keepout | `layout_rules` numerici |
| `PE-SI-001` | skew coppia | `length_match` mm |
| `PE-DRT-001` | Vop > Vrated sul cap (derating.py) | entrambe le tensioni |
| `PE-Z0-001` | Z0 fuori target | target in regola o netclass; mai 50 Ω default |
| `PE-PWR-001` | Larghezza × spessore rame vs I_load | I_load + width; IPC-2221 solo con `copper_thickness_mm` e Tjmax (ΔT=Tjmax25 °C) |
| `PE-VIA-001` | I_load / N via | geometria via + I_load; INFO (niente tabella via inventata) |
| `PE-THM-001` | P=I_load×(VinVout) senza pour/via courtyard | I_load, Vin/Vout, courtyard |
| `PE-KEL-001` | Pin sense/Kelvin su net di carico | nome pintable + ≥2 altri sul net |
| `PE-STCH-001` | Segnale sopra pour GND senza via GND nel bbox | zone GND + segmenti; INFO |
| Creepage | — | **skip** senza numero datasheet/IEC |
| Crystal keepout | `PE-PLC-004` | `layout_rules` kind=keepout |
Filtri: `check_filters` **non** duplicato nel report PCB (resta schema). LAI e i groups usano `role_hint=filter` per proximity se c’è mm.
### 3.3 AI exam (layout-only, shared library)
Per ogni IC con **pintable in `library/extracted` o extracted/ di progetto** (stesso JSON):
- **Non** si ri-legge il PDF. Lesame datasheet profondo è quello della pipeline schema.
- System prompt **PCB**: layout vs JSON di libreria.
- User: `format_library_extraction` + `build_pcb_layout_context`.
- `review_ic_async(..., pdf_path=None)` — niente attach, niente quote-verify PDF.
- Skip: `no library extraction — run schematic review first`.
- Recommendation obbligatoria; isolation per-IC.
UI: sezione report **PCB exam** (`pcb-exam-section.tsx`) — findings `source=pcb_review` e PE-PWR/THM/VIA/KEL/STCH. Nascosta con `?domain=schema`.
### 3.4 Skip (no folklore)
3W, creepage IEC senza numero, CPWG, HV isolation, length-match USB spec, confronto foto TI vs gerber, 1 oz / 10 °C / 50 Ω di default.
---
## 4. UI
| Superficie | Comportamento |
| --- | --- |
| Hub | **Run PCB review** se `hasPcb` |
| `/project/[id]/pcb` | Stepper SSE (include `ai_review`) |
| Sidebar | **Layout**`/pcb` |
| Report | Merge + sezione **PCB exam**; `?domain=layout`; badge Layout; recommendation sempre visibile |
| Inventory | Traces/buses/Z0 + domains/groups |
---
## 5. Fasi di implementazione
Dopo **ogni** fase: test delle funzioni toccate, commit, push. Dopo ogni macro-fase operativa: deploy `ssh periscope` + `scripts/update-periscope.sh` (niente chiavi/sshd).
### Fase 0 — Split schema / layout
Togliere `placement_check` / `si_check` da `_run_deterministic_checks` schema. Eval schema: `layout=None` resta no-op.
**Done when:** schema senza PCB = zero `PE-PLC`/`PE-SI`.
### Fase 1 — Job + deterministici + UI (macro operativa)
Meta `pcb_*`, worker, router, `run_pcb_checks`, inventory, report merge, UI start/progress/filtro.
**Done when:** upload PCB → start → finding nel report. Deploy.
### Fase 2 — AI exam + domains/groups (macro operativa)
`classify` + `ai_review` per-IC, prompt PCB, recommendation obbligatoria, changelog Layout.
**Done when:** con API key, IC con libreria producono finding `source=pcb_review` o coverage vuota; senza key, skip loggato. Deploy.
### Fase 3 — Plugin + eval PCB
Cad-bridge pcbnew; golden fixture. Packing resta fuori.
### Fase 4 — Libreria unica + sezione PCB exam (macro operativa)
Un store `library/extracted` (più extracted/ di progetto). PCB non duplica lesame PDF. Sezione report PCB exam + PE-PWR/THM/VIA/KEL/STCH.
**Done when:** IC senza pintable skipped; con libreria, AI layout-only; check IPC solo con stackup+Tjmax. Deploy.
---
## 6. Fuori scope
- Auto-placement, packing mm, write-back pcbnew.
- Autore di sbroglio / change width.
- SPICE / IBIS / EM.
- Inventare mm, Ω, V/mm.
- EasyEDA, Gerber come ingresso, PADS layout.
- Unire il job PCB nella run schema.
- Toccare ssh keys / `sshd`.
---
## 7. Done (fixture)
1. Decoupling 15 mm vs regola 2 mm → `PE-PLC-001` + recommendation.
2. 1 mm → niente proximity.
3. Skew coppia > `length_match``PE-SI-001`.
4. Pad net mismatch → `PE-LAY-001`.
5. Senza PCB → 400 sul start.
6. AI: contesto contiene domain/group; finding senza recommendation rifiutati/completati dal parser.
---
## 8. Relazione
Wave G di `piano-implementazione.md` = questo job di **esame** (ora anche LLM). F2 pack non entra.