Тех-требования и архитектура: Safety-пороги, daily_log, RPE/боль по сетам, РПЭ в грамматике

This commit is contained in:
virus-home 2026-10-17 19:05:29 +05:00
parent 842876802c
commit 2b3b0125fa
2 changed files with 12 additions and 4 deletions

View File

@ -52,8 +52,8 @@ vision 1.1); перечень моделей — открытый вопрос 8
| `AdminWeb` | `Server.WatchBody.Web` | Консоль владельца (логин/пароль): атлеты, тренировки + ход, программы, планы, метрики, CSV | | `AdminWeb` | `Server.WatchBody.Web` | Консоль владельца (логин/пароль): атлеты, тренировки + ход, программы, планы, метрики, CSV |
| `FitFetcher` | `Server.WatchBody.Fetch` | Клиент Garmin Connect (неофициальный, опросник 4.3); `--mode fetch`; дедупликация по `fit_file_id` | | `FitFetcher` | `Server.WatchBody.Fetch` | Клиент Garmin Connect (неофициальный, опросник 4.3); `--mode fetch`; дедупликация по `fit_file_id` |
| `FitParser` | `Server.WatchBody.Import` | Garmin FIT SDK: Session/Lap/Record/Set → `workout_facts`; `--mode import` (fallback: .fit/.tcx/.gpx из папки) | | `FitParser` | `Server.WatchBody.Import` | Garmin FIT SDK: Session/Lap/Record/Set → `workout_facts`; `--mode import` (fallback: .fit/.tcx/.gpx из папки) |
| `MetricsEngine` | `Server.WatchBody.Core` | adherence, тоннаж по группам, 1ПМ, пульс-метрики → `workout_metrics` | | `MetricsEngine` | `Server.WatchBody.Core` | adherence, тоннаж по группам, 1ПМ, пульс-метрики, красные флаги (АД/пульс/боль — документ метрик) → `workout_metrics` |
| `ProgressionRules` | `Server.WatchBody.Core` | Правила прогрессии и делоада → draft-версии программ (`author=rules`) | | `ProgressionRules` | `Server.WatchBody.Core` | Правила прогрессии, делоада и координации 1–6 (документ метрик) → draft-версии программ (`author=rules`) |
| `ProgramStore` | `Server.WatchBody.Core` | Версионированный JSON программ; неизменяемость версий; `active` — ровно один на атлета | | `ProgramStore` | `Server.WatchBody.Core` | Версионированный JSON программ; неизменяемость версий; `active` — ровно один на атлета |
| БД | схема `src` \| `ref` | PostgreSQL: атлеты, тренировки/факты, метрики, программы, журнал LLM (v2) | | БД | схема `src` \| `ref` | PostgreSQL: атлеты, тренировки/факты, метрики, программы, журнал LLM (v2) |

View File

