Files
periscope/docs/albero-analisi.md
T
michele 8f434ffd31 Skip module-die and truncated QFN pintable false PE-BOM hits (2.63.3).
WROOM lands are not the ESP32 die table (U11). QFN-48 pads 25–48 are
not extras when extraction stopped at 1–24 (U12). VQFN is the QFN
family (U19 24-QFN 4×4). Real extra signal pads still ERROR.
2026-09-22 00:57:57 +02:00

37 KiB
Raw Blame History

Albero delle analisi Periscope

Versione codice 2.63.1 (periscope/src/frontend/content/changelog.md). Letto in /Users/michelebigi/Development/periscope. Costituzione senza eccezioni: via ≠ pad ≠ traccia ≠ zona; niente I/Z/mm inventati; skip se manca evidenza. Non è DRC KiCad. DRC = KiCad. Questo documento mappa lanalisi, non implementa.

I test pytest stanno in tests/datasheet/, tests/library/, tests/schematic/, tests/pcb/, tests/af_ai/ (stessi file di 2.62.1, cartelle di mestiere). I path tests/test_*.py sotto i nodi restano i nomi file.

Due pipeline più una porta libreria (non è un esame):

  1. LibreriaPOST /api/library/datasheets registra un componente da PDF senza MODE=run/MODE=pcb.
  2. Schematico / review AIMODE=run, services/pipeline.pyvalidate_design_async (validation.py): estrazione datasheet, check deterministici, review IC DeepSeek.
  3. Esame PCBMODE=pcb, services/pcb_pipeline.pyrun_pcb_checks (pcb_checks.py, lista 2.62.1 invariata) + sezione additiva AF Board+AI (af_ai_hf.py) + review AI PCB (pcb_review.py / pcb_validation.py). Non auto-place.

I certifier USB-C / Ethernet / PoE girano su entrambe le pipeline (grafo, non geometria). DDR / CPU / FPGA / USB-PD sono la stessa qualità di finding ma partono da run_pcb_checks (grafo). Niente pezzo sul grafo → silenzio, non N/A.

Nodi analisi: 108 (99 PE-* + 1 LED senza rule_id + 8 processo estrazione/AI). Test pytest citati sotto i nodi: nomi reali da tests/.


Periscope 2.63.1
├── 0. Libreria (porta, non esame)
│   └── PDF + MPN → scheda (inbox IC / passivo / discreto) senza MODE=run/pcb
├── 1. Schematico / review AI (MODE=run)
│   ├── ingest (non è analisi: parser → grafo)
│   ├── estrazione datasheet
│   ├── check deterministici schema
│   ├── certifier di classe (condivisi con PCB)
│   └── review AI per-IC + post-pass
└── 2. Esame PCB (MODE=pcb)
    ├── ingest layout (non è DRC)
    ├── run_pcb_checks   ← 2.62.1 invariato (SI + HF line inclusi)
    │   ├── net / footprint
    │   ├── placement vs layout_rules
    │   ├── SI + linee HF (2.62.0 Fase A)
    │   ├── DDR / CPU / FPGA (2.62.0)
    │   ├── potenza / via / termico
    │   ├── derating / timing / PI
    │   ├── ESD / return / EMI / SPOF
    │   ├── BOM ↔ PCB ↔ datasheet
    │   └── resto Fase B (2.62.1)
    ├── AF Board + AI (additivo: flag → investigate_hf_hypotheses; non sostituisce SI/HF)
    ├── review AI PCB
    └── tab antenna RF (non in run_pcb_checks)

1. Schematico / review AI (MODE=run)

Orchestrazione: pipeline.py stadi bom_parseic_extractionsimple_extractionpassive_extractiongraph_buildvalidation. Check deterministici: _run_deterministic_checks in validation.py. Finding ID schema PS-{ref}-{nnn} (non PCB-).

1.1 Ingest (prerequisito, non analisi)

Parser e grafo non emettono PE-*. Skip MPN: ic_mpn_skip_reason (silenzio onesto, niente MPN inventato).

  • Test parser/grafo: tests/test_bom_parser.py (test_parse_bom_uses_value_for_ic_when_mpn_column_empty, test_parse_bom_keeps_pnm_and_datasheet_url); tests/test_hubaudio_bom.py (tutti e 4); tests/test_netlist_parser.py (tutti e 3); tests/test_edif_parser.py (14); tests/test_kicad_parser.py (17); tests/test_kicad_project.py (19); tests/test_netlist_bundle.py (9); tests/test_functional_groups.py (8).
  • Test overlay parser: tests/test_periscope_parsers_rewrite.py, tests/test_periscope_graph_rewrite.py, tests/test_periscope_models_rewrite.py.

1.2 Estrazione datasheet (processo)

Skip se manca PDF o lo skill non ha numero. Libreria library/extracted condivisa schema+PCB. PCB review non rilegge il PDF (pdf_path=None).

extract-pintable — skill skills/extract-pintable/

Modulo: services/datasheet_extract.py + llm/local_skill.py. Analizza: pin table, package, taxonomy IC.

  • Skip se: niente PDF; IC già in libreria alla model_version minima.
  • Test: tests/test_native_datasheet_extract.py (test_coerce_abs_max_matches_inherited, test_native_extract_has_no_anthropic_import); tests/test_pdf_ingest.py (6); tests/test_deepseek_provider.py (test_local_skills_load, test_extract_pdf_text_includes_page_markers, test_wroom_rejects_bare_soc_pin1_ant); tests/test_periscope_taxonomy_skills_src.py (test_pintable_skill_mentions_save_tool_and_wroom, test_skills_dir_is_src_and_local).

extract-specs — skill skills/extract-specs/

Analizza: specs discreti/connettori/cristalli; parametri fuori taxonomy → scartati.

  • Skip se: niente PDF o tipo non in SIMPLE_TYPES.
  • Test: tests/test_pdf_ingest.py (test_coerce_abs_max_keeps_valid_drops_junk); tests/test_layout_rules.py (5 — layout_rules numerici, niente mm inventati).

extract-pattern — skill skills/extract-pattern/

Analizza: pattern MPN passivi (R/C/L/FB).

  • Skip se: MPN opaco; DigiKey/value fallback copre prima.
  • Test: tests/test_inductor_specs.py (13, Z ferrite solo se il PDF dice N Ω @ freq); tests/test_pcb_software_bugs.py (test_lqw_decoder_and_unknown_skip, test_fb1_blm_is_bead_not_dcr_resistor).

Resolve DigiKey / catalogo (esatto MPN)

Modulo: services/digikey.py, passive_from_distributor.py, passive_from_mpn.py. Analizza: parametri catalogo per auto-resolve. Hit fuzzy rifiutati.

  • Skip se: MPN non esatto; API assente (fail-soft).
  • Test: tests/test_digikey_match.py (3); tests/test_passive_from_distributor.py (7); tests/test_passive_from_mpn.py (7); tests/test_datasheet_finder.py (17); tests/test_library.py (5).

Resolve da stringa Value (solo progetto)

Modulo: services/passive_from_value.py. Specs value-derived non in libreria condivisa.

  • Skip se: stringa ambigua / placeholder.
  • Test: tests/test_passive_from_value.py (8).

1.3 Check deterministici schema

Fail-soft per modulo. Senza evidenza: skip (lista vuota), non folklore.

PE-MUX-001pin_mux_check.py

Analizza: funzione pin vs net (UART/SPI/I2C mux).
Skip se: functions vuote; link inter-device stesso peripheral; net opaco.

  • Test: tests/test_pin_mux_check.pytest_real_defect_uart5_swapped_is_error, test_correct_assignment_no_finding, test_inter_device_same_peripheral_link_is_skipped, test_transceiver_peer_without_peripheral_still_fires, test_empty_functions_skipped, test_pin_exposes_peripheral_but_not_signal_no_complement, test_opaque_net_not_flagged, test_token_parser_and_normalizer, test_spi_legacy_net_names_match_modern_pin_functions, test_spi_controller_peripheral_names_are_synonyms, test_simple_project_uart0_nets_are_feasible_on_mspm0_pins, test_simple_project_uart0_swapped_on_mspm0_is_error, test_spi_genuine_infeasibility_still_fires_with_modern_names, test_finding_prints_full_raw_capability_list_and_intent_caveat, test_legacy_report_without_source_validates.

PE-NC-001nc_pin_check.py

Analizza: pin NC collegato a net attivo.
Skip se: niente pintable.

  • Test: tests/test_nc_pin_check.pytest_nc_pin_on_active_net_warns, test_nc_pin_on_nc_net_silent, test_no_pintable_silent.

PE-DEC-001 / PE-DEC-002passive_rail_check.py check_supply_decoupling

Analizza: condensatore sul net di alimentazione IC (001 presenza; 002 valore vs datasheet).
Skip se: net NC; pin enable strap; manca valore per 002.

  • Test: tests/test_passive_rail_check.pytest_missing_decoupling_is_warning, test_cap_to_gnd_clears_decoupling, test_enable_strapped_to_rail_is_not_decoupling, test_nc_supply_net_is_skipped, test_ldo_vout_needs_cout, test_ldo_vout_100n_only_is_value_warning, test_vdd_100n_is_not_a_value_warning, test_ki_cad_voltage_prefix_is_power, test_fb_and_rn_prefixes.

PE-I2C-001 / PE-I2C-002passive_rail_check.py check_i2c_pullups

Analizza: pull-up I2C (001 presenza; 002 valore vs banda).
Skip se: pin SDA è alias SPI; pull-up senza valore (002 non sizato); bus assente.

  • Test: tests/test_passive_rail_check.pytest_i2c_missing_pullup, test_i2c_pullup_present, test_i2c_pullup_to_3v3_digital_typed_as_signal, test_spi_pin_alias_sda_is_not_i2c, test_i2c_from_slash_alias_in_pin_name, test_i2c_4k7_pullup_is_in_nxp_wide_band, test_i2c_100ohm_pullup_is_too_stiff, test_i2c_100k_pullup_is_too_weak, test_i2c_pullup_without_value_is_not_sized.

PE-RST-001 / PE-RST-002passive_rail_check.py check_reset_pullups

Analizza: reset/enable pull (001 presenza; 002 verso vs datasheet).
Skip se: GPIO guida il reset.

  • Test: tests/test_passive_rail_check.pytest_reset_no_finding_when_gpio_drives, test_reset_floating_is_warning, test_nrst_pulldown_is_warning, test_nrst_pullup_is_not_pulldown.

PE-BOM-001 / PE-BOM-002bom_match_check.py

Analizza: MPN schema vs BOM (001 mismatch; 002 riga BOM orfana).
Skip se: mappa schematica vuota (PADS/EDIF senza properties).

  • Test: tests/test_bom_match_check.pytest_matching_mpns_produce_no_findings, test_mpn_mismatch_is_error_ps_bom_001, test_orphan_bom_ref_is_warning, test_mpn_case_and_whitespace_are_not_a_mismatch, test_empty_bom_mpn_with_schematic_mpn_is_not_a_mismatch, test_empty_schematic_map_skips_check, test_legacy_design_graph_without_source_fields_still_validates, test_build_graph_kicad_mpn_mismatch_surfaces.

