# Capordia — 切り替えと再開の演習、バージョン 1.0.0

この CPU 演習では、継続的な処理と中断された処理を比較します。中断された処理は別のフォルダにコピーされ、新しいプロセスで再開されます。これにより、どのバッチが完了し、進行中で、再開が必要かを確認できます。GPU の測定は行わず、無停止での移行を実証するものでもありません。

## 演習の準備

書き込み可能なローカルディスク上で、標準モジュール `sqlite3` と `hashlib` を備えた Python 3.10 以降を使用してください。パッケージ、ネットワークアクセス、アカウント、シークレット、管理者権限は一切不要です。フォルダ内のすべてのファイルを展開し、そのフォルダでターミナルを開きます。システムが `python3` または `py -3` を使用する場合は、コマンド内の `python` を置き換えてください。スクリプトと入力セットは、作成される作業フォルダとは分離されたままです。

本番フォルダやネットワーク共有上でこの演習を実行しないでください。存在しない作業フォルダ名を選択してください。プログラムは既存のフォルダの再利用や上書きを拒否します。

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

このコマンドは `essai-capordia/rapport-verification.json` と各シナリオのフォルダを作成します。すべてのチェックが成功した場合にのみ、終了コード 0 で終了します。新しい試行には新しい名前で再実行してください。このコマンドは以前の試行を一切消去しません。

## 例：架空のクーポン 8 ロット

8 つの CSV にはそれぞれ、6 つの独自の架空の寸法測定値が含まれています。各行には `coupon`、`cible_um`、`mesure_um` が含まれます。単位は整数のマイクロメートルです。いかなる数値も本番マシンや顧客に由来するものではありません。各ロットについて、処理はクーポン数、絶対偏差の合計と最大値、および 15 µm 以下の偏差の数を計算します。このしきい値は演習のルールであり、推奨される産業公差ではありません。

結果にはロット番号、レシピのバージョン、入力の SHA-256 ハッシュが含まれます。ここでは整数を使用することで正確な比較が可能になります。浮動小数点計算を伴う GPU ワークロードには、独自の比較ルールと正当化された公差が必要です。

## 状態の読み方

| レジストリ内の状態 | この演習での意味 | 再開時の処理 |
|---|---|---|
| `termine` | 結果が承認され、状態が同一トランザクション内で記録済み | 検証する。再計算しない |
| `en_cours` | 試行が宣言済み、承認された結果なし | 以前の権限を調査してから再開を許可する |
| `a_reprendre` | ロットが未開始、または試行が明示的に再キュー投入済み | 試行を実行する |

LOT-004 に注入された切断後：LOT-001 から LOT-003 は完了、LOT-004 は進行中、LOT-005 から LOT-008 は再開待ちです。LOT-004 の結果は承認されていません。`preparer-reprise` 後、完了が 3 つ、再開待ちが 5 つ残ります。最終的に、8 つの結果はすべて参照と等しくなければなりません。2 回の試行があるのは LOT-004 のみです。

## 切り替えを段階的にやり直す

以下のパスは `exercice.py` を含むフォルダからの相対パスです。切断は計算後かつ承認前に注入される例外で、この段階でのコード 75 は想定内です。プロセスは停止し、ロックを解放します。コンピュータの強制停止や停電ではありません。

```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` はローカルロックを取得し、セットを検査し、ソースを閉鎖し、SQLite 接続を閉じ、フォルダをコピーします。コピーは検証が完了するまで閉鎖されたままです。その後、生成が許可されるのはターゲットのみです。閉鎖されたソースで実行コマンドを起動すると、コード 2 と `SOURCE_CLOTUREE` が返されます。

比較コマンドは、双方から8件の受理済み結果を要求し、それぞれの入力と出力を検証したうえで、結果の正規JSONシリアライゼーションを比較します。テキストエクスポートはSQLiteから再構築できます。それらは結果が受理されたかどうかを決める権威ではありません。

## 生成されるファイル