@ -12,7 +12,8 @@
| # ОВ | Решение | Обоснование | | # ОВ | Решение | Обоснование |
|---|---|---| |---|---|---|
| 1. Максимальная ЧСС | Формула Танаки: `HRmax = 208 − 0,7 × возраст`; ручной ввод `Hr.MaxBpm` перекрывает расчёт | Точнее для 45+ (профиль пользователя); ручной ввод — окончательная истина | | 1. Максимальная ЧСС | Формула Танаки: `HRmax = 208 − 0,7 × возраст`; ручной ввод `Hr.MaxBpm` перекрывает расчёт | Точнее для 45+ (профиль пользователя); ручной ввод — окончательная истина |
| 2. Офлайн-STT | **Vosk** (малая русская модель ~50 МБ) + узкая грамматика команд (Ф-1.2: числа и слова «подход/вес/отдых/секунд»); TTS-подтверждения — системный Android TTS | Работа без сети, малый словарь → устойчивость к шуму; sherpa-onnx — запасная кандидатура, если точность < КУ-1 на контрольной тренировке | | 2. Офлайн-STT | **Vosk** (малая русская модель ~50 МБ) + узкая грамматика команд (Ф-1.2: числа и слова «подход/вес/отдых/секунд/РПЭ» — «РПЭ 8» ставит RPE последнему
подходу, Ф-13.3); TTS-подтверждения — системный Android TTS | Работа без сети, малый словарь → устойчивость к шуму; sherpa-onnx — запасная кандидатура, если точность < КУ-1 на контрольной тренировке |
| 3. Канал телефон ↔ часы | Connect IQ **Communications SDK** (companion-канал через приложение Garmin Connect Mobile на телефоне). Передаётся: текущий пульс (≈1 Гц), зона, таймер отдыха (секунды до конца), заряд часов. Ограничение: на телефоне должно быть установлено и залогинено Garmin Connect Mobile; канал может не доставлять — обе стороны деградируют молча (Ф-2.4, Ф-3.2) | Единственный штатный канал сторонних приложений Garmin; проверка объёма передачи — прототипом в итерации 1 шага 7 (критерий: пульс и таймер доходят при экране часов активным) | | 3. Канал телефон ↔ часы | Connect IQ **Communications SDK** (companion-канал через приложение Garmin Connect Mobile на телефоне). Передаётся: текущий пульс (≈1 Гц), зона, таймер отдыха (секунды до конца), заряд часов. Ограничение: на телефоне должно быть установлено и залогинено Garmin Connect Mobile; канал может не доставлять — обе стороны деградируют молча (Ф-2.4, Ф-3.2) | Единственный штатный канал сторонних приложений Garmin; проверка объёма передачи — прототипом в итерации 1 шага 7 (критерий: пульс и таймер доходят при экране часов активным) |
| 4. Расписание fetch | Внешний планировщик ОС: systemd timer (Linux-сервер) / Планировщик задач (Windows) вызывает `--mode fetch`; внутри сервера планировщика нет | Проще, надёжнее, не дублирует средства ОС | | 4. Расписание fetch | Внешний планировщик ОС: systemd timer (Linux-сервер) / Планировщик задач (Windows) вызывает `--mode fetch`; внутри сервера планировщика нет | Проще, надёжнее, не дублирует средства ОС |
| 5. Формула 1ПМ | **Эпли**: `1ПМ = w × (1 + reps/30)` | Стандарт индустрии; при reps ≤ 10 различие с Бжицки < 2 % | | 5. Формула 1ПМ | **Эпли**: `1ПМ = w × (1 + reps/30)` | Стандарт индустрии; при reps ≤ 10 различие с Бжицки < 2 % |
@ -48,8 +49,11 @@
`status` (active|finished|cancelled), `program_version_id` (nullable), `status` (active|finished|cancelled), `program_version_id` (nullable),
`avg_hr`; `avg_hr`;
- `workout_set`: `workout_id`, `exercise_id`, `seq`, `weight_kg`, `reps`, - `workout_set`: `workout_id`, `exercise_id`, `seq`, `weight_kg`, `reps`,
`done_at`, `source` (voice|watch|edit), `in_plan` (bool); `done_at`, `source` (voice|watch|edit), `in_plan` (bool), `rpe` (int? 0–10),
`knee_pain` (int? 0–10, только группа «ноги»);
- `profile`: `sex`, `birth_year`, `weight_kg`, `hr_max` (nullable); - `profile`: `sex`, `birth_year`, `weight_kg`, `hr_max` (nullable);
- `daily_log`: `date` (YYYY-MM-DD), `bp_sys`, `bp_dias`, `weight_kg`
(Ф-13.1; v2 добавит `hr_resting`, `waist_cm`, `sleep_h`, `wellbeing`);
- `program_version`: JSON-схема программы из дизайна LLM-планирования - `program_version`: JSON-схема программы из дизайна LLM-планирования
(разд. 2) + `athlete_id` (выводится из ключа, в теле не передаётся). (разд. 2) + `athlete_id` (выводится из ключа, в теле не передаётся).
@ -103,6 +107,10 @@
| `Progression.BaseStepKg` | double | 0,5–10 | | `Progression.BaseStepKg` | double | 0,5–10 |
| `Progression.BackoffPercent` | int | 1–20 | | `Progression.BackoffPercent` | int | 1–20 |
| `Deload.MaxWeeks` | int | 3–12 | | `Deload.MaxWeeks` | int | 3–12 |
| `Safety.BpCancelSys / BpCancelDias` | int | 120–200 / 70–130 (умолчания 150/90) |
| `Safety.BpCardioSys / BpCardioDias` | int | ≤ BpCancel (умолчания 140/90) |
| `Safety.RestingHrSitting` | int | 60–120 (умолчание 90) |
| `Safety.LightWeekHrRise` | int | 3–15 (умолчание 8) |
| `Log.Path / Log.Level` | — | уровень: Debug/Info/Error | | `Log.Path / Log.Level` | — | уровень: Debug/Info/Error |
Валидация конфигурации выполняется при старте любого режима; ошибки — Валидация конфигурации выполняется при старте любого режима; ошибки —