Перейти к содержанию

Разбор совета — 2026-08-13

Пятеро независимых рецензентов читали репозиторий вслепую, затем прошли перекрёстный допрос с обязательной контрфактической проверкой. Здесь — что нашли, что с этим делаем и на чём остановились.

Это не протокол ради протокола: разбор изменил формулировку цели проекта (ADR-0019) и вскрыл четыре подтверждённых дефекта контрактов.

Главный вывод

Проект не надо останавливать. Его посылка была сформулирована неверно — не ложна, а нереализуема как записано, — и это чинится дёшево.

Трое рецензентов независимо потребовали «сначала проверить гипотезу, потом строить». Контрфактический проход сломал их же вывод: проверка требует таймстампов подходов, то есть самого логгера. «Остановиться и проверить» превращается в «построй 60% системы, потом решай» — то есть не в стоп, а в переупорядочивание.

Что не так с исходной формулировкой

Цель звучала как «какой был пульс во время конкретного подхода». Два независимых физических возражения:

  1. Пик не там. Пульс после тяжёлого подхода достигает максимума в первые 5–20 секунд отдыха. Запрос «максимум внутри [T1, T2]» промахивается мимо пика по построению.
  2. Выборка смещена, а не разрежена. Fitbit Air пишет точку раз в ~5 секунд и отбрасывает точки при низком качестве оптического сигнала, а качество падает ровно при хвате штанги. На подход в 40 секунд приходится 0–8 точек, и уцелевшие смещены к спокойным моментам.

Отдельно: даже при идеальном датчике пульс за подход может полностью предсказываться упражнением, весом, повторами и предыдущим отдыхом. Тогда число точное — и бесполезное. Поэтому критерий проверки гипотезы — остаточная дисперсия, а не совпадение с эталонным датчиком: нагрудный ремень проверяет датчик, а не полезность величины.

Подтверждённые дефекты (проверены по коду, не со слов)

Дефект Где Проверка
MAX_BACKDATE рубит бэкфилл на пути синк-воркера core-service/internal/server/validate.go:39 правило обосновано для часов телефона (ADR-0013), применено на границе воркера
Ack обещает частичный приём, обработчик — «всё или ничего», без идентичности записи common.proto:27 vs server.go:58 выборочный ретрай невозможен в принципе
rir = 0 («до отказа») неотличим от «не записано» workout.proto:36-38 proto3 без optional
UNIQUE (source, external_id) не работает при NULL migrations/0001_init.sql:12,17 Postgres считает NULL различными

Плюс организационный: Спринт 1 недостижим как написан — S1-06 требует кнопку web_app, TLS для неё даёт S4-01 через три спринта; фолбэк описан в SERVICES.md §2, но ни в одной задаче не зафиксирован.

Что осталось неразрешённым

  • ~~Топология.~~ Закрыто владельцем 2026-08-13. Микросервисы — осознанный выбор архитектуры, а не побочный эффект; все они живут в одной VM pet. Претензия совета была основана на прочтении проекта как одиночного инструмента. Отдельно снята и главная её часть: форк wger больше не несёт вечного ребейза, потому что upstream не отслеживается (ADR-0020), а сам wger используется как полноценный интерфейс из Mini App, а не только как хранилище.
  • Какое решение меняет этот датасет в понедельник — нигде не записано.
  • Реальное разрешение Google Health v4 под нагрузкой — никто не измерял, включая совет.
  • Смещение часов телефона относительно часов — нигде не измеряется, а 5 секунд съедают весь бюджет сигнала.

Статус работ

# Что Статус
1 Переписать посылку: эпизод усилия вместо подхода сделаноPROJECT.md, DATA_MODEL.md, ADR-0019, задача S3-04 (issue #22)
2 Провенанс в health.proto и схеме до первого ингеста 📋 issue #29
3 Починить 4 дефекта контрактов до персистентности 📋 issue #30
4 Развязать Спринт 1 от TLS 📋 issue #31
5 Отчёт о покрытии и остаточной дисперсии 📋 issue #32
6 user_id в схему до персистентности (ADR-0021) 📋 issue #33

Позже (2026-08-13): бот стал единственной точкой входа (ADR-0023), из-за чего публичный HTTPS оказался предусловием, а не финальным штрихом (ADR-0025) — issue #31 закрывается этим решением. Порядок этапов пересобран в ROADMAP.md, новые задачи —

34 (туннель), #35 (регистрация), #36 (OAuth через бота), #37 (мультипользовательский

синк). Актуальное состояние целиком — COUNCIL-BRIEF.md.

Следующей сессии

Пункт 1 закрыт. Дальше по порядку — issue #29, он самый срочный: провенанс точек единственный из всего списка невозможно добавить задним числом. Как только пойдёт первый ингест пульса без confidence/recording_method/интервалов, собранные данные нельзя будет оценить на достоверность.

Затем #33 вместе с #30 — обе правят натуральные ключи в одной миграции, делать их порознь значит мигрировать схему дважды. Затем #31 (до старта Спринта 1) и #32 (после первых реальных сессий).

Вопрос про топологию закрыт владельцем (см. выше): микросервисы остаются, wger — хард-форк. Из открытого осталось только то, что требует данных: разрешение датчика на реальной тренировке и смещение часов телефона относительно часов.

Что уточнилось после разбора (ADR-0020…0022): хард-форк wger снимает ребейз и разрешает удалить nutrition; мультипользовательность закладывается в схему сразу, до реализации персистентности; брокер сообщений не заводится.