From 8582d3540df8e027a5b826669213f99eee0955cb Mon Sep 17 00:00:00 2001 From: Anton Vakhrushev Date: Mon, 3 Aug 2026 21:24:09 +0300 Subject: [PATCH] =?UTF-8?q?=D0=B7=D0=B0=D0=BA=D1=80=D1=8B=D1=82=D0=B0=20?= =?UTF-8?q?=D0=B7=D0=B0=D0=B4=D0=B0=D1=87=D0=B0=20categorical-value-dictio?= =?UTF-8?q?nary?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/tasks/SPRINT.md | 1 - .../items/categorical-value-dictionary.md | 67 ------------------- 2 files changed, 68 deletions(-) delete mode 100644 docs/tasks/items/categorical-value-dictionary.md diff --git a/docs/tasks/SPRINT.md b/docs/tasks/SPRINT.md index 09c6a10..5826844 100644 --- a/docs/tasks/SPRINT.md +++ b/docs/tasks/SPRINT.md @@ -5,5 +5,4 @@ Урожай спринта поднимается `tasks.py list --tag sprint:2026-08-03` — это первая порция переоценки на сессии. ## Набор -- [Словарь категориальных значений → коды HealthKit](items/categorical-value-dictionary.md) — Фазы сна и типы тренировок приходят строками русской локали — с экспортом Apple их не сверить - [Активная проверка: поток принёс секцию, которой раньше не было](items/unseen-sections-check.md) — Момент появления новой секции фиксируется в базе, но заметить его может только тот, кто догадается заглянуть в колонку diff --git a/docs/tasks/items/categorical-value-dictionary.md b/docs/tasks/items/categorical-value-dictionary.md deleted file mode 100644 index 32577a7..0000000 --- a/docs/tasks/items/categorical-value-dictionary.md +++ /dev/null @@ -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`.