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

6.2 KiB

Why

Приём работает третьи сутки, но дальше архива данные не идут: 89 доставок лежат телами .json.gz, а в SQLite только строки delivery. Ни одна из трёх целей проекта — агент-медик, трекер тренировок, фитнес-игра — не может прочитать ничего, потому что читать нечего. Каталог, Read API, MCP и OpenAPI упираются в эту задачу.

Правила разбора не надо изобретать: они выведены измерением на живом потоке и записаны в docs/local-research.md (находки 30, 33, 35, 36, 38, 39, 41). Задача — перенести их в код, а не спроектировать заново.

What Changes

  • Секция metrics тела доставки разбирается в точки: метрика, слой, метка времени, содержимое как пришло.
  • Слой выводится из выравнивания меток, а не из заголовка HAE: плотная метрика (≥10 точек) классифицируется сама, редкая наследует преобладающий слой доставки. Заголовок automation-aggregation непригоден — значение Default соответствует трём разным режимам.
  • Точки складываются в часовые объекты (bucket, ключ метрика + слой + час), содержимое — gzip-BLOB. Запись — read-modify-write со слиянием.
  • Идентичность точки — координаты (метрика + слой + метка). source в ключ не входит: он нестабилен и меняется задним числом. При столкновении выигрывает более полная точка, а не последняя пришедшая.
  • Канонизация с округлением чисел до ~12 значащих цифр; хеш канонической формы — детектор изменений, а не ключ.
  • sleep_analysis разводится на два имени: поэпизодное и суточную сводку — под одним именем HAE шлёт две несовместимые схемы.
  • Три формата времени на входе: локальное со смещением, RFC 3339 Z, Unix-эпоха внутри heartbeatSeries. В хранилище — UTC RFC 3339 плюс офсет исходной зоны.
  • Разбор не влияет на код ответа приёма: непонятое содержимое по-прежнему даёт 200, исход разбора виден в delivery.parse_status и в логе.

Не входит в изменение (сознательно, чтобы задача мерджилась целиком):

  • тренировки и секции с собственными id (workouts, stateOfMind, прочие record) — отдельная задача, у них другая модель хранения;
  • healthlog reindex — отдельная задача. Следствие: разбираются только доставки, пришедшие после выката; накопленные 89 доедут пересборкой. Сходимость на них проверяется скриптом поверх архива, а не командой сервиса;
  • словарь категориальных значений (переведённые строки → коды HealthKit) — отдельная задача; пока строка хранится дословно и без кода рядом;
  • род агрегации и каталог разрезов — отдельная задача, она следующая.

Capabilities

New Capabilities

  • parsing: превращение тела доставки Health Auto Export в точки — вывод слоя, разбор трёх форматов времени, канонизация содержимого, разделение схем под одним именем метрики. Отдельно от хранения потому, что импорт родного экспорта Apple будет другим разбором поверх того же хранилища.
  • storage: идентичность точки, слияние и хранение часовыми объектами — координатный ключ, правило разрешения столкновений, хеш как детектор изменений, признак запечатанного часа.

Modified Capabilities

Нет: openspec/specs/ пуст, приём кодом существует, но спекой не описан и в этом изменении не трогается.

Impact

  • Новые пакеты internal/hae (разбор) и расширение internal/store (объекты).
  • Миграция internal/store/migrations/00003_bucket.sql — первая миграция после приёма; вместе с ней заводится docs/database.md (ER-схема), которую требует шаг гейта er-schema.
  • internal/ingest получает шаг разбора после записи в архив; контракт приёма не меняется.
  • Появляется testdata с реальными пакетами HAE. Значения в них вычищаются: структура, порядок ключей, форматы времени, неразрывные пробелы в именах устройств и точность чисел сохраняются, измеренные величины заменяются — данные о здоровье не попадают под контроль версий.