Files
TieMeasureFlow/docs/specs/2026-09-14-visione-stato-e-specifica.md
T
Adriano f930fd98f0 docs: stato verificato della visione su V3.0.0 e specifica di cosa manca
Verificato sul codice, non sui piani: le fondamenta del 16-17/08 ci sono
tutte, ma pattern matching e DXF compare non sono eseguibili dal grafo —
vs-task registra dieci strumenti, tutti geometrici, e vs-dxf non è
nemmeno negli extra. Il ponte va costruito in VisionSuite.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JyL1sTGpFxx7Qw3xP58eoZ
2026-09-14 09:18:11 +02:00

290 lines
19 KiB
Markdown

# La visione in TieMeasureFlow — stato verificato e specifica del lavoro che manca
> Progetto: TieMeasureFlow, ramo **`V3.0.0`** (HEAD `39a6f62`, 17/08/2026)
> Data: 14 settembre 2026
> Stato: specifica da approvare
> Sostituisce, come documento operativo: il piano `docs/superpowers/plans/2026-08-16-vision-fondamenta-server.md`
> (eseguito) e la corsia `A1-tiemeasureflow.md` del piano ferie (eseguita, cancellata dal disco il 01/09 e
> recuperabile con `git show 874a7a4^:docs/plans/corsie-fase2/A1-tiemeasureflow.md` nel repo AI-OS).
> **Resta in vigore** `docs/superpowers/specs/2026-08-16-visionsuite-integration-design.md`: le sue otto
> decisioni architetturali non vengono riscritte qui, vengono richiamate.
## 1. Perché questo documento
Fra il 16 e il 17 agosto sono entrate in TieMeasureFlow le fondamenta della visione: ventiquattro commit,
sette file di test nuovi, tre migrazioni. Da allora il lavoro si è fermato. Nel frattempo VisionSuite è
andato avanti di sessantasette commit, la scheda di commessa non registra nulla dopo il 25 agosto, e
l'installazione a Tràfilo, prevista per settembre, è alle porte insieme alla fiera del 27-29 ottobre.
Questo documento fa due cose. Prima dichiara, verificandolo sul codice e non sui piani, **che cosa esiste
davvero** sul ramo `V3.0.0`. Poi specifica **che cosa manca** per arrivare a ciò che il cliente ha chiesto
il 27 luglio: pattern matching, confronto del profilo con il disegno DXF e due o tre quote lineari, dentro
l'interfaccia di TieMeasureFlow, con l'esito OK/warning/fail che il prodotto già sa dare.
La distanza fra le due cose è più grande di quanto i documenti di agosto lascino credere, e la ragione è
una sola, spiegata al capitolo 3.
## 2. Quello che esiste, verificato sul ramo V3.0.0
Ogni riga di questa tabella è stata controllata aprendo il file indicato nel clone del ramo `V3.0.0` il
14/09/2026. Non è lo stato dichiarato da un piano: è lo stato del disco.
| Cosa | Stato | Dove si vede |
|---|---|---|
| VisionSuite come sottomodulo git, su commit fisso | ✅ | `.gitmodules`, pin `f095fcc` (15/08) |
| Runner unico, senza HTTP né database | ✅ | `src/vision/runner.py`, 129 righe |
| Versione del motore timbrata su ogni numero prodotto | ✅ | `runner.engine_version()`, errore se non risolve |
| Vision worker come servizio separato nel compose | ✅ | `src/vision_worker/main.py`, `Dockerfile.vision`, servizio `vision` |
| Il server non importa mai VisionSuite | ✅ e **sorvegliato** | `src/backend/tests/test_vision_boundary.py` |
| Grafo di visione sul task (`vision_json`) | ✅ | migrazione `011`, `models/orm/task.py` |
| Legame quota del grafo → quota della ricetta (`vision_output`) | ✅ | migrazione `011`, `recipe_subtasks` |
| `camera` fra i metodi di ingresso misura | ✅ | migrazione `011`, enum `input_method` |
| Tabella `vision_results`, una riga per acquisizione | ✅ | migrazione `012`, `models/orm/vision.py` |
| Immagini di riferimento con provenienza | ✅ | migrazione `013`, `vision_reference_images` |
| Il verdetto lo dà TieMeasureFlow, non il grafo | ✅ | `vision_service` chiama `measurement_service` |
| Gate del fuori tolleranza valutato per acquisizione | ✅ | `enforce_tolerance_gate=False` più gate a monte |
| Copy-on-write delle ricette che copia anche il grafo | ✅ | `test_vision_copy_on_write.py` |
| Il refuso `xf_compare` corretto in `dxf_compare` | ✅ | migrazione `011`, prima che una riga lo usasse |
| Limiti di tipo e dimensione sugli endpoint di upload | ✅ | `test_vision_upload_limits.py` |
| Il guasto del worker resta del worker | ✅ | `vision_service._call_worker`, 502/504 nominati |
| L'applicazione parte senza internet | ✅ | `static/vendor/`, `test_offline.py` |
| API `POST /api/vision/execute`, `/preview`, `/reference-images` | ✅ | `api/routers/vision.py` |
Trentanove test di visione fra `src/backend/tests/test_vision_*.py`, `src/vision/tests/` e
`src/vision_worker/tests/`. ⚠️ **Non li ho eseguiti**: l'albero della visione richiede Python 3.13 e il
sottomodulo inizializzato, cioè un'installazione da alcuni gigabyte che su questa macchina non c'è. Il
conteggio è dei file; la loro verdezza è dichiarata dai commit del 16-17 agosto e va riverificata da chi
riprende, prima di scriverci sopra.
**In sintesi: le fondamenta ci sono e sono fatte bene.** Il confine architetturale è difeso da un test
invece che da una buona intenzione, la provenienza di ogni numero è tracciata, e il modello dati regge il
resto del lavoro senza ristrutturazioni.
## 3. Il buco strutturale: pattern matching e DXF compare non sono eseguibili dal grafo
È il punto che i documenti di agosto non dicono, ed è quello che decide il calendario.
Il runner esegue **un grafo `vs-task`**: `Task.from_dict(graph)`, poi `task.run(context)`. Gli strumenti
che un grafo può contenere sono quelli registrati in `vs-task`, e al 14/09 — sia sul commit fissato
`f095fcc`, sia sull'ultimo commit di VisionSuite — sono **dieci, tutti geometrici**:
`DetectLine`, `DetectCircle`, `CircleCenter`, `PointIntersectionLL`, `Distance2P`, `DistancePL`,
`DistanceCL`, `Angle2L`, `Radius`, `Diameter`.
Nessuno strumento di pattern matching. Nessuno strumento di confronto DXF. Una ricerca di `pm2d`,
`shape_model` o `dxf` dentro `packages/vs-task/src` non trova nulla.
Coerentemente, in `pyproject.toml` gli extra `vision` e `vision-worker` installano `visionsuite` (core),
`vs-task`, `vs-measure`, `vs-pm2d` e `numpy`: **`vs-dxf` non è installato affatto**, e `vs-pm2d` è
installato ma il grafo non ha modo di chiamarlo.
I due motori esistono, e sono buoni: `visionsuite.pm2d` ha il matcher e l'auto-tune, `visionsuite.dxf` ha
`DXFCompare`, l'`ICPAligner`, il ricampionamento, il controllo di tolleranza e il generatore di rapporto.
Ma sono **librerie**, non strumenti di grafo. Fra loro e TieMeasureFlow manca un ponte, e il ponte va
costruito **in VisionSuite**, non qui: la decisione 4 della spec di agosto — il server non importa mai
VisionSuite — e il criterio di accettazione della corsia A1 — *«`grep` non trova algoritmi di visione dentro
il repo di TieMeasureFlow»* — rendono illegittima qualunque scorciatoia che scriva visione dentro questo
repository.
🔑 **La conseguenza commerciale, detta chiara:** oggi TieMeasureFlow sa eseguire un grafo che misura
distanze, angoli, raggi e diametri su un'immagine. Le due cose che Menoncin ha chiesto per nome — il
confronto DXF, che il suo cliente finale non ha, e il pattern matching, che il loro «funziona male» — non
sono ancora raggiungibili da nessun percorso del prodotto.
## 4. Le altre lacune, in ordine di peso
1. **Nessuna interfaccia.** Nel frontend Flask la visione compare in due sole righe di
`templates/measure/task_list.html`, le etichette «Confronto profilo» e «Misura camera». Non esiste la
schermata del Maker per comporre un grafo, scegliere un'immagine di riferimento, agganciare un'uscita a
una quota o premere «prova»; non esiste la schermata dell'operatore che acquisisce e vede l'esito. Oggi
un grafo entra solo via `POST /api/tasks` scrivendo il JSON a mano.
2. **Nessun agente di stazione, nessun registro dei device.** La tabella `station_devices` della spec non
esiste in nessuna migrazione; il WebSocket `/api/stations/agent` non esiste; `vs-camera`, cioè il
pacchetto che contiene il driver Itala, non è montato. L'unico modo di far entrare un'immagine è un
upload HTTP.
3. **L'immagine di produzione non viene conservata.** `vision_results.image_path` e `overlay_path`
migrano e restano vuote: nessuna riga le scrive. Una misura contestata non ha prova materiale, e
l'overlay — l'immagine con sopra le zone dove il sistema ha guardato — non esiste.
4. **La prova di non regressione è promessa e non mantenuta.** `expected_json` esiste sulla tabella delle
immagini di riferimento; nessun percorso la scrive, `preview` compreso. È la rete di sicurezza che
rende sostenibile aggiornare il sottomodulo con il motore installato su due host: senza, ogni
aggiornamento di VisionSuite è un salto al buio.
5. **Il sottomodulo è indietro di 67 commit**, dal 15/08 al 10/09. Fra questi c'è almeno una correzione di
`vs-core` sulla ricomposizione dei mosaici. Aggiornare il pin non è manutenzione facoltativa: è la
decisione 2 della spec, che vuole server e stazione sullo stesso commit, e va fatta con la prova di non
regressione già in piedi — cioè dopo il punto 4, non prima.
6. **Le tre verifiche a monte non sono mai state fatte**, e la spec di agosto le poneva come condizione
d'ingresso: lo stato reale di VisionSuite rispetto al suo README, il test di calibrazione dato per
rosso (focale recuperata a 373 contro 456 attesi, tolleranza 5%) e il peso effettivo del sottoinsieme
di pacchetti che il worker installa. La seconda pesa più delle altre: **tutte le quote in millimetri
poggiano sulla calibrazione**, e finché quel test non è verde o spiegato, i millimetri che il sistema
produce non hanno garanzia.
## 5. Che cosa si vuole ottenere
Un operatore apre un task di visione su una postazione, appoggia il profilato sul piano, e il sistema:
- riconosce il pezzo e la sua posa (**pattern matching**);
- ne confronta il profilo con il **DXF di riferimento**, dichiarando lo scarto massimo e dove sta;
- ne ricava **due o tre quote lineari** (le quote massima e minima che il cliente chiede);
- applica le tolleranze della ricetta e dà **OK / warning / fail**, con il gate del fuori tolleranza e
l'autorizzazione del capoturno come per qualunque altra misura;
- registra tutto in `measurements` e `vision_results`, con immagine, overlay, versione del motore e
taratura in vigore.
Nulla di quanto il prodotto già fa — ricette, SPC, Cp/Cpk, carta di controllo, export, tracciabilità —
deve cambiare. Una quota da camera resta una misura come le altre: è la decisione 7, e va tenuta.
## 6. Il lavoro, in sei fasi
Le fasi sono ordinate per dipendenza. Le prime due sono il cammino critico verso la fiera; la terza è il
cammino critico verso l'installazione a Tràfilo. Non sono stimate in ore: una stima si scrive dopo aver
guardato il codice dei due motori, e quella lettura fa parte della fase V0.
### V0 — Le verifiche a monte, prima di scrivere righe
Le tre della spec di agosto (capitolo 4, punto 6), più una quarta che nasce da questo documento: leggere
`visionsuite.pm2d.matcher` e `visionsuite.dxf.compare` per sapere **che forma hanno gli ingressi e le
uscite** dei due motori, perché è quella forma che decide la firma degli strumenti della fase V1.
*Fatto quando:* il test di calibrazione è verde o il suo scarto è spiegato per iscritto; il peso
dell'ambiente del worker è un numero misurato; esiste una nota di due pagine con le firme reali dei due
motori.
### V1 — Il ponte: pattern matching e DXF compare diventano strumenti del grafo
**Si lavora in VisionSuite, non in TieMeasureFlow.** In `vs-task` nascono gli strumenti nuovi, con la
stessa forma dei dieci esistenti:
- `MatchPattern` — ingresso: immagine più modello; uscite: presenza, punteggio, posizione e rotazione
dell'istanza trovata. È anche ciò che fornisce la posa alle quote successive, invece di pretendere che
il pezzo sia appoggiato sempre uguale.
- `CompareDXF` — ingressi: immagine, disegno di riferimento, fattore di scala; uscite: scarto massimo,
scarto medio, numero di zone fuori tolleranza, e l'esito zona per zona.
Due vincoli che decidono se il ponte è fatto bene:
1. **Gli strumenti espongono numeri, non verdetti.** `vs-dxf` ha di suo un `ToleranceChecker` e un
`CompareResult` con il proprio giudizio: quel giudizio va ignorato, esattamente come la decisione 7
impone già per le quote di `vs-measure`. Due giudici sullo stesso valore è il modo più rapido per
ottenere un CSV che si contraddice.
2. **`vs-dxf` si porta dietro PyTorch (~2,5 GB) per una riga** (`config.py:53`, annotato nella scheda
VisionSuite). Prima di aggiungerlo agli extra del worker, quella riga va tolta: altrimenti il container
della visione triplica, e con lui i tempi di ogni deploy a Tràfilo.
In TieMeasureFlow cambia **soltanto** `pyproject.toml`: `vs-dxf` entra negli extra `vision` e
`vision-worker`, il pin del sottomodulo avanza al commit che contiene i due strumenti nuovi. Nessuna riga
di algoritmo entra in questo repository.
*Fatto quando:* un grafo JSON che contiene `MatchPattern` e `CompareDXF` viene eseguito da
`POST /api/vision/preview` su un'immagine caricata, e restituisce le uscite attese. Senza camera, senza
interfaccia. E `test_vision_boundary.py` continua a passare.
### V2 — L'authoring nel Maker
La schermata che oggi non esiste. Il Maker, alla scrivania:
- carica o sceglie un'**immagine di riferimento** per il task (l'API esiste già);
- compone il grafo — e qui va deciso *come*, vedi il capitolo 7, decisione A;
- preme **prova** e vede le uscite (`/preview` esiste già);
- **aggancia** ciascuna uscita a una quota della ricetta, scrivendo `vision_output` sulla subtask (il
campo esiste già), e su quella quota mette nominale e tolleranze come su qualunque altra;
- **promuove le uscite della prova a `expected_json`**, che è ciò che accende la prova di non regressione
(lacuna 4) e chiude una promessa che la spec di agosto ha fatto e non ha mantenuto.
*Fatto quando:* una ricetta con un task di visione si compone interamente dall'interfaccia, senza scrivere
JSON a mano, e rieseguendo l'intero parco ricette su immagini di riferimento si vede quali quote si sono
mosse.
### V3 — L'agente di stazione, i device, la camera
È il cammino critico per Tràfilo, perché è ciò che rende il sistema utilizzabile in reparto.
- Tabella `station_devices` e migrazione, così com'è descritta nella spec di agosto (specchio in sola
lettura, popolato dall'agente; un device che non si dichiara più è **offline**, non cancellato).
- WebSocket `/api/stations/agent`: **è l'agente che apre la connessione**, il server non bussa mai a un PC
di reparto. È la scelta che evita di aprire porte in fabbrica.
- L'agente: sottile, monta `vs-core` e `vs-camera` e basta; acquisisce e carica il fotogramma. Camera
**Itala** di Opto Engineering, il cui producer GenTL è già stato provato in VisionSuite e ha richiesto
mezz'ora invece delle sei-dieci ore stimate.
- `vision_results.image_path` e `overlay_path` finalmente scritte (lacuna 3), con l'overlay prodotto dal
worker.
*Fatto quando:* un operatore misura un pezzo da una postazione vera, e la riga in `vision_results` porta
immagine, overlay, device, taratura e versione del motore.
### V4 — L'esecuzione sulla stazione
La policy per stazione, il ripiego in locale quando il server non risponde, e il **rifiuto di misurare**
quando la versione del motore non concorda con quella del server. Quest'ultimo non è un dettaglio di
build: è la garanzia metrologica su cui poggia tutto il resto.
*Fatto quando:* una stazione con un pin discorde si rifiuta di misurare e lo dichiara, invece di produrre
numeri plausibili.
### V5 — Il task `dxf_compare` come tipo a sé
Il valore `dxf_compare` esiste già nell'enum. Qui prende il suo comportamento: quote sintetiche derivate
dal confronto (scarto massimo, numero di zone fuori tolleranza) trattate come misure normali, e il
**rapporto allegato** che `visionsuite.dxf.report` sa già generare, archiviato accanto all'immagine.
## 7. Le decisioni che restano da prendere
Nessuna di queste si può dedurre dal codice: vanno chiuse da Adriano, alcune con il cliente.
**A. Come si compone un grafo.** L'editor visuale a nodi (TieWorkflow) è stato **revocato il 09/08** con
una motivazione che vale ancora: un editor ha senso solo se a comporre le pipeline è qualcuno che non
programma, e il cliente aveva chiesto misure, non un editor. Ma qualcosa deve pur esserci, perché scrivere
JSON a mano non è un prodotto. Le tre strade: un modulo per tipo di task con i soli parametri in chiaro
(il minimo che funziona); una libreria di grafi preconfezionati che il Maker sceglie e tara; l'editor,
che è la strada cara. **Questa decisione decide la fase V2 per intero.**
**B. La scala: pixel o millimetri.** Il 09/08 si era deciso che le quote potessero restare **in pixel**, e
che per il DXF compare servisse un fattore di scala ricavato da una quota nota misurata col calibro. Va
confermato: sono due prodotti diversi da spiegare al cliente, e il secondo dipende dal test di
calibrazione della fase V0.
**C. Il dimensionamento del server di Tràfilo.** Con l'esecuzione lato server come default, il pattern
matching contende la CPU fra tutte le stazioni. La domanda alla D-4 non è più solo quale macchina e quanto
disco: è anche quanti core e quanta RAM. Venti postazioni non sono tre.
**D. La conservazione delle immagini.** Quelle di riferimento sono poche e vivono quanto la ricetta;
quelle di produzione sono una per pezzo e crescono senza limite. Serve una scadenza, o una regola del tipo
«si conservano solo quelle dei pezzi fuori tolleranza». Senza, il disco del cliente si riempie e nessuno
lo ha avvertito.
**E. Che cosa fa la stazione se la rete cade** e non è configurata per elaborare in locale: si blocca, o
consente il calibro segnando il task come non eseguibile? È una domanda per Tràfilo.
**F. Chi paga.** L'ampliamento nasce dentro una commessa venduta come setup più canone. Un modulo di
visione non sta in quel perimetro, e non c'è offerta. La domanda è aperta dal 06/08 e ogni fase di questo
documento la rende più costosa da rimandare.
## 8. Quello che non va fatto
- **Non scrivere algoritmi di visione in questo repository.** Il confine è sorvegliato da un test; se
domani il server importasse VisionSuite per una scorciatoia, il vantaggio si perderebbe in silenzio.
- **Non rifare l'interfaccia** oltre le schermate nuove che le fasi V2 e V3 richiedono.
- **Non toccare SPC, ricette e integrazione GAIA.** GAIA è il gestionale del cliente finale e non è in
questo perimetro.
- **Non aggiungere il modulo AI** di cui si è parlato in call: è perimetro nuovo, senza offerta.
- **Non far giudicare il grafo.** I verdetti di `vs-dxf` e di `vs-measure` restano inutilizzati: decide
`measurement_service`.
- **Non avanzare il pin del sottomodulo senza la prova di non regressione in piedi.** Con il motore
installato su due host, un aggiornamento non verificato sposta i numeri senza che nessuno se ne accorga
fino alla contestazione.
## 9. Il calendario, per capire le priorità
La catena è **Tielogic produce → Ricerca e Misure (Menoncin) rivende → Tràfilo usa**, venti postazioni.
Due scadenze esterne, entrambe vicine:
- **Installazione a Tràfilo**, attesa per settembre. La serve la fase V3, ed è la ragione per cui l'agente
di stazione non può aspettare la fiera.
- **Fiera del 27-29 ottobre**, banchetto Tielogic nella zona Opto Engineering. La serve la fase V1, perché
è lì che si mostrano il confronto DXF e il pattern matching, cioè le due cose che a Menoncin interessano
commercialmente.
Se le due si contendono le stesse ore, la V1 è quella che non ha alternative: un'installazione può
slittare di due settimane, una fiera no.