PE-DNP-001dnp_check.py

Analizza: DNP vs enable floating.
Skip se: colonna DNP assente.

  • Test: tests/test_dnp_check.pytest_dnp_pull_leaves_enable_floating, test_fitted_pull_is_silent, test_no_dnp_column_skips_floating_enable, test_parse_bom_reads_dnp_and_skips_when_column_absent.

LED corrente — led_current_check.py (nessun PE-*)

Analizza: I_f Ohm vs rating canale. Source led_current_check.
Skip se: niente forward_current_*; tensione rail sconosciuta (non si indovina).

  • Test: tests/test_led_current_check.pytest_over_current_is_error, test_proper_resistor_no_finding, test_unknown_rail_no_error, test_no_rating_skipped, test_parse_resistance.

PE-TH-001 / PE-TH-002 / PE-TH-003thermal_check.py

Analizza: P = I_load × drop; Tj = Ta + P·θJA (001 INFO senza θJA o Tj ok; 002 WARNING Tj alto — non in catalogo finding_engine; 003 I²R shunt).
Skip se: manca I_load (Iout_max non è carico).

  • Test: tests/test_thermal_check.pytest_ldo_without_theta_ja_is_info, test_iout_max_is_not_used_as_load, test_ldo_hot_tj_is_warning, test_shunt_over_rating_is_warning, test_led_resistor_within_rating_is_silent.

PE-PWR-001 (schema) — power_margin_check.py

Analizza: Σ IQ + I_load vs Iout regolatore; caduta su R serie. Source power_margin_check.
Skip se: manca I_load; IQ assente non è fail.

  • Test: tests/test_power_margin_check.pytest_load_over_iout_max_is_ps_pwr_001, test_missing_iq_is_not_guessed_into_margin_fail, test_series_r_ir_drop_uses_i_load_not_trace, test_no_series_r_does_not_invent_trace_drop.

PE-SEQ-001sequencing_check.py

Analizza: PG → EN da note datasheet.
Skip se: niente spec power_sequence.

  • Test: tests/test_sequencing_check.pytest_pg_not_tied_to_en_is_warning, test_pg_tied_to_en_is_silent, test_no_power_sequence_spec_skips_even_if_pg_open.

PE-FLT-001 / PE-FLT-002 / PE-FLT-003filter_check.py

Analizza: topologia filtro (001), pezzo (002), fc vs ADC / DCR ferrite (003).
Skip se: manca C; pull-up+decoupling non è filtro; DCR ferrite senza limite datasheet.

  • Test: tests/test_filter_check.pytest_rc_reports_fc_info_without_adc_rate, test_rc_vs_adc_rate_is_warning, test_pullup_plus_decoupling_is_not_a_filter, test_missing_c_value_does_not_invent_fc_warning, test_pi_and_t_need_l_and_c, test_ferrite_dcr_warns_only_with_datasheet_limit.

PE-XTAL-001 / PE-XTAL-002 / PE-XTAL-003crystal_cl_check.py

Analizza: CL vs C1/C2 (001 coppia; 002 serie/stray; 003 drive). Cstray solo se in specs.
Skip se: niente CL in specs.

  • Test: tests/test_crystal_cl_check.pytest_no_cl_in_specs_is_silent, test_series_above_cl_without_stray_warns, test_with_stray_mismatch_warns, test_simple_project_without_cl_silent.

PE-LF-001 / PE-LF-002 / PE-LF-003lifecycle.py

Analizza: Obsolete / NRND / RoHS non-compliant.
Skip se: catalogo assente.

  • Test: tests/test_lifecycle_check.pytest_obsolete_is_warning_and_uses_distributor_replacement, test_nrnd_is_info, test_explicit_rohs_non_compliant_is_warning, test_active_is_silent, test_rohs_not_applicable_is_not_a_fail, test_missing_catalog_and_missing_substitute_are_not_guessed.

PE-INT-001internal_features_check.py

Analizza: ESD/pull interni vs net.
Skip se: internal_features vuoto (non si indovina open-drain).

  • Test: tests/test_internal_features_check.pytest_listed_open_drain_without_pull_is_warning, test_listed_pin_with_pullup_is_silent, test_empty_features_does_not_guess_open_drain.

PE-ESR-001hf_coverage_check.py

Analizza: copertura HF/ESR (bulk vs 100 n).
Skip se: valore C sconosciuto.

  • Test: tests/test_hf_coverage_check.pytest_bulk_only_is_info_ps_esr_001, test_bulk_plus_100n_is_silent, test_unknown_cap_value_is_not_guessed.

PE-ERRATA-001errata_check.py

Analizza: errata pubblicata vs pull sul pin.
Skip se: MPN sconosciuto o entry senza URL.

  • Test: tests/test_errata_check.pytest_missing_errata_pullup_is_ps_errata_001, test_pullup_present_is_silent, test_unknown_mpn_and_url_less_entry_are_silent.

Suite deterministica end-to-end: tests/test_validation_deterministic_seed.py test_deterministic_findings_seeded_and_not_reviewed; tests/test_eval_report.py test_simple_project_eval_matches_committed_golden.

1.4 Certifier di classe (grafo — schema e PCB)

Moduli: interface_class_check.py (schema e PCB), hf_bus_class.py (2.62.0, solo run_pcb_checks), usb_pd_check.py (2.62.1, solo PCB). Niente geometria. Niente connettore/dispositivo → silenzio.

