## MODIFIED Requirements ### Requirement: Пересборка витрины проигрыванием журнала Система SHALL уметь собрать витрину заново, проиграв журнал целиком: `import(снапшот) + replay(доставки)`. Стадия снапшота в этой дельте пуста — пересборка из архива есть вырожденный случай с пустым снапшотом, — и отдельной операции «пересборка из архива» рядом с импортом экспорта заводить MUST NOT. Проигрываться SHALL **все** доставки журнала, а не только те, чей `parse_status` говорит о неразобранности. Отбор по учётному статусу сделал бы результат функцией предыдущего прогона, а не журнала; дешевизну повторного проигрывания обеспечивает хеш-детектор объекта, а не пропуск доставок. Пересборка собственного разбора и собственного слияния иметь MUST NOT: она зовёт тот же код, что и приём, по идентификатору доставки, и тело читает из архива тем же путём, с тем же пределом размера распакованного тела. Второй путь разбора разошёлся бы с первым молча, а другой предел означал бы, что тело, принятое со `200`, вечно отказывает на каждой пересборке. **Условие сходимости SHALL называться требованием, а не оговоркой сценария.** Правило слияния точек разрешает равную полноту в пользу пришедшей доставки, то есть содержимое витрины есть функция **порядка** свёртки, а не только множества доставок. Отпечаток пересборки равен отпечатку накопленной приёмом витрины тогда и только тогда, когда живая свёртка шла в порядке журнала. Прежде от порядка зависел только вывод слоя; теперь от него зависят значения точек, то есть цена нарушения выросла и должна быть названа здесь, а не выведена читателем. **Посылка равенства SHALL перечисляться рядом с ним**, а не подразумеваться, потому что оракул, чья посылка не названа, краснеет по причине, к правилу отношения не имеющей, и краснота становится неотличимой от дефекта. Посылок три: живая свёртка шла в порядке журнала; в журнале нет доставок, чью свёртку живой путь провалил, а пересборка проведёт (статус `failed`); за время пересборки новых доставок не приезжало. Из этих трёх посылок прогон пересборки SHALL печатать рядом с отпечатком ту, которую он измеряет сам, — число `failed`. Первая посылка прогону **недоступна по построению**: записи «свёртка вне порядка журнала» рождаются только в живом воркере, нигде не хранятся, и пересборке та же спека проверку прямо запрещает. Она проверяется журналом сервиса, и это сказано здесь, чтобы следующий автор не приписал к отпечатку константный ноль, выдав его за подтверждение. Равенство «пересборка = приём» SHALL проверяться оракулом, а не рассуждением: журнал, содержащий доставки с равнополными столкновениями, проигранный живым путём (фоновый воркер, в том числе с доставкой, отложенной занятостью базы) и путём пересборки, обязан давать один отпечаток витрины. **Место снапшота в порядке журнала этой дельтой не определяется, и это сказано вслух.** Под правилом «побеждает пришедшая» исход столкновения снапшота Apple с точкой HAE зависит от того, какую позицию журнала получит доставка импорта: учтённая сегодняшним временем, она перебила бы все равнополные точки, включая досчитанные задним числом. Стадия снапшота сегодня пуста, поэтому вопрос отложен — но решать его SHALL задача импорта, и явно, а не выбором первого автора. Отчёт пересборки SHALL называть два числа про точки — удержанные правилом полноты против пришедшей доставки и потерявшие содержание в пользу пришедшей — рядом с удержанными версиями сущностей и по той же причине: сходимость отпечатка ни одно из них не проверяет по построению. #### Scenario: Пересобранная витрина совпадает с накопленной приёмом - **GIVEN** рабочая витрина накоплена тем же разбором, приём во время накопления шёл последовательно, и за время пересборки новых доставок не приезжало - **WHEN** журнал проигрывается заново с пустой витрины - **THEN** отпечаток пересобранной витрины совпадает с отпечатком накопленной #### Scenario: Отложенная занятостью доставка не разводит приём и пересборку - **GIVEN** журнал, где одни координаты получают равнополные точки с разными значениями от разных доставок - **AND** свёртка одной из доставок откладывается занятостью базы - **WHEN** тот же журнал проигрывается живым путём и путём пересборки - **THEN** отпечатки витрин совпадают #### Scenario: Повторная пересборка ничего не меняет - **WHEN** пересборка того же журнала выполняется второй раз - **THEN** отпечаток витрины не меняется #### Scenario: Разобранная доставка проигрывается наравне с неразобранной - **WHEN** в журнале есть доставки со статусом `parsed` и со статусом `pending` - **THEN** проигрываются обе