Fix euristica BOM, unifica script/GUI su un'unica fonte, aggiungi test integrazione/E2E

Due bug reali trovati confrontando l'estrazione BOM con la BOM ufficiale Creo:
un componente scartato per placement fallito in un file veniva bloccato per
sempre anche quando il file giusto aveva un vero placement (perdendo interi
sotto-alberi come 9256510047), e i codici con suffisso (_C01 ecc.) richiedevano
sempre placement esplicito invece dell'eccezione per occorrenze ripetute già
presente nella GUI. Entrambi corretti.

AssemblyComponentScanner reso pubblico e scripts/BomViaDb.cs, ExtractCreoStrings.cs
riscritti per referenziarlo via "#:project" invece di duplicare l'euristica:
un'unica fonte di verità condivisa da GUI e script standalone.

Aggiunti test di integrazione per Indexer.ScanAsync (mai coperto oltre al
parsing del nome file) e test end-to-end che ricostruiscono l'intera pipeline
disco -> indice -> risoluzione albero componenti senza toccare la UI.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
davideandClaude Sonnet 5 committed 2026-09-21 13:43:54 +02:00
1 parent 353a1028d9
commit 5c9661eb12
8 files changed
+514 -171

No files matched your search

+76
View File
@@ -281,6 +281,82 @@ per `data_modifica DESC` e tenuta solo la riga più recente per tipo, altrimenti
si rischia di risolvere un codice contro una copia diversa (e potenzialmente
diversa nel contenuto) da quella realmente referenziata.
### Trappola nella BFS: un fallimento di placement non è definitivo
Un codice può comparire come riferimento fantasma (senza vero placement, vedi
sopra) in un file scansionato **prima** di quello in cui invece ha un vero
placement — tipicamente perché lo stesso codice è mostrato anche nel file
dell'assieme padre come promemoria/metadato, oltre che nel file del proprio
assieme dove è effettivamente posizionato. Osservato su un caso reale
(assieme `9244228558.asm`): il componente `9244236104` compare nel file
dell'assieme generale come riferimento nudo senza placement (viene scartato
lì, correttamente), ma ha un vero `Component id 45 (9244236104.PRT)` dentro
`9244228558_c01.asm`, il sotto-assieme che lo contiene realmente — scansionato
solo _dopo_ il file padre nella BFS.
Una BFS che marca un candidato come "già visto" al primo incontro, anche
quando quell'incontro è un fallimento di placement, blocca per sempre ogni
ri-verifica successiva: il componente resta perso anche quando il file giusto
viene scansionato più avanti. Nei casi più gravi il codice bloccato è esso
stesso un **sotto-assieme** (osservato con `9256510047` dentro
`9256518042.asm`): se il suo codice viene scartato prematuramente, il suo file
non viene nemmeno accodato, e si perde l'intero sotto-albero sottostante
(compresi `9056510047`/`9056510047_C01`/`9056510047_C02` in questo caso).
`scripts/BomViaDb.cs` (versione iniziale) aveva esattamente questo bug: un set
`codiciVisti` unico bloccava sia i candidati confermati sia quelli scartati
per mancato placement. Corretto separando le due cose: un fallimento di
placement non aggiunge il codice a nessun set di blocco, quindi resta
ritestabile ogni volta che lo stesso candidato ricompare in un file successivo
già in coda. L'accodamento di un nuovo file da scansionare resta invece
condizionato al placement confermato (non al solo essere un codice noto nel
DB) — senza questo secondo vincolo, un codice generico che per puro caso
coincide con un codice noto (es. `"915"`, `"932"`) farebbe esplodere la
scansione su file estranei in tutto l'indice (verificato: passa da ~100 a
quasi 19000 "componenti trovati" e la scansione si blocca).
**Il codice della GUI (`Form1.RisolviAlberoComponenti` +
`AssemblyComponentScanner.EstraiCodiciReferenziati`) non ha questo bug**,
verificato riproducendo lo stesso caso reale con un test dedicato: la
classificazione placement-sì/no è già interamente delegata a
`EstraiCodiciReferenziati`, chiamata da zero per ogni file scansionato — un
fallimento in un file non lascia traccia nel set `codiciVisti` del chiamante,
che accumula solo codici già confermati. Il file successivo che referenzia
davvero il componente lo ritrova quindi senza ostacoli, senza bisogno di
nessuna modifica. Vale comunque come nota di design da preservare: il giorno
in cui la logica di `RisolviAlberoComponenti` venisse riscritta per fare la
verifica di placement inline nella BFS (come `BomViaDb.cs`), andrebbe
applicata la stessa correzione.
### Seconda discrepanza trovata: l'eccezione dei codici con suffisso
Confrontando `scripts/BomViaDb.cs` (corretto come sopra) con la GUI sullo
stesso assieme di un caso reale più grande (`9284218024b.asm`, ~530
componenti), le due liste **non coincidevano**: lo script perdeva l'intero
sotto-assieme `2546220101` (`_C01`..`_C04`, inclusi i cuscinetti
`INAFAG_NA6901-XL_...` dentro `_C04`), presente invece nella BOM ufficiale
Creo e trovato correttamente dalla GUI.
Causa: `2546220101_C01`..`_C04` hanno un vero placement nel proprio file
(`2546220101.asm`), ma **senza il suffisso** - il testo riporta solo
`Componente ID N (2546220101.PRT)`, il dettaglio `_C01` compare solo altrove
nei metadati, non vicino al placement (stesso fenomeno già documentato sopra
in "Placement senza il dettaglio del suffisso/bracket", osservato lì solo per
famiglie UNI/dimensionali). `AssemblyComponentScanner.EstraiCodiciReferenziati`
già gestisce questo caso: un codice con suffisso di revisione/variante
(`SuffissoRegex`, es. `_C01`, `_D100`) o prefisso di family table nota (`UNI`,
`CUSCI_`) è considerato "forma nota" ed esentato dal placement esplicito -
basta che occorra almeno 2 volte nel file. `BomViaDb.cs` richiedeva invece
sempre il placement letterale per ogni codice, senza questa eccezione.
Corretto portando la stessa regola (`FormaNota` + conteggio occorrenze) in
`BomViaDb.cs`. Riverificato su entrambi i casi reali (`9244228558.asm`,
`9284218024b.asm`): script e GUI producono ora **esattamente lo stesso
insieme** di componenti, e in entrambi coincide con la BOM ufficiale Creo (a
meno delle sole istanze di family table risolte al nome del file realmente
indicizzato, es. `2502020105<CUSCI_DGBB7>` → `CUSCI_DGBB7` - comportamento
corretto, non una discrepanza).
## Strumento di analisi manuale
[`scripts/Analyze.cs`](../scripts/Analyze.cs) stampa il contesto testuale ed