- байтовый порядок канонических форм остался тай-брейком только внутри одной доставки: на живом корпусе он решал 98,8% спорных координат и системно хранил меньшее значение, из-за чего step_count терял род и verify:archive был красным - правило перестало быть коммутативным осознанно, поэтому порядок свёртки приведён к журнальному: проход воркера прекращается на отложенной доставке, а свёртка вне порядка журнала пишет WARN - заведены счётчики PointsHeld и PointsErased — удержание полнотой и единственное направление, в котором правило теряет содержание
6.0 KiB
Why
Тай-брейк при равной полноте точек сегодня — порядок канонических форм, и он решает 98,8% спорных координат (83 956 из 84 978 при 453 171 координате): полнота отвечает лишь в 1,2% случаев. Лексикографический порядок системно берёт меньшее значение (1 847 из 1 912, находка 49), то есть хранит устаревшую версию точки там, где HAE досчитывает задним числом (находка 10).
У дефекта появился независимый оракул: task verify:archive покраснел на
master без единого коммита, с ростом корпуса. Час 2026-08-03T07:00Z метрики
step_count получил четыре доставки с двумя различными значениями; победило
меньшее, оно же приехавшее первым, и сверка слоёв объявила метрику мгновенной
против 23 согласных часов. step_count ушёл в unknown — Read API больше не
имеет права суммировать шаги.
Решение владельца от 2026-08-04: при равной полноте побеждает пришедшая точка, а не сохранённая. Значение при этом не интерпретируется — правило остаётся структурным.
What Changes
- BREAKING (содержимое витрины): при равной полноте побеждает точка, пришедшая этой доставкой, а не сохранённая. Отпечаток витрины обязан измениться; состояние восстанавливается пересборкой из архива.
- Порядок канонических форм остаётся тай-брейком внутри одной доставки, где провенанс общий и различать нечем.
- Правило слияния точек перестаёт быть функцией множества и становится явной функцией порядка журнала. Отсюда — плата, которую изменение обязано внести целиком: порядок свёртки приводится к порядку журнала.
- Фоновый воркер прекращает проход на первой отложенной доставке, а не перешагивает её. Иначе занятость базы переставляет доставки местами, и живая витрина расходится с пересборкой молча.
- Свёртка доставки, у которой в журнале уже есть свёрнутая преемница, пишет
WARN: остаточное окно (конкурентный приём делает строку учёта видимой не в порядке меток) закрыть без изменения приёма нельзя, но молчать о нём нельзя тем более. - Заводится счётчик «пришедшая точка проиграла сохранённой» — отдельно от
общего
MergeStats.Overwrites, который считает столкновения в обе стороны и различить их не даёт. - Схема не трогается: колонок провенанса на точку не заводится, формат
payloadне меняется, миграции нет.
Capabilities
New Capabilities
Новых нет.
Modified Capabilities
storage: тай-брейк при равной полноте точек — пришедшая побеждает сохранённую; порядок канонических форм остаётся только внутри доставки. Требование «победитель есть функция множества точек» заменяется на «функция множества точек и позиции в журнале». Новый счётчик удержаний.ingest: проход воркера прекращается на первой отложенной доставке; свёртка вне порядка журнала становится наблюдаемой.reindex: посылка сходимости («приём шёл последовательно») из оговорки сценария становится названным условием требования — теперь от порядка свёртки зависит не только вывод слоя, но и содержимое точек.
Impact
internal/store/bucket.go—mergePoints,resolve,candidate,pointLess,MergeStats.internal/store/delivery.go— запрос «есть ли свёрнутая доставка позже этой».internal/replay/worker.go— барьер на отложенной доставке,WARNо свёртке вне порядка журнала.internal/fold/fold.go— проброс нового счётчика в итог свёртки и в лог.- Витрина в
./data: отпечаток изменится. Пересборка — действие человека при остановленном сервисе, этим изменением не выполняется. - Оракулы:
task verify:archive(ноль противоречащих часов,step_countснова накопительная), тест сходимости «живой приём = пересборка» с отложенной доставкой.