# Формат пакета программы (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`.