VEU.WathBody/1-docs/2-arch/architecture.md

12 KiB
Raw Blame History

Архитектура: Феникс 6X v1

Шаг 4 процесса разработки (std1\_process\process.md). Источники: vision.md (v1.2, изменения 1.1–1.2), requirements.md (утверждён 2026-10-17), дизайн LLM-планирования (разд. 8), документ форматов. Схема компонентов: hld.puml (+ рендер hld.svg, hld.png). Версия 1.0 — УТВЕРЖДЕНО (2026-10-17).

1. Компоненты и размещение

1.1. Часы атлета — FenixDataField (Monkey C, Connect IQ)

Поле данных «Феникс» в штатном профиле «Силовая». Только отображение (пульс, средний за подход, время, цвет зоны, вибро) — запись .fit ведёт платформа Garmin (инвариант из requirements, Ф-2.7). Один исходный код, сборки под целевые модели Garmin — конфигурациями (изменение vision 1.1); перечень моделей — открытый вопрос 8 требований.

Связь с телефоном — companion-канал Connect IQ (WatchChannel, компонент телефона): live-пульс, зоны, таймер отдыха передаются в объёме возможностей канала (открытый вопрос 3); отсутствие связи ничего не ломает — часы автономны.

1.2. Телефон атлета — Phone.WatchBody (Android, Kotlin)

  • TrainingUi — экраны (Jetpack Compose — кандидат, фиксируется шагом 5): активная тренировка, история, программы, профиль, «Сегодня» (дневник) и «Допуск»; тёмная тема, крупные зоны касания.
  • VoiceInput — офлайн-STT (движок — открытый вопрос 2) + грамматика команд (Ф-1.2) + TTS-подтверждения; журнал команд для сопоставления с .fit.
  • WorkoutCore — логика тренировки и программ: подходы, таймеры, план/факт, редактор программ; 🛡 предстартовый допуск (пороги Safety, экран допуска) и дневник самоконтроля (daily_log); автомат перерывов и формула возврата (Ф-14); единственный писатель LocalDb.
  • LocalDb — Room/SQLite: текущая тренировка, история, программы, библиотека, профиль, очередь.
  • SyncQueue — исходящие записи с client_guid, пакеты ≤ 50, идемпотентная отправка POST /api/v1/sync; тихие баннеры статуса.
  • WatchChannel — companion-канал Connect IQ.

🛡 Офлайн-first: сеть стоит только на пути SyncQueue; все остальные компоненты работают без сети (requirements, раздел 5).

1.3. Личный сервер — Server.WatchBody (C# / .NET 10, PostgreSQL)

Проекты в 3-app\:

Компонент Проект (3-app\2-cli\) Ответственность
RestApi Server.WatchBody.Web POST /api/v1/sync, GET workouts, GET programs/active; ключ атлета → athlete_id; HTTPS
AdminWeb Server.WatchBody.Web Консоль владельца (логин/пароль): атлеты, тренировки + ход, программы, планы, метрики, CSV
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 из папки)
MetricsEngine Server.WatchBody.Core adherence, тоннаж по группам, 1ПМ, пульс-метрики, красные флаги (АД/пульс/боль — документ метрик) → workout_metrics
ProgressionRules Server.WatchBody.Core Правила прогрессии, делоада и координации 1–11 (документ метрик) + 12–17 перерывы (документ перерывов): детекция break по пропускам, формула возврата → draft-версии (author=rules)
ProgramStore Server.WatchBody.Core Версионированный JSON программ; неизменяемость версий; active — ровно один на атлета
БД схема src | ref PostgreSQL: атлеты, тренировки/факты + session_kind, дневник (daily_log), перерывы (breaks), метрики, программы, журнал LLM (v2)

Общая библиотека — Kit.Helpers (3-app\1-lib, std1). Взаимодействие с LLM (v2, LlmPlanner) — по правилам std1 c-llm; в v1 компонент не реализуется (на схеме — серым).

