# Платформа для Minecraft-модпаков — план реализации ## 1. Цель Создать local-first платформу для создания, версионирования, упаковки, развёртывания и сопровождения воспроизводимых Minecraft-модпаков для небольшой группы игроков. Платформа должна быть оптимизирована под: - пользовательские модпаки на NeoForge и Forge; - запуск без обязательного Microsoft/Mojang-аккаунта и без онлайн-проверки сессии; - Prism Launcher как первоначальный клиентский лаунчер. - Docker Compose как серверный runtime. - удалённый доступ к серверу по SSH. - Git как источник истины для описания сборки и конфигурации. - обычные читаемые файлы на диске вместо непрозрачных Docker volumes. - простую установку, удаление и обновление модов. - воспроизводимые сборки. - простой rollback. - минимум собственной логики там, где задача уже хорошо решена существующими инструментами экосистемы. Сама платформа должна в первую очередь выступать как orchestration-слой вокруг: - packwiz - Modrinth `.mrpack` - Prism Launcher - `itzg/minecraft-server` - Docker Compose - Git - SSH / rsync Не разрабатывать собственный resolver зависимостей Minecraft-модов без реальной необходимости. Авторизация аккаунтов не является задачей платформы. Целевой сервер использует online-mode=false и enforce-secure-profile=false; для Prism допускается offline-аккаунт/Launch Offline. NeoForge и Forge — целевые loader; проверка Fabric не заменяет их integration spike. --- # 2. Основная архитектура Система состоит из четырёх концептуальных слоёв. ```text ┌──────────────────────────────────────────┐ │ 1. ИСХОДНИК МОДПАКА │ │ │ │ packwiz │ │ mods / configs / datapacks / resources │ │ Minecraft + версии loader │ └────────────────────┬─────────────────────┘ │ build │ ┌──────────┴──────────┐ ▼ ▼ ┌──────────────────┐ ┌──────────────────┐ │ 2. CLIENT PACK │ │ 3. SERVER PACK │ │ │ │ │ │ Modrinth .mrpack │ │ Modrinth .mrpack│ │ Prism Launcher │ │ itzg installer │ └──────────────────┘ └─────────┬────────┘ │ ▼ ┌──────────────────┐ │ 4. SERVER STATE │ │ │ │ world │ │ logs │ │ backups │ │ whitelist │ │ server runtime │ └──────────────────┘ ``` Ключевое правило: > Git source является источником истины для желаемого состава сборки и управляемой конфигурации. Runtime является источником истины для текущего мира и прочего persistent state. Сгенерированные артефакты фиксируют конкретный релиз, но не заменяют его исходники. --- # 3. Выбор технологий ## Обязательные компоненты ### packwiz Использовать packwiz для: - метаданных зависимостей модов; - фиксации точных версий модов; - интеграции с Modrinth; - интеграции с CurseForge там, где это необходимо; - metadata о client/server side; - индексирования конфигов и ресурсов; - генерации `.mrpack`. ### Modrinth `.mrpack` Основной формат распространяемого артефакта. Причины: - Prism Launcher импортирует его напрямую. - Формат поддерживает client/server side metadata. - Он переносим. - Хорошо работает с packwiz. - Может использоваться серверным tooling для установки сборки. ### Prism Launcher Основной клиентский лаунчер. Платформа должна генерировать артефакты, которые Prism может использовать без необходимости вручную изменять созданный instance. ### Docker Compose Оркестрация сервера. ### itzg/minecraft-server Контейнерный runtime Minecraft-сервера. По возможности использовать конфигурацию через environment variables и bind-mounted директории. ### Git Git отслеживает: - metadata модпака; - определения модов; - конфиги; - скрипты; - server compose-файлы; - конфигурацию платформы. Git не должен отслеживать: - миры; - логи; - большие backups; - runtime cache; - секреты. ### SSH + rsync Основной транспорт deployment для первой версии. В v1 не требовать Kubernetes, Docker Registry, серверных агентов или CI/CD-инфраструктуры. --- # 4. Структура репозитория Начальная структура репозитория: ```text minecraft-platform/ ├── README.md ├── PLAN.md ├── Makefile ├── .gitignore │ ├── platform/ │ ├── config.yaml │ └── schemas/ │ ├── pack/ │ ├── pack.toml │ ├── index.toml │ ├── mods/ │ ├── config/ │ ├── defaultconfigs/ │ ├── resourcepacks/ │ ├── shaderpacks/ │ ├── datapacks/ │ └── kubejs/ │ ├── server/ │ ├── compose.yaml │ ├── compose.override.yaml.example │ ├── server.properties │ ├── config/ │ └── .env.example │ ├── scripts/ │ ├── build │ ├── deploy │ ├── rollback │ ├── backup │ ├── doctor │ └── console │ ├── dist/ │ └── .gitkeep │ └── runtime/ └── .gitkeep ``` `runtime/` используется только для локального development-runtime и должен быть добавлен в `.gitignore`, кроме `.gitkeep`. Удалённый сервер должен использовать аналогичную структуру runtime-директорий. --- # 5. Конфигурация платформы Добавить единый высокоуровневый конфигурационный файл платформы. Рекомендуемый начальный формат: ```yaml schema_version: 1 pack: directory: ./pack build: output_directory: ./dist server: host: minecraft directory: /srv/minecraft/friday memory: 8G port: 25565 deploy: transport: ssh healthcheck_timeout: 120 ``` Рекомендуемый файл: ```text platform/config.yaml ``` Этот файл является manifest верхнего уровня для платформы. packwiz остаётся источником истины для metadata отдельных модов. Имя, версия сборки, Minecraft, loader и его версия читаются из `pack/pack.toml`. Не дублировать их и версии модов в `config.yaml`. Примеры версий в плане иллюстративны; совместимую комбинацию выбрать и проверить в Phase 0. --- # 6. Правила источников истины Необходимо явно зафиксировать зоны ответственности. ## Platform config отвечает за - версию схемы конфигурации; - серверные значения по умолчанию; - deployment target; - схему именования релизов. ## packwiz отвечает за - имя и версию сборки в `pack.toml`; - Minecraft, тип и точную версию loader в `pack.toml`; - моды; - версии модов; - side metadata; - downloads; - pack indexes; - правила включения на client/server. ## Серверная конфигурация отвечает за - `server.properties`; - начальные шаблоны whitelist и operators; - server-specific overrides конфигурации модов; - настройки Docker runtime. ## Runtime отвечает за - действующие whitelist и operators (шаблоны применяются только при первом запуске); - persistent данные модов, в том числе вне world; - world; - logs; - cache; - временные downloads; - сгенерированное runtime-состояние. Никогда не считать `runtime/mods` источником истины. --- # 7. Дизайн CLI В перспективе user-facing интерфейс должен быть одной командой. Пример имени: ```text mcpack ``` Точный язык реализации можно выбрать позже. В v1 допустимо реализовать всё shell-скриптами или Makefile. Ожидаемые команды в долгосрочной перспективе: ```bash mcpack init mcpack add create mcpack add sodium --client mcpack remove create mcpack update create mcpack update --all mcpack check mcpack doctor mcpack build mcpack release mcpack deploy mcpack restart mcpack status mcpack logs mcpack console mcpack backup mcpack rollback ``` CLI должен оставаться тонким orchestration-слоем. По возможности команды должны напрямую делегировать работу packwiz, Docker Compose, SSH и rsync. --- # 8. Процесс сборки Канонический flow: ```text source pack + server config + pinned toolchain → validation → временная копия source → packwiz refresh + packwiz modrinth export в копии → dist/-/ ``` Build не меняет tracked source. Если refresh выявляет устаревший исходный индекс, release прекращается с инструкцией явно обновить и закоммитить его. Состав релиза: ```text dist/friday-minecraft-0.4.0/ ├── friday-minecraft-0.4.0.mrpack ├── server/ │ ├── compose.yaml │ ├── server.properties │ └── config/ ├── manifest.json └── SHA256SUMS ``` Manifest обязателен: schema version, имя и версия, Minecraft, loader и его версия, Git commit, признак dirty build, версия packwiz, image digest и список управляемых файлов. SHA256SUMS покрывает все файлы релиза кроме самого SHA256SUMS. Секреты и deployment target в релиз не включаются. Prism получает .mrpack, сервер — весь каталог релиза. Общий .mrpack — начальный вариант; отдельная серверная трансформация допустима по результатам spike и должна быть воспроизводимой. Локальный development build допускает dirty worktree и явно помечается. Release и deployment требуют чистый worktree. Готовые релизы сохраняются для deployment и rollback без повторной сборки. --- # 9. Валидация сборки `mcpack check` должен как минимум проверять: - platform config успешно парсится; - версия Minecraft указана; - loader входит в комбинации, подтверждённые spike; - версия loader зафиксирована; - packwiz-файлы существуют; - metadata packwiz внутренне консистентны; - отсутствуют очевидные дубликаты определений модов; - необходимые server-файлы существуют; - output directory доступна для записи; - известные пути секретов не отслеживаются Git (это не гарантия обнаружения всех секретов); - pack может быть успешно экспортирован; - Java образа соответствует выбранному Minecraft/loader; - manifest и checksums согласованы. Позже можно добавить: - проверку совместимости client/server dependencies; - обнаружение несовместимого loader; - duplicate mod IDs; - неподдерживаемые версии Minecraft; - расширенную проверку совместимости Java runtime; - schema validation конфигов. --- # 10. Распространение клиентской сборки Основной клиентский артефакт: ```text *.mrpack ``` Ожидаемый flow для пользователя: ```text Prism Launcher → Add Instance → Import → выбрать .mrpack → launch ``` Игрок не должен вручную устанавливать: - loaders; - отдельные моды; - config-файлы. Корректная side-разметка обязательна и проверяется на клиенте и сервере. Разметка модов не определяет установку произвольных config/resource/datapack-файлов: их стороны и целевые пути проверить в spike. Для v1 начать с Modrinth. Перед добавлением CurseForge или внешних JAR проверить скачивание и право распространения: packwiz может включить JAR непосредственно в архив. См. [документацию packwiz](https://packwiz.infra.link/tutorials/hosting/modrinth/). Для обновления в v1 игрок импортирует новый релиз в отдельный instance. Автоматическое обновление прежнего instance не обещается; личные настройки и saves не входят в релиз. Примеры: - Sodium: client-side; - server performance mods: server-side; - gameplay/content mods: обе стороны, если это требуется. --- # 11. Server runtime Использовать itzg/minecraft-server с закреплённым image digest и подходящей Java. Пример контракта Compose (placeholders заменить при реализации): ```yaml services: minecraft: image: itzg/minecraft-server:PINNED_TAG@sha256:PINNED_DIGEST restart: unless-stopped ports: - "${MC_PORT:-25565}:25565" environment: EULA: "${MC_EULA:?Set MC_EULA after accepting the Minecraft EULA}" MEMORY: "${MC_MEMORY:-8G}" TYPE: MODRINTH ONLINE_MODE: "false" ENFORCE_SECURE_PROFILE: "false" MODRINTH_MODPACK: /modpack/friday-minecraft-0.4.0.mrpack volumes: - ${MC_ROOT:?Set absolute server root}/runtime:/data - ${MC_RELEASE_DIR:?Set absolute release directory}:/modpack:ro ``` Compose входит в релиз; абсолютные bind paths не зависят от cwd. Все операции явно передают одно стабильное Compose project name. Глобальный container_name не требуется. Локальный .mrpack поддерживается [itzg](https://docker-minecraft-server.readthedocs.io/en/latest/types-and-platforms/mod-platforms/modrinth-modpacks/). Выбранный loader, очистку старых модов, side filtering и перезапись overrides проверить на закреплённом образе в Phase 0. Критичные изменяемые данные хранятся в runtime на host, без named volumes. Первичная настройка включает UID/GID, принятие EULA и локальный файл секретов .env. --- # 12. Процесс deployment mcpack deploy применяет готовый неизменяемый релиз. Если его нет, сначала выполняется build из чистого worktree. 1. Проверить source, релиз и checksums. 2. Подключиться к host с установленными Docker, Compose, rsync, tar и zstd. 3. Получить общую remote-блокировку для deploy/backup/rollback. 4. Проверить права, свободное место, состояние предыдущей операции и конфликты конфигов. 5. Загрузить релиз во временный каталог, проверить checksums на host и атомарно опубликовать каталог releases/-. 6. Если этот релиз уже активен и healthy, завершить без restart. 7. Корректно остановить сервер и убедиться в завершении процесса. 8. Создать и проверить backup существующего persistent state. 9. Записать deployment state и применить новый релиз. 10. Запустить контейнер и дождаться healthcheck. 11. Только после успеха атомарно обновить active-release и previous-release. При первом запуске с пустым runtime backup не требуется; этот случай фиксируется явно. Любая смена релиза существующего сервера требует backup, включая изменения конфигурации. Ошибка загрузки не останавливает сервер. Ошибка backup запрещает запуск нового релиза; прежний можно запустить, если runtime ещё не менялся. При ошибке после применения нового релиза остановить сервер, вернуть non-zero и сохранить failed deployment state с инструкциями восстановления. Автоматически запускать старый pack на потенциально изменённом мире нельзя. Одинаковая версия с другим содержимым отклоняется. Прерывание оставляет читаемый state: этап, исходный и целевой релизы, checksums, backup ID. Повторный запуск проверяет state и не начинает новую операцию поверх незавершённой. --- # 13. Структура удалённого сервера ```text /srv/minecraft/friday/ ├── .env ├── active-release ├── previous-release ├── deployment-state.json ├── releases/ │ ├── friday-minecraft-0.3.0/ │ └── friday-minecraft-0.4.0/ ├── runtime/ └── backups/ ``` active-release содержит имя каталога последнего успешно запущенного релиза. Compose и серверные overrides берутся из этого релиза. Host settings и секреты остаются в .env; rollback их не меняет. Указатели обновляются атомарно. Deployment state различает последний успешный и фактически применяемый релизы во время перехода. Все операции используют одну remote-блокировку. --- # 14. Стратегия серверной конфигурации Разделить конфигурацию на три класса. ## Конфигурация уровня модпака Хранится в: ```text pack/config/ pack/defaultconfigs/ pack/kubejs/ ``` Это часть релиза модпака. ## Конфигурация уровня сервера Хранится в: ```text server/ ``` Примеры: - базовый `server.properties`; - Compose-конфигурация; - шаблоны server-specific config. ## Runtime-generated конфигурация Хранится в: ```text runtime/ ``` Порядок применения: pack defaults → server overrides → runtime generation для неуправляемых файлов. У каждого управляемого пути один владелец; пересечения разрешаются явно как overrides, иначе validation прекращается. Manifest содержит управляемые пути. Удалять только файлы прежнего релиза; неизвестные файлы не удалять молча. Для конфигов, изменяемых самим runtime, определить в spike политику replace, seed-only или preserve. Проверить defaultconfigs и datapacks на существующем мире. Не определять тип или владельца конфига только по директории: в проверяемом NeoForge 1.21.1 серверные конфиги создаются в `runtime/config/`. Путь, поддержку `defaultconfigs/` и per-world overrides проверять для закреплённого loader; результаты одной ветки не переносить автоматически на Forge. Не коммитить runtime-generated файлы автоматически. В будущем добавить явную команду для переноса полезных runtime-изменений обратно в source. Например: ```bash mcpack config import server ``` --- # 15. Ручное редактирование runtime-файлов Одно из требований — администратор должен иметь возможность вручную править файлы через SSH. Например: ```bash ssh minecraft cd /srv/minecraft/friday/runtime vim config/example.toml vim server.properties ``` Эта возможность должна сохраняться. Перед deployment сравнивать управляемые конфиги с ожидаемым состоянием прежнего релиза. При ручных изменениях показать diff и прекратить применение до явного выбора: перенести правки в source либо разрешить замену. Известные runtime-generated изменения обрабатывать по политике раздела 14. Это обязательная минимальная проверка конфликтов v1; неуправляемые persistent файлы сохраняются. Будущее улучшение: ```bash mcpack diff-runtime ``` Команда сравнивает server runtime config с конфигами под Git. --- # 16. Backups Перед сменой релиза существующего сервера обязателен backup после корректной остановки. mcpack backup использует ту же блокировку и в v1 также останавливает сервер, затем возвращает его в прежнее состояние работы после успешного backup. Начальный вариант — архивировать весь runtime, кроме явно установленных disposable logs/cache/downloads. Исключения подтвердить в spike. Сохранять данные модов вне world, конфиги, server.properties, whitelist и operators. Releases и backups не входят в архив runtime. Каждый snapshot имеет уникальный timestamp + ID, архив tar.zst и metadata JSON: исходный и целевой релизы, checksums релиза и архива, исключения и время. Писать временный архив, проверить завершение tar/zstd и читаемость архива, затем публиковать атомарно. Ошибка блокирует deployment. В v1 обязательна проверенная инструкция восстановления в отдельную директорию вместе с соответствующим сохранённым релизом. Backup не удаляется автоматически. Off-host копии и retention policy — последующее улучшение. --- # 17. Rollback В v1 различать явные операции: ```bash mcpack rollback-pack 0.3.0 mcpack rollback --backup ``` rollback-pack меняет релиз без восстановления persistent state и требует явного подтверждения совместимости с текущим миром. SemVer не доказывает совместимость. Команда rollback без указания режима показывает план и ничего не меняет. rollback --backup восстанавливает snapshot и связанный с ним исходный релиз, явно сообщая о потере прогресса после снимка. В v1 эта операция может оставаться документированной ручной процедурой, проверенной на практике. Обе операции используют блокировку, останавливают сервер и сначала сохраняют текущее состояние отдельным backup. Целевой релиз и snapshot проверяются до изменения runtime. Восстановление — в отдельный каталог с последующей заменой runtime; распаковка поверх существующих файлов запрещена. Откат возвращает .mrpack, server overrides и Compose/image исходного релиза. Host secrets остаются прежними. Указатели обновляются только после healthcheck. Старый pack не запускается автоматически на мире, изменённом неудачным deployment. --- # 18. Health checks Deployment успешен, когда контейнер стабильно работает и Minecraft status query подтверждает готовность отвечать по игровому протоколу. Использовать штатный healthcheck itzg, проверив его на закреплённом образе. Container state и TCP connect — диагностические проверки, недостаточные для подтверждения готовности. Crash, restart loop и timeout возвращают non-zero с указанием logs и recovery state. Timeout настраиваемый; 120 секунд — пример, не универсальный предел. Первый запуск с загрузкой dependencies учитывать отдельно. Реальное подключение клиента и состав модов проверяются в spike. --- # 19. Логи и консоль Предоставить wrappers: ```bash mcpack logs mcpack logs --follow mcpack console ``` Ожидаемый mapping: ```bash ssh host docker compose logs ``` и: ```bash ssh -t host docker exec -it rcon-cli ``` Не реализовывать собственный протокол Minecraft console. --- # 20. Версионирование Использовать semantic versioning для самого модпака: ```text MAJOR.MINOR.PATCH ``` Предлагаемая семантика: SemVer описывает масштаб изменений, но не гарантирует безопасность мира; совместимость отката оценивается отдельно. ## PATCH - исправления конфигурации; - небольшие compatibility fixes; - server tuning; - безопасные patch-update модов. ## MINOR - добавление модов; - удаление некритичных модов; - gameplay additions; - значимые изменения конфигурации. ## MAJOR - миграция версии Minecraft; - крупная миграция loader; - намеренно world-breaking изменения; - существенная переработка сборки. Не выводить версию Minecraft из semantic version самого модпака. --- # 21. Требования к воспроизводимости Для: ```bash git checkout v0.4.0 ``` проект должен воспроизвести ту же эффективную сборку при доступности внешних downloads. Побайтово одинаковый ZIP не обещается: timestamps и порядок упаковки могут отличаться. Idempotency deployment определяется checksum сохранённого релиза, а не повторным export. Git и .mrpack не гарантируют вечную доступность downloads. Готовые релизы хранить; offline cache/mirror — отдельная будущая возможность. Избегать: ```text latest recommended newest automatic unpinned loader versions ``` Фиксировать: - версию Minecraft; - loader; - моды; - digest container image и версию Java; - версию или commit packwiz и других инструментов, влияющих на build. Toolchain зафиксировать уже в spike; формат lock file уточнить после него. Пример: ```yaml packwiz: "..." itzg_image: "..." platform_schema: 1 ``` --- # 22. Git strategy Отслеживать: ```text platform/ pack/ server/ scripts/ Makefile README.md PLAN.md ``` Игнорировать: ```gitignore dist/* !dist/.gitkeep runtime/* !runtime/.gitkeep server/.env *.log backups/ ``` Создавать Git tags для релизов: ```bash git tag v0.4.0 ``` Потенциальный будущий release flow: ```bash mcpack release 0.4.0 ``` который: 1. валидирует дерево; 2. требует clean working copy; 3. обновляет версию; 4. выполняет build; 5. при ошибке восстанавливает прежнюю версию; 6. коммитит изменение версии в pack.toml; 7. собирает финальный release из чистого commit и генерирует checksums; 8. создаёт tag только после успешного build. При ошибке финального build tag не создаётся, состояние явно выводится. Не выполнять Git push автоматически в v1. --- # 23. Секреты Никогда не хранить в Git: - SSH private keys; - RCON passwords; - server secrets; - API tokens; - CurseForge credentials, если они потребуются; - credentials backup repository. Использовать: ```text .env environment variables SSH config ``` Предоставить: ```text .env.example ``` --- # 24. SSH configuration Предполагать, что администраторы могут определить: ```sshconfig Host minecraft HostName example.org User minecraft IdentityFile ~/.ssh/minecraft_ed25519 ``` Тогда platform config достаточно: ```yaml server: host: minecraft ``` Не требовать хранить SSH username или путь до private key в config, если это не нужно. --- # 25. Обработка ошибок Команды должны падать рано и с понятной диагностикой. Плохо: ```text deployment failed ``` Хорошо: ```text ERROR: packwiz export failed Command: packwiz modrinth export Exit status: 1 No files were uploaded to the server. ``` Этапы deployment должны быть явно видны. Например: ```text [1/7] Validate pack [2/7] Build release [3/7] Upload and verify release [4/7] Stop server and backup state [5/7] Apply release [6/7] Start and healthcheck [7/7] Record active release ``` --- # 26. Dry run Важная будущая возможность: ```bash mcpack deploy --dry-run ``` Команда должна показать: - какой локальный release будет собран; - destination host; - какие файлы будут загружены; - какой backup будет создан; - какое Compose-действие будет выполнено; - переход между active versions. Dry run не должен изменять локальное или удалённое состояние. Желательно предусмотреть эту возможность архитектурно с самого начала. --- # 27. Команда doctor Реализовать: ```bash mcpack doctor ``` Проверять локальное окружение: - packwiz установлен; - Docker установлен, если используются локальные server tasks; - SSH установлен; - rsync установлен; - Git repository корректен; - config валиден. Опциональные remote checks: ```bash mcpack doctor --remote ``` Проверять: - SSH connectivity; - доступность Docker; - доступность Docker Compose; - права на remote directory; - свободное место на диске. --- # 28. Этапы разработки ## Phase 0 — Spike Цель: Вручную проверить интеграцию компонентов экосистемы. Задачи: - создать минимальный packwiz pack; - выбрать и закрепить NeoForge или Forge и совместимую версию Minecraft; - добавить минимальный совместимый набор Modrinth-модов, включая gameplay-мод и client-only мод; - экспортировать `.mrpack`; - импортировать `.mrpack` в Prism; - запустить совместимый modded server через `itzg/minecraft-server`; - установить тот же pack на серверной стороне; - проверить, что клиент может подключиться; - проверить bind-mounted runtime и сохранение мира при recreate; - проверить client-only мод и его отсутствие на сервере; - обновить релиз, удалить мод и проверить отсутствие старого JAR; - проверить pack config, server override и ручные правки; - проверить defaultconfigs/datapacks на существующем мире; - создать backup остановленного сервера и восстановить его с прежним релизом; - проверить healthcheck и startup failure. Результат: ```text docs/spike-results.md ``` Не писать основной CLI до подтверждения integration path. Минимальные скрипты, Compose и каркас для spike допустимы. Prism import и подключение требуют реальной GUI-сессии; проверять offline-аккаунт/Launch Offline с сервером online-mode=false. При отсутствии GUI отметить проверки pending, а не passed. Acceptance criteria: - Prism импортирует сгенерированный pack; - сервер успешно запускается; - modded client с целевым loader подключается к серверу без онлайн-проверки аккаунта; - runtime-файлы существуют как обычные host-файлы. --- ## Phase 1 — Оформление каркаса после spike Статус: завершена для NeoForge 1.21.1. Каркас и проверка чистого локального clone описаны в `docs/phase1-results.md`. Platform manifest подключается к командам в Phase 2. Создать: - структуру репозитория; - `platform/config.yaml`; - `.gitignore`; - первоначальный packwiz pack; - первоначальный Compose-файл; - `.env.example`. Acceptance criteria: ```bash git clone packwiz refresh packwiz modrinth export docker compose config ``` выполняются успешно. --- ## Phase 2 — Build command Статус: завершена. `./mcpack build` читает platform config и создаёт полный development release 0.0.4; `--release` требует чистого Git worktree. Проверки и текущие ограничения описаны в `docs/phase2-results.md`, контракт — в `docs/build.md`. Реализовать: ```bash mcpack build ``` или первоначально: ```bash make build ``` Ответственность: - парсинг platform config; - валидация pack; - создание `dist`; - экспорт `.mrpack`; - детерминированное переименование артефакта; - генерация SHA-256; - генерация release manifest. Acceptance criteria: ```text dist/-/-.mrpack dist/-/server/ dist/-/SHA256SUMS dist/-/manifest.json ``` существуют после build. --- ## Phase 3 — Управление модами Статус: завершена. Mod wrappers сохраняют вывод/prompts/exit code packwiz. Реальные add/remove/update/update --all и четыре full build проверены в тестовом clone; результаты — `docs/phase3-results.md`, контракт — `docs/mods.md`. Предоставить тонкие wrappers: ```bash mcpack add mcpack remove mcpack update mcpack update --all ``` Не скрывать без необходимости сообщения об ошибках packwiz. Acceptance criteria: - добавленные моды появляются в metadata packwiz; - удаление мода корректно меняет source; - build остаётся валидным. --- ## Phase 4 — Server runtime Статус: завершена. Full release 0.0.4 проверен на пустом runtime через `scripts/server.sh`: pinned Minecraft/NeoForge/image, host bind mounts, restart/recreate без потери мира. Основной Phase 0 сервер не менялся. Результаты — `docs/phase4-results.md`, контракт — `docs/runtime.md`. Создать Docker runtime, который: - использует pinned Minecraft version; - использует pinned loader; - использует host bind mounts; - загружает сгенерированный pack; - сохраняет world между restart/recreate. Acceptance criteria: ```bash docker compose up -d ``` запускает сервер с пустой runtime directory после явной настройки EULA, host env, прав и путей согласно разделу 11. --- ## Phase 5 — Backups и восстановление Статус: завершена. `./mcpack backup` сохраняет весь остановленный runtime и исходный полный релиз под общей lifecycle lock; `restore` проверяет snapshot и восстанавливает только в новый root. Ошибка backup блокирует apply callback. Реальный backup/ошибка tar/запуск восстановленного NeoForge проверены на отдельном сервере; результаты — `docs/phase5-results.md`, инструкция — `docs/backups.md`. До remote deployment реализовать раздел 16: блокировку, остановку, backup и проверенную процедуру восстановления. Acceptance criteria: ошибка backup блокирует применение; snapshot восстанавливается в отдельный каталог; данные модов вне world сохраняются. --- ## Phase 6 — Healthcheck Статус: завершена. `scripts/server.sh up/start/restart --wait` и `health` проверяют штатный mc-health, свежий Minecraft status query и окно стабильности. Реальные timeout, crash с exit 137 и restart loop проверены на отдельных test roots; ошибки возвращают non-zero с report/logs и recovery state. Результаты — `docs/phase6-results.md`, контракт — `docs/health.md`. Реализовать раздел 18. Успешный старт возвращает 0; crash, restart loop и timeout — non-zero с указанием logs. --- ## Phase 7 — SSH Deployment Статус: завершена для проверенного NeoForge 1.21.1. `mcpack deploy` использует SSH/rsync, общую host lock, immutable checksums, проверку ручных конфликтов, backup-before-apply и healthcheck перед active/previous pointers. Полный update flow проверен на локальном SSH-стенде; clean release 0.0.4 реально установлен и healthy на crab@192.168.1.61:2228 в отдельном root. Повторный deploy — no-op. Результаты — `docs/phase7-results.md`, контракт — `docs/deploy.md`. Реализовать полный flow раздела 12 с готовыми backup и healthcheck. Acceptance criteria: - первый релиз устанавливается на host с готовыми зависимостями; установка Docker и cloud provisioning вне scope; - повторный deploy healthy релиза не перезапускает сервер; - та же версия с другим содержимым отклоняется; - world сохраняется; - параллельная операция блокируется; - сбой передачи, backup или startup оставляет восстановимое состояние; - ручные конфликты конфигов выявляются до замены файлов. --- ## Phase 8 — Rollback Статус: завершена. Реализованы pack-only и snapshot rollback по SSH без build. Результаты и ограничения: [docs/phase8-results.md](docs/phase8-results.md). Acceptance criteria: ```bash mcpack rollback ``` без указания режима ничего не меняет. Явный rollback использует сохранённый полный релиз без повторного build; pack-only требует подтверждения совместимости. Восстановление persistent snapshot автоматизировано и проверено на изолированном SSH/Docker-стенде. Оба режима требуют явного подтверждения и проверенного backup текущего состояния; pointers меняются после health. Ручной recovery после ошибки описан в [docs/rollback.md](docs/rollback.md). --- ## Phase 9 — Release workflow Статус: завершена. Candidate build, version commit, чистый финальный build, checksums и annotated tag проверены с настоящим packwiz в отдельном Git clone. Результаты: [docs/phase9-results.md](docs/phase9-results.md). Workflow и recovery: [docs/releases.md](docs/releases.md). Реализовано: ```bash mcpack release ``` Проверки: - Git worktree чистый; - version валидна и ещё не занята релизом или tag; - версия явно обновляется в pack.toml согласно разделу 22; - build успешен; - checksum создан; - Git tag создан. Публикация остаётся вне scope первой версии. --- # 29. Выбор языка реализации Не принимать решение преждевременно. Начать с: ```text Makefile + shell ``` если этого достаточно. Перейти к полноценному CLI, когда orchestration станет сложным. Возможные варианты: ## Go Преимущества: - один binary; - отличный CLI tooling; - удобно работать с SSH/process orchestration; - простая cross-platform distribution; - strong typing. Предпочтительный вариант, если платформа станет переиспользуемым инструментом. ## Python Преимущества: - быстрая разработка; - хорошая экосистема YAML/TOML; - удобно писать automation. Недостаток: - управление runtime/environment. ## Shell Преимущества: - минимум начального кода; - прозрачность. Недостатки: - error handling; - portability; - сложное state management; - тестирование. Рекомендация: Для integration spike использовать shell/Makefile. Если проект переживёт spike и deployment-логика начнёт расти, реализовать основной CLI на Go. --- # 30. Предлагаемая структура Go CLI Если выбран Go: ```text cmd/ └── mcpack/ └── main.go internal/ ├── config/ ├── packwiz/ ├── build/ ├── deploy/ ├── backup/ ├── health/ ├── ssh/ ├── docker/ ├── release/ └── cli/ ``` Ключевое правило: Integration packages должны оборачивать внешние инструменты, а не переписывать их функциональность. Например: ```text internal/packwiz ``` должен вызывать packwiz и переводить только релевантный платформе результат. Он не должен реализовывать Modrinth dependency resolver. --- # 31. Абстракция выполнения команд При переходе к Go создать executor по требованиям реальных вызовов; spike не требует этой абстракции. Концепция: ```go type Executor interface { Run(ctx context.Context, name string, args ...string) error } ``` Позже реализовать: - local executor; - SSH executor; - dry-run executor. Это даст: - testability; - command logging; - dry runs; - единообразные ошибки. --- # 32. Модель состояния Не использовать скрытую database платформы в v1. Предпочитать state, представленный через: ```text Git filesystem release manifest active-release ``` Remote state: ```text releases/ active-release previous-release deployment-state.json backups/ runtime/ ``` Состояние должно намеренно оставаться inspectable и repairable без binary самой платформы. --- # 33. Idempotency Команды должны нормально переносить повторный запуск. Например: ```bash mcpack build ``` может заменять локальный development artifact. Финализированный release неизменяем: совпадающие checksums дают no-op, другое содержимое требует новой версии. Сборка выполняется во временном каталоге. ```bash mcpack deploy ``` должен сверять checksums всего релиза и различать uploaded, applied и healthy active state. ```bash mcpack backup ``` должен создавать уникальные timestamped backups. Не полагаться на одноразовое hidden initialization state, которое нельзя восстановить. --- # 34. Стратегия тестирования ## Unit tests Для внутреннего кода платформы: - config parsing; - validation; - release naming; - version parsing; - command generation; - manifest generation. ## Integration tests Использовать временные директории для: - pack build; - release layout; - атомарного переключения `active-release` после healthcheck; - backup archive и восстановления в отдельный каталог; - блокировок, interrupted deployment и отказа при несовпадении checksums; - конфликтов управляемых конфигов и сохранения неизвестных файлов. ## External integration tests Ручные или opt-in: - packwiz; - Docker; - SSH; - реальный запуск Minecraft. Не требовать запуск Minecraft-сервера при каждом unit test run. --- # 35. Fixtures Создать небольшие test fixtures. Например: ```text testdata/ ├── minimal-pack/ ├── invalid-config/ ├── valid-config/ └── fake-runtime/ ``` Fixtures должны быть минимальными. Не коммитить Minecraft binaries или крупные mod jars в test data. --- # 36. Observability CLI должен выводить достаточно информации для диагностики проблем. Для всех внешних команд предусмотреть verbose logging. Например: ```bash mcpack deploy --verbose ``` Возможный output: ```text remote host: minecraft remote path: /srv/minecraft/friday release: 0.4.0 artifact sha256: ... ``` Никогда не выводить секреты. --- # 37. Будущая возможность: hosting сборок Позже можно добавить optional HTTP publication. Возможная архитектура: ```text build │ ├── .mrpack └── packwiz files │ ▼ static HTTP host ``` Возможные сценарии: - Prism import по URL; - автоматические packwiz updates; - сервер сам забирает pack; - release index. Не входит в v1. --- # 38. Будущая возможность: автообновление клиентов Потенциальное решение: - разместить packwiz files по HTTP; - использовать Prism-compatible bootstrap/update mechanism; - игрок импортирует pack один раз; - pack обновляется автоматически перед launch. Не реализовывать до стабилизации базового release/deployment flow. --- # 39. Будущая возможность: CI/CD Потенциальный pipeline: ```text git push │ ▼ validate │ ▼ build │ ▼ publish artifact │ ▼ optional deploy ``` Возможные провайдеры: - GitHub Actions; - GitLab CI; - Gitea Actions; - self-hosted CI. Не делать CI обязательным. Локальные команды остаются каноническими. --- # 40. Будущая возможность: несколько серверов В будущем конфигурация может поддерживать: ```yaml servers: survival: host: mc-prod directory: /srv/minecraft/survival test: host: mc-test directory: /srv/minecraft/test ``` Тогда: ```bash mcpack deploy survival mcpack deploy test ``` Не реализовывать, пока deployment на один сервер не станет стабильным. Config schema нужно проектировать так, чтобы такое расширение оставалось возможным. --- # 41. Будущая возможность: profiles Возможные profiles: ```text client server performance-client performance-server optional-content ``` Но сначала использовать side metadata packwiz. Не вводить собственную систему profiles без реального use case. --- # 42. Не-цели для v1 Не реализовывать: - собственный Minecraft launcher; - собственный mod repository; - собственный dependency solver; - web UI; - поддержку Kubernetes; - автоматический public hosting; - database; - multi-user authentication; - cloud provisioning; - автоматическую миграцию world; - автоматическое разрешение конфликтующих модов; - автоматический Git push; - dynamic container orchestration. v1 должна оставаться максимально простой и предсказуемой. --- # 43. Definition of Done для v1 Первая полезная версия готова, когда следующий flow работает надёжно: ```bash git clone mcpack doctor mcpack add create mcpack build # друг импортирует сгенерированный .mrpack в Prism mcpack deploy mcpack logs ``` И выполняются следующие свойства: - client artifact импортируется в Prism; - сервер запускается из того же определения сборки; - клиент на NeoForge/Forge может подключиться без Microsoft/Mojang-аккаунта; - моды версионируются через packwiz; - server files хранятся как обычные директории на host; - world переживает recreation контейнера; - deployment выполняется через SSH; - pack можно пересобрать из Git; - перед любой сменой релиза существующего сервера создаётся проверенный backup; - предыдущий полный release и его persistent snapshot можно восстановить; - удаление мода, конфликт конфигов и failed deployment проверены; - для критичных данных не требуется Docker named volume. --- # 44. Первая задача для Codex Codex должен начать с integration spike, а не с реализации финального CLI. Задача: ```text Реализуй только Phase 0. Создай минимально возможный рабочий репозиторий, который доказывает: 1. packwiz может описывать модпак. 2. packwiz может экспортировать Modrinth .mrpack. 3. Prism Launcher может импортировать этот артефакт. 4. itzg/minecraft-server может запустить сервер на основе той же сборки. 5. Состояние сервера хранится в bind-mounted директории. 6. Модифицированный клиент Prism может подключиться к серверу. 7. Обновление удаляет старые моды и предсказуемо применяет конфиги. 8. Backup и восстановление persistent state с прежним релизом работают. Недоступные GUI-проверки отметить pending; Phase 0 не считать завершённой до фактического импорта и подключения. Пока не реализовывай mcpack CLI. Задокументируй все команды, предположения, точные версии инструментов, обнаруженные проблемы и любые необходимые изменения архитектуры в docs/spike-results.md. Не добавляй generated runtime data в Git. ``` --- # 45. Принципы реализации для Codex При реализации проекта: 1. Предпочитай простые и прозрачные механизмы. 2. Не дублируй функциональность, которую надёжно предоставляют packwiz или Docker. 3. Не вводи скрытое mutable state без веской причины. 4. Любой deployment должен быть восстановим. 5. Фиксируй версии. 6. Сохраняй возможность человеку напрямую работать с исходными файлами. 7. Разрушительные операции должны быть явными. 8. Делай backup перед изменением persistent Minecraft state. 9. Считай world более ценным, чем application runtime. 10. Client и server artifacts должны происходить из одного source pack. 11. По возможности держи код платформы независимым от конкретного modpack. 12. Не исправляй и не изменяй пользовательскую конфигурацию молча. 13. Команды должны возвращать осмысленные exit codes. 14. Ошибки внешних команд должны содержать полезный контекст. 15. Предпочитай deterministic output paths и имена артефактов. --- # 46. Ближайшие шаги Выполнять в таком порядке: ```text 1. Создать каркас репозитория. 2. Установить и зафиксировать версию packwiz. 3. Выбрать одну версию Minecraft. 4. Выбрать один loader. 5. Добавить минимальный заведомо совместимый набор модов. 6. Экспортировать .mrpack. 7. Импортировать его в Prism. 8. Создать Docker Compose для сервера. 9. Запустить сервер с bind-mounted runtime. 10. Подключиться к серверу из Prism. 11. Проверить обновление, удаление мода, конфиги, backup/restore и healthcheck. 12. Записать результаты spike и pending проверки. 13. После подтверждения критериев начинать разработку mcpack CLI. ``` Главный архитектурный вопрос, который необходимо проверить во время spike: > Может ли один и тот же source pack чисто порождать и Prism client experience, и Dockerized server runtime без ручного расхождения между ними? Если да — сохранить эту архитектуру. Если нет — задокументировать минимально необходимый слой трансформации между client/server до разработки дополнительного tooling.