docs: документация приведена к канону av-dev-pm 4
- каждая запись каталога задач получила тип вместо тега kind: и префикса заголовка; секция роадмапа «Разработка» стала «Сопровождением», порядок секций канонический - поправлены протухшие факты: нереализованные маршруты Read API, MCP и `healthlog import`, словарь слоёв в инварианте, семантика гейта по покрытию диффа, периметр перестал дублировать security.md - замер слияния переведён с находки 49 на находку 54, заполнены Purpose спек storage и parsing
This commit is contained in:
+37
-37
@@ -11,43 +11,43 @@
|
||||
|
||||
## Ядро
|
||||
|
||||
- [[idea] Человеческие аннотации поверх выведенных схем](items/schema-annotations.md) — Выведенная схема говорит форму, но не смысл метрики — нужно ли описание сверху, зависит от стабильности формата
|
||||
- [Проверять целостность собранной витрины до подмены](items/integrity-before-swap.md) — Подмена файла необратима, а годность выхода подтверждена отпечатком на ещё открытом дескрипторе
|
||||
- [Снизить цену слияния на широкой доставке](items/merge-cost-wide-delivery.md) — 63 МБ на одной координате держат транзакцию 5.15 с при busy_timeout 5 с — соседние доставки уходят в failed
|
||||
- [Не терять сущность с id и неразобранной меткой](items/entity-without-parsed-label.md) — Тренировка с меткой в неизвестном формате пропадает целиком, а после включения ретеншена окно становится необратимым
|
||||
- [Не задваивать тренировки при импорте родного экспорта](items/workout-identity-on-import.md) — В export.xml у тренировки нет id — импорт снапшота задвоит тренировки, приехавшие от HAE
|
||||
- [Импортировать родной экспорт Apple Health](items/apple-export-import.md) — Слой sample пуст: полная история и точные сэмплы лежат в zip-архиве и никуда не едут
|
||||
- [[idea] Месячный проход по ручным секциям](items/monthly-manual-sections-pass.md) — Симптомы и лекарства заводятся задним числом на недели — недельного глубокого прохода им не хватит
|
||||
- [[idea] NDJSON-поток для больших выборок Read API](items/ndjson-stream.md) — Выборка нижнего слоя за месяц не влезает в один JSON-ответ — либо поток, либо пагинация
|
||||
- [Не отбирать строки в data-миграциях по обрезаемым спискам](items/data-migration-row-selection.md) — Миграция 00007 отбирает по uncovered_sections, который обрезается на 32 — следующая покрытая секция унаследует слепую зону
|
||||
- [[idea] Отказ от heartbeatSeries](items/drop-heartbeat-series.md) — 93% объёма HRV ради данных, которых нет ни в одном планируемом запросе
|
||||
- [Не держать весь журнал в памяти при пересборке](items/rebuild-memory-footprint.md) — Учёт доставок и список путей архива материализуются целиком: расход растёт вместе с журналом, а у журнала конца нет
|
||||
- [[idea] Пересекающиеся источники одной метрики](items/overlapping-sources.md) — Сон пишут и часы, и стороннее приложение — сумма по обоим задвоит ночь
|
||||
- [[idea] Порог sealed: с какого возраста час считается запечатанным](items/sealed-threshold.md) — WARN на изменение старого часа уже пишется, но порог не выбран — ставим по факту, когда накопится статистика досчёта
|
||||
- [Держать порядок журнала при конкурентных приёмах](items/journal-order-on-ingest.md) — Доставка, свёрнутая раньше своей предшественницы, уходит в failed навсегда, и живая витрина молча расходится с пересборкой
|
||||
- [Ограничить размер и число заголовков доставки](items/delivery-header-limits.md) — MaxHeaderBytes не задан, в базу заголовки пишутся целиком: дефект спит до деплоя, а просыпается вместе с ним
|
||||
- [Ограничить размер сущности и считать форму потоково](items/entity-size-limits.md) — Тело 40 МиБ даёт 768 МиБ пика кучи, 63 МиБ держат блокировку 5.019 с — предела на одну сущность нет вовсе
|
||||
- [[idea] Разворачивание маршрутов тренировок в отдельную таблицу](items/workout-routes-table.md) — Маршрут лежит блобом внутри тренировки — понадобится, только если появится клиент, которому мало отдачи одним пакетом
|
||||
- [Выводить схемы содержимого из данных](items/derived-content-schemas.md) — Метрик больше сотни и формы точек разные — клиент вынужден угадывать структуру по выборке
|
||||
- [[idea] Что считать сутками при смене часового пояса](items/day-boundary-timezone.md) — Шаги за день — базовый запрос трекера и игры, но чей это день при перелёте, не решено
|
||||
- [Сверять живую витрину с пересборкой](items/rebuild-comparison-check.md) — reindex печатает оба отпечатка, но сравнивать их некому — расхождение с журналом молчит
|
||||
- [Помечать нижний слой устаревшим после экспорта](items/lower-layer-expiry.md) — Нижний слой растёт на ~100 тысяч координат в сутки, а после экспорта Apple он избыточен
|
||||
- [[idea] Выгрузка в parquet отдельной командой](items/parquet-export.md) — Дверь для тяжёлой аналитики снаружи: DuckDB читает и parquet, и файл SQLite — спешить некуда, но и закрывать не нужно
|
||||
- [Класть заголовки доставки в архив рядом с телом](items/delivery-headers-in-archive.md) — Заголовки живут только в базе — потеря базы навсегда ломает вывод слоя при пересборке
|
||||
- [Измерить, нужно ли правило полноты рядом с LWW](items/last-wins-over-completeness.md) — Полнота решает 1,2% спорных координат, и неизвестно, была ли более полная точка более поздней — от этого зависит, нужна ли она вообще
|
||||
- [Поднять MCP-сервер поверх Read API](items/mcp-server.md) — Агент-медик — первый заказчик проекта, а подключить его сейчас нечем
|
||||
- [Написать OpenAPI-спеку руками](items/openapi-spec.md) — Потребителей три и один из них агент — контракт должен читаться машиной, а не пересказываться в чате
|
||||
- [Ловить гейтом расхождение спеки с маршрутами](items/openapi-gate-check.md) — Рукописная спека — источник истины, а расходится она с кодом молча: без гейта решение о рукописной спеке не держится
|
||||
- [Поднять Swagger UI без внешней сети](items/swagger-ui.md) — Контракт читается машиной, но человеку нечем выполнить запрос к живому сервису из браузера, а внешних CDN в локальной сети нет
|
||||
- [✨ Проверять целостность собранной витрины до подмены](items/integrity-before-swap.md) — Подмена файла необратима, а годность выхода подтверждена отпечатком на ещё открытом дескрипторе
|
||||
- [🐞 Снизить цену слияния на широкой доставке](items/merge-cost-wide-delivery.md) — 63 МБ на одной координате держат транзакцию 5.15 с при busy_timeout 5 с — соседние доставки уходят в failed
|
||||
- [🐞 Не терять сущность с id и неразобранной меткой](items/entity-without-parsed-label.md) — Тренировка с меткой в неизвестном формате пропадает целиком, а после включения ретеншена окно становится необратимым
|
||||
- [✨ Не задваивать тренировки при импорте родного экспорта](items/workout-identity-on-import.md) — В export.xml у тренировки нет id — импорт снапшота задвоит тренировки, приехавшие от HAE
|
||||
- [✨ Импортировать родной экспорт Apple Health](items/apple-export-import.md) — Слой sample пуст: полная история и точные сэмплы лежат в zip-архиве и никуда не едут
|
||||
- [🐞 Не отбирать строки в data-миграциях по обрезаемым спискам](items/data-migration-row-selection.md) — Миграция 00007 отбирает по uncovered_sections, который обрезается на 32 — следующая покрытая секция унаследует слепую зону
|
||||
- [🧹 Не держать весь журнал в памяти при пересборке](items/rebuild-memory-footprint.md) — Учёт доставок и список путей архива материализуются целиком: расход растёт вместе с журналом, а у журнала конца нет
|
||||
- [🐞 Держать порядок журнала при конкурентных приёмах](items/journal-order-on-ingest.md) — Доставка, свёрнутая раньше своей предшественницы, уходит в failed навсегда, и живая витрина молча расходится с пересборкой
|
||||
- [✨ Ограничить размер и число заголовков доставки](items/delivery-header-limits.md) — MaxHeaderBytes не задан, в базу заголовки пишутся целиком: дефект спит до деплоя, а просыпается вместе с ним
|
||||
- [✨ Ограничить размер сущности и считать форму потоково](items/entity-size-limits.md) — Тело 40 МиБ даёт 768 МиБ пика кучи, 63 МиБ держат блокировку 5.019 с — предела на одну сущность нет вовсе
|
||||
- [✨ Выводить схемы содержимого из данных](items/derived-content-schemas.md) — Метрик больше сотни и формы точек разные — клиент вынужден угадывать структуру по выборке
|
||||
- [✨ Сверять живую витрину с пересборкой](items/rebuild-comparison-check.md) — reindex печатает оба отпечатка, но сравнивать их некому — расхождение с журналом молчит
|
||||
- [✨ Помечать нижний слой устаревшим после экспорта](items/lower-layer-expiry.md) — Нижний слой растёт на ~100 тысяч координат в сутки, а после экспорта Apple он избыточен
|
||||
- [🐞 Класть заголовки доставки в архив рядом с телом](items/delivery-headers-in-archive.md) — Заголовки живут только в базе — потеря базы навсегда ломает вывод слоя при пересборке
|
||||
- [✨ Поднять MCP-сервер поверх Read API](items/mcp-server.md) — Агент-медик — первый заказчик проекта, а подключить его сейчас нечем
|
||||
- [✨ Написать OpenAPI-спеку руками](items/openapi-spec.md) — Потребителей три и один из них агент — контракт должен читаться машиной, а не пересказываться в чате
|
||||
- [🧹 Ловить гейтом расхождение спеки с маршрутами](items/openapi-gate-check.md) — Рукописная спека — источник истины, а расходится она с кодом молча: без гейта решение о рукописной спеке не держится
|
||||
- [✨ Поднять Swagger UI без внешней сети](items/swagger-ui.md) — Контракт читается машиной, но человеку нечем выполнить запрос к живому сервису из браузера, а внешних CDN в локальной сети нет
|
||||
- [🔬 Измерить, нужно ли правило полноты рядом с LWW](items/last-wins-over-completeness.md) — Полнота решает 1,2% спорных координат, и неизвестно, была ли более полная точка более поздней — от этого зависит, нужна ли она вообще
|
||||
- [🔬 Человеческие аннотации поверх выведенных схем](items/schema-annotations.md) — Выведенная схема говорит форму, но не смысл метрики — нужно ли описание сверху, зависит от стабильности формата
|
||||
- [🔬 Месячный проход по ручным секциям](items/monthly-manual-sections-pass.md) — Симптомы и лекарства заводятся задним числом на недели — недельного глубокого прохода им не хватит
|
||||
- [🔬 NDJSON-поток для больших выборок Read API](items/ndjson-stream.md) — Выборка нижнего слоя за месяц не влезает в один JSON-ответ — либо поток, либо пагинация
|
||||
- [🔬 Отказ от heartbeatSeries](items/drop-heartbeat-series.md) — 93% объёма HRV ради данных, которых нет ни в одном планируемом запросе
|
||||
- [🔬 Пересекающиеся источники одной метрики](items/overlapping-sources.md) — Сон пишут и часы, и стороннее приложение — сумма по обоим задвоит ночь
|
||||
- [🔬 Порог sealed: с какого возраста час считается запечатанным](items/sealed-threshold.md) — WARN на изменение старого часа уже пишется, но порог не выбран — ставим по факту, когда накопится статистика досчёта
|
||||
- [🔬 Разворачивание маршрутов тренировок в отдельную таблицу](items/workout-routes-table.md) — Маршрут лежит блобом внутри тренировки — понадобится, только если появится клиент, которому мало отдачи одним пакетом
|
||||
- [🔬 Что считать сутками при смене часового пояса](items/day-boundary-timezone.md) — Шаги за день — базовый запрос трекера и игры, но чей это день при перелёте, не решено
|
||||
- [🔬 Выгрузка в parquet отдельной командой](items/parquet-export.md) — Дверь для тяжёлой аналитики снаружи: DuckDB читает и parquet, и файл SQLite — спешить некуда, но и закрывать не нужно
|
||||
|
||||
## Инфра
|
||||
|
||||
- [Слать уведомление, когда данных нет N часов](items/stream-silence-alert.md) — Пропажу потока сейчас замечает человек, а не сервис
|
||||
- [Выложить сервис на rivendell](items/deploy-rivendell.md) — Сервис живёт на рабочей машине — телефон достаёт до него только дома
|
||||
- [Хранить счётчики слияния вне логов](items/merge-counters-in-db.md) — Единственный след несравнимых наборов — строка WARN в docker-логе с ротацией 3×10 МБ: событие может произойти и не оставить ничего
|
||||
- [Развести бюджеты остановки и оставить следы миграции в логе](items/shutdown-and-migration-traces.md) — Долгий запрос чтения съедает бюджет остановки, и WARN обвиняет воркер свёртки; миграция молчит и не прерывается SIGTERM
|
||||
- [Назвать механизм отката релиза после наката миграции](items/release-rollback-after-migration.md) — Страж версии схемы делает возврат старого бинаря отказом, а понизить схему нечем — аварийный путь пришлось бы изобретать в аварии
|
||||
- [Подчищать сырой архив до последнего проверенного экспорта](items/raw-archive-retention.md) — Архив не подчищается вовсе, а резать его раньше даты проверенного экспорта нельзя — в журнале останется дыра, которую нечем пересобрать
|
||||
- [Отдавать состояние сервиса маршрутом /stats](items/stats-endpoint.md) — Тихо сломавшаяся автоматизация — главный эксплуатационный риск, а сейчас факт виден только в логах
|
||||
- [Свести умолчания конфига с рабочей раскладкой данных](items/config-defaults-data-dir.md) — Запуск без конфига заведёт пустую базу в корне рядом с настоящей — тихая ловушка
|
||||
- [Развести токены контуров и убрать секреты из репозитория](items/token-and-secret-management.md) — Проверка токенов выключена, config.docker.toml коммитится — так нельзя выезжать наружу
|
||||
- [✨ Слать уведомление, когда данных нет N часов](items/stream-silence-alert.md) — Пропажу потока сейчас замечает человек, а не сервис
|
||||
- [✨ Выложить сервис на rivendell](items/deploy-rivendell.md) — Сервис живёт на рабочей машине — телефон достаёт до него только дома
|
||||
- [✨ Хранить счётчики слияния вне логов](items/merge-counters-in-db.md) — Единственный след несравнимых наборов — строка WARN в docker-логе с ротацией 3×10 МБ: событие может произойти и не оставить ничего
|
||||
- [🐞 Развести бюджеты остановки и оставить следы миграции в логе](items/shutdown-and-migration-traces.md) — Долгий запрос чтения съедает бюджет остановки, и WARN обвиняет воркер свёртки; миграция молчит и не прерывается SIGTERM
|
||||
- [✨ Назвать механизм отката релиза после наката миграции](items/release-rollback-after-migration.md) — Страж версии схемы делает возврат старого бинаря отказом, а понизить схему нечем — аварийный путь пришлось бы изобретать в аварии
|
||||
- [✨ Подчищать сырой архив до последнего проверенного экспорта](items/raw-archive-retention.md) — Архив не подчищается вовсе, а резать его раньше даты проверенного экспорта нельзя — в журнале останется дыра, которую нечем пересобрать
|
||||
- [✨ Отдавать состояние сервиса маршрутом /stats](items/stats-endpoint.md) — Тихо сломавшаяся автоматизация — главный эксплуатационный риск, а сейчас факт виден только в логах
|
||||
- [🐞 Свести умолчания конфига с рабочей раскладкой данных](items/config-defaults-data-dir.md) — Запуск без конфига заведёт пустую базу в корне рядом с настоящей — тихая ловушка
|
||||
- [✨ Развести токены контуров и убрать секреты из репозитория](items/token-and-secret-management.md) — Проверка токенов выключена, config.docker.toml коммитится — так нельзя выезжать наружу
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
- 2026-08-01 `bekap-dannyh` — Резервное копирование ./data. Причина: бекап обеспечивает готовый механизм на сервере пет-проектов — своего заводить не нужно, задача снимается деплоем. Была секция: высокий.
|
||||
- 2026-08-01 `identichnost-epizodnyh-metrik` — Идентичность эпизодных метрик. Причина: решён измерением и prior art: ключ эпизода — метрика+слой+start+end (находка 47), вариант А; вернулся в scope razbor-metrik-v-obekty. Была секция: блокеры.
|
||||
- 2026-08-01 `edinicy-metriki-v-razreze` — Единицы метрики: часть координаты или свойство объекта. Причина: измерено: на 99 доставках единицы не менялись ни у одной из 30 метрик (находка 49 → 48); реализованное правило «сохранённое побеждает + WARN + счётчик» делает событие наблюдаемым. Была секция: блокеры.
|
||||
- 2026-08-04 `mcp` — [goal] MCP. Причина: поглощена целью read-api («Чтение данных клиентами»): MCP — не направление, а последний шаг того же направления; адаптер переводит вызовы в те же обработчики и собственной логики не несёт. Очередь «Read API перед MCP» стала порядком задач внутри цели. Задача mcp-server жива и перевешена на read-api. Была секция: порядок.
|
||||
- 2026-08-04 `mcp` — 🎯 MCP. Причина: поглощена целью read-api («Чтение данных клиентами»): MCP — не направление, а последний шаг того же направления; адаптер переводит вызовы в те же обработчики и собственной логики не несёт. Очередь «Read API перед MCP» стала порядком задач внутри цели. Задача mcp-server жива и перевешена на read-api. Была секция: порядок.
|
||||
- 2026-08-04 `read-api-points` — Read API: точки, выбор слоя, свёртка по сетке. Причина: разложена на read-api-envelope-and-points (конверт, точки за период, форма провода, условный запрос), read-api-bucketing (свёртка по сетке, предел размера ответа, порог неполного ведра) и read-api-workouts-and-records (тренировки и записи наружу). Одним заходом не мерджилась: десяток критериев приёмки и три развилки в одном файле. Была секция: ядро.
|
||||
- 2026-08-04 `read-api-envelope-and-points` — Конверт ответа и точки за период. Причина: разложена на read-api-wire-format (форма провода, мерджится первой и трогает только живой каталог), read-api-points-period (точки за период с конвертом) и read-api-points-conditional (условный запрос со scope-etag). Была секция: ядро.
|
||||
- 2026-08-04 `read-api-bucketing` — Свёртка по сетке и предел размера ответа. Причина: разложена на read-api-points-bucket (свёртка по сетке), read-api-partial-bucket (порог неполного ведра и его полярность) и read-api-response-limit (предел размера ответа, общий для всех маршрутов чтения). Была секция: ядро.
|
||||
|
||||
+30
-27
@@ -1,9 +1,37 @@
|
||||
# Роадмап
|
||||
|
||||
Что приложение уже умеет и чего ещё не умеет. Цель — возможность приложения,
|
||||
файл `[goal]` в `items/`; её задачи здесь **не перечисляются** — перечень даёт
|
||||
файл типа `goal` в `items/`; её задачи здесь **не перечисляются** — перечень даёт
|
||||
`tasks.py list --goal <слаг>`. Очередь значима только в «Запланировано» и
|
||||
обосновывается прозой рядом.
|
||||
обосновывается прозой рядом. В «Сопровождении» лежит то, чем держат проект —
|
||||
выкладка, инструмент, эксплуатация; граница проходит по тому, кто наблюдает:
|
||||
сообщает ли о состоянии приложение своему пользователю или дежурный смотрит на
|
||||
сервис снаружи.
|
||||
|
||||
## Запланировано
|
||||
|
||||
Очередь держится на двух зависимостях. **`healthlog import` идёт перед чисткой
|
||||
нижнего слоя:** пока импорт экспорта не написан, помечать что-либо устаревшим не
|
||||
на основании чего. **MCP входит в чтение, а не идёт отдельной целью:** адаптер
|
||||
собственной логики не несёт, он переводит вызовы в те же обработчики, и очередь
|
||||
осталась порядком задач внутри цели.
|
||||
|
||||
- [🎯 Клиенты читают данные через HTTP и MCP](items/read-api.md) — Данные видны только через sqlite на хосте — ни один из трёх потребителей, включая агента-медика, ничего прочитать не может
|
||||
- [🎯 Клиент узнаёт форму данных из ответа](items/self-description.md) — Метрик больше сотни и формы точек разные — клиент вынужден угадывать структуру по выборке
|
||||
- [🎯 История из родного экспорта Apple лежит в хранилище](items/native-export-import.md) — Слой sample пуст: полная история и точные сэмплы лежат в zip-архиве и никуда не едут
|
||||
- [🎯 Нижний слой чистится после проверенного экспорта](items/lower-layer-cleanup.md) — Нижний слой растёт на ~100 тысяч координат в сутки, а после экспорта Apple он избыточен
|
||||
- [🎯 Приложение сообщает о своём состоянии](items/observability.md) — Тихо сломавшаяся автоматизация — главный эксплуатационный риск, а сейчас факт виден только в логах
|
||||
|
||||
## Направления
|
||||
|
||||
- [🎯 Исход слияния не зависит от порядка элементов на проводе](items/merge-robustness.md) — Правила слияния держатся на замерах, и каждый новый замер находит зависимость от порядка на проводе
|
||||
- [🎯 Расхождение витрины с журналом не молчит](items/journal-and-rebuild.md) — Расхождение витрины с журналом сейчас молчит: reindex печатает оба отпечатка, а сравнивать их некому
|
||||
- [🎯 У каждого входа есть названный предел](items/limits-and-load.md) — Предела на одну сущность нет вовсе: 63 МиБ держат блокировку 5.019 с, соседние доставки уходят в failed
|
||||
- [🎯 Новая форма от источника не теряется молча](items/parsing-completeness.md) — Пять секций HAE поток ещё не приносил, а ручные секции заводятся задним числом — разбор полон ровно до следующей новой формы
|
||||
|
||||
## Сопровождение
|
||||
|
||||
- [🎯 Сервис доступен телефону из любой сети](items/deploy.md) — Сервис живёт на рабочей машине — телефон достаёт до него только дома, и оба контура открыты
|
||||
|
||||
## Готово
|
||||
|
||||
@@ -24,28 +52,3 @@
|
||||
[research/apple-health.md](../research/apple-health.md): правило вывода слоя,
|
||||
модель идентичности и формы точки проверены на живом потоке. Возможностью
|
||||
приложения она не была, поэтому строки среди достигнутых целей не занимает.
|
||||
|
||||
## Запланировано
|
||||
|
||||
Очередь держится на двух зависимостях. **`healthlog import` идёт перед чисткой
|
||||
нижнего слоя:** пока импорт экспорта не написан, помечать что-либо устаревшим не
|
||||
на основании чего. **MCP входит в чтение, а не идёт отдельной целью:** адаптер
|
||||
собственной логики не несёт, он переводит вызовы в те же обработчики, и очередь
|
||||
осталась порядком задач внутри цели.
|
||||
|
||||
- [[goal] Клиенты читают данные через HTTP и MCP](items/read-api.md) — Данные видны только через sqlite на хосте — ни один из трёх потребителей, включая агента-медика, ничего прочитать не может
|
||||
- [[goal] Клиент узнаёт форму данных из ответа](items/self-description.md) — Метрик больше сотни и формы точек разные — клиент вынужден угадывать структуру по выборке
|
||||
- [[goal] История из родного экспорта Apple лежит в хранилище](items/native-export-import.md) — Слой sample пуст: полная история и точные сэмплы лежат в zip-архиве и никуда не едут
|
||||
- [[goal] Нижний слой чистится после проверенного экспорта](items/lower-layer-cleanup.md) — Нижний слой растёт на ~100 тысяч координат в сутки, а после экспорта Apple он избыточен
|
||||
- [[goal] Приложение сообщает о своём состоянии](items/observability.md) — Тихо сломавшаяся автоматизация — главный эксплуатационный риск, а сейчас факт виден только в логах
|
||||
|
||||
## Направления
|
||||
|
||||
- [[goal] Исход слияния не зависит от порядка элементов на проводе](items/merge-robustness.md) — Правила слияния держатся на замерах, и каждый новый замер находит зависимость от порядка на проводе
|
||||
- [[goal] Расхождение витрины с журналом не молчит](items/journal-and-rebuild.md) — Расхождение витрины с журналом сейчас молчит: reindex печатает оба отпечатка, а сравнивать их некому
|
||||
- [[goal] У каждого входа есть названный предел](items/limits-and-load.md) — Предела на одну сущность нет вовсе: 63 МиБ держат блокировку 5.019 с, соседние доставки уходят в failed
|
||||
- [[goal] Новая форма от источника не теряется молча](items/parsing-completeness.md) — Пять секций HAE поток ещё не приносил, а ручные секции заводятся задним числом — разбор полон ровно до следующей новой формы
|
||||
|
||||
## Разработка
|
||||
|
||||
- [[goal] Сервис доступен телефону из любой сети](items/deploy.md) — Сервис живёт на рабочей машине — телефон достаёт до него только дома, и оба контура открыты
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Спринт
|
||||
|
||||
- **Цель:** [[goal] Клиенты читают данные через HTTP и MCP](items/read-api.md)
|
||||
- **Цель:** [🎯 Клиенты читают данные через HTTP и MCP](items/read-api.md)
|
||||
- **Начат:** 2026-08-04
|
||||
- **Спринт:** `2026-08-04`
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
|
||||
## Набор
|
||||
|
||||
- [Отвечать 304 на повторный запрос точек](items/read-api-points-conditional.md) — Агент опрашивает по расписанию, а каждый повтор стоит полного чтения: на каталоге это 693 мс и +153 МиБ
|
||||
- [Сворачивать точки по заданной сетке](items/read-api-points-bucket.md) — «Шаги за неделю по дням» — базовый запрос трекера и игры, и сегодня его нечем задать
|
||||
- [Отличать неполное ведро от полного](items/read-api-partial-bucket.md) — Текущий час неполон всегда, и без порога свёртка отдаёт его наравне с полными — клиент видит провал вместо неизвестности
|
||||
- [Ограничить размер ответа маршрутов чтения](items/read-api-response-limit.md) — У маршрутов чтения нет ни одного потолка: множители «метрики × окно × точки × одновременные запросы» ничем не ограничены
|
||||
- [Отдавать тренировки вместе с маршрутом](items/read-api-workouts.md) — Тренировки с маршрутами разобраны и лежат в витрине, а маршрутов чтения нет — сценарий трекера не закрыт
|
||||
- [Отдавать записи со своим id за период](items/read-api-records.md) — stateOfMind разобран и хранится, но наружу не отдаётся — а восстановить его нечем: в экспорте Apple его нет
|
||||
- [✨ Отвечать 304 на повторный запрос точек](items/read-api-points-conditional.md) — Агент опрашивает по расписанию, а каждый повтор стоит полного чтения: на каталоге это 693 мс и +153 МиБ
|
||||
- [✨ Сворачивать точки по заданной сетке](items/read-api-points-bucket.md) — «Шаги за неделю по дням» — базовый запрос трекера и игры, и сегодня его нечем задать
|
||||
- [✨ Отличать неполное ведро от полного](items/read-api-partial-bucket.md) — Текущий час неполон всегда, и без порога свёртка отдаёт его наравне с полными — клиент видит провал вместо неизвестности
|
||||
- [✨ Ограничить размер ответа маршрутов чтения](items/read-api-response-limit.md) — У маршрутов чтения нет ни одного потолка: множители «метрики × окно × точки × одновременные запросы» ничем не ограничены
|
||||
- [✨ Отдавать тренировки вместе с маршрутом](items/read-api-workouts.md) — Тренировки с маршрутами разобраны и лежат в витрине, а маршрутов чтения нет — сценарий трекера не закрыт
|
||||
- [✨ Отдавать записи со своим id за период](items/read-api-records.md) — stateOfMind разобран и хранится, но наружу не отдаётся — а восстановить его нечем: в экспорте Apple его нет
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Импортировать родной экспорт Apple Health
|
||||
# ✨ Импортировать родной экспорт Apple Health
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** feature
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** Слой sample пуст: полная история и точные сэмплы лежат в zip-архиве и никуда не едут
|
||||
- **Теги:** goal:native-export-import
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Свести умолчания конфига с рабочей раскладкой данных
|
||||
# 🐞 Свести умолчания конфига с рабочей раскладкой данных
|
||||
|
||||
- **Секция:** Инфра
|
||||
- **Тип:** fix
|
||||
- **Категория:** Инфра
|
||||
- **Зачем:** Запуск без конфига заведёт пустую базу в корне рядом с настоящей — тихая ловушка
|
||||
- **Теги:** goal:deploy
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Не отбирать строки в data-миграциях по обрезаемым спискам
|
||||
# 🐞 Не отбирать строки в data-миграциях по обрезаемым спискам
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** fix
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** Миграция 00007 отбирает по uncovered_sections, который обрезается на 32 — следующая покрытая секция унаследует слепую зону
|
||||
- **Теги:** goal:journal-and-rebuild
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# [idea] Что считать сутками при смене часового пояса
|
||||
# 🔬 Что считать сутками при смене часового пояса
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** research
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** Шаги за день — базовый запрос трекера и игры, но чей это день при перелёте, не решено
|
||||
- **Теги:** goal:read-api
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Ограничить размер и число заголовков доставки
|
||||
# ✨ Ограничить размер и число заголовков доставки
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** feature
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** MaxHeaderBytes не задан, в базу заголовки пишутся целиком: дефект спит до деплоя, а просыпается вместе с ним
|
||||
- **Теги:** goal:limits-and-load
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Класть заголовки доставки в архив рядом с телом
|
||||
# 🐞 Класть заголовки доставки в архив рядом с телом
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** fix
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** Заголовки живут только в базе — потеря базы навсегда ломает вывод слоя при пересборке
|
||||
- **Теги:** goal:journal-and-rebuild
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Выложить сервис на rivendell
|
||||
# ✨ Выложить сервис на rivendell
|
||||
|
||||
- **Секция:** Инфра
|
||||
- **Тип:** feature
|
||||
- **Категория:** Инфра
|
||||
- **Зачем:** Сервис живёт на рабочей машине — телефон достаёт до него только дома
|
||||
- **Теги:** goal:deploy
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# [goal] Сервис доступен телефону из любой сети
|
||||
# 🎯 Сервис доступен телефону из любой сети
|
||||
|
||||
- **Секция:** Разработка
|
||||
- **Тип:** goal
|
||||
- **Секция:** Сопровождение
|
||||
- **Зачем:** Сервис живёт на рабочей машине — телефон достаёт до него только дома, и оба контура открыты
|
||||
- **Теги:** decomposed
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Выводить схемы содержимого из данных
|
||||
# ✨ Выводить схемы содержимого из данных
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** feature
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** Метрик больше сотни и формы точек разные — клиент вынужден угадывать структуру по выборке
|
||||
- **Теги:** goal:self-description
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# [idea] Отказ от heartbeatSeries
|
||||
# 🔬 Отказ от heartbeatSeries
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** research
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** 93% объёма HRV ради данных, которых нет ни в одном планируемом запросе
|
||||
- **Теги:** goal:lower-layer-cleanup
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Ограничить размер сущности и считать форму потоково
|
||||
# ✨ Ограничить размер сущности и считать форму потоково
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** feature
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** Тело 40 МиБ даёт 768 МиБ пика кучи, 63 МиБ держат блокировку 5.019 с — предела на одну сущность нет вовсе
|
||||
- **Теги:** goal:limits-and-load
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Не терять сущность с id и неразобранной меткой
|
||||
# 🐞 Не терять сущность с id и неразобранной меткой
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** fix
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** Тренировка с меткой в неизвестном формате пропадает целиком, а после включения ретеншена окно становится необратимым
|
||||
- **Теги:** goal:parsing-completeness
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Проверять целостность собранной витрины до подмены
|
||||
# ✨ Проверять целостность собранной витрины до подмены
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** feature
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** Подмена файла необратима, а годность выхода подтверждена отпечатком на ещё открытом дескрипторе
|
||||
- **Теги:** goal:journal-and-rebuild
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# [goal] Расхождение витрины с журналом не молчит
|
||||
# 🎯 Расхождение витрины с журналом не молчит
|
||||
|
||||
- **Тип:** goal
|
||||
- **Секция:** Направления
|
||||
- **Зачем:** Расхождение витрины с журналом сейчас молчит: reindex печатает оба отпечатка, а сравнивать их некому
|
||||
- **Теги:** decomposed
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Держать порядок журнала при конкурентных приёмах
|
||||
# 🐞 Держать порядок журнала при конкурентных приёмах
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** fix
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** Доставка, свёрнутая раньше своей предшественницы, уходит в failed навсегда, и живая витрина молча расходится с пересборкой
|
||||
- **Теги:** goal:journal-and-rebuild, question
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Измерить, нужно ли правило полноты рядом с LWW
|
||||
# 🔬 Измерить, нужно ли правило полноты рядом с LWW
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** research
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** Полнота решает 1,2% спорных координат, и неизвестно, была ли более полная точка более поздней — от этого зависит, нужна ли она вообще
|
||||
- **Теги:** goal:merge-robustness, sprint:2026-08-03
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# [goal] У каждого входа есть названный предел
|
||||
# 🎯 У каждого входа есть названный предел
|
||||
|
||||
- **Тип:** goal
|
||||
- **Секция:** Направления
|
||||
- **Зачем:** Предела на одну сущность нет вовсе: 63 МиБ держат блокировку 5.019 с, соседние доставки уходят в failed
|
||||
- **Теги:** decomposed
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# [goal] Нижний слой чистится после проверенного экспорта
|
||||
# 🎯 Нижний слой чистится после проверенного экспорта
|
||||
|
||||
- **Тип:** goal
|
||||
- **Секция:** Запланировано
|
||||
- **Зачем:** Нижний слой растёт на ~100 тысяч координат в сутки, а после экспорта Apple он избыточен
|
||||
- **Теги:** decomposed
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Помечать нижний слой устаревшим после экспорта
|
||||
# ✨ Помечать нижний слой устаревшим после экспорта
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** feature
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** Нижний слой растёт на ~100 тысяч координат в сутки, а после экспорта Apple он избыточен
|
||||
- **Теги:** goal:lower-layer-cleanup
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Поднять MCP-сервер поверх Read API
|
||||
# ✨ Поднять MCP-сервер поверх Read API
|
||||
|
||||
- **Секция:** Ядро — набор ограничен HTTP-слоем чтения после дробления; адаптер берётся следующим спринтом по той же цели
|
||||
- **Тип:** feature
|
||||
- **Категория:** Ядро — набор ограничен HTTP-слоем чтения после дробления; адаптер берётся следующим спринтом по той же цели
|
||||
- **Зачем:** Агент-медик — первый заказчик проекта, а подключить его сейчас нечем
|
||||
- **Теги:** goal:read-api
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Снизить цену слияния на широкой доставке
|
||||
# 🐞 Снизить цену слияния на широкой доставке
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** fix
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** 63 МБ на одной координате держат транзакцию 5.15 с при busy_timeout 5 с — соседние доставки уходят в failed
|
||||
- **Теги:** goal:limits-and-load
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Хранить счётчики слияния вне логов
|
||||
# ✨ Хранить счётчики слияния вне логов
|
||||
|
||||
- **Секция:** Инфра
|
||||
- **Тип:** feature
|
||||
- **Категория:** Инфра
|
||||
- **Зачем:** Единственный след несравнимых наборов — строка WARN в docker-логе с ротацией 3×10 МБ: событие может произойти и не оставить ничего
|
||||
- **Теги:** goal:observability
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# [goal] Исход слияния не зависит от порядка элементов на проводе
|
||||
# 🎯 Исход слияния не зависит от порядка элементов на проводе
|
||||
|
||||
- **Тип:** goal
|
||||
- **Секция:** Направления
|
||||
- **Зачем:** Правила слияния держатся на замерах, и каждый новый замер находит зависимость от порядка на проводе
|
||||
- **Теги:** decomposed
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# [idea] Месячный проход по ручным секциям
|
||||
# 🔬 Месячный проход по ручным секциям
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** research
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** Симптомы и лекарства заводятся задним числом на недели — недельного глубокого прохода им не хватит
|
||||
- **Теги:** goal:parsing-completeness
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# [goal] История из родного экспорта Apple лежит в хранилище
|
||||
# 🎯 История из родного экспорта Apple лежит в хранилище
|
||||
|
||||
- **Тип:** goal
|
||||
- **Секция:** Запланировано
|
||||
- **Зачем:** Слой sample пуст: полная история и точные сэмплы лежат в zip-архиве и никуда не едут
|
||||
- **Теги:** decomposed
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# [idea] NDJSON-поток для больших выборок Read API
|
||||
# 🔬 NDJSON-поток для больших выборок Read API
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** research
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** Выборка нижнего слоя за месяц не влезает в один JSON-ответ — либо поток, либо пагинация
|
||||
- **Теги:** goal:read-api
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# [goal] Приложение сообщает о своём состоянии
|
||||
# 🎯 Приложение сообщает о своём состоянии
|
||||
|
||||
- **Тип:** goal
|
||||
- **Секция:** Запланировано
|
||||
- **Зачем:** Тихо сломавшаяся автоматизация — главный эксплуатационный риск, а сейчас факт виден только в логах
|
||||
- **Теги:** decomposed
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Ловить гейтом расхождение спеки с маршрутами
|
||||
# 🧹 Ловить гейтом расхождение спеки с маршрутами
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** chore
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** Рукописная спека — источник истины, а расходится она с кодом молча: без гейта решение о рукописной спеке не держится
|
||||
- **Теги:** goal:read-api, sprint:2026-08-04
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Написать OpenAPI-спеку руками
|
||||
# ✨ Написать OpenAPI-спеку руками
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** feature
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** Потребителей три и один из них агент — контракт должен читаться машиной, а не пересказываться в чате
|
||||
- **Теги:** goal:read-api, sprint:2026-08-04
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# [idea] Пересекающиеся источники одной метрики
|
||||
# 🔬 Пересекающиеся источники одной метрики
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** research
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** Сон пишут и часы, и стороннее приложение — сумма по обоим задвоит ночь
|
||||
- **Теги:** goal:read-api
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# [idea] Выгрузка в parquet отдельной командой
|
||||
# 🔬 Выгрузка в parquet отдельной командой
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** research
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** Дверь для тяжёлой аналитики снаружи: DuckDB читает и parquet, и файл SQLite — спешить некуда, но и закрывать не нужно
|
||||
- **Теги:** goal:read-api
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# [goal] Новая форма от источника не теряется молча
|
||||
# 🎯 Новая форма от источника не теряется молча
|
||||
|
||||
- **Тип:** goal
|
||||
- **Секция:** Направления
|
||||
- **Зачем:** Пять секций HAE поток ещё не приносил, а ручные секции заводятся задним числом — разбор полон ровно до следующей новой формы
|
||||
- **Теги:** decomposed
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Подчищать сырой архив до последнего проверенного экспорта
|
||||
# ✨ Подчищать сырой архив до последнего проверенного экспорта
|
||||
|
||||
- **Секция:** Инфра
|
||||
- **Тип:** feature
|
||||
- **Категория:** Инфра
|
||||
- **Зачем:** Архив не подчищается вовсе, а резать его раньше даты проверенного экспорта нельзя — в журнале останется дыра, которую нечем пересобрать
|
||||
- **Теги:** goal:journal-and-rebuild
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
# Отличать неполное ведро от полного
|
||||
# ✨ Отличать неполное ведро от полного
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** feature
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** Текущий час неполон всегда, и без порога свёртка отдаёт его наравне с полными — клиент видит провал вместо неизвестности
|
||||
- **Теги:** goal:read-api, sprint:2026-08-04, kind:feature
|
||||
- **Теги:** goal:read-api, sprint:2026-08-04
|
||||
|
||||
Ведро, в котором известна не вся сетка, отличимо от полного — а полярность
|
||||
порога названа вслух, а не выводится читателем из умолчания.
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
# Сворачивать точки по заданной сетке
|
||||
# ✨ Сворачивать точки по заданной сетке
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** feature
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** «Шаги за неделю по дням» — базовый запрос трекера и игры, и сегодня его нечем задать
|
||||
- **Теги:** goal:read-api, sprint:2026-08-04, kind:feature
|
||||
- **Теги:** goal:read-api, sprint:2026-08-04
|
||||
|
||||
«Шаги за неделю по дням» отвечаются одним запросом `?from&to&bucket`, и род
|
||||
свёртки берётся измеренным, а не угаданным.
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
# Отвечать 304 на повторный запрос точек
|
||||
# ✨ Отвечать 304 на повторный запрос точек
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** feature
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** Агент опрашивает по расписанию, а каждый повтор стоит полного чтения: на каталоге это 693 мс и +153 МиБ
|
||||
- **Теги:** goal:read-api, sprint:2026-08-04, kind:feature
|
||||
- **Теги:** goal:read-api, sprint:2026-08-04
|
||||
|
||||
Повторный опрос точек с той же меткой стоит `304` вместо полного чтения, и метка
|
||||
не может ответить на другой набор данных.
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
# Отдавать записи со своим id за период
|
||||
# ✨ Отдавать записи со своим id за период
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** feature
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** stateOfMind разобран и хранится, но наружу не отдаётся — а восстановить его нечем: в экспорте Apple его нет
|
||||
- **Теги:** goal:read-api, sprint:2026-08-04, kind:feature
|
||||
- **Теги:** goal:read-api, sprint:2026-08-04
|
||||
|
||||
Записи со своим `id` — сегодня это `stateOfMind` — достаются за период через
|
||||
`GET /records/{kind}`.
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
# Ограничить размер ответа маршрутов чтения
|
||||
# ✨ Ограничить размер ответа маршрутов чтения
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** feature
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** У маршрутов чтения нет ни одного потолка: множители «метрики × окно × точки × одновременные запросы» ничем не ограничены
|
||||
- **Теги:** goal:read-api, sprint:2026-08-04, kind:feature
|
||||
- **Теги:** goal:read-api, sprint:2026-08-04
|
||||
|
||||
У маршрутов чтения появляется названный потолок: сетка не задана и ответ не
|
||||
влезает — сервер огрубляет её и **называет** в ответе; сетка задана явно и не
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
# Отдавать тренировки вместе с маршрутом
|
||||
# ✨ Отдавать тренировки вместе с маршрутом
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** feature
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** Тренировки с маршрутами разобраны и лежат в витрине, а маршрутов чтения нет — сценарий трекера не закрыт
|
||||
- **Теги:** goal:read-api, sprint:2026-08-04, kind:feature
|
||||
- **Теги:** goal:read-api, sprint:2026-08-04
|
||||
|
||||
Трекер забирает тренировку одним пакетом вместе с маршрутом: `GET /workouts` за
|
||||
период и `GET /workouts/{id}` поштучно.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# [goal] Клиенты читают данные через HTTP и MCP
|
||||
# 🎯 Клиенты читают данные через HTTP и MCP
|
||||
|
||||
- **Тип:** goal
|
||||
- **Секция:** Запланировано
|
||||
- **Зачем:** Данные видны только через sqlite на хосте — ни один из трёх потребителей, включая агента-медика, ничего прочитать не может
|
||||
- **Теги:** decomposed
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Сверять живую витрину с пересборкой
|
||||
# ✨ Сверять живую витрину с пересборкой
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** feature
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** reindex печатает оба отпечатка, но сравнивать их некому — расхождение с журналом молчит
|
||||
- **Теги:** goal:journal-and-rebuild
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Не держать весь журнал в памяти при пересборке
|
||||
# 🧹 Не держать весь журнал в памяти при пересборке
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** chore
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** Учёт доставок и список путей архива материализуются целиком: расход растёт вместе с журналом, а у журнала конца нет
|
||||
- **Теги:** goal:journal-and-rebuild
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Назвать механизм отката релиза после наката миграции
|
||||
# ✨ Назвать механизм отката релиза после наката миграции
|
||||
|
||||
- **Секция:** Инфра
|
||||
- **Тип:** feature
|
||||
- **Категория:** Инфра
|
||||
- **Зачем:** Страж версии схемы делает возврат старого бинаря отказом, а понизить схему нечем — аварийный путь пришлось бы изобретать в аварии
|
||||
- **Теги:** goal:deploy
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# [idea] Человеческие аннотации поверх выведенных схем
|
||||
# 🔬 Человеческие аннотации поверх выведенных схем
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** research
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** Выведенная схема говорит форму, но не смысл метрики — нужно ли описание сверху, зависит от стабильности формата
|
||||
- **Теги:** goal:self-description
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# [idea] Порог sealed: с какого возраста час считается запечатанным
|
||||
# 🔬 Порог sealed: с какого возраста час считается запечатанным
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** research
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** WARN на изменение старого часа уже пишется, но порог не выбран — ставим по факту, когда накопится статистика досчёта
|
||||
- **Теги:** goal:merge-robustness
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# [goal] Клиент узнаёт форму данных из ответа
|
||||
# 🎯 Клиент узнаёт форму данных из ответа
|
||||
|
||||
- **Тип:** goal
|
||||
- **Секция:** Запланировано
|
||||
- **Зачем:** Метрик больше сотни и формы точек разные — клиент вынужден угадывать структуру по выборке
|
||||
- **Теги:** decomposed
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Развести бюджеты остановки и оставить следы миграции в логе
|
||||
# 🐞 Развести бюджеты остановки и оставить следы миграции в логе
|
||||
|
||||
- **Секция:** Инфра
|
||||
- **Тип:** fix
|
||||
- **Категория:** Инфра
|
||||
- **Зачем:** Долгий запрос чтения съедает бюджет остановки, и WARN обвиняет воркер свёртки; миграция молчит и не прерывается SIGTERM
|
||||
- **Теги:** goal:deploy
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Отдавать состояние сервиса маршрутом /stats
|
||||
# ✨ Отдавать состояние сервиса маршрутом /stats
|
||||
|
||||
- **Секция:** Инфра
|
||||
- **Тип:** feature
|
||||
- **Категория:** Инфра
|
||||
- **Зачем:** Тихо сломавшаяся автоматизация — главный эксплуатационный риск, а сейчас факт виден только в логах
|
||||
- **Теги:** goal:observability
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Слать уведомление, когда данных нет N часов
|
||||
# ✨ Слать уведомление, когда данных нет N часов
|
||||
|
||||
- **Секция:** Инфра
|
||||
- **Тип:** feature
|
||||
- **Категория:** Инфра
|
||||
- **Зачем:** Пропажу потока сейчас замечает человек, а не сервис
|
||||
- **Теги:** goal:observability
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Поднять Swagger UI без внешней сети
|
||||
# ✨ Поднять Swagger UI без внешней сети
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** feature
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** Контракт читается машиной, но человеку нечем выполнить запрос к живому сервису из браузера, а внешних CDN в локальной сети нет
|
||||
- **Теги:** goal:read-api, sprint:2026-08-04
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Развести токены контуров и убрать секреты из репозитория
|
||||
# ✨ Развести токены контуров и убрать секреты из репозитория
|
||||
|
||||
- **Секция:** Инфра
|
||||
- **Тип:** feature
|
||||
- **Категория:** Инфра
|
||||
- **Зачем:** Проверка токенов выключена, config.docker.toml коммитится — так нельзя выезжать наружу
|
||||
- **Теги:** goal:deploy
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Не задваивать тренировки при импорте родного экспорта
|
||||
# ✨ Не задваивать тренировки при импорте родного экспорта
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** feature
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** В export.xml у тренировки нет id — импорт снапшота задвоит тренировки, приехавшие от HAE
|
||||
- **Теги:** goal:native-export-import
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# [idea] Разворачивание маршрутов тренировок в отдельную таблицу
|
||||
# 🔬 Разворачивание маршрутов тренировок в отдельную таблицу
|
||||
|
||||
- **Секция:** Ядро
|
||||
- **Тип:** research
|
||||
- **Категория:** Ядро
|
||||
- **Зачем:** Маршрут лежит блобом внутри тренировки — понадобится, только если появится клиент, которому мало отдачи одним пакетом
|
||||
- **Теги:** goal:read-api
|
||||
|
||||
|
||||
Reference in New Issue
Block a user