1.4. Внешние системы (жёлтым на схеме)

  • Garmin Connect — облако: источник .fit (забор FitFetcher по расписанию — внешний планировщик, открытый вопрос 4).
  • Garmin (устройства) — запись .fit на часах, companion-канал.

2. Поток цикла обработки

  1. Допуск и перерывы. Перед стартом — экран допуска (АД/пульс; красные флаги блокируют или переводят в лёгкое кардио; обход логируется); автомат перерывов ставит break по пропускам и запрашивает причину у атлета; при возврате — формульная версия (Ф-14).
  2. Тренировка. Атлет запускает «Силовую» на часах (FenixDataField показывает пульс/зоны/подходы) и активирует голосовой ввод на телефоне (VoiceInput → команды → WorkoutCore → LocalDb). Часы и телефон независимы: любой из них работает без другого (🛡).
  3. Фиксация плана. WorkoutCore показывает позицию активной программы (RestApi → ProgramStore, при наличии сети; локальная копия — офлайн), помечает подходы «по плану/отклонение».
  4. Синхронизация. SyncQueue досылает новые записи на RestApi при появлении сети; сервер пишет их по client_guid (идемпотентно) от имени атлета ключа.
  5. Трек. Часы синхронизируются с Garmin Connect; FitFetcher по расписанию забирает новые .fit, FitParser раскладывает в workout_facts; сопоставление с тренировкой телефона — по времени начала ± 15 минут (Ф-8.4).
  6. Метрики и правила. MetricsEngine считает adherence/тоннаж/1ПМ; ProgressionRules формируют draft-версию следующей программы (микроправки ±2,5 кг / −5 %, делоад).
  7. Подтверждение. Draft показывается атлету на телефоне (дифф) или владельцу в AdminWeb; после подтверждения версия становится active (🛡 автоматической смены нет).
  8. Наблюдение. Владелец видит в AdminWeb ход тренировок, планы/факт, динамику; CSV — выгрузка выборки.

3. Границы и контракты

Граница Контракт Открытые вопросы
Телефон ↔ сервер REST/HTTPS, X-Api-Key (атлет), client_guid-идемпотентность, пакеты ≤ 50; формат записей — JSON (документ форматов) — (спецификация — шаг 5)
Телефон ↔ часы companion-канал Connect IQ: live-пульс, зоны, таймер отдыха; деградация без связи ОВ-3 (шаг 4)
Сервер ↔ Garmin Connect неофициальный клиент, учётка владельца; деградация — папка импорта --mode import —
Сервер ↔ LLM (v2) structured output, валидатор, офлайн-fallback на правила (дизайн LLM-планирования) до v2

4. Точки расширения

  • Модели часов — новая конфигурация сборки FenixDataField (разметка под экран), код не меняется (изменение vision 1.1).
  • LLM-планирование (v2) — LlmPlanner потребляет сводку MetricsEngine и предлагает версии через ProgramStore; ProgressionRules остаются базовым режимом (офлайн-fallback).
  • Трековые виды спорта (v3+) — расширение FitParser (телеметрия) и WorkoutCore (ввод темпа/дистанции); пульс/синхронизация/архив не меняются (опросник 4.7).
  • Общий справочник упражнений (v2) — надстройка над изолированными библиотеками атлетов (ОВ-11 требований).

5. Архитектурные инварианты (🛡)

  1. Независимость частей — часы, телефон, сервер работают при отсутствии остальных; ни один путь записи не проходит через сеть.
  2. Офлайн-first — источник истины на телефоне — LocalDb; сервер — архив и планирование.
  3. Идемпотентность — client_guid на телефоне ↔ сервере, fit_file_id на заборе, архивация файлов импорта: повторы не создают дублей.
  4. Изоляция атлетов — ключ → athlete_id; все выборки API и метрики — в пределах атлета; веб — только владелец.
  5. Неизменяемость истории — версии программ и факт-записи не переписываются; корректировка = новая версия.
  6. LLM не источник истины — в v1 решений LLM нет; в v2 — только предложения через валидатор и подтверждение (БР-5).