# Capordia — esercizio di commutazione e ripresa, versione 1.0.0

Questo esercizio CPU confronta un'elaborazione continua con un'elaborazione interrotta,
copiata in un'altra cartella e poi ripresa in un nuovo processo. Permette
di constatare quali lotti sono completati, in corso e da riprendere. Non misura
alcuna GPU e non dimostra una migrazione senza interruzione.

## Preparare l'esercizio

Usare Python 3.10 o più recente con i moduli standard `sqlite3` e
`hashlib`, su un disco locale scrivibile. Non sono necessari pacchetti, accesso di rete,
account, segreti o amministratore. Estrarre tutti i file
dalla cartella, poi aprire un terminale in quella cartella. Se il sistema usa
`python3` o `py -3`, sostituire `python` nei comandi. Lo script e il
set di input restano separati dalle cartelle di lavoro che crea.

Non eseguire questo esercizio in una cartella di produzione o su una condivisione
di rete. Scegliere un nome di cartella di lavoro che non esiste: il programma
rifiuta di riutilizzare o sovrascrivere una cartella esistente.

```text
python exercice.py demonstration --dossier essai-capordia
```

Questo comando crea `essai-capordia/rapport-verification.json` e le cartelle
di ogni scenario. Termina con il codice 0 solo se tutti i
controlli sono superati. Rilanciare con un nuovo nome per un nuovo tentativo.
Il comando non cancella alcun tentativo precedente.

## Il nostro esempio: otto lotti di coupon fittizi

Gli otto CSV contengono ciascuno sei misure dimensionali originali e
fittizie. Ogni riga contiene `coupon`, `cible_um` e `mesure_um`. Le unità
sono micrometri interi. Nessun numero proviene da una macchina di
produzione o da un cliente. Per ogni lotto, l'elaborazione calcola il numero
di coupon, la somma e il massimo degli scostamenti assoluti, e il numero di scostamenti
inferiori o uguali a 15 µm. Questa soglia è una regola dell'esercizio, non una
tolleranza industriale raccomandata.

Il risultato contiene il numero di lotto, la versione della ricetta e l'impronta
SHA-256 dell'input. L'uso di interi permette qui un confronto esatto.
Un carico GPU con calcoli in virgola mobile richiederebbe la propria regola di
confronto e tolleranze giustificate.

## Leggere gli stati

| Stato nel registro | Significato in questo esercizio | Elaborazione alla ripresa |
|---|---|---|
| `termine` | Risultato accettato e stato registrato nella stessa transazione | Verificare; non ricalcolare |
| `en_cours` | Tentativo dichiarato, nessun risultato accettato | Esaminare la vecchia autorità poi autorizzare la ripresa |
| `a_reprendre` | Lotto non iniziato o tentativo esplicitamente rimesso in coda | Eseguire un tentativo |

Dopo l'interruzione iniettata su LOT-004: LOT-001 a LOT-003 sono completati,
LOT-004 è in corso, LOT-005 a LOT-008 sono da riprendere. Nessun risultato di
LOT-004 è accettato. Dopo `preparer-reprise`, restano tre completati e
cinque da riprendere. Alla fine, gli otto risultati devono essere uguali a quelli
del riferimento. Solo LOT-004 ha due tentativi.

## Rifare la commutazione passo dopo passo

I percorsi seguenti sono relativi alla cartella che contiene `exercice.py`.
L'interruzione è un'eccezione iniettata dopo il calcolo e prima dell'accettazione;
il codice 75 in questa fase è atteso. Il processo si arresta e libera il suo
lock. Non è né un arresto brusco del computer né un guasto elettrico.

```text
python exercice.py initialiser --dossier manuel/reference --proprietaire reference
python exercice.py executer --dossier manuel/reference
python exercice.py initialiser --dossier manuel/source --proprietaire atelier-source
python exercice.py executer --dossier manuel/source --interrompre-sur LOT-004
python exercice.py etat --dossier manuel/source
python exercice.py basculer --source manuel/source --destination manuel/cible --proprietaire atelier-cible
python exercice.py preparer-reprise --dossier manuel/cible
python exercice.py executer --dossier manuel/cible
python exercice.py comparer --reference manuel/reference --candidat manuel/cible
```

`basculer` prende il lock locale, controlla il set, chiude la sorgente, chiude
le connessioni SQLite e copia la cartella. La copia resta chiusa fino alla
fine della sua verifica; solo la destinazione è poi autorizzata a produrre.
Un comando di esecuzione lanciato sulla sorgente chiusa restituisce il codice 2
con `SOURCE_CLOTUREE`.

