54 lines
4.2 KiB
Markdown
54 lines
4.2 KiB
Markdown
# Формат пакета программы (program-import.json)
|
||
|
||
> Шаг 5 процесса разработки (`std1\_process\process.md`), решение ОВ-11
|
||
> (ревью №3, О-4-Б, З-31). Пакет — **импортируемый механизм
|
||
> эксплуатации** (уточнение владельца 2026-10-17): назначается атлету
|
||
> индивидуально, нормативным источником документации разработки не
|
||
> является. Пример — `..\..\program-import.json` (эксплуатационные
|
||
> данные). Импорт — `--mode import` (`Server.WatchBody.Import`),
|
||
> коды возврата — как у import (requirements 2.3).
|
||
|
||
## 1. Структура пакета
|
||
|
||
| Поле | Тип | Назначение при импорте |
|
||
|---|---|---|
|
||
| `program_id` | string | внешний идентификатор пакета → `src.program.external_id` (UNIQUE) |
|
||
| `version` | int | номер версии; при конфликте с существующей — новая строка `program_version` (max+1) |
|
||
| `based_on_version` | int? | → `program_version.based_on_version` |
|
||
| `status` | string | `draft` \| `active` \| `archived` → `program_version.status` (🛡 правила смены — Ф-10.3, `program_version_update`) |
|
||
| `author` | string | `user` \| `admin` \| `rules` → `program_version.author` (`llm` — v2) |
|
||
| `created_at` | ISO 8601 | информационное поле (в БД — `created_at` строки версии) |
|
||
| `profile` | object | **v1 игнорируется** (не переносится в `body`): `limitations` и прочее носят справочный характер; Safety-порогами управляет только конфиг `Safety.*` (Р3-А). Поля задокументированы для совместимости v2 |
|
||
| `weeks` | array | основное содержимое → `program_version.body` (см. раздел 2) |
|
||
| `safety`, `nutrition`, `coordination_rules`, `metrics`, `rationale` | mixed | переносятся в `body` как есть (`rationale` — также в колонку `program_version.rationale`) |
|
||
|
||
## 2. Содержимое `weeks` → `body`
|
||
|
||
Иерархия: `weeks[] → sessions[] → exercises[] → sets[]` — соответствует
|
||
схеме `program_version.body` (дизайн LLM-планирования, разд. 2):
|
||
|
||
- `week` (номер), `goal`, `load_pattern` — атрибуты недели;
|
||
- `sessions[]`: `day`, `title`, `exercises[]`;
|
||
- `exercises[]`: `name` (→ сопоставление с `src.exercise` по
|
||
`UNIQUE(athlete_id, name)`; отсутствующее упражнение создаётся при
|
||
импорте — группа по разделу пакета, иначе `core` и пометка в логе),
|
||
`sets[]`: `weight_kg`, `reps`, `rest_sec`, `rpe_target`.
|
||
- `progression_gate` (у недель/пакета) — текст, в v1 переносится в
|
||
`body` без интерпретации (правила прогрессии — конфиг
|
||
`Progression.*`, Ф-12.2).
|
||
|
||
## 3. Маппинг и идемпотентность
|
||
|
||
1. `program_id` отсутствует в `src.program` → создаются `program`
|
||
(`external_id`, `title` = `program_id`) и `program_version` (v1).
|
||
2. `program_id` есть → создаётся новая `program_version` (номер
|
||
`based_on_version`/`version` из пакета; конфликт номеров — max+1
|
||
с записью в лог, код возврата 0).
|
||
3. 🛡 Неизменяемость версий не нарушается: повторный импорт никогда
|
||
не переписывает существующую `program_version`.
|
||
4. Назначение атлета: пакет импортируется в контексте конкретного
|
||
атлета (параметр режима import / сопоставление по каталогу файла);
|
||
🛡 изоляция атлетов сохраняется.
|
||
5. Ошибки схемы пакета (нет `weeks`, пустой `program_id`) — код
|
||
возврата 2, файл остаётся в `Import.Dir`.
|