## 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` в ключ не входит: он нестабилен и меняется задним числом. При столкновении выигрывает **более полная** точка, а не последняя пришедшая. - **Точка-интервал адресуется интервалом**: `метрика + слой + начало + конец`. Под одной меткой лежит до трёх эпизодов сна, и 33 столкновения из измеренных происходят внутри одной доставки, где тай-брейк по времени приёма неприменим. Эпизодность выводится из формы точки, а не из списка имён метрик. - **Канонизация с округлением** чисел до ~12 значащих цифр; хеш канонической формы — детектор изменений, а не ключ. - `sleep_analysis` разводится на два имени: поэпизодное и суточную сводку — под одним именем HAE шлёт две несовместимые схемы. - Метка точки разбирается из локального времени со смещением и хранится в UTC плюс офсет исходной зоны. Эпоха внутри `heartbeatSeries` **не разбирается** — серия проходит исходными байтами; RFC 3339 встречается только в `stateOfMind` и нормируется вместе с ним, отдельной задачей. - Разбор не влияет на код ответа приёма: непонятое содержимое по-прежнему даёт 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/canon` (каноническая форма, полнота, хеш — общий дом для разбора и хранения) и расширение `internal/store` (объекты). - Миграция `internal/store/migrations/00003_bucket.sql` — первая миграция после приёма; вместе с ней заводится `docs/database.md` (ER-схема), которую требует шаг гейта `er-schema`. - `internal/ingest` получает шаг разбора после записи в архив; контракт приёма не меняется. - Появляется `testdata` с реальными пакетами HAE. Значения в них **вычищаются**: структура, порядок ключей, форматы времени, неразрывные пробелы в именах устройств и точность чисел сохраняются, измеренные величины заменяются — данные о здоровье не попадают под контроль версий.