# Capordia — exercício de troca e retomada, versão 1.0.0

Este exercício de CPU compara um processamento contínuo a um processamento interrompido,
copiado para outra pasta e depois retomado em um novo processo. Ele permite
verificar quais lotes estão concluídos, em andamento e a retomar. Ele não mede
nenhuma GPU e não demonstra uma migração sem interrupção.

## Preparar o exercício

Usar Python 3.10 ou mais recente com os módulos padrão `sqlite3` e
`hashlib`, em um disco local gravável. Nenhum pacote, acesso à rede,
conta, segredo ou administrador é necessário. Extrair todos os arquivos
da pasta e abrir um terminal nessa pasta. Se o sistema usar
`python3` ou `py -3`, substituir `python` nos comandos. O script e o
conjunto de entradas permanecem separados das pastas de trabalho que ele cria.

Não executar este exercício em uma pasta de produção ou em um compartilhamento
de rede. Escolher um nome de pasta de trabalho que não exista: o programa
recusa reutilizar ou sobrescrever uma pasta existente.

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

Este comando cria `essai-capordia/rapport-verification.json` e as pastas
de cada cenário. Ele termina com o código 0 somente se todos os
controles forem bem-sucedidos. Executar novamente com um novo nome para um novo teste.
O comando não apaga nenhum teste anterior.

## Nosso exemplo: oito lotes de cupons fictícios

Os oito CSV contêm cada um seis medidas dimensionais originais e
fictícias. Cada linha contém `coupon`, `cible_um` e `mesure_um`. As unidades
são micrômetros inteiros. Nenhum número vem de uma máquina de
produção ou de um cliente. Para cada lote, o processamento calcula o número
de cupons, a soma e o máximo dos desvios absolutos, e o número de desvios
menores ou iguais a 15 µm. Este limite é uma regra de exercício, não uma
tolerância industrial recomendada.

O resultado contém o número do lote, a versão da receita e a impressão
SHA-256 da entrada. O uso de inteiros permite aqui uma comparação exata.
Uma carga de GPU com cálculos de ponto flutuante exigiria sua própria regra de
comparação e tolerâncias justificadas.

## Ler os estados

| Estado no registro | Significado neste exercício | Processamento na retomada |
|---|---|---|
| `termine` | Resultado aceito e estado registrado em uma mesma transação | Verificar; não recalcular |
| `en_cours` | Tentativa declarada, nenhum resultado aceito | Examinar a antiga autoridade e então autorizar a retomada |
| `a_reprendre` | Lote não iniciado ou tentativa explicitamente reenfileirada | Executar uma tentativa |

Após a interrupção injetada em LOT-004: LOT-001 a LOT-003 estão concluídos,
LOT-004 está em andamento, LOT-005 a LOT-008 estão a retomar. Nenhum resultado de
LOT-004 é aceito. Após `preparer-reprise`, restam três concluídos e
cinco a retomar. No final, os oito resultados devem ser iguais aos
da referência. Apenas LOT-004 tem duas tentativas.

## Refazer a troca passo a passo

Os caminhos a seguir são relativos à pasta que contém `exercice.py`.
A interrupção é uma exceção injetada após o cálculo e antes da aceitação;
o código 75 nessa etapa é esperado. O processo para e libera seu
bloqueio. Não é nem um desligamento abrupto do computador nem uma falha elétrica.

```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` obtém o bloqueio local, controla o conjunto, encerra a origem, fecha
as conexões SQLite e copia a pasta. A cópia permanece encerrada até
o fim de sua verificação; somente o destino é então autorizado a produzir.
Um comando de execução lançado na origem encerrada retorna o código 2
com `SOURCE_CLOTUREE`.

A comparação exige oito resultados aceitos de cada lado,
verifica suas entradas e saídas, e então compara uma serialização JSON
canônica dos resultados. As exportações de texto podem ser reconstruídas a partir
do SQLite: elas não são a autoridade que decide se um resultado é aceito.

## Os arquivos produzidos