| ファイル | 役割 |
|---|---|
| `registre.sqlite` | 基準となる状態、試行、所有者、クローズ処理、受理済み結果 |
| `manifeste.json` と `donnees/` | 期待されるフィンガープリントを伴う固定入力セット |
| `etat.json` | 可読な状態と3つのステータスの内訳 |
| `registre-lots.csv` | エクスポート: id、etat、tentatives、entree_sha256、sortie_sha256 |
| `resultats.json` | 受理済み結果のエクスポート、識別子の順 |
| `rapport-verification.json` | 全体デモフォルダ内: チェック、環境、コマンドの出力 |
| `worker.lock` | 当プログラムの一時ロック。正常終了時または注入された切断時に解除される |

リソースに含まれる `registre-lots-vierge.csv` ファイルは、あなたのチーム向けのより広範なテンプレートです。担当者、許可されたマシン、受理基準、再開理由を追加します。これは演習のデータベースを置き換えるものではなく、プログラムによってインポートされることもありません。

## 検証されるエラー

デモでは、完了したジョブの再起動、同じロットの2回目の受理の拒否、変更された入力、マニフェスト内の重複識別子、改ざんされた出力、既に存在するロック、受理トランザクション内部の例外もテストします。最後のケースでは、受理済み出力が4件ではなく3件のままとなり、再開後に8件の結果を復元します。復帰は、ターゲットの最新状態を3番目のフォルダにコピーし、ターゲットをクローズすることによってテストされます。古いスナップショットを再有効化することはありません。

終了コードは次のとおりです: 0 成功、2 想定された業務上の拒否、75 想定された注入切断、1 読み取りまたはデータベースのエラー。全体シナリオは、自らが引き起こす拒否を明示的に期待します。それ以外のエラーが発生した場合、試行は失敗します。

## 結果と併せて保持すべき制約

この演習に参加するworkerは1つだけです。ロックとクローズ処理フィールドは、このプログラムが操作するローカルフォルダ内で機能します。それらは、人がデータベースをコピーすることや、別のプログラムがロックを無視することを防ぎません。これは分散フェンシングではありません。実際の切り替えの前に、旧マシンは独立した検証済みのメカニズムによって公開する権利を失う必要があります。その停止が確認されない場合、2つ目の権威を開始してはなりません。

ここでのトランザクションは、結果とステータスを**同一のローカルデータベース**内でまとめます。外部システムへの送信、通知、他の場所で既に消費されたファイルは対象外です。検証される二重受理の不在は、このデータベースとこの演習に限定されます。ここでのSHA-256は、バイトと期待されるフィンガープリントの間の不一致を検出します。データとともに変更可能なマニフェストは、その出自を認証しません。

プロセスが強制終了された場合、ロックが残ることがあります。手動で介入する前に、その実際の停止を確認してください。演習は、古いと判断されたロックを自動的に削除することは決してありません。コピーの中断はソースをクローズ状態のままにします。フォルダを保持してインシデントを調査し、2つのコピーを再び稼働させないでください。電源喪失、ネットワークファイルシステム、マシン間の競合、GPUドライバー、フレームワークのチェックポイント、パフォーマンスは、ここでは認定されていません。

## 当社のチェック結果

2026年9月24日、Windows AMD64、Python 3.14.6、SQLite 3.50.4 にて: 16件のチェック成功、37件のコマンド実行、切り替え後に8件の受理済み結果が同一。参照可能な証拠は `preuve-execution-cpu.json` です。正規結果のフィンガープリントは `bde1bc833092cc8ca481cda5f44cfef36f14f0a94dff3f856624e169f5456660` です。これらの数値はこの48行のセットを記述するものであり、GPUベンチマークではありません。

責任と復帰については [PROCEDURE.md](PROCEDURE.md) を、一次情報源については [SOURCES.md](SOURCES.md) を、再利用条件については [LICENSE.txt](LICENSE.txt) を参照してください。
