# Требования к модулю: m05-progression-rules > Модуль — сервисы `ProgressionRules` и `BreakEngine` в > `Server.WatchBody.Core`: детерминированные правила прогрессии и > делоада (Ф-12.2–12.4, правила 3–5 и 10 документа метрик), перерывы > и возврат (Ф-14, правила 12–17 документа перерывов). Результат > работы — предложение draft-версии программы (`author=rules`) через > ProgramStore (m03). Самодостаточная копия требований (d-dev-6). ## 1. Назначение и границы **В границах модуля:** - класс `ProgressionRules` (`Server.WatchBody.Core`, каталог `Programs\`): микроправка весов на следующее занятие после каждой синхронизированной тренировки (Ф-12.2) и делоад (Ф-12.4) — предложение draft-версии (`author=rules`, `rationale`); - класс `BreakEngine` (тот же каталог): авто-детект перерыва по пропускам (Ф-14.1, `break_insert` source=auto), закрытие break первой сессией (`ended_on`), формула возврата (Ф-14.3, документ перерывов разд. 3.2) → draft-версия с `session_kind=return` (Ф-14.4–14.5), учёт правила 17 (break ≥ 14 дней → `session_kind=test`); - вызов из m02: после пересчёта метрик (m04) sync вызывает правила; сбой расчёта не откатывает sync (как у метрик); - пороги — из конфигурации сервера `Progression.*`/`Deload.*` (умолчания — requirements разд. 3); коэффициенты возврата — документ перерывов разд. 3.2; - тесты сервисов (интеграционные, docker `watchbody-pg`). **Вне границ модуля:** показ диффа и подтверждение предложения (телефон m09/m10, веб-консоль m08 — Ф-12.3); активация draft-версии (только явным действием атлета/владельца, 🛡 vision 2.4); пометка следующей тренировки лёгкой — телефон по Ф-13.2 (обнаружение — `red_flags` m04); правила координации 7–9 (вес тела/дефицит) и 11 (VO2max) — v2/v3 (документ метрик п. 5); правила 13/14 (средняя тренировка при аврале, домашний комплекс) — телефон; правило 15 (ужесточение порогов АД после break ≥ 14 дней) — кандидат v2 (меняет пороги m04, отдельное решение); свободный текст ограничений (`body.profile.limitations`) правила не интерпретируют — учёт ограничений детерминированный, через персональную библиотеку атлета (см. разд. 2.4); интерпретация текста — LLM-контур A (v2). ## 2.4. Учёт индивидуальных ограничений атлета (решение гейта 1.3) Ограничения атлета (травмы, недоступные тренажёры, противопоказания) влияют на набор упражнений в предложениях правил детерминированно, через персональную библиотеку (🛡 библиотека принадлежит атлету, Ф-4.4; ведут атлет/владелец по своим ограничениям): 1. `src.exercise.is_active=false` — «противопоказано/исключено»: упражнение не попадает в draft-версию; микроправка для него решений не генерирует; сессия только из неактивных упражнений исключается из плана целиком. 2. Исключаемое упражнение с парой-заменой в `src.exercise_replacement` (замена активна, та же группа) → в draft подставляется замена (веса исходного плана; пометка в `rationale`). 3. Сопоставление плана и факта: `body.exercises[].exercise_id` == `src.exercise.name` (так создаёт импорт пакета, m06); упражнение библиотеки не найдено → решение не генерируется, пометка в `rationale`. 4. Свободный текст `body.profile.limitations` переносится между версиями без изменений (не интерпретируется). ## 2. Правила (v1 — детерминированные) ### 2.1. Микроправка весов (Ф-12.2, документ метрик правила 3–5) По каждому упражнению тренировки, по факту `workout_set`: | # | Условие | Действие | |---|---|---| | 1 | все плановые подходы закрыты «по плану» при RPE ≤ 7 в 2 тренировках подряд | вес + `Progression.BaseStepKg` (базовые) / + `Progression.IsoStepKg` (изоляция) | | 2 | RPE ≥ 9 в 2+ сетах | вес − `Progression.BackoffPercent` % | | 3 | повторения достигли верхней границы диапазона (15–20) | вес ↑ (шаг прогрессии), повторения к 12 | | 4 | ≥ 2 подходов не дотянуты по повторениям | вес − `Progression.BackoffPercent` % | | 5 | иначе (частичное выполнение) | вес без изменения | Правила проверяются по порядку, срабатывает первое; решения по всем упражнениям собираются в одну draft-версию. ### 2.2. Делоад (Ф-12.4, правило 10) `Deload.MaxWeeks` недель подряд без делоада → draft-версия с объёмом −40–50 % (веса × 0.6, подходы −1), `session_kind=deload`. ### 2.3. Перерывы и возврат (Ф-14, документ перерывов разд. 3.2) - авто-детект: все запланированные сессии за 4 дня подряд пропущены → `break_insert` (source=auto); break закрывается первой сессией (`ended_on`); - формула возврата по длительности простоя: 4–6 дней → 100 % (первая сессия −1 подход, RPE 5–6); 7–13 → −10 %; 14–27 → −15 % (1 вводная неделя); 28–59 → −25 % (2 вводные); 60+ / болезнь с температурой → −30…−40 % (перезапуск). Кардио возвращается со 100 % сразу; - первая сессия после break → draft-версия с формульными весами, `session_kind=return` (после break ≥ 14 дней — `test`), rationale — причина снижения. Применение — подтверждением атлета/владельца (Ф-12.3), 🛡 автоматической смены активной версии нет. ## 3. Инварианты (🛡 — нарушать запрещено) 1. **Изоляция атлета** — все выборки и записи по одному `athleteId`. 2. **Только предложение, не смена** — правила создают draft-версии (`author=rules`); активация — только человеком (Ф-12.3, vision 2.4). 3. **Неизменяемость версий** — правила ничего не переписывают в существующих версиях; новая версия — через ProgramStore.CreateDraft (m03); ссылки тренировок на версии не трогаются. 4. **Без записи в факт** — правила ничего не пишут в `workout`/`workout_set`/`workout_metrics`/`daily_log`; запись разрешена только в `breaks` (детект/закрытие перерыва). 5. **Сбой правил не ломает sync** — исключение логируется, пакет остаётся принятым (как у метрик m04). 6. **Детерминированность** — тот же вход → тот же выход; никакого LLM. 7. **Пороги — только из конфига** (`Progression.*`, `Deload.*`; коэффициенты возврата — константы документа перерывов). ## 4. Критерии приёмки модуля 1. Микроправка: сценарии правил 1–4 из разд. 2.1 дают ожидаемые решения; правило 5 — вес не меняется. 2. Draft-версия создаётся через ProgramStore (`author=rules`, `based_on_version` = активная, `rationale` заполнен), активная версия не меняется; повторный вызов до подтверждения не плодит черновики (одна rules-черновая на активную версию). 3. Делоад: `Deload.MaxWeeks` без делоада → draft с `session_kind=deload`. 4. Перерыв: пропуски 4 дней → строка `breaks` (source=auto); первая сессия закрывает break (`ended_on`); draft возврата с `session_kind=return|test` и коэффициентом по таблице. 5. Изоляция: данные атлета Б не влияют на решения атлета А. 6. Сбой правил не мешает принятию пакета sync. 7. Тесты интеграционные против docker `watchbody-pg` — зелёные; сборка решения без ошибок.