## MODIFIED Requirements ### Requirement: Отчёт, оракул и исход команды Система SHALL завершать пересборку отчётом, который несёт счётчики (проиграно, свёрнуто, отказов по классам, тел без учётной записи, строк без тела, пропущенных файлов, повторов, объектов **до и после**) и **два отпечатка** — рабочей витрины и пересобранной, — с прямым ответом, совпали они или нет. Отказы SHALL считаться **по классам**: слой не выводится, содержимое не разбирается, работа отложена по обстоятельствам, всё прочее. Невыведенный слой есть в каждом журнале и штатен; общий счётчик отправлял бы человека искать дефект там, где его нет. Отдельно называть человеку следует только нештатные отказы. Отложенная доставка (занятость базы, отмена работы снаружи) SHALL считаться нештатной **для пересборки**, хотя для фоновой свёртки она штатна: пересборка идёт в свежий файл при единственном писателе, и такая доставка в собранной витрине просто отсутствует — вместе с теми, кто наследовал от неё слой. Классы при этом общие с фоновой свёрткой: второй классификатор разошёлся бы с первым молча. Число объектов «было и стало» SHALL печататься рядом с отпечатками: отпечатки отвечают «да/нет», а решение о подмене необратимо, и по «да/нет» нельзя судить о **направлении** расхождения. Именно пара чисел — 1737 против 1742 — поймала прошлый дефект наследования слоя. Отпечаток здесь оракул, а не украшение: число объектов к правилу разрешения столкновений нечувствительно — на координате всегда ровно одна точка, и правило выбирает, какая, а не сколько. «Объектов столько же» совпало бы и при заведомо сломанном правиле. Отпечаток рабочей витрины SHALL сниматься **до** начала проигрывания, а число доставок в рабочей базе — до и после. Ненулевая разница SHALL называться в отчёте, и при ней процедура подмены печататься MUST NOT: доставки, приехавшие за время прогона, есть в рабочей базе и в архиве, но не в собранном файле, и подмена стёрла бы их учёт вместе с заголовками, которых в архиве нет. Величины, которые не снимались, отчёт печатать MUST NOT. При отмене отпечаток пересобранной витрины и число доставок после прогона не измеряются вовсе — печатать их сравнение значило бы выдать неизмеренное за измеренное, причём в единственном оракуле задачи. Ожидаемые классы расхождения (новые доставки за время прогона, непереносимый признак запечатанного часа, исправленный разбор) SHALL называться отдельно от самого факта расхождения. **Исход команды.** Расхождение отпечатков отказом быть MUST NOT: после исправления разбора оно ожидаемо и есть сам смысл пересборки. Отказ отдельной доставки отказом команды тоже MUST NOT быть: доставка, слой которой не выводится, — штатный исход. Отказом команды SHALL быть: пустой журнал, отсутствие хотя бы одной свёрнутой доставки, отмена и любая ошибка окружения. Пустая витрина совпадает по отпечатку с пустой витриной, поэтому прогон по пустому журналу выглядит идеальной сходимостью — а все умолчания подыгрывают такому запуску: конфига может не быть вовсе, и тогда пути указывают в рабочий каталог процесса. Человек, выполнивший напечатанную процедуру, заменил бы витрину пустой. Отчёт значений точек, имён метрик, имён устройств и содержимого тел содержать MUST NOT: отпечаток берёт содержимое хешем. Ограничение относится к отчёту в стандартном выводе; лог свёртки живёт по правилам спеки хранения, где координаты столкновения (метрика, слой, час) разрешены явно. Отчёт идёт в стандартный вывод человеческим текстом. Прогресс длинного прогона SHALL идти в поток ошибок, а не смешиваться с отчётом: прогон на полном архиве молчит минутами, и зависший неотличим от идущего. #### Scenario: Отчёт сравнивает отпечатки - **WHEN** пересборка завершилась - **THEN** отчёт содержит отпечаток рабочей витрины и отпечаток пересобранной - **AND** прямо называет, совпали они или нет - **AND** называет, изменилось ли число доставок в рабочей базе за время прогона #### Scenario: Расхождение отпечатков не является отказом - **WHEN** отпечаток пересобранной витрины отличается от рабочей, и при этом хотя бы одна доставка свёрнута - **THEN** команда завершается успешно, а расхождение названо в отчёте #### Scenario: Пустой журнал — отказ, а не идеальная сходимость - **WHEN** в архиве не нашлось ни одного тела - **THEN** команда завершается ненулевым кодом - **AND** процедуры подмены не печатает #### Scenario: Ни одна доставка не свернулась - **WHEN** журнал непуст, но свернуть не удалось ни одной доставки - **THEN** команда завершается ненулевым кодом - **AND** процедуры подмены не печатает #### Scenario: Приезд доставок за время прогона отменяет подмену - **WHEN** число доставок в рабочей базе за время прогона изменилось - **THEN** отчёт называет разницу - **AND** процедуры подмены не печатает #### Scenario: Отчёт после отмены не сравнивает неизмеренного - **WHEN** прогон отменён - **THEN** отчёт не содержит ни ответа о совпадении отпечатков, ни разницы числа доставок #### Scenario: Рабочей базы нет вовсе - **WHEN** файла рабочей базы не существует - **THEN** пересборка идёт по одним подобранным телам - **AND** отчёт называет, что сверять не с чем и что заголовки доставок не восстанавливаются #### Scenario: Отчёт не раскрывает данных о здоровье - **WHEN** отчёт напечатан - **THEN** он не содержит ни значений точек, ни имён метрик, ни имён устройств