# Conformità coding — Periscope intero Percorso locale: `/Users/michelebigi/Development/periscope/docs/conformita-coding.md`. Costituzione: `docs/development/CODING_CONSTITUTION.md` (*code that fits in your head*). **Per sezione**, non per funzione: conforme sì / no e perché. Taglio 2.62.1 + questa macro-fase (libreria come porta, test riorganizzati, AF+AI extra). Auth/JWT/users: **non toccati**; la sezione esiste e viene giudicata, non modificata. Giudizio: **conforme** = un ingegnere legge la sezione senza ricostruire un sistema nascosto. **Non conforme** = troppe responsabilità, stato implicito, eccezioni ingoiate, o semantica a rischio. Un file lungo può essere conforme se il flusso è ovvio; uno corto no se fa tre mestieri. Zero eccezioni al principio. Le sezioni “non conformi” restano debito: non si “passa” la costituzione dichiarandole OK. --- ## 1. Albero nativo / dependency **Non conforme.** `periscope/src` (nativo) e `periscope/dependency` (PinScope ereditato) si fondono con `sys.path` + `pkgutil.extend_path`. Chi vince dipende dall’ordine di insert (`backend/__init__.py` vs `tests/conftest.py`). Due `projects.py`, due `pipeline.py`, due `extraction.py`. Per capire un import serve la mappa dei shadow, non il modulo. È un adattatore temporaneo con path di rimozione (Fase C) ma **oggi** non sta in testa. ## 2. Glue di root (Docker, compose, `backend/__init__.py`, script) **Conforme a metà.** `backend/__init__.py` è corto e dice il mestiere. `scripts/update-periscope.sh` è una procedura esplicita (`/root/periscope`, niente `data/`). `docker-compose.yml` è piccolo. Il debito è il merge dei due tree a boot, non gli script. ## 3. Motore finding (`periscopex/finding_engine.py`, schema) **Conforme.** Un oggetto finding, FACT / REQUIREMENT / INFERENCE, clamp verso il basso, `INSUFFICIENT`. Flusso visibile. Test stretti su tipo, codice, severity. ~450 righe: lungo ma un mestiere. ## 4. Modello semantico (`models.py`) **Conforme.** Pad, via, track, zone, pin, net sono tipi distinti. Pydantic, niente god-class UI. ~534 righe di dati, non di orchestrazione. ## 5. Parser schematico (PADS, EDIF, KiCad sch) **Conforme a metà.** Funzioni pure, fixture `simple_project`. `parsers_kicad.py` (~760) e `parsers_edif.py` (~465) sono grandi; il mestiere resta “testo → grafo”. Non classificano via PCB come pad (coperto da test rewrite). Debito: taglia dei file, non la semantica. ## 6. Parser PCB KiCad (`parsers_kicad_pcb.py`) **Conforme.** Via ≠ pad è esplicito e testato. Un input `.kicad_pcb` → `LayoutGraph`. Non è DRC. ~446 righe. ## 7. Grafo (`graph.py`, `netlist_bundle.py`) **Conforme.** Costruzione da BOM+netlist, helper di attraversamento. Ferrite Z è un innesto a parte (`ferrite_z.py`), non un if U1. ## 8. Check deterministici PCB (`pcb_checks.py` + moduli `PE-*`) **Conforme nel disegno, non nel dispatcher.** Ogni modulo (`si_check`, `hf_line_check`, `stackup_check`, …) ha un mestiere e skip senza evidenza. `run_pcb_checks` è un elenco esplicito — si legge. **Non conforme:** `except Exception: log + skip` per ogni check (fallimento strumento vs finding vs dati, collassati). `pcb_power_thermal.py` (~748) e `si_check.py` (~862) e `interface_class_check.py` (~831) sono al limite: ancora un dominio, ma non “piccoli moduli”. AF Board+AI (`af_ai_hf.py`) è **additivo**: `pcb_pipeline` chiama `append_investigated` dopo `run_pcb_checks`. Non entra nella lista 2.62.1. Non è DRC. Non è DRC (clearance/track_width/annular restano KiCad). FEM assente: **conforme al vincolo**. ## 9. Check schematico (derating, LED, crystal, mux, rail, …) **Conforme.** Un file ≈ un check, grafo in → finding out, niente mm inventati. Alcuni file >400 righe (`passive_rail_check`, `filter_check`) ma il flusso è lo stesso. ## 10. Review AI (validate, pcb_review, review_tools) **Non conforme come sezione unica.** L’autorità deterministica è nei check; l’LLM spiega — questo è il disegno giusto (costituzione §8). In pratica `review_tools.py` (~940) e `validation.py` (dependency + native) sono loop di tool + state. `pcb_review.py` (~327) è il prompt + vicinato: quello sta in testa. Il loop live dipende ancora da pezzi ereditati. AF+AI (ipotesi HF → indagine deterministica) è un modulo extra, non sostituisce `run_pcb_checks`. ## 11. Estrazione datasheet (skills, `datasheet_extract.py`, `extraction.py`) **Non conforme.** `datasheet_extract.py` ~1322 righe e `extraction.py` ereditato ~1298: prompt, tool, coerce, taxonomy, auto-resolve nello stesso file. Il mestiere “PDF → JSON libreria” è uno, l’implementazione no. Native vs inherited duplicato finché il pipeline non switcha. **Conforme nel ruolo:** LLM estrae, non è il verificatore. ## 12. Libreria componenti (store + porta HTTP/UI) **Prima: non conforme come porta.** Catalogo e `library_has_*` vivevano in `services/projects.py` (CRUD progetti + libreria). La pagina `/library` era sola lettura e l’empty state mandava a “crea un progetto e lancia la review”. Admin `/admin/components` mescola libreria e users. **Dopo 2.63.1: conforme come porta.** `POST /api/library/datasheets` registra una scheda (inbox IC o modello passivo/discreto) senza esame. Pintable vuota non va in `library/extracted/` (`library_gate`). PUT promuove inbox → extracted. `projects.py` re-export resta debito. `list_library_catalog` logga e salta JSON rotti. ## 13. Pipeline orchestrazione (`pipeline.py`, `pcb_pipeline.py`, job) **Non conforme.** `pipeline.py` ~1522 righe: stage, storage, LLM, copy-in-library, graph. `pcb_pipeline.py` è più lineare (ensure_graph → parse → checks → **af_ai additivo** → AI → report) e si segue. Job/SSE sono un secondo asse di stato. Flusso reale: sì, ma non locale. `run_pcb_checks` 2.62.1 non è stato svuotato. ## 14. Storage (`storage.py`, GCS) **Conforme.** Backend con chiavi stringa, locale vs GCS. Prefissi `users/…/projects/` e `library/` visibili. ## 15. HTTP — progetti, pipeline, report, impedance **Non conforme per `routers/projects.py` (~1004)** e `pipeline.py` router (~783): troppi mestieri (CRUD, upload KiCad, DigiKey, LCSC). Report e impedance sono sezioni più piccole. La nuova `routers/library.py` è la porta libreria (un mestiere). ## 16. Auth / JWT / users **Non toccata in questa macro-fase (vincolo).** La sezione **non è conforme** alla costituzione (Clerk + JWT locale + `admin.py` users nello stesso router, middleware che decide tre modi). Non si “sistema” qui. Non si aggiunge auth alla libreria. ## 17. Frontend — shell e pagina libreria **Conforme a metà.** Overlay `src` su `dependency` (materialize) è un secondo albero da tenere in testa. Pagine progetto/report/dashboard sono lunghe ma a mestiere. `/library` era browse-only; ora è porta (import + modifica scheda) con form/editor spezzati. `admin/page.tsx` ~1780: **non conforme** (libreria + users + usage). Non toccato (users). ## 18. Frontend `api.ts` / types **Non conforme.** `api.ts` nativo ~1179 righe, client unico per tutto. Types allineati ai modelli: sì. Un file non sta in testa. Nuove funzioni libreria restano lì per non inventare un secondo client. ## 19. Skills e taxonomy **Conforme.** `skills/*/SKILL.md` + `validate.py` in-process; taxonomy JSON per tipo. `repo_paths` al posto di `Path(__file__)` magici (test rewrite). Non si chiama `upload_skills.py`. ## 20. Vendor ImpedenceFinder **Conforme come confine, non come licenza.** Core Z0 chiuso, non FEM, non secondo set di formule (test). LICENSE UNKNOWN resta debito legale, non di forma del codice. ## 21. Test **Prima: non conforme come mappa.** Un flat `tests/test_*.py` mescolava datasheet, libreria, schema, PCB, rewrite, auth. Copertura vera, ordine mentale no. **Dopo: conforme come mappa, copertura tenuta.** | Cartella | Mestiere | | --- | --- | | `tests/datasheet/` | preliminare PDF / pin / abs-max / I / Z / ferrite / DigiKey | | `tests/library/` | porta libreria (anche senza esame) | | `tests/schematic/` | net, BOM, review IC, check su grafo | | `tests/pcb/` | `run_pcb_checks`, geometria, SI/HF già in 2.62.1 | | `tests/impedancefinder/` | vendor Z0 (stesso nome package del vendor — non va sotto `pcb/`) | | `tests/af_ai/` | extra: ipotesi HF → indagine deterministica (non DRC, no Z inventata) | | `tests/` root | identity/rewrite/auth/job — non analisi | `conftest.py` e `paths.py` restano in root. Test stretti (codice finding, via≠pad) restano la regola; i rewrite “il file sta in src” sono deboli ma sono recinti di albero, non di fisica. ## 22. Costituzioni Cursor (`.cursor/rules`, questo doc) **Conforme.** Un master Markdown, `.mdc` operativi, niente Rust speculativo. Questo file è il giudizio, non una seconda costituzione. ## 23. Git / deploy **Conforme al testo, fragile in pratica.** Commit+push a fine fase; deploy a fine macro-fase; no force. Il worktree locale era un pointer a `~/Development/pinscope` sparito: history recuperata da `github` `cursor/pcb-hf-analisi-675d` @ `20733f0` (2.62.1). Non si tocca `~/Development/pinscope` per edit di prodotto. --- ## Sintesi | Sezione | Conforme | | --- | --- | | Finding engine + modelli + parser PCB | sì | | Check PE-* come moduli | sì (dispatcher fail-soft no) | | Skills/taxonomy/storage/Z0 vendor | sì | | Dual tree src/dependency | no | | Pipeline + extract ~1.3k + projects router | no | | Auth/admin users | no (non toccare) | | Libreria come porta | sì dopo questa fase (re-export debito) | | Test a cartelle di mestiere | sì dopo questa fase | Priorità debito (non questa fase): spezzare `pipeline.py` / `datasheet_extract.py`; togliere lo shadow dependency quando un modulo nativo è provato; non ingoiare Exception nei check PCB (distinguere tool failure). **Niente Rust in questa macro-fase** — vedi `docs/rust-criteri.md`. FEM fuori. DRC = KiCad.