- каждая запись каталога задач получила тип вместо тега kind: и префикса заголовка; секция роадмапа «Разработка» стала «Сопровождением», порядок секций канонический - поправлены протухшие факты: нереализованные маршруты Read API, MCP и `healthlog import`, словарь слоёв в инварианте, семантика гейта по покрытию диффа, периметр перестал дублировать security.md - замер слияния переведён с находки 49 на находку 54, заполнены Purpose спек storage и parsing
5.9 KiB
✨ Импортировать родной экспорт Apple Health
- Тип: feature
- Категория: Ядро
- Зачем: Слой sample пуст: полная история и точные сэмплы лежат в zip-архиве и никуда не едут
- Теги: goal:native-export-import
Слой sample пуст: настоящих сэмплов HealthKit в потоке нет вовсе — HAE отдаёт
посекундную развёртку, а не измерения (находка 34). Полная история и точные
сэмплы лежат в zip родного экспорта.
Это же основание для устаревания нижнего слоя и единственный способ поднять историю глубже недели: дыра старше недели проходами синхронизации не чинится.
Формат разобран на девяти экспортах за 5.5 лет (находки 42–45), гадать не придётся:
- версии 11 → 13 → 14, на 14 стоит больше года; за всё время ни один тип записи не исчез, только добавлялись. Значит незнакомый тип — новый тип, а не сломанный парсер: падать на нём нельзя;
Correlation— обёртка из двух записей, ею приезжает давление. Появилась только в 2026 году. Парсер по одним<Record>разберёт давление как две несвязанные метрики и потеряет их парность;WorkoutStatisticsвнутри тренировки — с 2024 года;- имя файла локализовано:
экспорт.xml, неexport.xml— так во всех девяти архивах; - DTD расходится с данными (в v11 у
<Me>на атрибут больше объявленного) — валидировать документ его же DTD нельзя; - объём: 1.6 ГБ XML и 3.6 млн записей в свежем экспорте — только потоковый разбор, документ целиком в память не влезет.
Шаги:
- потоковый разбор
экспорт.xmlв слойsample, включаяCorrelation; HeartRateVariabilityMetadataListсInstantaneousBeatsPerMinute— это тот жеheartbeatSeries, что в HAE (находка 39), 1.25 млн ударов;- маршруты GPX и ЭКГ отдельными файлами — их в XML нет;
- заливка кусками по годам, идемпотентно: повторный импорт того же архива не должен ничего менять;
export_cda.xmlигнорируем — это клинический формат тех же данных.
Двигает строку «Завершения» цели: «Слой sample наполнен историей с 2019 года, повторный импорт того же экспорта ничего не меняет».
Импорт выставляет пометку покрытия
Импорт — единственный, кто знает, какой период каким слоем обеспечен, поэтому пометку ставит он, а не отдельный проход задним числом.
Форма пометки решена в lower-layer-expiry: одна
строка на диапазон — метрика + слой + период + «покрыто проверенным экспортом». Провенанс на каждую точку не заводим: вопрос диапазонный, а поле у
точки стоило бы того же объёма, который устаревание нижнего слоя и приходит
экономить.
Два условия, оба из ограничителей той задачи:
- пометка ставится по проверенному импорту, а не по факту запуска команды. Проверка та же, что уже названа в приёмке: непрерывность по дням и сходимость сумм с часовым слоем HAE на пересечении периодов. Не сошлось — пометки нет, и это не отказ импорта, а честный отказ от обещания;
- пометка ничего не удаляет. Она только даёт устареванию нижнего слоя основание; само удаление включается отдельно и позже.
stateOfMind пометку не получает никогда — его в экспорте Apple нет ни
одним типом (находка 42), источник у него единственный, и устаревание к нему
неприменимо. Это надо записать явно, а не оставить следовать из отсутствия
данных.
Готово, когда история за несколько лет лежит в слое sample, повторный импорт
не меняет ничего, суммы по слою сходятся с часовым слоем HAE на пересечении
периодов, а покрытые периоды помечены и видны без пересборки.
Архивы: /home/av/MediaEverything/HealthData/apple_health/ — девять штук,
2021-12 … 2026-08. Старые версии формата годятся как регрессионный набор.