Files
av b278501a6e store: при равной полноте точек побеждает пришедшая доставка
- байтовый порядок канонических форм остался тай-брейком только внутри одной
  доставки: на живом корпусе он решал 98,8% спорных координат и системно хранил
  меньшее значение, из-за чего step_count терял род и verify:archive был красным
- правило перестало быть коммутативным осознанно, поэтому порядок свёртки
  приведён к журнальному: проход воркера прекращается на отложенной доставке,
  а свёртка вне порядка журнала пишет WARN
- заведены счётчики PointsHeld и PointsErased — удержание полнотой и
  единственное направление, в котором правило теряет содержание
2026-08-04 11:16:24 +03:00

119 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## 1. Правило слияния точек
- [x] 1.1 `candidate` получает флаг `incoming`; схлопывание совпавших
канонических форм поднимает флаг, а байты оставляет встреченные первыми
- [x] 1.2 `pointLess` — лексикографический порядок по паре
`(не incoming, каноническая форма)`; `pointDominates` не трогается
- [x] 1.3 `resolve` возвращает признак «победил сохранённый при наличии
пришедших»; `mergePoints` считает удержания
- [x] 1.4 `MergeStats.PointsHeld` и `PointsHeldAt`; проброс через `mergeResult`,
`SaveBuckets`, `fold.Stats`, `replay.Outcome`/`Report` и лог свёртки — без
значений точек
## 2. Порядок свёртки равен порядку журнала
- [x] 2.1 `Worker.Pass` прекращает проход на исходе `Deferred`; доставка,
оставшаяся `pending` без такого исхода, курсор двигает
- [x] 2.2 `Store.ParsedAfter` — есть ли доставка позже данной в статусе
`parsed` или `partial` (кортежный предикат; индекс — `delivery_received_at`,
цена измерена и названа в design.md)
- [x] 2.3 воркер пишет одну запись `WARN` на доставку о свёртке вне порядка
журнала; пересборка эту проверку не выполняет
## 3. Тесты
- [x] 3.1 пришедшая побеждает сохранённую при равной полноте
- [x] 3.2 столкновение внутри одной доставки решается порядком канонических
форм и не зависит от порядка элементов массива
- [x] 3.3 повторная присылка канонически совпавшего содержимого не переписывает
объект (хеш не двигается)
- [x] 3.4 полнота сильнее происхождения; счётчик удержаний растёт
- [x] 3.5 сходимость: живой путь через воркер с отложенной занятостью базы
доставкой даёт тот же отпечаток, что пересборка
- [x] 3.6 проход воркера не перешагивает отложенную доставку
- [x] 3.7 `WARN` о свёртке вне порядка журнала пишется, не содержит значений и
не пишется на `failed`-преемнице
- [x] 3.8 при разошедшихся значениях пустые ключи сохранённой точки её не
удерживают (сценарий, парный к 3.4)
## 4. Документы
- [x] 4.1 `docs/architecture.md` — «Разрешение столкновений» плюс **все**
упоминания правила: инвариант в шапке, «порядок прихода значения не имеет» в
разделе синхронизации; таблица двух правил равной полноты (точки против
сущностей) с критерием выбора
- [x] 4.2 `CLAUDE.md` — формулировка инварианта «ничего не теряем молча»:
«выигрывает более полная, при равной полноте — стоящая позже в журнале»
- [x] 4.3 `internal/store/entity.go` — комментарии, чей довод («порядок свёртки
журналу не равен») этим изменением сужен до окна видимости
- [x] 4.4 `docs/research/apple-health.md` — перемер 2026-08-04 с **методом**:
ключ со слоем, 155 доставок, 460 995 координат, 80 129 спорных, 981 полнотой,
79 148 тай-брейком, 75 494 меняют исход
- [x] 4.5 `docs/review.md` — запись о дефекте (посылка оракула умерла с ростом
корпуса) и о том, что конвейер её не ловил
- [x] 4.7 вопрос владельцу в `docs/tasks/items/journal-order-on-ingest.md`
(раздел «Вопросы» + тег `question`): решение (в) порядок журнала не
восстанавливает, а цена окна выросла с вывода слоя до значений точек
- [x] 4.6 `docs/conventions/` — промоут двух правил: «в проверке на живом
корпусе утверждается инвариант, число печатается» и «оракул сходимости
называет свою посылку рядом с собой»
## 5. Оракулы
- [x] 5.1 `task gate` зелёный
- [x] 5.2 `task verify:archive` — ноль противоречащих часов, `step_count`
накопительная, отпечаток изменился
- [x] 5.3 `task verify:archive` второй раз подряд — тот же отпечаток
- [x] 5.4 `task verify:busy` зелёный
- [x] 5.5 замер удержаний на живом архиве — число названо, не утверждено
## Приёмочные критерии из ревью предложения (профиль `design`, проход `rubric`)
Свойства, по которым судится узел рода «правило слияния версий в
хранилище-свёртке по журналу» плюс «упорядочивающий воркер очереди».
- [x] Р1 исход слияния — функция префикса журнала и только его; запрос воркера
«есть ли доставка позже» влияет на лог и MUST NOT влиять на содержимое
- [x] Р2 законные расхождения живого пути и пересборки перечислены поимённо, и
у оракула названа посылка
- [x] Р3 повторная свёртка идемпотентна на суффиксе журнала; свёртка более
ранней доставки после более поздней меняет состояние наблюдаемо
- [x] Р4 победитель — функция множества кандидатов и их происхождения, но не
порядка точек внутри доставки; отношение победы ациклично (проверка
перестановками ТРОЙКИ, не пары)
- [x] Р5 правило тотально на вырожденном входе: один кандидат, равные
канонические формы с разными байтами, не-JSON, несравнимые множества
- [x] Р6 победитель сохраняется дословно; цена лишних записей названа числом
- [x] Р7 правило структурно: не читает ни значение точки, ни род, ни витрину
- [x] Р8 барьер очереди не останавливает поток: названо, что держит очередь и
что её освобождает; канонизация и сжатие вне транзакции записи
- [x] Р9 наблюдаемость отличает «правило сработало» от «не сработало» и не
несёт значений здоровья; тест на утечку разбирает запись, а не ищет
подстроку в сыром буфере
- [x] Р10 ни одно утверждение теста не пришпилено к числу, производному от
размера корпуса: утверждается инвариант, число печатается
- [x] Р11 два правила равной полноты (точки и сущности) не расходятся молча:
различие механизмов и критерий выбора записаны
- [x] Р12 место снапшота Apple в порядке журнала — либо названо, либо явно
отложено до задачи импорта (сегодня стадия снапшота пуста)
## Критерии приёмки задачи
Приходят из `docs/tasks/items/tie-break-equal-completeness.md`, дословно. Числа
в них производны от размера корпуса — по каждому названо, чем именно измерено и
что при этом печатается, а не утверждается (`docs/review.md`, 2026-08-02).
- [x] ни одна метрика не теряет род из-за столкновения равной полноты;
`step_count` снова накопительная — оракул: `task verify:archive`, ноль
противоречащих часов
- [x] живая свёртка и пересборка дают **один** отпечаток витрины — оракул:
`healthlog reindex` против живого состояния; это же и есть страховка от
потерянной коммутативности
- [x] повторный прогон реплея даёт тот же отпечаток — оракул:
`task verify:archive`, второй прогон подряд
- [x] столкновение **внутри одной доставки** разрешается прежним байтовым
порядком — оракул: тест на двух точках одной доставки с равной полнотой
- [x] «пришедшая точка проиграла сохранённой» считается отдельно от общего
`MergeStats.Overwrites` — оракул: тест плюс прогон на живом архиве, число
сходится с замером 2026-08-04