USB-C — solo se receptacle USB-C sul grafo

  • PE-USBC-001 classe USB2 vs USB3 da BOM/footprint/MPN/net.
  • PE-USBC-002 CC1 e CC2.
  • PE-USBC-003 Rd 5.1 kΩ ±10% o Rp 56/22/10 kΩ. Skip/INSUFFICIENT se R ignota o CC verso controller senza R.
  • PE-USBC-004 VBUS e GND.
  • PE-USBC-005 SuperSpeed solo se classe USB3; USB2 = N/A (non ERROR).

Test: tests/test_interface_class_check.pytest_no_connector_emits_nothing, test_usbc_rd_vbus_gnd_certified, test_usbc_missing_cc2_is_error, test_usbc_wrong_rd_is_error, test_usbc_cc_to_controller_without_r_is_insufficient_not_error, test_usbc_unknown_r_value_is_insufficient, test_usb3_class_without_ss_pairs_is_error, test_usb3_with_ss_pairs_is_certified, test_missing_vbus_is_error, test_simple_project_usbc_not_false_error, test_hubaudio_like_usbc_usb2_and_poe_magjack, test_usbc_vbus_does_not_invent_usb_500ma, test_does_not_use_layout_geometry, test_rule_catalog_shared_not_si.

Ethernet — solo se RJ45/MagJack

  • PE-ETH-001 classe 10/100 vs GbE. Skip/INSUFFICIENT se velocità assente (non si inventa GbE).
  • PE-ETH-002 TX/RX (10/100) o quattro MDI (GbE).
  • PE-ETH-003 magnetics se GbE.
  • PE-ETH-004 Bob Smith 75 Ω: REVIEW (spesso in MagJack).

Test: tests/test_interface_class_check.pytest_ethernet_10_100_magjack_no_gbe_magnetics_error, test_gbe_without_magnetics_is_error, test_gbe_with_magnetics_is_certified, test_rj45_without_speed_is_insufficient_not_invented_gbe.

PoE — solo con evidenza PoE (RJ45 nudo = skip)

  • PE-POE-001 evidenza PoE.
  • PE-POE-002 classe/tipo (802.3af/at/bt, Class n) — mai inventata.
  • PE-POE-003 magnetics/isolamento (MagJack o LAN transformer).
  • PE-POE-004 (2.62.1) tensione di isolamento solo da numero sourced. Skip senza V.

Test: tests/test_interface_class_check.pytest_bare_rj45_does_not_invent_poe, test_poe_with_evidence_requires_magnetics_isolation, test_poe_evidence_on_bare_jack_is_isolation_error, test_hubaudio_bom_has_usbc_and_poe_rj45_not_ddr, test_run_pcb_checks_skips_absent_interfaces; tests/test_pcb_phase_b.pytest_poe_isolation_skips_without_voltage_fact.

DDR — solo se DRAM sul grafo (2.62.0)

  • PE-DDR-001 classe DRAM.
  • PE-DDR-002 CK, DQS, ≥8 DQ.
  • PE-DDR-003 VTT/VREF solo se quei net esistono (altrimenti skip, non VTT inventato).

Test: tests/test_hf_line_check.pytest_no_ddr_cpu_fpga_on_usb_only_graph, test_ddr_present_class_and_nets_skip_invented_vtt, test_rule_catalog_hf_ids.

CPU bus parallelo — solo se D/A/controllo esistono (2.62.0)

  • PE-CPU-001 presenza bus parallelo.
  • PE-CPU-002 ≥8 D/DQ/AD.
  • PE-CPU-003 address o AD mux.
  • PE-CPU-004 CS/WE/OE (o FMC).

Test: tests/test_hf_line_check.pytest_cpu_parallel_bus_only_when_data_addr_control_exist.

FPGA — solo se FPGA sul grafo (2.62.0)

  • PE-FPGA-001 classe FPGA.
  • PE-FPGA-002 flash di config se c’è un flash IC (altrimenti skip).
  • PE-FPGA-003 VCCINT/VCCIO solo se net nominati.

Test: tests/test_hf_line_check.pytest_fpga_only_when_present_config_flash_optional.

USB-PD contratto — usb_pd_check.py (2.62.1)

  • PE-PD-001 controller PD sul grafo (FUSB302/TPS257/…). Non è USB2 Rd. PDO non inventati.

Test: tests/test_pcb_phase_b.pytest_usb_pd_skips_without_pd_controller.

1.5 Review AI per-IC + post-pass

Moduli: review_session.py, pcb_review.py non entra qui. DeepSeek, PDF una volta per IC, fail-soft. Prompt tools grafo (find_connected_components, get_net_for_pin, get_pintable, get_datasheet_excerpt). Finding LLM = REVIEW, mai RULE ERROR (finding_engine).

Skip se: niente MPN; niente PDF (not_reviewed); fingerprint invariato (review_fingerprint.py).

  • Review loop: tests/test_native_review_loop.py (5); tests/test_validation_no_tool_recovery.py test_no_tool_calls_triggers_forced_submit_next_turn; tests/test_validation_concurrency.py (3); tests/test_validation_trace_log.py (3); tests/test_review_parse.py (2); tests/test_quote_verify.py (5); tests/test_finding_engine.py (test_llm_review_is_never_rule, test_review_and_risk_cannot_stay_error, test_insufficient_evidence_does_not_stay_error); tests/test_fase_b_checks.py test_llm_error_review_clamped_in_complete_finding; tests/test_review_fingerprint.py (2); tests/test_reprocess.py (4); tests/test_deepseek_provider.py (test_thinking_only_echoes_reasoning_content_on_follow_up e roundtrip tool).
  • Excerpt cross-IC: tests/test_datasheet_excerpt_tool.py (12); tests/test_cache_breakpoint_limit.py (3).
  • Normalize (downgrade-only): tests/test_normalize_findings.py (14); tests/test_periscope_postpass_rewrite.py test_emmaforo_uart_normalize_cannot_promote_warning.
  • Dedupe cross-IC: tests/test_dedupe_findings.py (11); tests/test_periscope_postpass_rewrite.py test_emmaforo_uart_dedupe_collapses_both_endpoints.

