f930fd98f0
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
290 lines
19 KiB
Markdown
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.
|