docs(spec): registra le correzioni imposte dall'esecuzione

Il gate del fuori tolleranza vale per l'acquisizione e non per la quota:
la regola era pensata per la misura sequenziale e su un evento simultaneo
produceva un blocco permanente.

Piu' il bi-ambiente Python, la versione del motore timbrata al build, la
motivazione della divisione degli extra corretta, e due cose promesse e non
mantenute -- expected_json e image_path -- dichiarate come consegne del
piano 1b invece che lasciate come intenzioni.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014BBnuACZSCJqXrMYC3LUMU
This commit is contained in:
2026-08-16 20:00:10 +02:00
parent 5717b3e7aa
commit 6bfe3a5d1a
@@ -159,6 +159,14 @@ Sblocca tre cose che altrimenti non ci sarebbero:
Quest'ultima è la rete di sicurezza che rende sostenibile aggiornare il
sottomodulo, con un motore che sta su due host.
> **Non ancora consegnata.** La colonna `expected_json` esiste, ma nessun
> percorso la scrive — nemmeno `preview`, che è l'unico posto dove un grafo gira
> davvero su un'immagine. La prova di non regressione è quindi **promessa da
> questo documento e non mantenuta da nessuna riga di codice**. Diventa una
> consegna nominata del piano 1b: «`preview` può promuovere le proprie uscite a
> `expected_json`». Finché non è fatta, questa decisione non va dichiarata
> completa.
## Architettura
### I componenti
@@ -379,6 +387,73 @@ richiede una camera collegata.
e i driver possono stare sulla macchina o nel container. La decisione è
volutamente tardiva; il design la rende tale tenendo l'agente sottile e neutro.
## Correzioni imposte dall'esecuzione
Il piano derivato da questo documento è stato eseguito il 16/08/2026. Sei cose
che qui erano scritte male o taciute, corrette dai fatti.
### Il gate del fuori tolleranza vale per l'acquisizione, non per la quota
La decisione 7 e il testo del punto 5 parlano di «la quota successiva». Quella
regola era stata pensata per la misura **manuale e sequenziale**, dove esiste
davvero un momento successivo in cui l'operatore potrebbe tirare avanti con una
lettura cattiva irrisolta.
Una camera produce tutte le N quote **nello stesso istante**. Dentro
un'acquisizione non esiste un «tirare avanti», quindi lì non c'è nulla da
presidiare — e applicare la regola sequenziale a un evento simultaneo produceva
un blocco permanente: la lettura fuori tolleranza non veniva mai registrata,
quindi nessuno poteva autorizzarla, e rifare la stessa foto ripeteva l'errore.
Il gate si valuta **una volta per acquisizione**: se la misura pendente è fra le
quote che questa acquisizione riprodurrà non blocca — riacquisire *è* rimisurare
quelle quote, che questo documento già dichiara la via d'uscita che non richiede
il capoturno. Fra due acquisizioni, e alla chiusura del ciclo, blocca come prima.
### Il repository è deliberatamente bi-ambiente
`vs-task`, `vs-measure` e `vs-pm2d` dichiarano `requires-python >= 3.13`;
`vs-core` si ferma a 3.10. Backend e frontend restano su **3.11**, l'albero della
visione gira su **3.13**, e l'extra `vision` porta i marker d'ambiente che
tengono separate le due risoluzioni.
Questo rafforza la decisione 4 più di come era argomentata: con VisionSuite dentro
il server FastAPI, questa scoperta avrebbe costretto l'intero backend a 3.13.
### La versione del motore si timbra al build
`vendor/visionsuite/.git` è un file che rimanda a `../../.git/modules/...`, che
nel contesto di build non esiste: interrogare git dentro il container non
funziona. `engine_version()` legge `VISION_ENGINE_VERSION` dall'ambiente, ripiega
su git nei checkout di sviluppo, e **alza un errore** se non risolve né l'uno né
l'altro. Il build fallisce se la variabile manca.
### La divisione degli extra compra esplicitezza, non peso
Gli extra sono due — `vision` per il runner, `vision-worker` per il servizio web
— ed è la forma giusta. Ma la motivazione che sembrava ovvia è falsa: `vs-pm2d`
dichiara **di suo** `fastapi`, `uvicorn`, `python-multipart` e `pillow`, quindi
un agente di stazione che fa pattern matching se li porterà dietro comunque. La
correzione vera è a monte — una libreria non dovrebbe dipendere da un server web
— e va aggiunta alle verifiche su VisionSuite qui sotto.
### L'immagine di produzione non viene ancora conservata
`vision_results.image_path` e `overlay_path` migrano e restano `NULL`: nulla le
scrive. Il flusso descritto in questo documento si chiude con «il client mostra
esito e immagine», e finché quelle colonne sono vuote una misura contestata non
ha prova materiale. Consegna nominata del piano 1b, insieme all'overlay.
### Prima di applicare le migrazioni in produzione
La 011 rinomina un valore di enum su una tabella in esercizio. Va contato prima
che nessuna riga usi `xf_compare`: in strict mode una riga sopravvissuta fa
fallire l'`ALTER` a metà deploy, fuori strict mode diventa `''` in silenzio.
Attenzione anche alla finestra: il `MODIFY` su `recipe_tasks` è una rinomina di
valore e userà `ALGORITHM=COPY`, mentre quello su `measurements.input_method`
aggiunge in coda e dovrebbe restare `INPLACE` — da confermare sulle dimensioni
reali, perché `measurements` è la tabella grossa.
## Da verificare prima di cominciare
VisionSuite è stato lavorato fino al 15/08/2026 e il suo ultimo commit è