2. Esame PCB (MODE=pcb)

Stadi: ensure_graphparse_pcbclassifyinventoryrun_pcb_checksai_reviewpcb_report.json. ID finding PCB-{ref}-{001}. Mutex vs analisi schema e vs placement. Inventario net (pcb_inventory.py) è numeri, non finding.

KiCad DRC non è un nodo Periscope. tests/test_pcb_software_bugs.py test_drc_unconnected_items_count e test_hubaudio_pcb_lay004_vs_drc_order_of_magnitude servono solo a non copiare il DRC.

Suite orchestrazione: tests/test_pcb_review.py test_run_pcb_checks_assigns_pcb_ids_and_recommendations, test_pcb_pipeline_imports_build_placement_plan; tests/test_pcb_phase_b.py test_run_pcb_checks_phase_b_absent_is_silent, test_phase_b_rule_catalog; tests/test_interface_class_check.py test_merge_drops_duplicate_pcb_interface_findings; tests/test_pcb_sse_terminal.py (4).

2.1 Layout ingest (non DRC)

parsers_kicad_pcb.pyLayoutGraph. Nessun default 1 oz.

  • Test: tests/test_kicad_pcb.py (14); tests/test_pcb_via_not_pad.py (geometria via≠pad); tests/test_pcb_software_bugs.py test_kicad10_name_only_nets_fill_index.

2.2 Net / footprint — pcb_net_match.py + pcb_checks._incomplete_layout_finding

PE-LAY-001

Pad PCB su net diverso dallo schema (stesso pin).
Skip se: layout assente.

  • Test: tests/test_pcb_review.pytest_pad_net_mismatch_is_pe_lay_001, test_hierarchy_plus_real_mismatch_keeps_only_real_pe_lay_001.

PE-LAY-002

