# Измерить, нужно ли правило полноты рядом с LWW - **Секция:** Ядро - **Зачем:** Полнота решает 1,2% спорных координат, и неизвестно, была ли более полная точка более поздней — от этого зависит, нужна ли она вообще - **Теги:** goal:merge-robustness, sprint:2026-08-03 Правило слияния перестаёт зависеть от того, чей набор полей богаче, — либо зависит ровно там, где замер показал, что без этого теряются данные. Сегодня неизвестно, какой из двух случаев верен. Двигает строку «Завершения» цели: «Правило выбора между версиями измерено: полнота либо нужна, либо снята». ## Откуда задача Владелец предложил 2026-08-04 держаться стратегии **LWW** («выигрывает последняя»): экспорт Apple Health — база снапшота, новые доставки HAE затирают предыдущие. Это отменяет `critical`-инвариант `CLAUDE.md` «при столкновении выигрывает более полная точка, а не последняя», и потому меняется не молча, а этой задачей. Соседняя задача «Тай-брейк при равной полноте» двигала то же правило в ту же сторону, но осторожнее: она поменяла только тай-брейк при **равной** полноте, оставив саму полноту первичной. Она сделана 2026-08-04 — решение записано в [ADR о тай-брейке по порядку журнала](../../adr/ADR-2026-08-04-tie-break-po-poryadku-zhurnala.md). Эта задача решает, надо ли снимать и саму полноту. ## Замер — первый шаг, и от него ветвится всё остальное Из 84 978 спорных координат живого архива (замер 2026-08-04, `tmp/diag`): | | координат | | --- | --- | | решено полнотой | 1 022 (1,2%) | | упало на тай-брейк | 83 956 (98,8%) | Вопрос ровно один: **в этих 1 022 случаях более полная точка была более поздней или более ранней?** - **Всегда более поздней** — полнота ничего не решает сверх порядка, LWW строго проще и ничего не теряет. Ветка полноты удаляется, инвариант в `CLAUDE.md` переписывается. - **Иногда более ранней** — значит HAE присылает обеднённые версии задним числом, и LWW будет молча стирать поля. Тогда полнота остаётся, а граница её применения записывается числом: сколько таких случаев, у каких метрик, какие поля пропадали. Замер обязан различать **точки метрик** и **сущности** (`workouts`, `stateOfMind`): у сущностей отношение другое — покрытие, код другой (`internal/store/winner.go`), и он не мерялся вовсе. Оба исхода — законный результат задачи. Исход «полнота нужна» не считается провалом и не отменяет предложение владельца: он его уточняет границей. ## Две рамки, без которых «экспорт — источник правды» ломает работающее Обе выведены при постановке и в замере не нуждаются: 1. **По времени.** Экспорт — снапшот на дату выгрузки; доставки HAE после этой даты обязаны его перекрывать, иначе новые данные не доедут. Совместимо с инвариантом «хранилище — свёртка по журналу»: `import(экспорт) + replay(доставки по received_at)`. 2. **По типам.** `stateOfMind` в экспорте Apple отсутствует ни одним типом (измерено, `docs/research/apple-health.md`). Для него единственный источник — доставки HAE, и объявить экспорт источником правды для него нельзя. ## Критерии приёмки - для 1 022 координат, где полнота решила исход, названо число: в скольких из них более полная точка была более поздней — оракул: прогон замера на живом архиве, число воспроизводится вторым прогоном - тот же вопрос отвечён отдельно для сущностей (`workouts`, `stateOfMind`) — оракул: тот же прогон, отдельная колонка - правило слияния приведено к исходу замера, и `CLAUDE.md` говорит то же, что делает код — оракул: глазами, сверка формулировки инварианта с реализацией - повторный прогон живого архива даёт тот же отпечаток, живая свёртка равна пересборке — оракул: `task verify:archive` дважды подряд - ни одна метрика не потеряла род из-за изменения правила — оракул: `task verify:archive`, ноль противоречащих часов ## Рамки Схему не трогаем. Отпечаток витрины изменится — пересборка обязательна и делается человеком при остановленном сервисе; подмена файла базы необратима и в задаче не выполняется. Тай-брейк при равной полноте уже влит, поэтому замер отвечает про действующее правило, а не про снятое. Связано: находки 10, 47, 49, 53; `docs/architecture.md` → «Разрешение столкновений»; `docs/review.md`, запись 2026-08-04.