Elimina i falsi "componenti mancanti" dal rilevamento delle family table

Il record "model_name" veniva preso per l'identita' del file, ma sui file
reali nomina quasi sempre un altro modello - tipicamente uno dei membri del
file stesso. Il parser esatto rifiutava percio' file perfettamente
leggibili, il chiamante ripiegava sull'euristica testuale e quella
estraeva codici inesistenti, riportati poi come componenti non trovati
nell'indice.

Il segnale ora richiede la conferma del nome proprio del modello
(objname): scatta solo se il file dichiara davvero se stesso come istanza.

Verificato contro le BOM esportate da Creo per 7 assiemi reali: 6 vengono
riprodotte byte per byte (3 di queste prima non si generavano affatto), e
la settima differisce per una sola parte, presente nella revisione di un
sotto-assieme che Creo ha caricato ma assente in quella piu' recente. La
verifica di completezza passa su tutti e 7 (prima 3 risultavano
incompleti), e tutti i 351 .asm di una cartella raw/ reale si leggono col
parser esatto, senza mai ricadere sull'euristica.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
davideandClaude Opus 5 committed 2026-09-22 10:47:08 +02:00
1 parent b136e7f49b
commit 0ae2a5e7cf
3 files changed
+100 -76

No files matched your search

+33 -53
View File
@@ -359,7 +359,7 @@ di ciascun punto segue sotto, in due gruppi.
| Deduplica blocchi + moltiplicazione quantità (§6.2/§6.3) | Risolto | BOM reale (§7.1) |
| Revisione del figlio che il padre si aspetta (§6.4) | Risolto | BOM reale (§7.1) |
| Stato soppresso/escluso in `members` | Risolto | BOM reale (§7.1) |
| Family table di **assiemi** (rilevamento) | Risolto lato sicurezza (mai un falso negativo pericoloso), segnale non affidabile al 100% | BOM reale + scala intera share (§7.1) |
| Family table di **assiemi** (rilevamento) | Risolto: serve la conferma del nome proprio (`objname`), il solo `model_name` dava falsi positivi | BOM reali + albero `raw/` completo (§7.1) |
| Family table di **assiemi** (contenuto di ogni istanza) | Non risolto, nessun impatto sulla BOM (fallback già corretto) | Scan sull'intera share (§7.2) |
| Costante `\x82\x7b` in `ConfigName` | Significato ignoto, rischio coperto | Scala 350 file (§7.2) |
| Occorrenze multiple di `members` (simplified rep) | Mai osservato, rischio coperto | Scala 350 file (§7.2) |
@@ -411,24 +411,32 @@ di sbagliare in silenzio.
\xf4
```
Il file generico è già di per sé un'istanza (`model_name` porta il suffisso `_C0n`, non è
neutro), e `stamp` elenca le sorelle. Il segnale usato per riconoscerlo è la combinazione
`model_t_type`+`model_name` (con suffisso `_C0n`)+`generic_name` vuoto
(`AsmRecordReader.OwnModelIdentityRegex` + `SuffissoIstanzaFamilyTableRegex`) - **non** la
sola presenza di `generic_name`, che su altri 119 file del corpus da 350 compare in un
contesto diverso e non correlato (`model_name` lì è un codice slegato dal nome del file, e
`members` in quei casi è già corretto). Verificato: solo 25/350 file rispettano il segnale
affidabile, e su quei 25 `AsmRecordReader.LeggiMembri` lancia `InvalidDataException` invece
di restituire il contenuto sbagliato della rappresentazione di default.
Quando questo succede il file generico è già di per sé un'istanza (`model_name` porta il
suffisso `_C0n`, non è neutro) e `stamp` elenca le sorelle.
> **Non è un segnale affidabile al 100%.** Un controllo su scala più ampia (tutta la share,
> §7.2) ha trovato un caso in cui il segnale scatta ma **non c'è nessuna family table**:
> `9053005060.asm` è un assieme ordinario con due parti figlie `_C01`/`_C02` (geometrie
> diverse, nessuna family table nell'albero Creo - verificato dall'utente). Il perché il
> record di identità propria porti comunque il suffisso `_C0n` in quel caso resta ignoto.
> Non cambia la sicurezza del comportamento (`InvalidDataException` → fallback su
> `AssemblyComponentScanner`, che legge comunque il file correttamente), ma il segnale va
> trattato come "candidato da verificare", non come conferma di family table.
> **Il record `model_name` da solo non è un'identità.** Su file reali quel record nomina
> quasi sempre **un altro modello** - tipicamente uno dei membri del file stesso, a volte un
> codice imparentato - e in quei casi `members` è già corretto e va usato. Serve una
> conferma indipendente: il **nome proprio del modello** (`objname`, §5). `LeggiMembri`
> segnala la family table solo se `objname` esiste **e** coincide con `model_name` privato
> del suffisso `_C0n`; negli altri casi legge `members` normalmente.
>
> Il controllo più largo (senza la conferma di `objname`) era la causa di
> **falsi "componenti mancanti"**: il parser esatto rifiutava file perfettamente leggibili,
> si ripiegava sull'euristica testuale e quella estraeva codici che non esistono, riportati
> poi come componenti non trovati nell'indice. Verificato contro BOM Creo di riferimento:
> sui file dove il segnale scattava senza conferma di `objname`, `members` elenca
> **esattamente** i componenti della BOM reale (anche nello stesso ordine); uno di questi
> file è stato inoltre aperto in Creo, e l'albero del modello mostra gli stessi componenti,
> senza alcuna family table. Con la conferma di `objname` richiesta, tutti i `.asm` di una
> cartella `raw/` reale (351 file, alberi completi di più macchine) si leggono col parser
> esatto, zero ricadute sull'euristica.
Da tenere presente: il sintomo dipende da **come il file è stato salvato**, non solo dal
modello. Rileggendo una revisione più recente dello stesso assieme generico, il record di
identità può non esserci più e `members` elencare direttamente tutte le istanze, col tipo
giusto per ciascuna - cioè esattamente quello che mostra la BOM. Il blocco quindi non è una
proprietà stabile del codice: va valutato file per file, revisione per revisione.
Verificato anche che il fallback su `AssemblyComponentScanner` **risolve già correttamente**
il caso vero: i nomi delle istanze compaiono come testo puro nel campo `stamp`, e
@@ -443,42 +451,14 @@ di sbagliare in silenzio.
- **Family table di assiemi — contenuto di ogni istanza.** Come recuperare il contenuto
specifico di un'istanza **senza** che esista già un file separato per essa sul disco (il
caso comune, se nessuno l'ha mai esportata a parte con "Salva una copia"): il meccanismo
dietro `stamp` non è stato decodificato oltre a nome+tipo di ciascuna istanza sorella.
Aperto anche cosa sia davvero il record `generic_name` sui 119 file dove non è questo
sintomo.
dietro `stamp` non è stato decodificato oltre a nome+tipo di ciascuna istanza sorella:
`stamp` porta **solo i nomi** delle sorelle, non il loro contenuto, quindi non è la
struttura da cui partire per risolvere questo punto.
**Aggiornamento (scan sull'intera share, non solo sul campione da 350 file).** Applicando
il segnale (`OwnModelIdentityRegex` + `SuffissoIstanzaFamilyTableRegex`) a tutti i `.asm`
indicizzati su `X:\` (7157 combinazioni cartella+codice uniche, ultima revisione ciascuna):
**95 candidati**, non solo i 25/350 del campione originale.
Sul primo candidato controllato (`9053005060.asm.1`, un'unica istanza sorella secondo il
segnale), `stamp` si decodifica a mano byte per byte:
```
\xe0\x00 "stamp"\0 \xe2\xf2\xf7\x07 \xe3\x02 "9053005060_C02"\0\0 \xe2
```
Confermato: **`stamp` porta solo i nomi** delle istanze sorelle, non il loro contenuto -
non è quindi la struttura giusta da cui partire per risolvere questo punto in generale.
**Ma il candidato stesso era un falso positivo.** Verificato in Creo (albero del modello,
screenshot dell'utente): `9053005060.asm` **non** è una family table - è un assieme
ordinario con due parti figlie distinte `9053005060_C01.prt` e `9053005060_C02.prt` (pesi e
geometrie diverse, nessuna icona di family table nell'albero). Il segnale ha comunque
acceso perché, in quella revisione, il record di identità propria del file portava
`model_name = 9053005060_C01` con `generic_name` vuoto - non si sa ancora perché (forse
legato all'ultimo componente attivo/rigenerato quando il file fu salvato, non a una vera
family table). **Conseguenza pratica: il segnale, validato con BOM reale solo su
`2546220101.asm` (§7.1), non è affidabile su larga scala senza verifica caso per caso** - i
95 candidati trovati dallo scan sono solo *papabili*, non confermati; non c'è motivo di
credere che la maggioranza sia una vera family table di assieme.
**Resta comunque un punto aperto solo per completezza documentale, non un problema da
correggere**: qualunque sia la causa del falso positivo, il fallback su
`AssemblyComponentScanner` gestisce comunque correttamente il file (legge i due membri via
euristica testuale, non tenta di interpretare `stamp`), quindi nessun comportamento della
app dipende da questa decodifica.
Resta aperto solo per completezza: sui file dove il segnale scatta davvero (con conferma
del nome proprio, §7.1) il parser si ferma invece di restituire un contenuto sbagliato, e
il chiamante ripiega sull'euristica testuale, che i nomi delle istanze li trova comunque
come testo puro. Nessun comportamento dell'app dipende da questa decodifica.
- **Costante `\x82\x7b`** nei record `ConfigName`: significato ignoto. Rischio coperto -
`LeggiMembri` conta le occorrenze grezze di `ConfigName` e le confronta col numero di match
del regex; se un campione avesse un valore diverso, il regex non farebbe più match (prima: