Files
av 7a7594e3e7 полнота точки — множество ключей, победитель — функция множества точек
- отношение победы было нетранзитивным: полнота (частичный порядок) плюс
  тай-брейк (тотальный) в попарной свёртке давали цикл, из-за которого одна
  и та же доставка меняла содержимое объекта при каждой пересборке
- надмножество побеждает только при совпадении значений общих содержательных
  ключей: иначе точка без единого измерения вытесняла измерение
- Less стал тотальным, isEmpty не материализует значение, имя метрики в
  координате столкновения обрезается, отпечаток витрины включает units и sealed
- на живом архиве строгий no-op: 1737 объектов, содержимое совпало побайтово
2026-08-01 21:05:43 +03:00

63 lines
4.6 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.
## Why
Полнота точки при разрешении столкновения считается **числом** ключей с
непустым значением. Число сравнимо всегда, а сравнивать надо содержание: точка
с пятью полями, где значения `0`, `{}` и `[]`, выигрывает у настоящего
измерения с двумя полями и стирает его безвозвратно.
```
точка {"qty":0,"a":0,"b":0,"c":{},"d":[]} полнота 5 ← выигрывает сегодня
точка {"date":"…","qty":123.4} полнота 2 ← стирается
```
Замер по всем 99 доставкам (docs/local-research.md, находка 49) даёт основание
для правильной формы правила: настоящих столкновений 2 897 из 444 256
координат (0.65%), из них наборы полей сравнимы в 981 случае, равны в 1 916 и
**несравнимы ни разу**. То есть правило сводится к «побеждает надмножество», а
самая дорогая часть — объединение полей из двух точек — на живом потоке не
нужна вовсе.
## What Changes
- Полнота точки перестаёт быть числом и становится **множеством ключей с
непустым значением**. Побеждает строгое надмножество; равные множества
уходят на прежний тай-брейк.
- Пустым значением считается не только `null` и `""`, но и `0`, `{}`, `[]`:
поле, не несущее содержания, не делает точку полнее отсутствующего поля.
Это и есть та часть, из-за которой сегодняшний счётчик даёт неверный исход
на приведённой выше паре. `false` пустотой НЕ считается — для булева поля
это одно из двух значений, а не отсутствие сведений.
- Надмножество побеждает только при совпадении значений общих содержательных
ключей: иначе точка без единого измерения вытесняла бы измерение.
- Несравнимые множества (ни одно не является надмножеством другого) не
объединяются, а **считаются**: счётчик в итоге слияния плюс `WARN` с
координатами объекта (метрика, слой, час), без значений. Победителя в этом
случае выбирает тот же тай-брейк, что и при равной полноте.
- **Не меняется** тай-брейк при равной полноте: он зависит от рода метрики,
а род измеряется сверкой слоёв (задача `rod-agregacii-i-katalog`). Выбирать
его сейчас — угадывать то, что скоро станет известно точно.
## Capabilities
### New Capabilities
Нет.
### Modified Capabilities
- `storage`: требование «Разрешение столкновений по полноте» переформулируется
с числа значащих полей на множество ключей с непустым значением; добавляется
наблюдаемость несравнимых множеств.
## Impact
- `internal/canon``Completeness` (число) заменяется сравнением множеств
ключей; расширяется понятие пустого значения.
- `internal/store/bucket.go``resolve` и `MergeStats` (новый счётчик и
координаты несравнимых случаев).
- `internal/fold` — новая ветвь `WARN` в единственном логирующем чекпоинте.
- `openspec/specs/storage/spec.md` — дельта-спека.
- Витрина не мигрирует: правило меняет исход только там, где сегодня он
неверен. Проверяется прогоном `task verify:archive` на живом архиве —
состояние обязано совпасть с прежним.