Шаг 2 утверждён (readme); шаг 3: черновик функциональных требований v1
This commit is contained in:
parent
3df0486303
commit
7f88753be0
|
|
@ -8,8 +8,8 @@
|
||||||
| Шаг процесса | Артефакты | Статус |
|
| Шаг процесса | Артефакты | Статус |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| 1. Инициация разработки | `1-docs\1-reqs\vision.md` (утверждён 2026-10-17, v1.0), `1-docs\0-mng\plan.md` | ✅ |
|
| 1. Инициация разработки | `1-docs\1-reqs\vision.md` (утверждён 2026-10-17, v1.0), `1-docs\0-mng\plan.md` | ✅ |
|
||||||
| 2. Создание рабочей области | `readme.md` системы, структура репозитория, `.gitignore` | 🔄 |
|
| 2. Создание рабочей области | `readme.md` системы, структура репозитория, `.gitignore` | ✅ |
|
||||||
| 3. Разработка функциональных требований | `1-docs\1-reqs\requirements.md` | ⬜ |
|
| 3. Разработка функциональных требований | `1-docs\1-reqs\requirements.md` | 🔄 |
|
||||||
| 4. Разработка архитектуры | `1-docs\2-arch\architecture.md`, `hld.puml` (+ рендер) | ⬜ |
|
| 4. Разработка архитектуры | `1-docs\2-arch\architecture.md`, `hld.puml` (+ рендер) | ⬜ |
|
||||||
| 5. Разработка технических требований | `1-docs\3-tech\tech-requirements.md`, спецификации библиотек | ⬜ |
|
| 5. Разработка технических требований | `1-docs\3-tech\tech-requirements.md`, спецификации библиотек | ⬜ |
|
||||||
| 6. Проектирование баз данных | решение о составе данных (фиксируется здесь) | ⬜ |
|
| 6. Проектирование баз данных | решение о составе данных (фиксируется здесь) | ⬜ |
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,365 @@
|
||||||
|
# Функциональные требования: Феникс 6X v1
|
||||||
|
|
||||||
|
> Шаг 3 процесса разработки (`std1\_process\process.md`).
|
||||||
|
> Источник: [vision.md](vision.md) (утверждён 2026-10-17, v1.0), разделы
|
||||||
|
> 1.3 (БЦ), 1.4 (КУ), 2.1–2.4; решения опросников 4.1–4.7; ТЗ
|
||||||
|
> (`..\..\Техническое задание.md`), дизайн LLM-планирования (разд. 2–3,
|
||||||
|
> 6–8, 11 — шаг 1).
|
||||||
|
> Версия: черновик 1 (2026-10-17). Формулировки — проверяемые (d-req-7).
|
||||||
|
|
||||||
|
## 1. Назначение и границы
|
||||||
|
|
||||||
|
Версия 1.0 реализует полный цикл «программа → тренировка без рук →
|
||||||
|
архив → план/факт» (Ф-1–Ф-11, правила прогрессии Ф-12):
|
||||||
|
|
||||||
|
- **В границах:** голосовой офлайн-учёт подходов на Android-телефоне;
|
||||||
|
поле данных на Fenix 6 в профиле «Силовая» (пульс, зоны, Lap);
|
||||||
|
офлайн-учёт с автосинхронизацией телефон ↔ сервер; забор .fit
|
||||||
|
из Garmin Connect неофициальным клиентом и парсинг на сервере;
|
||||||
|
REST API со статическим ключом; веб-история с CSV; программы
|
||||||
|
(версионированный JSON) с контролем «план/факт» и правилами
|
||||||
|
прогрессии (без LLM).
|
||||||
|
- **Вне границ v1:** LLM-планирование — еженедельный контур (v2,
|
||||||
|
опросник 4.6), мезоциклы и «генератор+ревьюер» (v2.x); wake-word
|
||||||
|
«Феникс, записывай» (v2, опросник 4.5); iOS (v2, опросник 4.2);
|
||||||
|
экспорт FIT из приложения и доставка программ на часы (v2);
|
||||||
|
трековые виды спорта — бег/вело (v3+, опросник 4.7); полная
|
||||||
|
автоматическая смена программы без подтверждения (vision 2.4).
|
||||||
|
|
||||||
|
## 2. Состав системы, точки входа и режимы
|
||||||
|
|
||||||
|
Система — три компонента. Каждый работает автономно от остальных
|
||||||
|
(vision 2.2, «независимость частей»).
|
||||||
|
|
||||||
|
### 2.1. Часы — поле данных «Феникс» (Monkey C, Connect IQ)
|
||||||
|
|
||||||
|
Точка входа: добавление поля данных в штатный профиль «Силовая»
|
||||||
|
(решение — опросник 4.1). Отдельных режимов нет: поле живёт в течение
|
||||||
|
активности. Кнопки не перехватываются (Lap и Start/Stop обрабатывает
|
||||||
|
Garmin штатно — Ф-2.5, Ф-2.6).
|
||||||
|
|
||||||
|
### 2.2. Телефон — приложение «Феникс» (Android, Kotlin)
|
||||||
|
|
||||||
|
Точка входа: значок приложения. Режимы — экраны: «Главная», «Активная
|
||||||
|
тренировка», «Библиотека», «История», «Программа», «Профиль»,
|
||||||
|
«Настройки». Работает офлайн целиком; сеть нужна только для
|
||||||
|
синхронизации (Ф-7).
|
||||||
|
|
||||||
|
### 2.3. Сервер — «Феникс.Server» (C# / .NET 10, PostgreSQL)
|
||||||
|
|
||||||
|
Единая точка входа: CLI `--mode serve|import|fetch`.
|
||||||
|
|
||||||
|
| Параметр | Обязательный | Умолчание | Семантика |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `--mode serve` | нет | этот режим | REST API + веб-интерфейс |
|
||||||
|
| `--mode import` | нет | выкл | разовый импорт .fit/TCX/GPX из папки импорта и выход |
|
||||||
|
| `--mode fetch` | нет | выкл | разовый забор .fit из Garmin Connect и выход (расписание — внешний планировщик, открытый вопрос 5) |
|
||||||
|
| `--config` | нет | `appsettings.json` рядом с исполняемым файлом | путь к файлу настроек |
|
||||||
|
|
||||||
|
**Коды возврата (`--mode import|fetch`):** `0` — успех (в т.ч. «новых
|
||||||
|
файлов нет»); `1` — авария конфигурации; `2` — частичный сбой (часть
|
||||||
|
файлов не обработана, детали в логе).
|
||||||
|
|
||||||
|
## 3. Настройки (конфигурация)
|
||||||
|
|
||||||
|
🛡 Все пути, адреса и секреты настраиваемые — не зашиты в код.
|
||||||
|
|
||||||
|
**Телефон (`appsettings`/Preferences):**
|
||||||
|
|
||||||
|
| Параметр | Семантика | Умолчание |
|
||||||
|
|---|---|---|
|
||||||
|
| `Server.BaseUrl` | адрес сервера для синхронизации | — (обязательный) |
|
||||||
|
| `Server.ApiKey` | статический API-ключ | — (обязательный) |
|
||||||
|
| `Sync.WifiOnly` | синхронизация только по Wi-Fi: `1`/`0` | `0` |
|
||||||
|
| `Hr.MaxBpm` | максимальная ЧСС для расчёта зон; пусто — расчёт по формуле (открытый вопрос 1) | пусто |
|
||||||
|
| `Voice.Engine` | офлайн-движок распознавания (фиксируется шагом 5, открытый вопрос 2) | шаг 5 |
|
||||||
|
| `Voice.Language` | язык команд | `ru` |
|
||||||
|
| `Rest.DefaultSec` | отдых по умолчанию, если не задан командой | `120` |
|
||||||
|
|
||||||
|
**Сервер (`appsettings.json`):**
|
||||||
|
|
||||||
|
| Параметр | Семантика | Умолчание |
|
||||||
|
|---|---|---|
|
||||||
|
| `Api.Key` | статический API-ключ для телефона | — (обязательный) |
|
||||||
|
| `Api.Port` | порт HTTPS | `8443` |
|
||||||
|
| `Db.ConnectionString` | подключение к PostgreSQL | — (обязательный) |
|
||||||
|
| `Garmin.Login / Garmin.Password` | учётная запись Garmin Connect (решение — опросник 4.3) | — (обязателен для `fetch`) |
|
||||||
|
| `Garmin.DownloadDir` | папка хранения скачанных .fit | `data\fit` |
|
||||||
|
| `Import.Dir` | папка импорта fallback (ручной экспорт, опросник 4.3) | `data\import` |
|
||||||
|
| `Import.ArchiveDir` | папка обработанных файлов импорта | `data\import_done` |
|
||||||
|
| `Progression.BaseStepKg` | шаг прогрессии веса, кг | `2.5` |
|
||||||
|
| `Progression.BackoffPercent` | снижение при недовыполнении, % | `5` |
|
||||||
|
| `Deload.MaxWeeks` | недель между делоадами | `6` |
|
||||||
|
| `Log.Path / Log.Level` | логи | `logs\`, `Info` |
|
||||||
|
|
||||||
|
🛡 Пароль Garmin и API-ключ — только в настройках, не в коде; логи их
|
||||||
|
не содержат (З-2, З-6).
|
||||||
|
|
||||||
|
## 4. Функциональные требования
|
||||||
|
|
||||||
|
### Ф-1. Голосовой учёт подходов (телефон)
|
||||||
|
|
||||||
|
1. Активация — кнопкой микрофона на экране активной тренировки
|
||||||
|
(решение — опросник 4.5); повторное нажатие выключает прослушивание.
|
||||||
|
Пока экран активной тренировки открыт, распознавание работает
|
||||||
|
офлайн, без сети.
|
||||||
|
2. Грамматика команд (голос → семантика):
|
||||||
|
- «Подход **W** на **R**» → подход: вес `W` кг × `R` повторений
|
||||||
|
(целые числа; `W` — 0–500, `R` — 1–100);
|
||||||
|
- «Вес **W**» → рабочий вес `W` кг для следующих подходов;
|
||||||
|
- «Отдых **S** (секунд)» → таймер отдыха `S` секунд (5–600).
|
||||||
|
3. Команда вне грамматики или с числом вне диапазона — отклоняется:
|
||||||
|
короткий сигнал ошибки, состояние не меняется, в лог пишется
|
||||||
|
распознанный текст.
|
||||||
|
4. Принятая команда: сохраняется в текущую тренировку, проигрывается
|
||||||
|
короткий «щелчок» и голосовое подтверждение («Принято, подход
|
||||||
|
120 на 8» — TTS, офлайн).
|
||||||
|
5. 🛡 Каждая команда фиксируется в журнале команд: исходный
|
||||||
|
распознанный текст, семантика, время (секунды от начала тренировки)
|
||||||
|
— журнал нужен для сопоставления с .fit (Ф-7.6) и не редактируется.
|
||||||
|
6. Правка записанного подхода — не более 2 касаний (тап по подходу →
|
||||||
|
правка веса/повторов), КУ-1.
|
||||||
|
|
||||||
|
### Ф-2. Поле данных на часах (Monkey C)
|
||||||
|
|
||||||
|
1. Метрики на экране: текущий пульс (шрифт 40–48 pt), средний пульс
|
||||||
|
текущего подхода (от начала подхода до текущего момента), время
|
||||||
|
текущего подхода (под нагрузкой).
|
||||||
|
2. Зона пульса — цвет ободка/фона: синий < 50 %, зелёный 50–70 %,
|
||||||
|
жёлтый 70–85 %, красный > 85 % от `Hr.MaxBpm`; границы — из настроек
|
||||||
|
поля данных (Connect IQ settings; автоматическая передача с телефона
|
||||||
|
— открытый вопрос 3).
|
||||||
|
3. Границы подхода: поле считает подход открытым от штатного события
|
||||||
|
нового подхода (Strength Set) до события Lap; метрики подхода
|
||||||
|
обнуляются на границе.
|
||||||
|
4. Вибрация: однократная лёгкая — конец таймера отдыха, переданного
|
||||||
|
с телефона (если связь есть); двойная — выход пульса за красную
|
||||||
|
зону. При отсутствии связи с телефоном вибраций отдыха нет —
|
||||||
|
часы не блокируются (не зависимость от телефона).
|
||||||
|
5. Кнопка Lap — штатная: фиксирует конец подхода/круга в записи
|
||||||
|
активности (требование — метки Lap попадают в .fit, КУ-2).
|
||||||
|
6. Кнопка Start/Stop — штатная пауза/стоп активности; поле не требует
|
||||||
|
подтверждений и не блокирует штатное сохранение тренировки.
|
||||||
|
7. 🛡 Поле не пишет в сеть и не хранит историю: только отображение;
|
||||||
|
запись ведёт сама платформа Garmin.
|
||||||
|
|
||||||
|
### Ф-3. Экран активной тренировки (телефон)
|
||||||
|
|
||||||
|
1. Статусная строка: связь с часами (зелёный/красный/серый — серый =
|
||||||
|
связь недоступна, приложение не блокируется), заряд часов (если
|
||||||
|
передаётся), статус сети (онлайн/офлайн).
|
||||||
|
2. Пульс: крупное текущее значение + линия за последний подход;
|
||||||
|
источник — канал телефон ↔ часы (открытый вопрос 3). Если связи
|
||||||
|
нет — прочерк; запись голосом работает (Ф-1.1).
|
||||||
|
3. Таймер отдыха: обратный отсчёт, фон — красный (идёт отдых),
|
||||||
|
жёлтый (последние 10 с), зелёный (время начинать); старт — командой
|
||||||
|
«Отдых S» или кнопкой (умолчание `Rest.DefaultSec`).
|
||||||
|
4. Блок упражнения: текущее упражнение (из активной программы, Ф-11.2)
|
||||||
|
и текущий рабочий вес.
|
||||||
|
5. Кнопки нижней панели: микрофон (Ф-1.1), «Сбросить» (отмена текущей
|
||||||
|
тренировки с подтверждением — тренировка помечается `cancelled`
|
||||||
|
и сохраняется в историю).
|
||||||
|
6. На экране одновременно ≤ 4 активных элемента, тёмная тема,
|
||||||
|
крупные зоны касания (vision 2.2).
|
||||||
|
|
||||||
|
### Ф-4. Библиотека упражнений (телефон, синхронизируется на сервер)
|
||||||
|
|
||||||
|
1. Сущность «Упражнение»: название (уникальное), двигательная группа
|
||||||
|
(жим/тяга/ноги/… — из фиксированного справочника, нужна для правил
|
||||||
|
замены и тоннажа), признак «базовое/изоляция».
|
||||||
|
2. Операции: добавить, переименовать, удалить. 🛡 Удаление упражнения,
|
||||||
|
на которое ссылаются программа или тренировки, — только логическое
|
||||||
|
(`is_active=0`): история остаётся читаемой.
|
||||||
|
3. 🛡 Идентификаторы упражнений (`exercise_id`) неизменяемы: программы
|
||||||
|
и факты ссылаются по ID (дизайн LLM-планирования, разд. 2).
|
||||||
|
|
||||||
|
### Ф-5. История тренировок (телефон)
|
||||||
|
|
||||||
|
1. Список завершённых тренировок: дата/время, длительность, средний
|
||||||
|
пульс, число подходов, названия упражнений.
|
||||||
|
2. Карточка тренировки: список подходов (упражнение, вес × повторения),
|
||||||
|
пометки источника («голос», «часы», «правка»), средний пульс
|
||||||
|
по подходам.
|
||||||
|
3. Офлайн список строится из локальной БД (без сети).
|
||||||
|
|
||||||
|
### Ф-6. Профиль и зоны пульса (телефон)
|
||||||
|
|
||||||
|
1. Поля профиля: пол, возраст, вес (ввод однократно, редактируется);
|
||||||
|
хранение — локально, синхронизируется на сервер (`athlete_state`).
|
||||||
|
2. Зоны: 50/70/85 % от `Hr.MaxBpm` (п. 3); расчёт по умолчанию —
|
||||||
|
формула максимальной ЧСС (открытый вопрос 1).
|
||||||
|
3. Зоны используются телефоном (график, статусы) и передаются на часы
|
||||||
|
в объёме, доступном каналу (открытый вопрос 3).
|
||||||
|
|
||||||
|
### Ф-7. Офлайн-учёт и синхронизация (телефон ↔ сервер)
|
||||||
|
|
||||||
|
1. 🛡 Все данные сначала пишутся в локальную БД телефона; сеть не стоит
|
||||||
|
на пути записи (аналог КУ-3).
|
||||||
|
2. Очередь `sync_pending`: каждая новая/изменённая сущность получает
|
||||||
|
`client_guid` (UUID v4, генерирует телефон) и попадает в очередь;
|
||||||
|
порядок — по времени создания; отправка — пакетами ≤ 50 записей.
|
||||||
|
3. Отправка: `POST /api/v1/sync` (пакет записей + `client_guid` каждой);
|
||||||
|
успех записи на сервере подтверждается ответом (принятые GUID);
|
||||||
|
подтверждённые удаляются из очереди. Неудача сети — тихий баннер
|
||||||
|
«Синхронизация временно недоступна», повтор по восстановлению сети
|
||||||
|
(и по `Sync.WifiOnly`).
|
||||||
|
4. 🛡 Идемпотентность: сервер считает запись по `client_guid` — повтор
|
||||||
|
пакета не создаёт дублей (КУ-3); ответ идемпотентен.
|
||||||
|
5. После первой успешной синхронизации — тихий баннер «Данные успешно
|
||||||
|
синхронизированы».
|
||||||
|
6. Восстановление связи с часами: телефон запрашивает пропущенный
|
||||||
|
период пульса (в объёме возможностей канала — открытый вопрос 3)
|
||||||
|
и сопоставляет его с локально записанными подходами по времени
|
||||||
|
(границы подхода из журнала команд Ф-1.5); пульс, не попавший
|
||||||
|
в окно подхода, к подходам не относится.
|
||||||
|
7. Конфликтов правок нет: один пользователь, единственный источник
|
||||||
|
правки — телефон; сервер не меняет факт-записи (🛡).
|
||||||
|
|
||||||
|
### Ф-8. Сервер: забор и парсинг .fit, REST API
|
||||||
|
|
||||||
|
1. `--mode fetch` / расписание: неофициальный клиент Garmin Connect под
|
||||||
|
учётной записью владельца (решение — опросник 4.3) скачивает .fit
|
||||||
|
новых силовых тренировок в `Garmin.DownloadDir` (список уже
|
||||||
|
скачанных — по `fit_file_id` в БД; повторный запуск не качает
|
||||||
|
дубли — 🛡).
|
||||||
|
2. Парсинг .fit (Garmin FIT SDK): извлекаются `Session` (тип
|
||||||
|
`strength_training`, время), `Lap` (границы кругов/подходов),
|
||||||
|
`Record` (дискретный пульс), `Set` (повторения/вес, если есть);
|
||||||
|
результат — канонический JSON тренировки в `workout_facts`
|
||||||
|
(дизайн LLM-планирования, разд. 4).
|
||||||
|
3. Fallback-импорт (`--mode import`): файлы из `Import.Dir` (.fit, .tcx,
|
||||||
|
.gpх — по документу форматов) парсятся тем же конвейером;
|
||||||
|
обработанные перемещаются в `Import.ArchiveDir`; необработанные
|
||||||
|
остаются с записью в логе (код возврата 2).
|
||||||
|
4. Сопоставление факт ↔ голосовой учёт: тренировка .fit сопоставляется
|
||||||
|
с тренировкой телефона по времени начала (± 15 минут) —
|
||||||
|
сопоставлённая пара связывается; несопоставленные остаются
|
||||||
|
раздельными (сопоставление не удаляет и не переписывает данные
|
||||||
|
— 🛡).
|
||||||
|
5. REST API (HTTPS, заголовок `X-Api-Key` = `Api.Key`; без ключа —
|
||||||
|
`401`): `POST /api/v1/sync` (Ф-7.3); `GET /api/v1/workouts`
|
||||||
|
(список с пагинацией); `GET /api/v1/workouts/{id}` (карточка);
|
||||||
|
`GET /api/v1/programs/active` (активная версия программы).
|
||||||
|
6. 🛡 API пишет факт-данные только из sync и импорта; ручного ввода
|
||||||
|
на сервере нет.
|
||||||
|
|
||||||
|
### Ф-9. Веб-интерфейс сервера
|
||||||
|
|
||||||
|
1. Страница истории: таблица тренировок (дата, длительность, средний
|
||||||
|
пульс, подходы, упражнений), сортировка по дате, пагинация.
|
||||||
|
2. Карточка тренировки: подходы, пульс-тренд, соответствие программе
|
||||||
|
(план/факт — Ф-11.4).
|
||||||
|
3. Выгрузка CSV текущей выборки (КУ-4). Доступ — по тому же
|
||||||
|
`X-Api-Key` (формa входа — ввод ключа; открытый вопрос 6).
|
||||||
|
|
||||||
|
### Ф-10. Программы тренировок (сервер + телефон)
|
||||||
|
|
||||||
|
1. Программа — версионированный JSON-документ (схема — дизайн
|
||||||
|
LLM-планирования, разд. 2): недели → тренировки (день, фокус) →
|
||||||
|
упражнения (`exercise_id` из библиотеки) → подходы-план (вес,
|
||||||
|
повторения, `target_rpe`, отдых). Хранение — таблица `programs`
|
||||||
|
(PostgreSQL); каждая версия неизменяема (🛡).
|
||||||
|
2. В v1 создание/правка версии — вручную в приложении на телефоне
|
||||||
|
(редактор программы) с отправкой на сервер; `author=user`.
|
||||||
|
3. Ровно одна версия в статусе `active` (🛡); смена активной — явным
|
||||||
|
действием пользователя; выполненные тренировки ссылаются на версию,
|
||||||
|
которая была активна на их начало (история не «поплывёт»).
|
||||||
|
4. Статусы версии: `draft` → `active` → `archived`; переходы —
|
||||||
|
действиями пользователя.
|
||||||
|
|
||||||
|
### Ф-11. Контроль исполнения программы (план/факт)
|
||||||
|
|
||||||
|
1. На экране активной тренировки — текущая позиция активной программы:
|
||||||
|
упражнение, план подходов (вес × повторения), отметка выполненных.
|
||||||
|
2. Подход фиксируется голосом (Ф-1) и помечается: «по плану» (вес
|
||||||
|
и повторения = план ± допустимое отклонение: вес ± 2,5 кг,
|
||||||
|
повторения ± 0) или «отклонение» (всё остальное).
|
||||||
|
3. По завершении тренировки — отчёт план/факт: по каждому упражнению
|
||||||
|
план (подходы × вес × повторения) против факта, доля закрытых
|
||||||
|
подходов (adherence) (КУ-5).
|
||||||
|
4. Отчёт доступен на телефоне и в веб-интерфейсе (Ф-9.2).
|
||||||
|
|
||||||
|
### Ф-12. Правила прогрессии (без LLM, v1)
|
||||||
|
|
||||||
|
1. После каждой синхронизированной тренировки MetricsEngine (сервер)
|
||||||
|
считает: adherence (доля закрытых подходов), тоннаж по упражнению
|
||||||
|
и группе, оценочный 1ПМ (формула — открытый вопрос 7) — в
|
||||||
|
`workout_metrics` (дизайн LLM-планирования, разд. 4).
|
||||||
|
2. Микроправка весов на следующее занятие (правила, детерминированно):
|
||||||
|
- все запланированные подходы закрыты «по плану» → вес +
|
||||||
|
`Progression.BaseStepKg` на базовых, + `BaseStepKg`/2 на изоляции;
|
||||||
|
- ≥ 2 подходов не дотянуты по повторениям → вес −
|
||||||
|
`Progression.BackoffPercent` %;
|
||||||
|
- иначе (частичное выполнение) — вес без изменения.
|
||||||
|
3. Правила применяются только к `active` версии; результат —
|
||||||
|
предложение следующей версии программы со статусом `draft`
|
||||||
|
(`author=rules`), показывается в приложении диффом; применение —
|
||||||
|
подтверждением пользователя (Ф-10.3). 🛡 Автоматической смены
|
||||||
|
активной версии нет (vision 2.4).
|
||||||
|
4. Делоад: если `Deload.MaxWeeks` недель подряд без делоада, правило
|
||||||
|
предлагает делоад-версию (объём −40–50 %) — тем же механизмом
|
||||||
|
диффа (дизайн LLM-планирования, разд. 6).
|
||||||
|
5. Офлайн-режим сервера: правила выполняются при следующем запуске
|
||||||
|
`serve`/`import` — телефон при этом полнофункционален (учёт и
|
||||||
|
локальные планы работают без сервера).
|
||||||
|
|
||||||
|
### Логирование (телефон и сервер)
|
||||||
|
|
||||||
|
1. `Info`: старт/остановка тренировки, каждая команда (Ф-1.5), пакеты
|
||||||
|
синхронизации (число записей, результат), забор/парсинг .fit
|
||||||
|
(файл, результат), применённые версии программ.
|
||||||
|
2. `Error`: все ошибки с текстом исключения (этап, объект, причина).
|
||||||
|
3. 🛡 В логах нет пароля Garmin, API-ключей и содержимого речи
|
||||||
|
(только распознанный текст команды — он нужен для диагностики
|
||||||
|
распознавания).
|
||||||
|
|
||||||
|
## 5. Контракты и инварианты
|
||||||
|
|
||||||
|
- 🛡 **Независимость частей:** часы, телефон и сервер работают при
|
||||||
|
отсутствии остальных; ни одна часть не блокирует другую (БЦ-4).
|
||||||
|
- 🛡 **Офлайн-first:** запись (голос, часы) и просмотр истории никогда
|
||||||
|
не ждут сеть; сеть — только синхронизация (КУ-3).
|
||||||
|
- 🛡 **Идемпотентность:** повтор отправки пакета (по `client_guid`)
|
||||||
|
и повторный `fetch`/`import` не создают дублей (КУ-3, Ф-8.1).
|
||||||
|
- 🛡 **Неизменяемость истории:** версии программ неизменяемы; факт-записи
|
||||||
|
сервер не переписывает; удаление упражнения — только логическое.
|
||||||
|
- 🛡 **Тайны:** пароль Garmin и API-ключи — только в настройках;
|
||||||
|
в логах их нет.
|
||||||
|
- 🛡 **Безопасность нагрузки:** автоматические изменения программы
|
||||||
|
ограничены лимитами правил (Ф-12.2, Ф-12.4); смена активной версии —
|
||||||
|
только вручную (БР-5, vision 2.4).
|
||||||
|
- **Отмена тренировки:** «Сбросить» сохраняет тренировку как
|
||||||
|
`cancelled` — молчаливой потери данных нет.
|
||||||
|
|
||||||
|
## 6. Трассировка
|
||||||
|
|
||||||
|
| Функция | Бизнес-цель | Критерий успеха | Версия |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Ф-1 голосовой учёт | БЦ-1 | КУ-1 | v1 |
|
||||||
|
| Ф-2 поле данных на часах | БЦ-2 | КУ-2 | v1 |
|
||||||
|
| Ф-3 экран тренировки | БЦ-1, БЦ-2 | КУ-1 | v1 |
|
||||||
|
| Ф-4 библиотека | БЦ-3 | — | v1 |
|
||||||
|
| Ф-5 история (телефон) | БЦ-3 | — | v1 |
|
||||||
|
| Ф-6 профиль и зоны | БЦ-2 | КУ-2 | v1 |
|
||||||
|
| Ф-7 офлайн + синхронизация | БЦ-4 | КУ-3 | v1 |
|
||||||
|
| Ф-8 сервер (.fit, API) | БЦ-5 | КУ-2, КУ-4 | v1 |
|
||||||
|
| Ф-9 веб + CSV | БЦ-5 | КУ-4 | v1 |
|
||||||
|
| Ф-10 программы | БЦ-3 | КУ-5 | v1 |
|
||||||
|
| Ф-11 план/факт | БЦ-3 | КУ-5 | v1 |
|
||||||
|
| Ф-12 правила прогрессии | БЦ-3 | КУ-6 | v1 |
|
||||||
|
| Ф-12 LLM-контур (еженедельно) | БЦ-3 | — | v2 |
|
||||||
|
| Wake-word (Ф-1) | БЦ-1 | — | v2 |
|
||||||
|
| iOS | БЦ-1, БЦ-2 | — | v2 |
|
||||||
|
| Бег/вело | — | — | v3+ |
|
||||||
|
|
||||||
|
## 7. Открытые вопросы
|
||||||
|
|
||||||
|
| # | Вопрос | Контекст | Решение |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 1 | Формула максимальной ЧСС | Умолчание для зон (Ф-6.2): 220 − возраст (классика) или Танака (208 − 0,7×возраст, точнее для пожилых); можно — ручной ввод `Hr.MaxBpm` | Закрыт шагом 5 |
|
||||||
|
| 2 | Офлайн-движок распознавания | Vosk (модель ~50 МБ, ru) против sherpa-onnx; грамматика цифр шумного зала; влияет на точность КУ-1. Кандидаты проверяются прототипом | Закрыт шагом 5 |
|
||||||
|
| 3 | Канал телефон ↔ часы | Connect IQ companion (Communications): что передаётся реально (пульс live, зоны, таймер отдыха, заряд); ограничения канала определяют Ф-2.4, Ф-3.2, Ф-6.3. Прототип на шаге 4 | Закрыт шагом 4 |
|
||||||
|
| 4 | Расписание `fetch` | cron/systemd-таймер на сервере против внутреннего планировщика; предпочтителен внешний планировщик | Закрыт шагом 5 |
|
||||||
|
| 5 | Способ сопоставления тренировок телефон ↔ .fit | Окно ± 15 минут (Ф-8.4) против точной метки начала из sync | ✅ Закрыт в этом документе (раздел 4, Ф-8.4) |
|
||||||
|
| 6 | Доступ в веб-интерфейс | Ввод ключа в форме против Basic Auth; личное использование — проще форма с ключом | Закрыт шагом 5 |
|
||||||
|
| 7 | Формула оценочного 1ПМ | Эпли против Бжицки (разд. 4 дизайна LLM-планирования); различие ~5 % на малых повторениях | Закрыт шагом 5 |
|
||||||
Loading…
Reference in New Issue