Files
healthlog/openspec/changes/razbor-metrik-v-obekty/tasks.md
T
av c6f27e3890 заведён change на разбор метрик в часовые объекты
- proposal и две capability: parsing (вывод слоя, форматы времени, канонизация)
  и storage (координатный ключ, слияние по полноте, часовые объекты)
- design фиксирует границы: разбор отдельным пакетом, синхронно после записи в
  архив, конкурентная запись в один час — риск с тестом
- вне scope сознательно: тренировки, reindex, словарь кодов, род агрегации
2026-08-01 14:50:10 +03:00

44 lines
5.0 KiB
Markdown
Raw 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. Фикстуры и схема
- [ ] 1.1 Скрипт `tmp/research/fixtures.py`: собирает фикстуры из `data/raw`, вычищая измеренные значения и сохраняя порядок ключей, точность чисел, неразрывные пробелы и форматы времени
- [ ] 1.2 Набор `internal/hae/testdata`: минутная доставка, посекундная, часовая, смешанная (перенастройка автоматизации), обе схемы `sleep_analysis`, точка с `heartbeatSeries`
- [ ] 1.3 Миграция `internal/store/migrations/00003_bucket.sql`: таблица `bucket` (`metric`, `layer`, `hour_utc`, `payload` BLOB, `content_hash`, `points`, `sealed`, `created_at`, `updated_at`), уникальность по `(metric, layer, hour_utc)`
- [ ] 1.4 `docs/database.md` — ER-схема с `delivery` и `bucket` (шаг гейта `er-schema` требует её при изменении миграций)
## 2. Разбор — пакет `internal/hae`
- [ ] 2.1 Разбор трёх форматов времени в UTC с сохранением офсета исходной зоны; неразобранная метка — не паника, а пропуск точки со счётчиком
- [ ] 2.2 Вывод слоя: выравнивание меток, плотная метрика (≥10 точек) сама, редкая наследует преобладающий слой, при отсутствии плотных — заголовок доставки
- [ ] 2.3 Расхождение выведенного слоя с заголовком доставки — запись `WARN` без значений точек
- [ ] 2.4 Разделение `sleep_analysis` на поэпизодную и `sleep_analysis_summary` со слоем `day`
- [ ] 2.5 Канонизация: рекурсивная сортировка ключей, округление чисел до 12 значащих цифр
- [ ] 2.6 `hae.Parse` возвращает точки со слоем, метрикой, меткой и содержимым как пришло; незнакомые поля и метрики сохраняются
- [ ] 2.7 Тесты разбора на фикстурах из 1.2, включая смешанную доставку и обе схемы сна
## 3. Хранение — часовые объекты
- [ ] 3.1 Модель точки и объекта в `internal/store`; сериализация содержимого в gzip-BLOB, точки внутри упорядочены по времени
- [ ] 3.2 Слияние: координатный ключ `метрика + слой + метка`, победа более полной точки, при равной полноте — по `received_at`
- [ ] 3.3 Хеш канонической формы объекта как детектор изменений: совпал — записи нет
- [ ] 3.4 Запись объекта в транзакции; повтор при `SQLITE_BUSY`
- [ ] 3.5 Признак `sealed`: изменение запечатанного часа пишет `WARN` и всё равно сохраняет
- [ ] 3.6 Тест конкурентной записи в один `hour_utc`: точки обеих сторон на месте
- [ ] 3.7 Тест идемпотентности: повторное слияние того же набора не меняет ни содержимое, ни хеш
## 4. Сшивка с приёмом
- [ ] 4.1 `internal/ingest` вызывает разбор после записи тела в архив и строки `delivery`
- [ ] 4.2 Отказ и паника разбора не меняют код ответа: `200`, `parse_status=failed`, запись лога уровня `ERROR` без значений
- [ ] 4.3 Единственный логирующий чекпоинт на границе: счётчики метрик, точек и объектов, идентификатор доставки; ни значений, ни имён устройств
- [ ] 4.4 Тест приёма: битый JSON — 400, непонятое содержимое — 200 с `parse_status=failed`
## 5. Сходимость на реальных данных
- [ ] 5.1 Скрипт `tmp/research/verify_buckets.py`: прогоняет архив через разбор и сверяет суммы по часовому слою с прежней проверкой из разведки
- [ ] 5.2 Прогон на всех накопленных доставках: расхождений по накопительным метрикам нет
- [ ] 5.3 `task gate` зелёный; `task restart` поднимает сервис, новая доставка с телефона разбирается
## 6. Приёмочные критерии ревью дизайна
<!-- Заполняется рубрикой из healthlog-review-rubric на шаге ревью дизайна -->