diff --git a/personal/plans/balda-callee-prism-plan.md b/personal/plans/balda-callee-prism-plan.md index aeccdd0a..cf285bb7 100755 --- a/personal/plans/balda-callee-prism-plan.md +++ b/personal/plans/balda-callee-prism-plan.md @@ -272,7 +272,46 @@ Runner: Broker не должен парсить человекочитаемый ANSI/TTY-вывод Callee. Если Callee уже имеет стабильный machine-readable API, runner становится тонким адаптером. -## 9. Изоляция и секреты +## 9. Execution workers и распределение ресурсов + +Broker планирует не только macOS VM. Все среды исполняют один versioned Runner protocol, но имеют разные `runtime_class`: + +- `linux-container` — обычный код, CLI, Docker builds и инфраструктурная автоматизация; +- `macos-vm` — Xcode, macOS APIs, GUI и UI tests; +- `remote-host` — изменение конкретного хоста после Human approval. + +Минимальный WorkerSpec: + +```json +{ + "runtime_class": "macos-vm", + "worker_profile": "xcode-27", + "agent_profile": "codex-default", + "workflow_id": "prism/story", + "repository": "git@host:org/repo.git", + "revision": "main" +} +``` + +### Параллельные задачи + +Balda поддерживает несколько независимых chat sessions. Turns внутри одной session сериализуются, разные sessions могут работать параллельно. + +Callee поддерживает `Parallel`, но это fan-out Role visits внутри одного workflow. VM создаёт и распределяет Broker, не Balda и не Callee. + +Политика пула: + +1. Одна изменяющая macOS Story получает одну эксклюзивную VM. +2. Implementer, reviewer и verifier используют ту же VM, но свежие ACP-сессии. +3. Отдельная VM на каждый Role не создаётся. +4. Одновременно работают максимум две macOS VM; остальные run стоят в очереди. +5. Linux containers масштабируются отдельно и не занимают macOS VM slots. + +Параллельные read-only роли могут работать в одной VM. Параллельные изменения получают отдельные Git worktrees; запись нескольких агентов в один checkout запрещена политикой Runner. + +Ограничение в две macOS VM задаёт Apple Virtualization.framework, а не Balda. Практический лимит дополнительно зависит от RAM и CPU. + +## 10. Изоляция, shared folder и секреты Основная граница безопасности — одноразовая macOS VM. @@ -284,7 +323,35 @@ Broker не должен парсить человекочитаемый ANSI/TT Хостовый Virfield API разрешает только операции жизненного цикла VM. Balda и Broker не получают `docker.sock`, пользовательский `~/.ssh` или произвольный shell на Mac. -## 10. Неподтверждённое +### Shared folder Lume + +Lume монтирует shared folder через virtiofs. Изменения содержимого должны появляться динамически; Lume также умеет добавлять folder к уже запущенной VM без reboot/remount. + +Для mutable workspace и Xcode build shared folder не считается надёжным источником истины. В текущем Virfield уже потребовались `sudo purge` и уникальные DerivedData snapshots из-за stale guest cache. + +Рабочий контракт: + +- репозиторий клонируется на локальный диск VM; +- обновления передаются через Git или `rsync/scp`; +- shared folder используется для immutable inputs и выгрузки artifacts; +- каждый набор artifacts получает уникальный путь `run_id/...`; +- Xcode не собирает проект непосредственно из `/Volumes/My Shared Files`. + +### Изменение других хостов + +Задачи настройки Mac, Kraken, TrueNAS и других машин используют `runtime_class: remote-host`. + +1. Agent в контейнере формирует plan и выполняет read-only preflight. +2. Balda показывает точный diff действий и запрашивает Human approval. +3. Broker выдаёт capability lease на конкретные host, identity, operations и TTL 15–30 минут. +4. Runner применяет изменения через dedicated service account или установленный host-runner. +5. Verify, audit log и rollback закрывают lease. + +Личные ключи из пользовательского `~/.ssh` не передаются. Для managed host используется небольшой Go host-runner. Для первичного bootstrap допускается отдельный SSH account с short-lived certificate и ограниченным `sudo`. + +Изменения самого Mac выполняет отдельный native launchd helper. Он принимает подписанный capability lease; Balda и модель не получают постоянный host shell. + +## 11. Неподтверждённое ### Блокирует прототип @@ -302,7 +369,7 @@ Broker не должен парсить человекочитаемый ANSI/TT - восстановление Broker после падения во время `waiting_human`; - параллельные Story и лимиты VM/CPU/RAM на Mac. -## 11. Варианты +## 12. Варианты ### A. Sidecar Broker + VM runner — выбран @@ -320,7 +387,69 @@ Balda остаётся оркестратором, Broker изолирует и Будущая transport abstraction в `runtime + acpagent` позволит Balda или Callee подключаться к ACP по WebSocket/Streamable HTTP. Она может заменить SSH-транспорт, но не заменяет Broker, VM lifecycle, durable events и cleanup. -## 12. Pitfalls +## 13. Аудит Virfield и целевая версия v2 + +### Что существует сейчас + +Virfield — TypeScript/Node.js приложение: + +- Express + WebSocket backend; +- React/Vite Web UI; +- SQLite; +- отдельный stdio MCP server; +- shell/Python provisioning scripts. + +Web UI уже реализован. TypeScript typecheck проходит. Собственной automated test suite практически нет. + +### Подтверждённые архитектурные проблемы + +1. Состояние VM определяется одновременно Lume API, Lume CLI, SQLite, JSON-файлами, PID и in-memory maps. +2. REST и MCP дублируют orchestration; MCP вызывает REST, а при ошибке обходит его и управляет Lume напрямую. +3. Recovery основан на `pgrep`, `pkill`, PID probing и ручном склеивании stale states. +4. Virfield читает личные SSH keys, имеет password fallback `lume`, хранит GitHub PAT в SQLite и предоставляет широкий `vm_ssh_exec`. +5. Long-running jobs частично живут только в памяти и теряют нормальную управляемость после restart. + +### Решение: переписать control plane, не Lume + +Lume остаётся hypervisor/backend. Проверенные provisioning scripts временно сохраняются как versioned jobs и постепенно заменяются только при наличии тестов. + +Virfield v2 состоит из пяти частей: + +1. `virfieldd` на Go — единственный владелец SQLite, Lume adapter, VM leases, jobs, events и cleanup; запускается через `launchd`. +2. Image Manager — модуль `virfieldd` для download/pull/build/promote golden images; отдельный daemon ему не нужен. +3. Web UI — отдельный API client на embedded HTML/HTMX или простом JavaScript без Node toolchain. +4. `virfield-mcp` на Go — тонкий stdio/HTTP adapter; не обращается к Lume или SQLite напрямую. +5. Execution Broker и Runner на Go — отдельный execution-контур рядом с Balda и внутри workers. + +Один Lume adapter скрывает различия HTTP/CLI. UI, MCP и Broker используют только versioned API `virfieldd`. + +Оценка: Virfield v2 MVP — 7–12 рабочих дней; Broker/Runner — 5–10 дней; UI migration и hardening — ещё 5–8 дней. + +## 14. Agent profiles и модельная политика + +Broker и Runner не содержат vendor-specific workflow logic. Run выбирает `agent_profile` из статического allowlist. + +Для Callee напрямую подтверждены Codex, Claude, Copilot, Grok, OpenCode и Cursor. Gemini и GLM подключаются через `generic_acp` или отдельный ACP adapter и считаются неподтверждёнными до integration test. + +Worker image содержит Runner, Callee и нужные provider binaries. Credentials выбранного provider выдаются только на срок run. Node отсутствует в Virfield/Broker control plane; он допускается внутри специализированного worker image, если конкретный agent CLI без него не работает. + +### Распределение моделей + +Схема `Balda → Callee → coding agent` остаётся правильной. Текущее назначение DeepSeek единственным оркестратором не оптимально: Balda использует один app-scoped provider для всех sessions. + +Рекомендуемая раскладка: + +- Balda — надёжное понимание запроса, выбор workflow, управление state и Human interaction; +- specify/design/review — сильная reasoning-модель; +- implementation — Codex или другой сильный coding agent; +- build/test/SSH apply — детерминированные Script/Runner operations; +- дешёвая модель — routing, summarization и простая диагностика. + +DeepSeek подходит для ограниченного routing и простых операций с жёсткими tool schemas. Он не принимает самостоятельные решения о privileged SSH-командах и сложной архитектуре. + +Оптимизация стоимости строится на deterministic routing, token/run budgets, bounded retries и escalation: после повторной неудачи задача повышает model tier, а не повторяет дешёвую модель бесконечно. + +## 15. Pitfalls ### Архитектура @@ -346,49 +475,57 @@ Balda остаётся оркестратором, Broker изолирует и 4. Host path, переданный как ACP cwd, не существует или указывает не туда внутри VM. 5. VM с доступом в локальную сеть может атаковать хостовые сервисы; egress и host API нужно ограничить. -## 13. План реализации Broker +### Исполнение и ресурсы -### Этап 1 — spike контрактов, 4–8 часов +1. Mutable build через virtiofs может прочитать stale content; workspace должен жить на локальном диске worker. +2. Более двух активных macOS VM невозможны; Broker обязан иметь очередь и admission control. +3. Parallel Callee roles, пишущие в один checkout, создают file conflicts даже внутри одной VM. +4. Свободный provider command или agent-generated `cmd` превращает профиль в arbitrary code execution. +5. Установка всех provider credentials в один golden image нарушает isolation и усложняет rotation. -1. Запустить один Callee workflow вручную внутри тестовой VM. -2. Зафиксировать фактический stdout/API, Human pause/resume и cancel. -3. Запустить Codex Role через локальный ACP stdio. -4. Проверить workspace path, build и terminal result. -5. Принять формат VM runner protocol на основании фактов. +## 16. План реализации -Результат: подтверждённый протокол Callee/runner без предположений. +### Этап 1 — live spike контрактов, 1–2 дня -### Этап 2 — Virfield control API, 4–8 часов +1. Запустить Virfield и Lume и проверить clone/start/stop/delete без fallback paths. +2. Проверить stale-cache сценарии shared folder и зафиксировать Git/rsync contract. +3. Запустить один Callee workflow вручную внутри тестовой VM. +4. Проверить Codex ACP, Human pause/resume, cancel и terminal result. +5. Принять versioned contracts Virfield API и VM Runner. -1. Обернуть существующий `vm_prepare_session` в узкий authenticated HTTP API. -2. Добавить операции lease status, stop и delete. -3. Ограничить templates, TTL и число параллельных VM. -4. Добавить idempotency key и audit log. -5. Проверить cleanup после таймаута и падения клиента. +Результат: фактические runtime-контракты без предположений. -Результат: Broker может безопасно получить и освободить VM без host shell. +### Этап 2 — Virfield v2 core, 7–12 дней -### Этап 3 — VM runner, 1–2 дня +1. Реализовать `virfieldd` и единую SQLite job/event model. +2. Реализовать один Lume adapter и reconciliation loop. +3. Добавить leases, idempotency, quotas, audit и cleanup. +4. Подключить существующие image/provisioning scripts как jobs. +5. Реализовать Go CLI/MCP adapters и минимальный Web UI. + +Результат: один надёжный владелец VM и images без Node runtime. + +### Этап 3 — универсальный Runner, 2–4 дня 1. Описать versioned JSON protocol command/event. 2. Реализовать start, events, Human response и cancel. -3. Подключить Callee workflow pack и Codex ACP. +3. Подключить Callee workflow pack и allowlisted agent profiles. 4. Сформировать artifact manifest для git diff, commit, logs и `.xcresult`. 5. Добавить terminal result и гарантированное завершение дочерних процессов. -Результат: одна команда запускает workflow в VM и возвращает структурированные события. +Результат: один протокол запускает workflow в VM или container и возвращает структурированные события. -### Этап 4 — Broker MVP, 1–2 дня +### Этап 4 — Broker MVP, 3–6 дней 1. Реализовать SQLite schema для runs, events, responses и artifacts. 2. Реализовать state machine и транзакционный event journal. -3. Подключить Virfield API и SSH/runner transport. +3. Подключить Virfield API, container driver и Runner transport. 4. Опубликовать MCP tools из §8. 5. Добавить restart recovery, lease renewal и cleanup worker. Результат: Balda управляет долговечным run через HTTP MCP. -### Этап 5 — Balda + Prism, 1–2 дня +### Этап 5 — Balda + Prism, 2–4 дня 1. Подключить Broker MCP к runtime Balda. 2. Развернуть Prism adapter и Dolt/Beads container. @@ -398,7 +535,7 @@ Balda остаётся оркестратором, Broker изолирует и Результат: Story ведётся в Beads, выполнение и approvals видны в Mattermost. -### Этап 6 — сквозная приёмка, 4–8 часов +### Этап 6 — сквозная приёмка, 1–2 дня 1. Создать Story из реального сообщения Mattermost. 2. Пройти specify/design/approval/implement/review/verify. @@ -408,15 +545,18 @@ Balda остаётся оркестратором, Broker изолирует и Результат: воспроизводимый end-to-end прогон без исполнения агентских команд на хосте. -Оценка MVP после spike: 4–7 рабочих дней. Production hardening зависит от возможностей Callee API и обычно добавит 3–7 дней. +Оценка после spike: рабочий end-to-end MVP — 17–30 рабочих дней. Срок сильнее всего зависит от Callee machine API, Lume reconciliation и переноса Web UI. -## 14. Критерии готовности +## 17. Критерии готовности 1. Balda создаёт одну Story и один idempotent run из сообщения Mattermost. 2. Все команды Codex, Xcode build и тесты исполняются внутри leased VM. 3. Callee управляет ролями и циклами; Broker не содержит workflow policy. 4. После рестарта Balda или Broker прогресс восстанавливается без двойного запуска. 5. Terminal run обновляет Beads, публикует артефакты и удаляет VM по lease policy. +6. Linux-задачи исполняются в containers и не занимают macOS VM slots. +7. Remote-host задача не использует личные SSH keys и не выполняется без capability lease. +8. UI и MCP показывают одно состояние из `virfieldd`, без собственных fallback orchestration paths. ## Связанные заметки