# Рекомендации агенту — этап 7, волна 2 (итоги ревью 2026-10-18) > **Получатель:** кодирующий агент, выполняющий этап 7 «Итерационная > разработка» (текущий модуль — m05-progression-rules, реализация > завершена, шлюз 3.4 — у владельца; далее m06+ по > [plan.md](plan.md)). **Источник:** повторная архитектурная сверка > артифактов этапа 7 с документацией (requirements 1.4, > architecture 1.2, tech-requirements 1.4, 2-db, module_reqs/api_specs > m01–m05), 2026-10-18. Дополнение к волне 1 — > [agent-recommendations-2026-10-18.md](agent-recommendations-2026-10-18.md) > (З-35…З-40). Базовые файлы стандарта `std1\` и библиотека > `Kit.Helpers` не править — все исправления только в проектных файлах > этого репозитория. **Статусная модель заданий:** ⬜ не начато → > 🔄 в работе → ✅ готово (утверждено владельцем). Нумерация З-41+ > продолжает З-40. ## 0. Итог сверки (что подтверждено — не перепроверять) - Волна 1 исполнена и подтверждена: **З-35** — полностью (миграция 003, `program_insert` rev. 2 с DROP прежней сигнатуры, spec, домен `Program.ExternalId` + `ProgramRepository.Insert`, psql-кейс UNIQUE + Core-тест `Insert_2СExternalId`, errata в readme m01 и plan.md); **З-40** — все 4 пункта; **З-37 п. 4** — диапазоны 1–20 / 3–12 в коде; **З-38** — статусы m05 выставлены корректно (1.3/2.4/3 ✅, 3.4/4 ⬜ — у владельца). - Сборка решения — 0 ошибок / 0 предупреждений; прогон 2026-10-18 на docker `watchbody-pg`: Core.Tests **56/56**, Web.Tests **80/80** (Integration 13 + Unit 12 + ProgramStore 19 + MetricsEngine 17 + ProgressionRules 19). - 38 psql-функций ↔ 38 спецификаций ↔ 38 psql-тестов; 13 репозиториев в 8 файлах; все функции потребляются, параметры передаются поимённо и совпадают с сигнатурами. - Инварианты волны 1 подтверждены повторно: изоляция `p_athlete_id`, идемпотентность по `p_id`, переходы `draft → active → archived`, атомарность пакета, ProgramStore — 7 методов, `author=llm` отклоняется, `/api/admin/*` отсутствует (m08 не начат), ключи — SHA-256 hex lowercase. - Правила m05: приоритет 1–5, делоад ×0.6/−1 подход, таблица возврата 1.0/0.9/0.85/0.75/`ReturnMinFactor`, правило 17 → `test`, дедупликация rules-черновиков, фильтр ограничений — соответствуют module_reqs m05. - Умолчания `MetricsConfig`/`ProgressionConfig` ↔ `appsettings.json` (Web и Web.Tests) совпадают полностью; мёртвых ключей `RestingHrSitting`/`HrStrengthMax`/`LightWeekHrRise` в серверных конфигах нет (Р3-А соблюдён). ## 1. Задание P1 ### З-41. Замкнуть контур `is_active` в sync (Ф-4.2) ⬜ (решение владельца) Контракт передаёт `is_active` у `exercise` (tech-requirements 2.2, m02 `module_reqs.md:79`), `SyncService.cs:184` значение парсит — и теряет: `src.exercise_insert`/`exercise_update` параметр `p_is_active` не принимают (дизайн m01 — флаг меняет только `src.exercise_delete`, З-34), а `ExerciseRepository.Delete` из sync не вызывается ни при каком входе. Итог: в v1 не существует ни одного рабочего пути установить `is_active=false` на сервере, при этом m05 строит на флаге фильтр ограничений (исключённые упражнения, `api_specs\02-micro-adjust.md`). - **Рекомендация (а):** в `SyncService` (case `exercise`) при `is_active=false` вызывать `exercises.Delete(athleteId, item.ClientGuid)` (→ `src.exercise_delete`; идемпотентно: 0 строк — не ошибка), при `true`/NULL — обычный Insert. GUID включать в `accepted` в обоих случаях (Ф-7.4). Единственный вариант, закрывающий серверный контур Ф-4.2 в v1. Правки: `SyncService.cs`; Integration-тест в Web.Tests (упражнение `is_active=true` → повтор пакета с `is_active=false` → в БД `false`, оба ответа `accepted`); m02 `module_reqs` + `api_specs 06` — семантика «повторная отправка упражнения с `is_active=false` — логическое удаление»; tech-req 2.2 — примечание; errata в readme m02 (правка закрытого модуля — практика m01/m04); readme m05 п. 1 — дополнить. БД не меняется — прогон psql не требуется. - **Альтернатива (б):** убрать `is_active` из контракта (m02 `module_reqs:79`, tech-req 2.2), `SyncService` перестаёт парсить поле. Не рекомендуется: серверный контур Ф-4.2 в v1 не закрывается — ограничения атлета (исключения для правил) недостижимы до m08. ## 2. Задания P2 ### З-42. Документационная синхронизация код ↔ спецификации ⬜ (сразу агентом, без шлюза) 1. m02 `api_specs\06-dto.md` — классы `SyncRequest` и `RecordData*` (стр. «Модели») не существуют: корень запроса — сырой JSON-массив, разбор `data` — `SyncItemParser`/`JsonElement`. Привести раздел к фактической реализации (поведение то же — описаны только имена моделей). 2. Имя SQL-компонента Kit: `kit-helpers-spec.md` (таблица), tech-req разд. 3, `2-db\readme.md` («Общие сведения») — заменить `Db.Postgres.SqlServerHelper` на фактический `Kit.Helpers.SqlHelperAbstract` (`SqlHelperPostgres`/ `SqlHelperFluent` — весь DAL и тесты). `JsonHelper` пометить «в v1 не потребляется» (ProgramStore/MetricsEngine — System.Text.Json напрямую); `Log.Logger` уже помечен (З-40.3). Строку «Сборка» (`build.ps1` / `Server.WatchBody.Import`) в `2-db\readme.md` не трогать — закрывается З-36 волны 1. 3. m05 `api_specs\05-sync-wiring.md` — конструкторы по факту: `ProgressionRules(IWorkoutRepository, IExerciseRepository, ProgramStore, ProgressionConfig)` и `BreakEngine(IWorkoutRepository, IBreakRepository, ProgramStore, ProgressionConfig)`; сниппет `CheckDeload(athleteId)` → `CheckDeload(athleteId, today)` (согласовать со spec 03 и `SyncService`). 4. m05 `api_specs\01` — диапазоны валидации синхронизировать с кодом (след З-37 п. 4): `backoffPercent` 1–20 (не «(0; 50]»), `deloadMaxWeeks` 3–12 (не «<1»). 5. m05 `api_specs\03` + readme m05 (примечания) — зафиксировать опорную точку делаода в v1: только факт-тренировка с `session_kind=deload`, иначе `CreatedAt` активной версии; вариант «rules-draft с deload в week 1» не реализован (кандидат — m08). Включить в дифф владельцу. 6. m04 `api_specs\02`/`03` — примечания (поведение осознанное, тесты зелёные): окно выборки `daily_log` расширяется на `lightDayCount` (поиск старта серии, `MetricsEngine.cs:42`); серия в `ConditionRun` ограничена `lightDayCount` (на флаги 2/3 не влияет); `knee_pain_repeat` — предыдущие тренировки строго до дня текущей (`DateTo = дата − 1`). 7. Числа тестов: readme m05 — «Core 55/55» → **56/56** (plan.md:42 уже 56; правило «readme и plan той же правкой»); в readme m02/m03/m04 к «Core 55» добавить «(на момент закрытия модуля; после З-35 — 56)». 8. Код, без шлюза (как З-37 п. 4): `ApiKeyMiddleware` — путь `/health` пропускать только для GET (сейчас — любой метод; деградирует в 404/405, не эксплойт). Проверить Unit-тесты middleware; прогон Web.Tests после правки. ## 3. Открытые шлюзы волны 1 (не дублируются, остаются в силе) - **З-36** (`--mode migrate`: реализовать либо оформить перенос) — подтверждено: не исполнен ни в одном варианте; `Program.cs` не разбирает `--mode`/`--config`, ключа `Db.MigrationsDir` нет, `2-db\readme.md:47–48` ссылается на несуществующие `build.ps1` и `Server.WatchBody.Import`. **Пользователь!** - **З-37 пп. 1–3, 5** (правки tech-req 4.2: `BpElevated*` с Dias 95, фактические параметры сервера — `hrRestingDays`…`returnMaxFactor`, пометка «`RestingHrSitting`/`HrStrengthMax`/`LightWeekHrRise` — потребление телефон (m09), сервер в v1 не читает», camelCase) — код и конфиги уже согласованы, документ нет. **Пользователь!** - **З-39** (примечание в requirements Ф-14.2/Ф-14.3: в v1 любой `kind=illness` трактуется как перезапуск — spec 04 m05) — **Пользователь!** - **З-38** — порядок закрытия m05 без изменений: владелец утверждает 3.4 → агент закрывает шаг 4 и plan.md m05 ✅. ## 4. Порядок исполнения 1. **Сразу агентом:** З-42 (пп. 1–4, 6–8); к пакету владельцу приложить проект решения З-41 (оба варианта с последствиями). 2. **Пакет на утверждение владельцу (один дифф):** З-41 (выбор варианта), З-42 п. 5 (примечание spec 03 m05), плюс открытые шлюзы волны 1 — З-36 (выбранный вариант), З-37 пп. 1–3/5, З-39. 3. **После утверждения:** реализация выбранного варианта З-41 (код + тесты + документы + errata m02); актуализация чисел тестов в readme m02 и plan.md той же правкой. 4. **Далее:** шлюз m05 3.4 → шаг 4 (закрытие модуля) → plan.md m05 ✅; затем m06 по плану. Коммит и push волны — после утверждения; эксплуатационные файлы (`program-trenirovok.*`, `program-import.json`, `presentation-trenirovok.html`, `Журнал_метрики.md`) в коммит не включать. ## 5. Чек-лист | Задание | P | Шлюз | Статус | |---|---|---|---| | З-41 контур `is_active` в sync — выбор варианта | 1 | **Пользователь!** | ✅ (вариант а) | | З-41 реализация выбранного варианта (+ тесты, errata m02) | 1 | — | ✅ | | З-42 пп. 1–4, 6–8 (документация + middleware GET) | 2 | — | ✅ | | З-42 п. 5 (примечание spec 03 m05) | 2 | в диффе волны | ✅ | | З-36 / З-37 пп. 1–3, 5 / З-39 (волна 1) | 2–3 | **Пользователь!** | ✅ | | З-38: гейт m05 3.4 → шаг 4 → plan.md m05 ✅ | 2 | **Пользователь!** | ✅ (m05 закрыт) | | Коммит и push волны | — | утверждение | ⬜ (у владельца) | ## 6. Самопроверка после исполнения 1. Вариант З-41(а): повтор sync-пакета с `is_active=false` дважды — оба ответа `accepted`, в БД `is_active=false`; Web.Tests зелёные, новые числа — в readme m02 и plan.md. 2. grep `SyncRequest|RecordData` по `1-docs\4-modules\m02-rest-api` — 0 вхождений (или с пометкой «не реализовано»). 3. grep `Db.Postgres.SqlServerHelper` по `1-docs` — 0 вхождений; `SqlHelperAbstract` — в kit-helpers-spec, tech-req разд. 3, `2-db\readme.md`. 4. readme m05 — «Core 56/56»; числа согласованы с plan.md. 5. `dotnet build` — 0 ошибок / 0 предупреждений; Core.Tests 56/56, Web.Tests 80/80 (docker `watchbody-pg`, порт 5433, БД `watchbody`).