предложение переработано по итогам ревью дизайна

- три решения опровергнуты экспериментами: повтор при SQLITE_BUSY не сходится
  без _txlock=immediate (242 из 800 против 800 из 800), разбор в map[string]any
  держит 197 МиБ против 54, канонизация без json.Number теряет литерал
- канонизации назначен дом: общий internal/canon вместо hae, иначе импорт
  экспорта Apple потребует второй реализации и хеш-детектор станет бесполезен
- вывод слоя вернул шаг наследования, WARN сравнивается только с надёжным
  заголовком; в bucket возвращены units и границы содержимого
This commit is contained in:
av
2026-08-01 15:16:58 +03:00
parent 65351ab6e7
commit 809153e03f
8 changed files with 394 additions and 76 deletions
@@ -27,9 +27,10 @@
формы — детектор изменений, а не ключ.
- `sleep_analysis` разводится на два имени: поэпизодное и суточную сводку —
под одним именем HAE шлёт две несовместимые схемы.
- Три формата времени на входе: локальное со смещением, RFC 3339 Z,
Unix-эпоха внутри `heartbeatSeries`. В хранилище — UTC RFC 3339 плюс офсет
исходной зоны.
- Метка точки разбирается из локального времени со смещением и хранится в UTC
плюс офсет исходной зоны. Эпоха внутри `heartbeatSeries` **не разбирается** —
серия проходит исходными байтами; RFC 3339 встречается только в
`stateOfMind` и нормируется вместе с ним, отдельной задачей.
- Разбор не влияет на код ответа приёма: непонятое содержимое по-прежнему
даёт 200, исход разбора виден в `delivery.parse_status` и в логе.
@@ -42,7 +43,13 @@
Сходимость на них проверяется скриптом поверх архива, а не командой сервиса;
- **словарь категориальных значений** (переведённые строки → коды HealthKit) —
отдельная задача; пока строка хранится дословно и без кода рядом;
- **род агрегации и каталог разрезов** — отдельная задача, она следующая.
- **род агрегации и каталог разрезов** — отдельная задача, она следующая;
- **хранение поэпизодного `sleep_analysis`** — вынуто ревью дизайна блокером
`identichnost-epizodnyh-metrik`: координатный ключ его схлопывает (измерено:
31 координата в 21 доставке из 89 задвоена внутри одной доставки, где
тай-брейк по времени приёма неприменим в принципе). Точки разбираются и
считаются, но не сохраняются; тела в архиве, подберёт пересборка.
Суточной сводки это не касается.
## Capabilities
@@ -63,7 +70,9 @@
## Impact
- Новые пакеты `internal/hae` (разбор) и расширение `internal/store` (объекты).
- Новые пакеты `internal/hae` (разбор), `internal/canon` (каноническая форма,
полнота, хеш — общий дом для разбора и хранения) и расширение
`internal/store` (объекты).
- Миграция `internal/store/migrations/00003_bucket.sql` — первая миграция после
приёма; вместе с ней заводится `docs/database.md` (ER-схема), которую требует
шаг гейта `er-schema`.