хранилище описано как свёртка по журналу событий

- экспорт Apple это снапшот всей истории, доставки после его даты — события
  поверх; состояние пересобирается как import(экспорт) + replay(доставки)
- отсюда ретеншен архива меняется с произвольных 14 дней на «до следующего
  проверенного экспорта» (~2 ГБ за квартал, измерено), а свёртка обязана быть
  детерминированной — воспроизведение строго по received_at
- названы границы модели: stateOfMind в экспорт не попадает вовсе, а верхние
  слои за периоды с удалёнными доставками не воскресают и досчитываться не
  должны — каталог обязан говорить это честно
This commit is contained in:
av
2026-08-01 14:27:13 +03:00
parent 7ee55057e0
commit b2885c79e3
10 changed files with 162 additions and 46 deletions
+32
View File
@@ -1427,6 +1427,38 @@ RFC3339 Z 20 data.stateOfMind[].end = 2026-07-31T18:03:51
То есть правило «экспорт говорит кодами» верно для типов записей и категориальных
значений, но не для всего документа.
## 46. `stateOfMind` в экспорт не попадает — единственная дыра в журнале
Экспорт плюс доставки после его даты образуют полный журнал событий: состояние
пересобирается свёрткой `import(снапшот) + replay(хвост)`. Проверка показала
ровно одно исключение.
В свежем экспорте **нет ни одного типа со словом `StateOfMind`**:
```
grep -oiE 'type="[^"]*(mind|mood|emotion)[^"]*"' → только
type="HKCategoryTypeIdentifierMindfulSession" ← минуты осознанности, другое
type="HKWorkoutEventTypeMotionPaused|Resumed" ← совпадение по подстроке
```
При этом HAE состояние разума шлёт исправно, и шлёт правильно — стабильными
кодами HealthKit (`momentary_emotion`, `slightly_pleasant`, `drained`), в
отличие от переведённых фаз сна (находка 37).
**Следствие:** для `stateOfMind` доставки HAE — не хвост журнала, а
единственный источник. Под общее правило ретеншена он не подпадает: удалив
доставки, мы потеряем возможность восстановить его историю навсегда.
### Цена журнала
Поток даёт **~23 МБ сырого архива в сутки** (89 доставок за 16.4 часа дали
15.6 МБ). При экспорте раз в 2–3 месяца это ~2 ГБ между снапшотами — дёшево за
возможность пересобрать хранилище с любой точки.
Прежние 14 дней ретеншена были произвольным числом; правильный срок — до
следующего проверенного экспорта, иначе между концом ретеншена и датой
снапшота в журнале образуется дыра.
## Инструмент
Разбор ведётся скриптом `tmp/research/hl.py` (Python 3, только стандартная