Il confronto richiede otto risultati accettati per ciascun lato,
verifica i loro input e i loro output, poi confronta una serializzazione JSON
canonica dei risultati. Gli export di testo possono essere ricostruiti da
SQLite: non sono l'autorità che decide se un risultato è accettato.

## I file prodotti

| File | Ruolo |
|---|---|
| `registre.sqlite` | Stato di riferimento, tentativi, proprietario, chiusura e risultati accettati |
| `manifeste.json` e `donnees/` | Set di input congelato con le impronte attese |
| `etat.json` | Stato leggibile e conteggio dei tre stati |
| `registre-lots.csv` | Export: id, stato, tentativi, entree_sha256, sortie_sha256 |
| `resultats.json` | Export dei risultati accettati, nell'ordine degli identificatori |
| `rapport-verification.json` | Nella cartella globale di dimostrazione: controlli, ambiente e output dei comandi |
| `worker.lock` | Lock temporaneo del nostro programma, rimosso alla sua uscita normale o all'interruzione iniettata |

Il file `registre-lots-vierge.csv` fornito nella risorsa è un modello
più ampio per il tuo team. Aggiunge responsabile, macchina autorizzata,
criterio di accettazione e motivo di ripresa. Non sostituisce la base
dell'esercizio e non viene importato dal programma.

## Gli errori verificati

La dimostrazione testa anche il rilancio di un lavoro completato, il rifiuto di una
seconda accettazione dello stesso lotto, un input modificato, un identificatore duplicato
nel manifesto, un output alterato, un lock già presente e un'eccezione
all'interno della transazione di accettazione. Quest'ultimo caso lascia tre
output accettati, non quattro, poi ritrova gli otto risultati dopo la ripresa.
Il ritorno viene testato copiando lo stato recente della destinazione in una terza
cartella, chiudendo la destinazione. Non si riattiva il vecchio snapshot.

I codici di uscita sono: 0 successo; 2 rifiuto di business atteso; 75 interruzione
iniettata attesa; 1 errore di lettura o di database. Lo scenario globale attende
esplicitamente i rifiuti che provoca. Un altro errore fa fallire il test.

## Limiti da tenere presenti con i risultati

Un solo worker partecipa a questo esercizio. Il lock e il campo di chiusura
funzionano nelle cartelle locali manipolate da questo programma. Non
impediscono a una persona di copiare il database o a un altro programma
di ignorare il lock. Non è fencing distribuito. Prima di un vero
switchover, la vecchia macchina deve perdere il diritto di pubblicare tramite un meccanismo
indipendente e testato. Se il suo arresto non è confermato, non si avvia una
seconda autorità.

Una transazione raggruppa qui risultato e stato nello **stesso database locale**.
Non copre un invio verso un sistema esterno, una notifica o un
file già consumato altrove. L'assenza di doppia accettazione verificata si
limita a questo database e a questo esercizio. SHA-256 rileva qui uno scostamento tra
byte e impronta attesa; un manifesto modificabile insieme ai dati
non autentica la loro origine.

Se un processo viene ucciso brutalmente, il lock può restare presente. Verifica
il suo arresto reale prima di qualsiasi intervento manuale; l'esercizio non elimina
mai automaticamente un lock considerato vecchio. Un'interruzione della copia
lascia la sorgente chiusa: conserva le cartelle ed esamina l'incidente,
senza rimettere in attività due copie. La perdita di alimentazione, i file system
di rete, la concorrenza tra macchine, i driver GPU, i
checkpoint dei framework e le prestazioni non sono qualificati qui.

## Risultato del nostro controllo

Il 24 settembre 2026, sotto Windows AMD64, Python 3.14.6 e SQLite 3.50.4:
16 controlli superati, 37 comandi eseguiti, 8 risultati accettati identici
dopo lo switchover. La prova consultabile è `preuve-execution-cpu.json`.
L'impronta dei risultati canonici è
`bde1bc833092cc8ca481cda5f44cfef36f14f0a94dff3f856624e169f5456660`.
Questi numeri descrivono questo set di 48 righe e non sono un benchmark GPU.

Vedi [PROCEDURE.md](PROCEDURE.md) per le responsabilità e il ritorno,
[SOURCES.md](SOURCES.md) per le fonti primarie, e [LICENSE.txt](LICENSE.txt)
per le condizioni di riutilizzo.
