# ✨ Подчищать сырой архив до последнего проверенного экспорта - **Тип:** feature - **Категория:** Инфра - **Зачем:** Архив не подчищается вовсе, а резать его раньше даты проверенного экспорта нельзя — в журнале останется дыра, которую нечем пересобрать - **Теги:** goal:journal-and-rebuild Срок жизни сырого архива объявлен (14 дней, `storage.raw_retention`), но удаления нет: архив растёт бесконечно. Пока это 16 МБ и проблемой не является. **Само правило изменилось.** Экспорт Apple — снапшот всей истории, доставки после его даты — события поверх снапшота, и состояние всегда пересобираемо свёрткой. Значит доставки должны жить **до следующего проверенного экспорта**, а не фиксированные две недели: иначе между концом ретеншена и датой снапшота образуется дыра в журнале, и пересобрать этот отрезок будет нечем. Цена измерена: ~23 МБ архива в сутки, то есть ~2 ГБ за квартал между экспортами. Дёшево за возможность пересобрать что угодно. Отдельное исключение: `stateOfMind` в экспорт не попадает вовсе (проверено на свежем архиве). Для него доставки — не хвост журнала, а единственный источник, и под общее правило удаления он не подпадает. Включать **после** того, как разбор устоится и пересборка докажет, что хранилище действительно восстанавливается: иначе страховка исчезнет раньше, чем перестанет быть нужна. Готово, когда удаляются только доставки старше последнего проверенного экспорта, записи `stateOfMind` не трогаются вовсе, а `/stats` показывает глубину архива и дату снапшота, до которой он подрезан. Двигает строку «Завершения» цели: «Сырой архив подчищается до последнего проверенного экспорта». ## Предусловие снова открыто Признак «доставка с непокрытой секцией» появился в change `2026-08-01-nerazobrannye-sekcii-dostavki` и работал заодно защитой `stateOfMind`: такие доставки числились `partial`, и ретеншен их не тронул бы. Change `2026-08-02-trenirovki-i-zapisi` покрыл `stateOfMind` разбором, и защита исчезла: доставка из одного состояния разума теперь получает `parsed` с пустым списком непокрытых, то есть **побайтово неотличима** от доставки из метрик — а метрики восстановимы из экспорта Apple, состояние разума нет (находка 46). Ретеншен, написанный по правилу «удаляем всё, что не `partial`», сотрёт ровно те тела, которых в экспорте не существует, и первая же пересборка потеряет историю состояния разума навсегда. Значит признак невосстановимости нужен **не производный от «непокрытости»**. Варианты: - **Перечень покрытых секций, которых нет в экспорте Apple** рядом с доставкой (сегодня — ровно `stateOfMind`). Цена: колонка и строка в свёртке; читается так же, как `uncovered_sections`, и одним запросом. - **Признак у доставки «тело — единственный источник»**, выставляемый разбором. Цена та же, но смысл шире и требует решения, что считать единственным источником для будущих секций. - **Никогда не подрезать тела доставок, у которых есть строки в `record`.** Цена нулевая по схеме, но неточная: провенанс записи указывает на доставку её **текущей** версии, а копий у записи бывает по 26. Рекомендация — первый вариант: он прямо отвечает на вопрос «что останется потерянным», как это уже делает `uncovered_sections`, и не требует додумывать семантику. Вместе с этим действует правило: задача, которая начинает разбирать секцию, тем же изменением переводит `partial`-строки с этим ключом в `pending` (так сделала миграция `00007`). Ретеншену позволено смотреть на `partial` только пока правило соблюдается. ## Что читать перед удалением тела Две колонки учётной записи, и обе обязательны: - `uncovered_sections` — непустой список означает, что в теле есть секции, которых разбор не покрывает; удалять нельзя; - `skipped_entities` — число сущностей с собственным `id`, которые разбор не понял. **`NULL` означает «не измерялось» и нулю не равен**: так выглядят доставки, свёрнутые разбором, который пропусков не считал, и те, чей разбор не досчитал. `NULL` — «не удалять». Прочитать его как ноль значит удалить тело тренировки, маршрута которой нет больше нигде: в экспорте Apple его не существует. Правило пришло из задачи «Дозакрыть находки ревью по слиянию сущностей» (миграция `00008`), где колонка и заведена — без `DEFAULT` именно ради этого различия.