## Why

HAE отдаёт перечислимые значения строками локали телефона («БДГ», «Сидячий
образ жизни», «В помещении Ходьба»), а родной экспорт Apple — кодами HealthKit
(`HKCategoryValueSleepAnalysisAsleepREM`). Источники несопоставимы (находка 37),
и на этой сверке стоит устаревание нижнего слоя. Плюс два молчащих отказа:
клиент вынужден угадывать словарь, а смена языка телефона расколет историю так,
что по координатному ключу это неотличимо от изменения данных.

Словарь фаз сна уже выведен сопоставлением потока с экспортом за тот же период
(находка 43) — составлять его руками не нужно, нужно завести механизм.

## What Changes

- Разбор извлекает **категориальные значения** объявленных полей HAE
  (`sleep_analysis.value`, `heart_rate.context`, `workouts.name`) и выводит для
  каждого стабильный код HealthKit по словарю `(локаль, строка) → код`. Локаль
  берётся из `Accept-Language` доставки (находка 32).
- Строка **не трогается**: она остаётся в точке дословно, код кладётся рядом —
  отдельной строкой реестра, а не полем внутри точки (обоснование — design.md).
  Ключ реестра — `(метрика, поле, значение)`; локаль сужает поиск по словарю, но
  в ключ не входит: её нет в сыром архиве, и ключ с ней сделал бы состояние
  функцией от того, уцелела ли строка учёта.
- Незнакомая строка даёт **пустой** код, а не догадку, и попадает в счётчик
  доставки и в реестр строкой с пустым кодом — это и есть список того, что пора
  добавить в словарь.
- Переименование кода самой Apple (`…Asleep` → `…AsleepUnspecified`, находка 43)
  не раскалывает историю: эквивалентность имён держит таблица синонимов, обе
  формы сходятся в один канонический код.
- Витрина получает таблицу `category_value` (миграция `00010`): наблюдённые
  категориальные значения с выведенным кодом и провенансом первой встречи. Её
  наблюдение входит в отпечаток витрины — как всякая единица хранения; **код в
  отпечаток не входит**: он функция не журнала, а версии словаря в бинаре.
- Отчёт `reindex` учится считать строки реестра и называть «появившуюся единицу
  хранения» ожидаемым классом расхождения — иначе первая сверка после выкатки
  безадресна, а по ней принимается необратимое решение о подмене базы.

## Capabilities

### New Capabilities
<!-- новых capability нет: поведение ложится в разбор и хранение -->

### Modified Capabilities
- `parsing`: разбор выделяет категориальные значения объявленных полей, выводит
  код по словарю и синонимам, считает неразобранные словарём строки; отсутствие
  или неизвестность локали не даёт догадки и не отменяет вывода кода, если
  строка однозначна.
- `storage`: реестр наблюдённых категориальных значений — единица хранения
  витрины: детерминированный по журналу upsert, участие наблюдения в отпечатке
  при исключении из него выведенного кода, происхождение словаря.
- `reindex`: счётчик строк реестра в отчёте и ожидаемый класс расхождения
  «появилась единица хранения».

## Impact

- `internal/healthkit` (новый пакет): словарь `(локаль, строка) → код` и таблица
  синонимов кодов. Знание о HealthKit, общее с будущим импортом родного
  экспорта Apple.
- `internal/hae`: `Meta.Locale`, извлечение категориальных значений из точек и
  сущностей, счётчики; `Point.Raw` и `Entity.Raw` не меняются.
- `internal/store`: миграция `00010`, таблица `category_value`, upsert внутри
  транзакции слияния, отпечаток.
- `internal/fold`: локаль из заголовков доставки, счётчик в логе свёртки.
- `docs/database.md` — описание таблицы (без него гейт красный),
  `docs/architecture.md` — раздел «Категориальные значения».
- Оракул `task verify:archive` обязателен: правило разбора меняется.
