# Capordia — упражнение по переключению и возобновлению, версия 1.0.0

Это упражнение на CPU сравнивает непрерывную обработку с прерванной,
скопированной в другую папку и затем возобновлённой в новом процессе. Оно
позволяет увидеть, какие пакеты завершены, какие выполняются и какие нужно
возобновить. Оно не измеряет никакой GPU и не демонстрирует миграцию без
прерывания.

## Подготовка упражнения

Используйте Python 3.10 или новее со стандартными модулями `sqlite3` и
`hashlib` на локальном диске с правом записи. Никакие пакеты, доступ к сети,
учётная запись, секрет или права администратора не нужны. Извлеките все файлы
из папки, затем откройте терминал в этой папке. Если в системе используется
`python3` или `py -3`, замените `python` в командах. Скрипт и
набор входных данных остаются отдельно от рабочих папок, которые он создаёт.

Не запускайте это упражнение в рабочей папке или на сетевом ресурсе.
Выберите имя рабочей папки, которого не существует: программа
отказывается повторно использовать или перезаписывать существующую папку.

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

Эта команда создаёт `essai-capordia/rapport-verification.json` и папки
каждого сценария. Она завершается кодом 0 только если все
проверки пройдены. Запустите заново с новым именем для новой попытки.
Команда не удаляет предыдущие попытки.

## Наш пример: восемь пакетов фиктивных образцов

Восемь CSV содержат каждый по шесть оригинальных и
фиктивных размерных измерений. Каждая строка содержит `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` остаётся три завершённых и
пять возобновляемых. В конце все восемь результатов должны быть равны результатам
эталона. Только у 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`.

Команда сравнения требует восемь принятых результатов с каждой стороны,
проверяет их входы и выходы, а затем сравнивает каноническую сериализацию JSON
результатов. Текстовые экспорты можно восстановить из
SQLite: они не являются источником, решающим, принят результат или нет.

## Создаваемые файлы

| Файл | Роль |
|---|---|
| `registre.sqlite` | Эталонное состояние, попытки, владелец, закрытие и принятые результаты |
| `manifeste.json` и `donnees/` | Зафиксированный набор входов с ожидаемыми хешами |
| `etat.json` | Читаемое состояние и подсчёт трёх статусов |
| `registre-lots.csv` | Экспорт: id, etat, tentatives, entree_sha256, sortie_sha256 |
| `resultats.json` | Экспорт принятых результатов в порядке идентификаторов |
| `rapport-verification.json` | В общем каталоге демонстрации: проверки, окружение и вывод команд |
| `worker.lock` | Временная блокировка нашей программы, снимаемая при её нормальном завершении или при внедрённом прерывании |

Файл `registre-lots-vierge.csv`, предоставленный в ресурсе, — это более
широкий шаблон для вашей команды. Он добавляет ответственного, разрешённую
машину, критерий приёмки и причину возобновления. Он не заменяет базу
упражнения и не импортируется программой.

## Проверяемые ошибки

Демонстрация также проверяет перезапуск завершённой работы, отклонение
второй приёмки того же лота, изменённый вход, дублированный идентификатор
в манифесте, изменённый выход, уже существующую блокировку и исключение
внутри транзакции приёмки. Последний случай оставляет три
принятых выхода, а не четыре, затем восстанавливает восемь результатов после возобновления.
Возврат проверяется копированием свежего состояния цели в третий
каталог с закрытием цели. Старый снимок не реактивируется.

Коды выхода: 0 — успех; 2 — ожидаемый отказ на уровне бизнес-логики; 75 — ожидаемое
внедрённое прерывание; 1 — ошибка чтения или базы данных. Глобальный сценарий
явно ожидает отказы, которые он вызывает. Любая другая ошибка приводит к провалу испытания.

## Ограничения, которые следует учитывать вместе с результатами

В этом упражнении участвует только один worker. Блокировка и поле закрытия
работают в локальных каталогах, обрабатываемых этой программой. Они
не мешают человеку скопировать базу или другой программе
игнорировать блокировку. Это не распределённый fencing. Перед настоящим
переключением старая машина должна потерять право публиковать через независимый
и проверенный механизм. Если её остановка не подтверждена, вторую
авторитетную инстанцию не запускают.

Транзакция объединяет здесь результат и статус в **одной и той же локальной базе**.
Она не охватывает отправку во внешнюю систему, уведомление или
файл, уже использованный в другом месте. Отсутствие проверенной двойной приёмки
ограничивается этой базой и этим упражнением. SHA-256 обнаруживает здесь расхождение между
байтами и ожидаемым хешем; изменяемый манифест вместе с данными
не подтверждает их происхождение.

Если процесс будет убит резко, блокировка может остаться. Проверьте
его реальное завершение перед любым ручным вмешательством; упражнение никогда
автоматически не удаляет блокировку, сочтённую устаревшей. Прерывание копирования
оставляет источник закрытым: сохраните каталоги и разберите инцидент,
не возвращая две копии в работу. Потеря питания, сетевые
файловые системы, конкуренция между машинами, драйверы GPU,
чекпоинты фреймворков и производительность здесь не оцениваются.

## Результат нашей проверки

24 сентября 2026 года, под 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)
для условий повторного использования.
