## MODIFIED Requirements ### Requirement: База назначения пригодна к подмене База назначения SHALL нести полноценный учёт доставок, а не только объекты витрины: подменяется файл базы **целиком**, а не одна таблица. Состав переноса нормируется явно, потому что колонки `delivery` двух разных родов: ``` факты журнала id, received_at, automation_name, automation_id, aggregation, period, session_id, bytes, sha256, raw_path, headers ← переносятся дословно производные parse_status, points, derived_layer, uncovered_sections, skipped_entities ← начинаются пустыми ``` Перечень производных полей SHALL пополняться **тем же изменением**, которое заводит новое поле: он единственное место, где сказано, чему нельзя пережить пересборку, и следующий автор решает по нему. Поле, не внесённое в перечень, однажды перенесут «для полноты учёта». Факты журнала SHALL переноситься дословно, включая записи, тела которых в архиве уже нет. Заголовки восстановлению не подлежат ничем — в архиве их нет, — и неполный перенос уничтожил бы их первой же подменой, а с ними и вывод слоя для **всех** доставок, не только подобранных. Запись без тела при этом не сворачивается и в наследовании слоя не участвует: выведенного слоя у неё нет. Производные от разбора поля MUST начинаться пустыми. Перенос `derived_layer` особенно опасен и незаметен: доставка, чей повторный разбор отказал (штатный исход, когда слой не выводится), сохранила бы слой **прежнего** разбора, и следующая доставка той же автоматизации унаследовала бы его. Витрина снова стала бы функцией предыдущего прогона, а не журнала, причём оба прогона были бы самосогласованы — проверка «повторная пересборка ничего не меняет» этого не ловит. Для числа пропущенных сущностей цена та же и хуже: пустота у него значит «не измерялось», и перенесённое число выдавало бы измерение прежнего разбора за измерение текущего — а по нему принимается необратимое решение об удалении тела. #### Scenario: Учёт переносится полностью - **WHEN** пересборка завершилась - **THEN** число строк учёта в базе назначения равно числу строк рабочей базы плюс число подобранных тел - **AND** заголовки перенесённых доставок совпадают с рабочей базой дословно #### Scenario: Слой прошлого разбора в наследование не попадает - **WHEN** в рабочей базе у доставок проставлен `derived_layer` - **THEN** отпечаток пересобранной витрины совпадает с отпечатком пересборки того же журнала из учёта без проставленных слоёв #### Scenario: Число пропущенных сущностей не переносится из журнала - **WHEN** в рабочей базе у доставки проставлено число пропущенных сущностей, а тела этой доставки в архиве уже нет - **THEN** в базе назначения её число пропущенных сущностей отсутствует ## ADDED Requirements ### Requirement: Отчёт пересборки показывает удержанные версии сущностей Отчёт пересборки SHALL называть число версий сущностей, удержанных правилом «не теряем содержания», — тем же счётчиком, что ведёт свёртка. Без него правило слияния сущностей проверить нечем. Сходимость отпечатка его не проверяет **по построению**: живой приём и пересборка пользуются одним правилом и одинаково сойдутся на одинаково удержанной версии. То есть слишком строгое правило — например, замораживающее тренировку на старой версии из-за исчезнувшего ключа с пустым значением — выглядело бы как идеальная сходимость. Счётчик несравнимых наборов точек выведен в отчёт по ровно той же причине и тем же рассуждением. Число SHALL печататься всегда, а не только при ненулевом значении: ноль здесь утверждение, а не отсутствие новостей. #### Scenario: Удержанная версия видна в отчёте пересборки - **WHEN** журнал содержит доставку, приехавшая версия сущности в которой теряет содержание сохранённой - **THEN** отчёт пересборки называет число удержанных версий больше нуля