идентичность эпизода — интервал: блокер снят измерением
- находка 47: ключ (date,start,end) даёт 174 координаты сна против 170 по метке и ноль столкновений внутри доставки против 33; value в ключе лишний - UUID в выгрузку Apple не попадает, другой идентичности у эпизода нет - поэпизодный sleep_analysis вернулся в scope razbor-metrik-v-obekty
This commit is contained in:
@@ -4,3 +4,4 @@
|
||||
|
||||
<!-- - ГГГГ-ММ-ДД `slug` — Заголовок. Причина: … Был приоритет: … -->
|
||||
- 2026-08-01 `bekap-dannyh` — Резервное копирование ./data. Причина: бекап обеспечивает готовый механизм на сервере пет-проектов — своего заводить не нужно, задача снимается деплоем. Был приоритет: высокий.
|
||||
- 2026-08-01 `identichnost-epizodnyh-metrik` — Идентичность эпизодных метрик. Причина: решён измерением и prior art: ключ эпизода — метрика+слой+start+end (находка 47), вариант А; вернулся в scope razbor-metrik-v-obekty. Был приоритет: блокеры.
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
одному — прерывать поток ради каждого дороже, чем накопить.
|
||||
|
||||
## блокеры
|
||||
- [Идентичность эпизодных метрик](identichnost-epizodnyh-metrik.md) — Координатный ключ схлопывает эпизоды сна: 31 координата в 21 доставке из 89, тай-брейк неисполним
|
||||
|
||||
## высокий
|
||||
- [Разбор метрик в часовые объекты](razbor-metrik-v-obekty.md) — Доставки копятся непрозрачными телами — точек в хранилище нет вовсе, всё остальное упирается в это
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
# Идентичность эпизодных метрик
|
||||
|
||||
**Приоритет:** блокеры
|
||||
|
||||
Вынуто из задачи `razbor-metrik-v-obekty` ревью дизайна (профиль `design`,
|
||||
находка №1 триажа, severity critical). Пока не решено — эпизодные схемы не
|
||||
хранятся, см. «Что стоит без решения».
|
||||
|
||||
## Что решить
|
||||
|
||||
Состав координатного ключа и правило слияния для метрик, у которых **метка
|
||||
времени не уникальна**. Принятая модель — `метрика + слой + метка` — для них
|
||||
неверна.
|
||||
|
||||
## Оракул: измерено на живых данных
|
||||
|
||||
Из 173 координат сна три несут разное содержимое, одна — три разных эпизода:
|
||||
|
||||
```
|
||||
sleep_analysis 2026-07-31 22:04:00
|
||||
start=22:04 end=22:16 qty=0.2 value=Во сне
|
||||
start=22:04 end=02:21 qty=4.28 value=В кровати
|
||||
start=22:04 end=07:51 qty=9.78 value=В кровати
|
||||
```
|
||||
|
||||
Хуже: **31 координата в 21 доставке из 89** (почти четверть) задвоена **внутри
|
||||
одной доставки**. Там `received_at` у обеих точек один и тот же, поэтому
|
||||
предписанный тай-брейк «побеждает больший `received_at`» неприменим в
|
||||
принципе — исход решил бы порядок элементов в JSON-массиве, а он нестабилен
|
||||
(находка 2). Это ломало бы и детерминированность свёртки: пересборка из архива
|
||||
давала бы другое состояние, чем живой приём.
|
||||
|
||||
Правило полноты не спасает: точка сна несёт одновременно `start`/`end` и
|
||||
`startDate`/`endDate`, так что два набора разных полей равной мощности
|
||||
равнополны.
|
||||
|
||||
## Варианты и цена
|
||||
|
||||
**(А) Включить `start`/`end` в координату для эпизодных схем.**
|
||||
Закрывает и междоставочные, и внутридоставочные дубли — все 31 относятся к
|
||||
`sleep_analysis`. Цена: ключ разной формы для разных классов метрик, и надо
|
||||
определить, что делает метрику «эпизодной» (наличие `start`/`end`? список?).
|
||||
|
||||
**(Б) Эпизодные метрики — множество с идентичностью по хешу канонической формы
|
||||
(append-only).** Ничего не теряется по построению. Цена: две модели
|
||||
идентичности в `store` и рост объекта — эпизоды не схлопываются никогда, даже
|
||||
когда повтор действительно повтор.
|
||||
|
||||
**(В) Принять потерю: нынешнее правило плюс обязательный `WARN`.**
|
||||
Дёшево. Цена: необратимая потеря эпизодов примерно в четверти доставок сна,
|
||||
обнаружимая только сверкой с экспортом Apple, то есть месяцами позже. Прямо
|
||||
противоречит инварианту «ничего не теряем молча».
|
||||
|
||||
Независимо от выбора: тай-брейк `received_at` надо заменить или дополнить
|
||||
детерминированным (например, лексикографически по канонической форме) — без
|
||||
провенанса в схеме нынешний неисполним даже между доставками.
|
||||
|
||||
## Рекомендация
|
||||
|
||||
**(А).** Она закрывает оба класса дублей, не плодит вторую модель хранения и не
|
||||
требует принимать потерю. «Эпизодность» выводится из данных, а не курируется:
|
||||
точка, несущая `start` и `end`, отличные от `date`, — эпизод. Это в духе того,
|
||||
как в проекте уже выводится слой — из формы данных, а не из объявления.
|
||||
|
||||
Против (Б): рост объекта ради случая, которого можно избежать. Против (В): это
|
||||
ровно тот класс молчаливой потери, ради защиты от которого заведён инвариант.
|
||||
|
||||
## Что стоит без решения
|
||||
|
||||
`sleep_analysis` (поэпизодная схема) в задаче `razbor-metrik-v-obekty` **не
|
||||
сохраняется**: точки разбираются и считаются, но в объекты не пишутся. Сохранять
|
||||
их по правилу, о котором известно, что оно теряет, — хуже, чем не сохранять:
|
||||
тела лежат в архиве, и после решения блокера их подберёт `reindex`.
|
||||
|
||||
Суточная сводка (`sleep_analysis_summary`) блокером не затронута — у неё метка
|
||||
на полуночи уникальна.
|
||||
|
||||
@@ -9,7 +9,8 @@ Read API, MCP — стоит на этой задаче.
|
||||
Правила выведены на живом потоке и проверены, изобретать заново не нужно
|
||||
(`docs/local-research.md`, находки 33, 35, 36, 38, 39, 41):
|
||||
|
||||
- ключ точки — координаты `метрика + слой + метка`; `source` в ключ не входит;
|
||||
- ключ точки — координаты `метрика + слой + метка`, у эпизода — `метрика + слой
|
||||
+ начало + конец` (находка 47); `source` в ключ не входит;
|
||||
- слой выводится из выравнивания меток: плотная метрика (≥10 точек)
|
||||
классифицируется сама, редкая наследует преобладающий слой доставки;
|
||||
- при столкновении выигрывает более полная точка, а не последняя пришедшая
|
||||
@@ -24,14 +25,9 @@ Read API, MCP — стоит на этой задаче.
|
||||
- слияние точек в объект read-modify-write, хеш объекта как детектор изменений;
|
||||
- `docs/database.md` — ER-схема (её требует шаг гейта `er-schema`).
|
||||
|
||||
**Границы после ревью дизайна.** Поэпизодный `sleep_analysis` в этой задаче не
|
||||
сохраняется — модель идентичности вынесена блокером
|
||||
[identichnost-epizodnyh-metrik](identichnost-epizodnyh-metrik.md). Остальное
|
||||
делается целиком.
|
||||
|
||||
Готово, когда по существующим 89 доставкам собирается хранилище (кроме
|
||||
эпизодов сна), а суммы по часовому слою сходятся с проверкой из
|
||||
`tmp/research/`.
|
||||
Готово, когда по существующим доставкам собирается хранилище, суммы по часовому
|
||||
слою сходятся с проверкой из `tmp/research/`, а эпизодов сна выходит 174, а не
|
||||
170 (находка 47).
|
||||
|
||||
Связано: `docs/architecture.md` → «Хранилище», план шаг 3.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user