Files
TieMeasureFlow/docs/specs/2026-09-14-visione-stato-e-specifica.md
T
Adriano 401457d21f docs: in fiera ci va anche la V2, e il grafo si compone con un editor a nodi
Decisione A chiusa il 14/09, e revoca la revoca del 09/08: allora il
committente era Trafilo e voleva misurare profilati, adesso il modulo e
un investimento e allo stand guarda chi deve immaginarci il proprio pezzo.
Il taglio per la fiera arriva fino alla misura vera; expected_json resta
dopo. La V3, che e cio che Trafilo ha pagato, scala indietro.

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

22 KiB

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 — in fiera (decisa il 14/09)

La schermata che oggi non esiste. Si compone con un editor visuale a nodi (decisione A, chiusa il 14/09). Il Maker, alla scrivania:

  • carica o sceglie un'immagine di riferimento per il task (l'API esiste già);
  • compone il grafo collegando gli strumenti — l'immagine entra, MatchPattern dà la posa, da lì scendono le quote e il CompareDXF;
  • 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.

Il taglio per la fiera (deciso il 14/09): ci va tutto fino alla misura vera — comporre, provare, agganciare alle quote, e il ciclo dell'operatore che misura e riceve OK/warning/fail con le tolleranze applicate. È la storia che vende: il confronto DXF dentro il flusso di produzione, non un tool a sé. Restano fuori dalla fiera, e si fanno dopo, la promozione a expected_json e la prova di non regressione: valgono per la robustezza, ma allo stand non si mostrano.

Fatto quando: una ricetta con un task di visione si compone interamente dall'interfaccia, senza scrivere JSON a mano, e un operatore la esegue ottenendo un esito vero. La prova di non regressione — rieseguire l'intero parco ricette su immagini di riferimento e vedere quali quote si sono mosse — è il criterio della parte differita.

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 — chiusa il 14/09/2026: un editor visuale a nodi. Adriano lo ha rimesso nel perimetro, e la scelta revoca la revoca del 09/08. Allora TieWorkflow era uscito perché «un editor ha senso solo se a comporre le pipeline è qualcuno che non programma, e il cliente aveva chiesto misure, non un editor»: motivazione giusta quando il committente era Tràfilo, che vuole misurare profilati. Adesso il modulo è un investimento per prendere lavori futuri (decisione F), e il pubblico dello stand non è l'operatore di Tràfilo — è chi allo stand deve immaginarci il proprio pezzo, e a quello un form fisso non parla.

Le altre due strade restano scritte qui perché sono la via d'uscita, non perché siano state scelte: un modulo per tipo di task con i parametri in chiaro (il minimo che funziona) e una libreria di grafi preconfezionati che il Maker sceglie e tara.

⚠️⚠️ È la più cara delle tre, su un cammino critico già pieno. Ad agosto l'editor era stimato 12-18 ore su un perimetro più piccolo — senza MatchPattern, senza CompareDXF, senza l'aggancio quota→uscita — ed è l'ordine di grandezza che aveva fatto sfondare il budget del piano ferie. Quelle ore ora si sommano alla V1, anch'essa obbligatoria per la fiera, dentro 43 giorni. Il ripiego va deciso adesso, non il 20 ottobre: se a metà ottobre l'editor non regge, si espone il modulo per tipo di task, che mostra le stesse misure con meno scena.

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 — chiusa il 14/09/2026. Nessuno, ed è una scelta. Il modulo di visione è un investimento commerciale di Tielogic: non si quota a Ricerca e Misure, non entra nel setup né nel canone dell'OFF-2026-022, e non aspetta un'offerta per cominciare. Serve a prendere lavori futuri, e il posto dove quell'investimento si trasforma in lavori è la fiera.

Ne discendono tre conseguenze che questo documento adotta:

  1. Il modulo non ha una data di consegna contrattuale, quindi l'unica scadenza che lo governa è la fiera del 27-29 ottobre. La fase V1 è l'unica del percorso visione che ha una data vera.
  2. Tràfilo va servito con il perimetro venduto — le dodici modifiche del 28/07, l'installazione on-premise, l'agente di stazione — e quel lavoro non si rallenta per la visione: è quello che è già stato fatturato. Dove la visione e Tràfilo si contendono le stesse ore, vince ciò che è stato venduto, con l'unica eccezione della V1 prima della fiera.
  3. Il confine va tenuto per iscritto: le ore spese per la fiera sono a carico Tielogic, quelle spese per Tràfilo stanno nella commessa. Senza quella riga, a consuntivo il modulo di visione sembrerà un costo della commessa Ricerca e Misure e ne falserà il margine.

⚠️ Resta aperto un pezzo che non è «chi paga» ma «che cosa»: cosa si mostra in fiera non coincide con cosa si consegna. Una demo può girare su un grafo preparato, un pezzo noto e una posa controllata; un prodotto no. Deciderlo prima cambia l'ampiezza della V1.

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, e dal 14/09 non pesano più allo stesso modo.

  • Fiera del 27-29 ottobre, banchetto Tielogic nella zona Opto Engineering. Le servono V1 e V2 insieme, perché allo stand si mostra il prodotto e non una demo: comporre una ricetta di visione dall'interfaccia, misurare un pezzo, vedere l'esito. È l'unica data del percorso visione, ed è il posto dove l'investimento della decisione F si trasforma in lavori.
  • Installazione a Tràfilo, attesa per settembre. Le serve la V3, ed è ciò che è stato fatturato. ⚠️ Con V1 e V2 entrambe prima della fiera, la V3 resta indietro: è una scelta consapevole, ma la tempistica dell'installazione era stata data a Menoncin, quindi va detta a lui invece di scoperta da lui.

⚠️ Il rischio non è che manchi una delle due: è che l'editor a nodi si prenda le ore della V1. Il ripiego è scritto nella decisione A, e va guardato a metà ottobre, quando cambiare strada costa ancora poco.