Files
healthlog/openspec/changes/archive/2026-08-01-nerazobrannye-sekcii-dostavki/proposal.md
T
av d79189be18 docs: документация переведена на канон av-dev-pm
- беклог и план переехали в docs/tasks (38 задач, 11 целей), слаги
  переименованы с транслита на английские, 85 ссылок поправлены
- conventions.md разобран в docs/conventions/, local-research.md — в
  docs/research/, review-journal.md — в docs/review.md с разделом настройки
  конвейера; заведены security.md, adr/ и .pm.json
- шаг docs.py check добавлен в task gate; поведение в architecture.md помечено
  девятью маркерами долга, database.md получил настройки с числовым значением
2026-08-03 17:14:53 +03:00

4.7 KiB
Raw Blame History

Why

Разбор читает только data.metrics. Доставка, целиком состоящая из другой секции, получает parse_status=parsed с нулём точек — неотличимо от доставки с пустой секцией метрик. Измерено на живом архиве: из 99 доставок 48 не содержат metrics вовсе (24 workouts, 24 stateOfMind), то есть почти половина потока сейчас числится разобранной, не будучи разобранной.

Само по себе это некритично — тела лежат в архиве. Опасность в сцепке с ретеншеном: он по замыслу срезает архив до следующего проверенного экспорта, и если станет опираться на parse_status, снесёт тела, которые числятся разобранными. Для stateOfMind это необратимо — в экспорте Apple его нет (находка 46), доставки HAE единственный его источник. Ретеншен — следующая задача, поэтому признак нужен до неё.

What Changes

  • hae.Parse перечисляет верхнеуровневые ключи data и возвращает те, что разбор не покрыл. Перечисление идёт без чтения содержимого секций: тела доходят до 42 МиБ, и удержание кучи здесь — часть контракта.
  • Появляется статус доставки partial рядом с parsed/failed: тело разобрано в той части, которую разбор покрывает, и в нём остались непокрытые секции.
  • Свёртка сохраняет список непокрытых ключей в исход доставки и называет их именами ключей в своём единственном логирующем чекпоинте. Содержимого секций в логе нет и быть не может.
  • Число ключей и длина имени в записи ограничены: ключи приходят из тела, которым отправитель управляет целиком; усечение видно счётчиком и маркером.
  • Миграция переписывает parse_status у всех накопленных доставок: существующие parsed становятся pending — «этим разбором ещё не смотрели». Статус, поставленный кодом, который частичного разбора не различал, ничего не доказывает, а ретеншен собирается на него опираться. Цена: 99 строк живой базы меняют статус на первом старте нового бинаря, и до появления подбора pending (задача otvet-i-svyortka) никто их не пересвернёт; тела при этом остаются в архиве, объекты витрины — на месте, и Down прежние статусы не восстановит.

Capabilities

New Capabilities

Новых нет.

Modified Capabilities

  • parsing: разбор обязан перечислять непокрытые верхнеуровневые ключи data, не читая их содержимого, и отдавать их вызывающему.
  • storage: у доставки появляется статус partial и список непокрытых секций; учёт обязан отличать «разобрано целиком» от «разобрано частично».

Impact

  • internal/hae — перечисление ключей в том же проходе, что и разбор метрик.
  • internal/store — константа статуса, колонка uncovered_sections, миграция.
  • internal/fold — исход свёртки, статус и атрибут лога.
  • docs/database.md, docs/architecture.md, docs/local-research.md — схема, статусы и находка о наборах секций в живом потоке.
  • Ретеншен сырого архива (задача raw-archive-retention) получает признак, на который ему можно опираться.