| Arquivo | Papel |
|---|---|
| `registre.sqlite` | Estado de referência, tentativas, proprietário, encerramento e resultados aceitos |
| `manifeste.json` e `donnees/` | Conjunto de entradas fixo com as impressões digitais esperadas |
| `etat.json` | Estado legível e contagem dos três status |
| `registre-lots.csv` | Exportação: id, etat, tentativas, entree_sha256, sortie_sha256 |
| `resultats.json` | Exportação dos resultados aceitos, na ordem dos identificadores |
| `rapport-verification.json` | Na pasta global de demonstração: controles, ambiente e saídas dos comandos |
| `worker.lock` | Bloqueio temporário do nosso programa, removido na sua saída normal ou na interrupção injetada |

O arquivo `registre-lots-vierge.csv` fornecido no recurso é um modelo
mais amplo para a sua equipe. Ele adiciona responsável, máquina autorizada,
critério de aceitação e motivo de retomada. Ele não substitui a base
do exercício e não é importado pelo programa.

## Os erros verificados

A demonstração também testa a retomada de um trabalho concluído, a rejeição de uma
segunda aceitação do mesmo lote, uma entrada modificada, um identificador duplicado
no manifesto, uma saída alterada, um bloqueio já presente e uma exceção
dentro da transação de aceitação. Este último caso deixa três
saídas aceitas, não quatro, e depois recupera os oito resultados após a retomada.
O retorno é testado copiando o estado recente do destino para uma terceira
pasta, encerrando o destino. Não se reativa o instantâneo antigo.

Os códigos de saída são: 0 sucesso; 2 recusa de negócio esperada; 75 interrupção
injetada esperada; 1 erro de leitura ou de base. O cenário global espera
explicitamente as recusas que provoca. Outro erro faz o teste falhar.

## Limitações a manter com os resultados

Um único worker participa deste exercício. O bloqueio e o campo de encerramento
funcionam nas pastas locais manipuladas por este programa. Eles
não impedem uma pessoa de copiar a base ou outro programa
de ignorar o bloqueio. Isso não é fencing distribuído. Antes de uma verdadeira
bascule, a máquina antiga deve perder seu direito de publicar por um mecanismo
independente e testado. Se a sua parada não for confirmada, não se inicia uma
segunda autoridade.

Uma transação agrupa aqui resultado e status no **mesmo banco de dados local**.
Ela não cobre um envio para um sistema externo, uma notificação ou um
arquivo já consumido em outro lugar. A ausência de dupla aceitação verificada se
limita a este banco de dados e a este exercício. SHA-256 detecta aqui uma divergência entre
bytes e impressão digital esperada; um manifesto modificável com os dados
não autentica sua origem.

Se um processo for morto abruptamente, o bloqueio pode permanecer presente. Verifique
sua parada real antes de qualquer intervenção manual; o exercício nunca remove
automaticamente um bloqueio considerado antigo. Uma interrupção de cópia
deixa a origem encerrada: conserve as pastas e examine o incidente,
sem colocar duas cópias em atividade. A perda de energia, os sistemas
de arquivos de rede, a concorrência entre máquinas, os drivers GPU, os
checkpoints de frameworks e o desempenho não são qualificados aqui.

## Resultado do nosso controle

Em 24 de setembro de 2026, no Windows AMD64, Python 3.14.6 e SQLite 3.50.4:
16 controles bem-sucedidos, 37 comandos executados, 8 resultados aceitos idênticos
após a bascule. A prova consultável é `preuve-execution-cpu.json`.
A impressão digital dos resultados canônicos é
`bde1bc833092cc8ca481cda5f44cfef36f14f0a94dff3f856624e169f5456660`.
Esses números descrevem este conjunto de 48 linhas e não são um benchmark GPU.

Veja [PROCEDURE.md](PROCEDURE.md) para as responsabilidades e o retorno,
[SOURCES.md](SOURCES.md) para as fontes primárias, e [LICENSE.txt](LICENSE.txt)
para as condições de reutilização.