Ref in schema, nessun footprint (tranne #PWR). Distingue “manca sulla PCB”.

  • Test: tests/test_pcb_review.py test_missing_footprint_is_pe_lay_002; tests/test_incomplete_pcb.py test_unplaced_ref_is_lay_002_not_invented_xy.

PE-LAY-003

Stesso net, solo prefisso /sheet/ KiCad (INFO, una volta).

  • Test: tests/test_pcb_review.py test_kicad_hierarchy_slash_is_one_sync_finding_not_per_pad.

PE-LAY-004pcb_checks.py (non in catalogo finding_engine)

Pad net senza rame (track o via o zone). Skip NC unconnected-(…). INFO INSUFFICIENT, non FAIL inventato.

  • Test: tests/test_incomplete_pcb.py test_run_pcb_checks_on_partial_layout_does_not_invent_tracks; tests/test_pcb_software_bugs.pytest_lay004_zone_counts_as_copper, test_lay004_skips_unconnected_nc_and_matches_sheet_prefix, test_hubaudio_pcb_lay004_vs_drc_order_of_magnitude.

2.3 Placement vs layout_rulesplacement_check.py

Senza mm in layout_rules: skip. Niente 3 mm default. Distanza euclidea pad-pad non usata.

PE-PLC-001

Path rame (segmenti) vs max_distance_mm.

  • Test: tests/test_placement_check.pytest_crystal_load_cap_beyond_max_distance_mm_is_ps_plc_001, test_crystal_load_cap_within_max_distance_mm_is_silent, test_track_path_longer_than_max_distance_mm_is_ps_plc_001; tests/test_pcb_review.py test_close_decoupling_has_no_plc_001; tests/test_placement_check.py test_simple_project_without_pcb_has_no_ps_plc.

PE-PLC-002

Via in courtyard vs min_via_count. Skip senza vertici courtyard e senza min.

  • Test: tests/test_placement_check.py test_via_count_is_calculated_from_courtyard_and_min_parameter (geometria _in_poly; non emette ancora il finding end-to-end).

PE-PLC-003

same_layer decoupling.

  • Test: tests/test_placement_check.pytest_same_layer_param_opposite_layers_is_ps_plc_003, test_same_layer_param_same_copper_is_silent, test_opposite_layers_without_same_layer_param_is_silent, test_opposite_layers_with_via_in_courtyard_is_silent.

PE-PLC-004

Keepout: net estraneo nel courtyard. Non è DRC rame-pad.

  • Test: tests/test_placement_check.pytest_keepout_foreign_track_in_courtyard_is_ps_plc_004, test_ic_courtyard_pad_nets_are_not_keepout_violations, test_keepout_own_net_in_courtyard_is_silent, test_keepout_without_courtyard_is_silent.

PE-PLC-005 (non in catalogo finding_engine)

Proximity non misurabile perché manca la traccia.

  • Test: tests/test_placement_check.py test_unrouted_crystal_cap_is_insufficient_not_euclidean.

Schema runner omette i check layout: tests/test_placement_check.py test_schema_deterministic_runner_omits_layout_checks.

2.4 SI — si_check.py + ImpedenceFinder

Gate: layout_rules kind + net_class/quote sul bus citato. Skip I2C/GPIO/EN/CC/strap RC. Bus: USB2, USB3, ETH MDI, RGMII, SGMII, DDR3 CLK/DQS/DQ/ADDR, HDMI, PCIe, LVDS; 2.62.0 aggiunge MIPI e clock HF (bus_class); XTAL/OSCIN fuori.

Z0: impedance.py / impedance_traces.py. CPWG → errore, non numero inventato. Senza stackup: skip misura.

Suite gate: tests/test_si_check.py test_skip_i2c_gpio_cc_regn, test_i2c_not_checked_as_50_ohm, test_simple_project_without_pcb_has_no_ps_si_001; tests/test_hf_line_check.py test_bus_class_mipi_hf_clk_not_xtal. Calcolatrice: tests/test_impedance.py (20); misura net: tests/test_impedance_traces.py (10).

PE-SI-001 length_match / skew coppia

Skip senza mm datasheet.

  • Test: tests/test_si_check.py test_length_match_2_5mm_vs_1mm_is_fail, test_coverage_mdi_rgmii_ddr3_usb3_gated_not_cross_mapped.

PE-SI-002 Zavg/min/max vs finestra datasheet

Mai folklore 90 Ω.

  • Test: tests/test_si_check.py test_emmaforo_usb_avg_in_window_min_out_is_margin, test_coverage_mdi_rgmii_ddr3_usb3_gated_not_cross_mapped.

PE-SI-003 lunghezza max mm

  • Test: tests/test_si_check.py test_coverage_mdi_rgmii_ddr3_usb3_gated_not_cross_mapped.

PE-SI-004 spacing intra-coppia mm

Skip senza mm. Copertura indiretta nella stessa suite SI gated.

PE-SI-005 piano di riferimento / layer

Skip senza FACT datasheet.

PE-SI-006 conteggio via HS vs min/max datasheet

Skip senza min/max.

PE-SI-008 return via accanto alla coppia (return_path)

Skip senza kind.

PE-SI-009 serie R ohm sul net HS (non EN-RC)

  • Test: tests/test_si_check.py test_en_rc_series_resistor_does_not_paint_usb.

PE-SI-010 bus HS misurato, libreria senza FACT Z → INFO, non FAIL 90 Ω

  • Test: tests/test_si_check.py test_usb_without_library_z_is_insufficient_not_90ohm_fail, test_empty_net_class_impedance_does_not_paint_usb; tests/test_hf_line_check.py test_existing_si_usb_not_polluted_by_hf_geometry.

Refresh extract SI vecchio: tests/test_pcb_plan_closeout.py test_si_refresh_when_old_extract_has_only_decoupling, test_si_extract_needed_skips_board_ics_only_not_shared_library.

2.5 Linee HF extra — hf_line_check.py (2.62.0 Fase A)

Track ≠ via ≠ pad ≠ zona. Stub = traccia dangling.

PE-SI-007 stub vs mm datasheet

INFO se misura c’è e mm mancano (INSUFFICIENT). Skip: pad-pad, via, zone.

  • Test: tests/test_hf_line_check.pytest_no_layout_skips_hf_geometry, test_pad_to_pad_usb_has_no_stub, test_via_is_not_a_stub, test_zone_is_not_a_track_stub, test_dangling_track_stub_vs_datasheet_mm_is_fail, test_measured_stub_without_datasheet_mm_is_insufficient.

PE-SI-011 gap pour GND sotto coppia HF (REVIEW)

Skip senza stackup/zone.

  • Test: tests/test_hf_line_check.py test_split_under_pair_needs_stackup_and_zone.

PE-SI-012 terminazione BOM serie/parallelo FACT

Skip se manca il terminatore (non si inventa 50 Ω).

  • Test: tests/test_hf_line_check.py test_bom_termination_is_fact_missing_is_skip.

Catalogo HF: tests/test_hf_line_check.py test_rule_catalog_hf_ids. DDR/CPU/FPGA: §1.4 (stesso check_memory_fpga_classes in run_pcb_checks).

2.6 Potenza / via / termico sul board — pcb_power_thermal.py

PE-PWR-001 (PCB) — check_pcb_power_traces

Larghezza traccia × spessore rame vs I_load/Imax/I_abs. IPC-2221 solo con thickness e ΔT da Tjmax. Iout_max non è carico. Niente 500 mA USB.

Skip se: manca I datasheet (skip vero, non INFO INSUFFICIENT — 2.61.1).

  • Test: tests/test_pcb_review.pytest_power_trace_ipc2221_errors_when_load_exceeds_ampacity, test_power_trace_uses_parsed_width_and_thickness, test_power_trace_skips_without_i_load, test_power_trace_skips_iout_max_as_load, test_power_trace_uses_imax_when_i_load_absent, test_power_trace_uses_i_abs_when_i_load_absent; tests/test_interface_class_check.py test_usbc_vbus_does_not_invent_usb_500ma.

PE-VIA-001check_pcb_via_current

Se I c’è e sul net zero via: INFO conteggio. Se le via ci sono: silenzio — nessuna tabella ampacity. Via ≠ traccia.

Skip se: manca I.

  • Test: tests/test_pcb_software_bugs.py test_via_current_skips_without_i_load.

PE-VIA-002 (2.62.1)

I + conteggio/drill FACT. Tabella IPC via non applicata.

Skip se: manca I.

  • Test: tests/test_pcb_phase_b.py test_via_current_skips_without_i_does_not_invent_ipc.

PE-THM-001check_pcb_thermal_copper

P = I_load × drop; courtyard senza pour/via.

Skip se: P sconosciuta.

  • Test: tests/test_pcb_review.py test_thermal_copper_warns_without_pour_or_vias.

PE-THM-002check_pcb_junction_temp

Tj = Ta + P·θJA solo con P, θJA, area rame, conteggio via. Non è FEM.

Skip/INSUFFICIENT se manca un fattore.

  • Test: tests/test_pcb_plan_closeout.pytest_tj_when_theta_copper_vias_exist, test_tj_insufficient_without_theta.

PE-KEL-001

Pin Kelvin/sense sullo stesso net di carico. Ignora CRS/IN±.

  • Test: tests/test_pcb_review.py test_kelvin_sense_pin_on_shared_net; tests/test_pcb_software_bugs.py test_kelvin_ignores_crs_and_in_plus.

PE-STCH-001

Segnale sopra pour GND senza via GND nel bbox. Skip GPIO minuscoli.

  • Test: tests/test_pcb_review.pytest_gnd_stitch_skips_tiny_gpio, test_gnd_stitch_info_when_signal_has_pour_but_no_via.

2.7 Derating / gerarchia / timing / PI

PE-DRT-001 / PE-DRT-002 / PE-DRT-003pcb_checks.check_pcb_derating + derating.py

Vop vs Vrated: ERROR / MARGIN / PASS INFO. Niente % dielettrico inventato. Skip se manca Vop o Vr.

  • Test: tests/test_fase_b_checks.py test_derating_pass_margin_risk; tests/test_derating.py (7, C_eff stima — non è un PE-* a parte).

PE-HIER-001hierarchy.py

Pin IC senza net nominato.

  • Test: tests/test_fase_b_checks.py test_hierarchy_component_pin_net_block.

PE-TIM-001 / PE-TIM-002timing_check.py

001 RC reset vs t_reset; 002 strap vs Vih/Vil.
Skip senza R/C e t_reset o Vih/Vil.

  • Test: tests/test_fase_b_checks.pytest_timing_skips_without_numbers, test_timing_reset_rc_vs_t_reset. PE-TIM-002 non ha un test che fa scattare il finding (solo skip condiviso).

PE-PI-001 / PE-PI-002pi_check.py

001 cap locale sul rail IC; 002 locale vs bulk se i valori C esistono. Distanza mm solo da layout_rules (altrimenti è PE-PLC-001). Skip net NC.

  • Test: tests/test_fase_b_checks.pytest_pi_missing_local_is_risk_not_error, test_pi_any_cap_on_slash_prefixed_rail_suppresses_missing_local, test_pi_bulk_only_does_not_claim_no_local; tests/test_pcb_software_bugs.py test_emi_and_pi_skip_unconnected_nets. PE-PI-002 non ha un assert dedicato sul rule_id.

2.8 ESD / return / EMI / SPOF

PE-ESD-001esd_return_check.check_esd

Net J* ∩ IC senza parte ESD: REVIEW, non ERROR. Niente GPIO/NC/rail spam.

  • Test: tests/test_fase_b_checks.pytest_esd_without_part_is_review_not_error, test_esd_skips_gpio_nc_unconnected_and_onboard_power, test_esd_one_finding_per_connector_ic_path, test_esd_skips_when_protection_part_on_net.

PE-ESD-002 (2.62.1) — check_esd_distance

Distanza pad TVSconnettore (via ≠ pad). INFO se no mm.

  • Test: tests/test_pcb_phase_b.py test_esd_distance_uses_pads_not_vias.

PE-RET-001check_return_path

Net HS sopra pour GND senza via GND nel bbox: REVIEW.

  • Test: tests/test_fase_b_checks.py test_return_path_hs_is_review.

PE-EMI-001emi_check.py

Solo se layout_rules cita choke/ferrite/shield. Non IEC 61000. Skip NC.

  • Test: tests/test_pcb_plan_closeout.py test_emi_only_with_datasheet_fact; tests/test_pcb_software_bugs.py test_emi_and_pi_skip_unconnected_nets.

PE-SPOF-001spof_check.py

Un regolatore o XTAL condiviso: REVIEW, mai ERROR.

  • Test: tests/test_pcb_plan_closeout.py test_spof_review_single_ldo.

2.9 BOM ↔ PCB ↔ datasheet — bom_pcb_check.py

Skip se manca un lato (BOM, footprint, o numero datasheet).

PE-BOM-010 famiglia package

VQFN/WQFN/HVQFN = QFN. LQFP ≠ QFN.

  • Test: tests/pcb/test_pcb_plan_closeout.py test_package_family_mismatch_is_pe_bom_010; tests/pcb/test_bom_011_named_join.py test_qfn_vs_vqfn_same_24_qfn_land_not_bom_010.

PE-BOM-011 pintable vs pad, join per nome

Join datasheet pintable × .kicad_mod lib × pad embedded. Non pin_count scalare. A5/B5 USB-C sono pin, non EP. EP/SH/mount classificati; via ≠ pad. Senza pintable: skip.

  • Test: tests/pcb/test_bom_011_named_join.py; tests/pcb/test_pcb_plan_closeout.py test_package_family_mismatch_is_pe_bom_010; tests/pcb/test_pcb_software_bugs.py test_ep_split_pads_not_bom_011; tests/pcb/test_pcb_via_not_pad.py.

PE-BOM-012 Vop vs rating/abs-max legato al pin

  • Test: tests/test_pcb_plan_closeout.py test_abs_max_voltage_and_temp_and_current; tests/test_pcb_software_bugs.py test_vddcr_absmax_does_not_bind_3v3_io.

PE-BOM-013 Top vs abs-max T

  • Test: tests/test_pcb_plan_closeout.py test_abs_max_voltage_and_temp_and_current.

PE-BOM-014 I_load vs rating

Skip se manca I.

  • Test: tests/test_pcb_plan_closeout.pytest_abs_max_voltage_and_temp_and_current, test_inductor_current_rating.

2.10 Resto Fase B (2.62.1)

PE-STK-001stackup_check.py

Spessore rame board vs stackup fab sourced. Mai 1 oz default.
Skip se: niente stackup layout o niente FACT fab.

  • Test: tests/test_pcb_phase_b.pytest_stackup_skips_without_fab_spec, test_stackup_vs_fab_spec_is_review_not_invented_oz.

PE-ANT-001 / PE-ANT-002antenna_layout_check.py

Keepout zona e matching L/C sul feed. Solo se antenna/net RF sul grafo. Niente 50 Ω inventati.
Skip se: antenna assente; matching manca e non c’è FACT (002 non emette).

  • Test: tests/test_pcb_phase_b.pytest_antenna_skips_when_absent, test_antenna_keepout_and_match_are_facts.

PE-PDN-001pdn_check.py

Z(f) solo con FACT in frequenza. Z0 SI non è PDN.

  • Test: tests/test_pcb_phase_b.py test_pdn_skips_without_zf.

Silenzio Fase B se assente: tests/test_pcb_phase_b.py test_run_pcb_checks_phase_b_absent_is_silent. Catalogo: test_phase_b_rule_catalog.

2.11 Review AI PCB

Modulo: pcb_review.py + services/pcb_validation.py. Stesso oggetto finding. Spiega FACT deterministici; non rilegge il PDF; non inventa interfacce / PoE / SuperSpeed / mm / Z / I.

Skip se: niente JSON libreria per lIC.

  • Test: tests/test_pcb_review.pytest_pcb_ai_finding_gets_action, test_parse_review_action_field_without_recommendation, test_layout_context_includes_via_counts, test_layout_context_includes_domain_and_group, test_pcb_ai_skips_without_library_extraction, test_library_constraints_fill_from_storage, test_inventory_lists_net_length_and_pair; tests/test_finding_engine.py test_pcb_review_ai_finding_action_without_recommendation; tests/test_pcb_software_bugs.py test_thinking_reasoning_content_echo_still_present.

2.12 Tab antenna RF (non in run_pcb_checks)

Moduli: antenna_rf.py, antenna_geometry.py. Topologia matching + ricetta routing. No EM/VSWR/CPWG. Distinto da PE-ANT-001/002.

  • Test: tests/test_antenna_rf.pytest_verify_finds_matching_path_to_ant_footprint, test_verify_missing_matching_is_warning, test_design_recipe_needs_marker_without_ant, test_design_recipe_ready_with_ant_and_stackup, test_geometry_templates_produce_export, test_geometry_overflow_tiny_zone, test_design_recipe_meander_template.

Placement/auto-place non è esame PCB: tests/test_placement_pack.py, tests/test_placement_pipeline.py (fuori da questo albero di analisi).


Motore finding (condiviso)

finding_engine.py: FACT / REQUIREMENT / INFERENCE; ERROR solo RULE+MANDATORY; decisions.json non ri-naga.

  • Test: tests/test_finding_engine.py (11); tests/test_finding_schema.py (7); tests/test_fase_b_checks.py test_sort_findings_error_then_class; tests/test_review_workflow.py (10 — stati finding UI, non check PE). CAD bridge: tests/test_cad_bridge.py (5).

Test che esistono ma non sono analisi

tests/ ha 114 file / ~730 test. Oltre ai nodi sopra restano overlay nativi, upload, auth, billing seam, UI rewrite. Non sono check PE-*.

Upload / ingest cartella (non analisi): tests/test_periscope_frontend_upload_rewrite.py test_upload_zone_is_src; tests/test_kicad_project.py (picker cartella, .history, Safari stem); tests/test_netlist_bundle.py (zip, zip-slip); tests/test_kicad_pcb.py test_upload_pcb_sets_has_pcb, test_upload_sch_as_pcb_is_rejected; tests/test_purple_parts_resolver.py (upload BOM/LCSC); tests/test_reopen_replace.py test_reopen_then_replace_bom_and_netlist.

Auth: i test auth esistono (tests/test_local_auth.py, tests/test_periscope_auth_rewrite.py, tests/test_pinscope_compat.py, più overlay che tengono il contratto login). Non si descrivono segreti, JWT, password, o flussi di autenticazione.

Altri non-analisi: rewrite frontend/Docker (test_periscope_*_rewrite.py, test_periscope_leftover_package_requirements.py, test_periscope_boot_without_dependency_product.py); delete progetto; cost estimator; event bridge; job runner; test_deepseek_only.py (routing modello, non finding).


Conteggio nodi

Gruppo Nodi
Check solo schema (27 PE-* + LED senza ID) 28
USB-C / ETH / PoE (schema e PCB) 13
PE-PWR-001 (due source: schema e PCB) 1
DDR / CPU / FPGA / PD (grafo, invocati da run_pcb_checks) 11
Check solo PCB (layout, SI/HF, potenza, Fase B, …) 47
Processo: 3 skill + DigiKey + value + IC AI + PCB AI + tab RF 8
Totale nodi analisi 108

Check PE-* in codice: 99 (tutti elencati). Più LED senza rule_id. PE-LAY-004, PE-PLC-005, PE-TH-002 sono in codice; PE-LAY-004 / PE-PLC-005 non sono in _seed() di finding_engine.py.

Buchi di test noti (il check c’è, il fire test no): PE-TIM-002, PE-PI-002 (nessun assert rule_id), PE-PLC-002 (solo geometria _in_poly), PE-SI-004 / PE-SI-005 / PE-SI-006 / PE-SI-008 (gate SI, niente caso dedicato).