добавлен словарь категориальных значений HAE → коды HealthKit
- фазы сна, контекст пульса и имена тренировок попадают в реестр `category_value` (миграция 00010): строка хранится дословно, выведенный код лежит рядом отдельной записью, а не полем внутри точки - словарь и синонимы кодов живут в бинаре (`internal/healthkit`); локаль из `Accept-Language` сужает поиск, но в ключ реестра не входит — заголовков в сыром архиве нет - наблюдение входит в отпечаток витрины, выведенный код — нет: он производная от словаря, а не от журнала
This commit is contained in:
+31
-7
@@ -1103,21 +1103,45 @@ HAE отдаёт перечислимые значения строками из
|
||||
Он объявлен источником истины, и на нём держится ретеншен нижнего слоя —
|
||||
но сверить покрытие по этим полям было бы нечем.
|
||||
|
||||
Поэтому строка **хранится дословно, а рядом кладётся выведенный код**:
|
||||
Поэтому строка **хранится дословно, а рядом кладётся выведенный код** —
|
||||
отдельной строкой реестра `category_value`, а не полем внутри точки:
|
||||
|
||||
```
|
||||
value "БДГ" ← как прислал HAE
|
||||
value_code "HKCategoryValueSleepAnalysisAsleepREM" ← выведено по словарю
|
||||
category_value sleep_analysis / value / "БДГ" → HKCategoryValueSleepAnalysisAsleepREM
|
||||
точка {"date": …, "value": "БДГ", …} ← не тронута
|
||||
```
|
||||
|
||||
Словарь ключуется парой `(локаль, строка)`; локаль берётся из
|
||||
`Accept-Language`, который мы уже сохраняем (находка 32). Для незнакомой
|
||||
строки код пустой — пустота честнее догадки, и она же видна в `/stats` как
|
||||
список того, что пора добавить в словарь.
|
||||
Рядом, а не внутри, по трём причинам: точка хранится исходными байтами и
|
||||
дописать в неё ключ можно только пересериализацией; параллельный массив кодов в
|
||||
`bucket` завёл бы производную величину в путь слияния и хеширования; пополнение
|
||||
словаря переписывало бы каждый объект с фазами сна. Обоснование целиком — в
|
||||
[журнале решений](adr/README.md).
|
||||
|
||||
Ключ реестра — `(метрика, поле, значение)`. Словарь при этом ключуется парой
|
||||
`(локаль, строка)`, локаль берётся из `Accept-Language` (находка 32) и **в ключ
|
||||
реестра не входит**: заголовков в сыром архиве нет, и ключ с локалью сделал бы
|
||||
состояние функцией от того, уцелела ли учётная строка. Локаль сужает поиск; её
|
||||
отсутствие вывода не отменяет, если строка однозначна по всем локалям.
|
||||
|
||||
Словарь и таблица синонимов кодов живут в бинаре (`internal/healthkit`), а не в
|
||||
базе: словарь, наполняемый руками, стал бы входом, которого нет в журнале, и
|
||||
`import + replay` перестал бы задавать состояние однозначно. Синонимы нужны
|
||||
потому, что коды тоже не вечны: Apple переименовала `…Asleep` в
|
||||
`…AsleepUnspecified` и переписывает историю при выгрузке (находка 43).
|
||||
|
||||
Для незнакомой строки код пустой — пустота честнее догадки, и перечень таких
|
||||
строк в реестре есть заявка на пополнение словаря. Счётчик неизвестных строк
|
||||
уходит в лог свёртки числом; сами строки — данные о здоровье и в лог не
|
||||
попадают.
|
||||
|
||||
Дословность инварианта не нарушена: код **приписывается**, а не подменяет
|
||||
строку. Обратное преобразование всегда возможно.
|
||||
|
||||
Реестр — единица хранения витрины и входит в отпечаток **наблюдением**, но не
|
||||
выведенным кодом: код производен от словаря в бинаре, а не от журнала, и в
|
||||
отпечатке он превратил бы всякое пополнение словаря в расхождение при совпавшем
|
||||
журнале.
|
||||
|
||||
### Тренировки и прочие секции
|
||||
|
||||
<!-- канон: поведение → openspec/specs/parsing -->
|
||||
|
||||
Reference in New Issue
Block a user