закрыта задача categorical-value-dictionary

This commit is contained in:
av
2026-08-04 07:32:19 +03:00
parent 1b649ba3d5
commit 8582d3540d
2 changed files with 0 additions and 68 deletions
-1
View File
@@ -5,5 +5,4 @@
Урожай спринта поднимается `tasks.py list --tag sprint:2026-08-03` — это первая порция переоценки на сессии. Урожай спринта поднимается `tasks.py list --tag sprint:2026-08-03` — это первая порция переоценки на сессии.
## Набор ## Набор
- [Словарь категориальных значений → коды HealthKit](items/categorical-value-dictionary.md) — Фазы сна и типы тренировок приходят строками русской локали — с экспортом Apple их не сверить
- [Активная проверка: поток принёс секцию, которой раньше не было](items/unseen-sections-check.md) — Момент появления новой секции фиксируется в базе, но заметить его может только тот, кто догадается заглянуть в колонку - [Активная проверка: поток принёс секцию, которой раньше не было](items/unseen-sections-check.md) — Момент появления новой секции фиксируется в базе, но заметить его может только тот, кто догадается заглянуть в колонку
@@ -1,67 +0,0 @@
# Словарь категориальных значений → коды HealthKit
- **Секция:** ядро
- **Зачем:** Фазы сна и типы тренировок приходят строками русской локали — с экспортом Apple их не сверить
- **Теги:** goal:parsing-and-storage
HAE отдаёт перечислимые значения строками локали телефона: «БДГ», «Сидячий
образ жизни», «В помещении Ходьба». Родной экспорт Apple при этом говорит
кодами (`HKCategoryValueSleepAnalysisAsleepREM`) — источники несопоставимы
(находка 37).
Три следствия, и третье решающее: клиент угадывает словарь; смена языка
телефона молча расколет историю; сверить покрытие экспортом нечем — а на этой
сверке стоит устаревание нижнего слоя.
Решение (вариант «б»): строка хранится **дословно**, рядом кладётся выведенный
код. Словарь ключуется парой `(локаль, строка)`, локаль берётся из
`Accept-Language`. Незнакомая строка → пустой код, а не догадка.
**Словарь фаз сна уже выведен** сопоставлением потока с экспортом за тот же
период (находка 43) — составлять руками не нужно:
```
Основная → AsleepCore Бодрствование → Awake БДГ → AsleepREM
Глубокий → AsleepDeep В кровати → InBed Во сне → AsleepUnspecified
```
Тем же способом добираются `heart_rate.context` и типы тренировок.
Осложнение, всплывшее на истории экспортов: **коды тоже не вечны.** Одни и те
же записи сна приезжают как `…Asleep` в экспорте 2021 года и как
`…AsleepUnspecified` в экспорте 2026-го: Apple переименовала значение и
переписывает историю при выгрузке (находка 43). Значит словарь должен
переживать переименование самих кодов, иначе после обновления iOS история
расколется вторично — уже на «стабильной» стороне. Простейшее решение: хранить код как есть, а
эквивалентность старых и новых имён держать отдельной таблицей синонимов.
`stateOfMind` в словаре не нуждается — он и так шлёт коды HealthKit.
## Критерии приёмки
- фаза сна из потока («БДГ») и из экспорта Apple
(`HKCategoryValueSleepAnalysisAsleepREM`) за один период сопоставляются
напрямую — оракул: запрос на живой базе за период с известным перекрытием,
ноль несопоставимых строк
- строка сохранена **дословно**, код лежит рядом отдельным полем — оракул: тест
разбора на реальном пакете HAE из `internal/hae/testdata`
- незнакомая строка даёт пустой код, разбор не падает, а событие попадает в
счётчик — оракул: тест на выдуманной фазе сна плюс проверка счётчика
- переименование кода самой Apple (`…Asleep``…AsleepUnspecified`, находка 43)
не раскалывает историю — оракул: тест на паре синонимов, обе формы сходятся
в один код
- повторный прогон живого архива даёт то же состояние — оракул:
`task verify:archive`
Критерий «`/stats` показывает строки без кода» снят при переоценке 2026-08-03:
`/stats` ещё нет ([stats-endpoint](stats-endpoint.md)), и вешать приёмку на
несуществующий оракул значит либо блокировать задачу, либо принять её
непроверенной. Наблюдаемость закрывается счётчиком; показ в `/stats` — строка
задачи наблюдаемости, а не этой.
## Рамки
Схема трогается: у категориального значения появляется поле кода, плюс таблица
синонимов. Дословную строку не заменяем и не нормализуем — инвариант «точки
хранятся дословно». Пересборка обязана оставаться детерминированной, оракул
тот же `task verify:archive`.