tasks: закрыт разбор и хранилище, начат спринт по чтению данных клиентами

- цель parsing-and-storage закрыта по своему критерию; незакрываемый остаток
  (новые формы от источника, ручные секции задним числом) переехал в тему
  parsing-completeness
- цель mcp поглощена целью read-api, переименованной в «Чтение данных
  клиентами»: адаптер — последний шаг того же направления, а не своё
- read-api-points разложена на конверт с точками, свёртку по сетке и
  тренировки с записями; спринт 2026-08-04 набран пятью задачами
This commit is contained in:
av
2026-08-04 14:01:38 +03:00
parent 637eb38bce
commit 79331ac670
17 changed files with 276 additions and 144 deletions
@@ -0,0 +1,46 @@
# Тренировки и записи наружу
- **Секция:** ядро
- **Зачем:** Тренировки с маршрутами и stateOfMind разобраны и лежат в витрине, а эндпоинтов нет — второй сценарий паспорта не закрыт
- **Теги:** goal:read-api
Трекер тренировок забирает тренировку одним пакетом вместе с маршрутом, а
записи `stateOfMind` достаются за период — без доступа к файлу базы.
Третья из трёх частей `read-api-points`. Разбор и хранение сущностей с
собственным `id` сделаны (change `2026-08-02-trenirovki-i-zapisi`), эндпоинтов
нет: данные лежат в витрине и наружу не отдаются. Второй сценарий паспорта до
тех пор не закрыт.
Маршруты: `GET /workouts`, `GET /workouts/{id}`, `GET /records/{kind}`.
**Конверт не изобретается заново** — наследуется от
[конверта ответа](read-api-envelope-and-points.md) вместе с формой провода и
условным запросом. Вводить эти маршруты раньше конверта значило бы задать
контракт мимоходом; именно поэтому они здесь, а не в задаче о разборе.
**Маршрут — первый по-настоящему тяжёлый ответ проекта.** Он лежит блобом внутри
тренировки, и правило размера ответа
([свёртка по сетке](read-api-bucketing.md)) обязано распространяться и на него —
иначе одна тренировка с длинным треком проходит мимо предела, названного для
точек. Разворачивание маршрута в отдельную таблицу остаётся идеей и этой задачей
не решается.
## Критерии приёмки
- тренировка отдаётся одним пакетом вместе с маршрутом — оракул: запрос к
поднятому сервису на живом архиве
- записи `stateOfMind` за период достаются `GET /records/{kind}` — оракул: тест
на пакетах `internal/hae/testdata`
- конверт, форма провода и условный запрос те же, что у точек, а не собственные
— оракул: тест, сравнивающий форму ответа обоих маршрутов
- тренировка с длинным маршрутом подчиняется тому же пределу размера ответа,
что и точки — оракул: тест на синтетическом треке за пределом
## Рамки
Схема не трогается, данные только читаются, сервис перезапускается. Берётся
после конверта ответа. Против `./data` — только `task up` / `task run`.
Связано: `docs/architecture.md` → «Read API»; идея
[разворачивания маршрутов в таблицу](workout-routes-table.md).