Files
obsidian-vault/personal/plans/balda-callee-prism-plan.md
T

22 KiB
Executable File
Raw Blame History

Balda + Prism/Beads + Execution Broker + Callee + Codex

Обновлено: 2026-09-29
Статус: целевая архитектура зафиксирована; Broker и интеграции ещё не реализованы.

1. Цель

Balda принимает задачу в Mattermost, ведёт её состояние в Prism/Beads и запускает изолированное выполнение в одноразовой macOS VM.

Код, сборка, тесты и Xcode выполняются только внутри VM. Хост Mac управляет VM через Virfield, но не исполняет команды агента в основной системе.

Единственная целевая цепочка исполнения:

Mattermost
  → Balda
  → Execution Broker
  → Virfield на Mac
  → macOS VM
  → Callee workflow
  → Codex ACP sessions

Контур состояния задачи:

Balda
  → Prism adapter
  → bd
  → Dolt/Beads database

Обратный поток:

Codex
  → ACP result
  → Callee event
  → Broker event log
  → Balda
  → Prism/Beads + Mattermost

2. Что уже есть

Подтверждено

  1. Balda работает в Docker на Mac и отвечает в Mattermost.
  2. Mattermost-сервер остаётся на Kraken; Balda подключается к нему с Mac.
  3. Obsidian MCP доступен Balda по http://host.docker.internal:3101/sse.
  4. Virfield MCP работает на хостовом Mac и умеет подготовить VM: clone golden image, start, wait for IP/SSH, create tunnel.
  5. Host Codex и Claude уже подключены к Virfield MCP.

Текущая конфигурация Balda

  • основной provider: DeepSeek через OpenAI-compatible API;
  • permissions.mode: allow_all;
  • workspace.mode: off;
  • Virfield в Balda не подключён;
  • Callee CLI и описания агентов находятся в окружении Balda по текущему сетапу, но целевой запуск Callee должен происходить внутри VM.

Чего пока нет

  • Execution Broker;
  • сетевого API управления Virfield для Broker;
  • VM runner для управляемого запуска Callee;
  • обратного журнала событий Callee → Balda;
  • адаптера Balda → Prism/Beads;
  • подтверждённого сквозного запуска Story → VM → build/test → отчёт.

3. Владельцы ответственности

Balda — оркестратор верхнего уровня

Balda:

  • принимает задачу и уточнения из Mattermost;
  • создаёт и обновляет Story в Prism/Beads;
  • выбирает разрешённый workflow по его идентификатору;
  • запускает выполнение через Broker;
  • показывает запросы Human и итог пользователю.

Balda не управляет процессами внутри VM напрямую. Она работает только через контракты Prism adapter и Execution Broker.

Prism adapter + Beads — долговременное состояние

Prism adapter принадлежит контуру Balda и физически может быть отдельным sidecar-контейнером.

Он:

  • предоставляет Balda узкие операции Story/Task/phase;
  • вызывает bd;
  • подключается к Dolt/Beads database в соседнем контейнере;
  • обеспечивает идемпотентную запись событий Broker;
  • остаётся единственным писателем предметного состояния задачи.

Broker, Callee и Codex не пишут в Beads напрямую. Они возвращают факты выполнения, а Balda решает, как отразить их в Story.

Execution Broker — инфраструктурный исполнитель

Broker живёт отдельным sidecar-контейнером рядом с Balda.

Он:

  • получает от Balda команду запуска;
  • арендует VM через Virfield;
  • запускает VM runner и Callee;
  • хранит техническое состояние run и журнал событий;
  • передаёт ввод, отмену и ссылки на артефакты.

Broker не выбирает workflow, не исполняет его граф и не меняет Prism/Beads.

Virfield — граница управления хостом

Virfield работает на Mac-хосте и владеет жизненным циклом VM:

  • clone/start/stop/delete;
  • IP и SSH readiness;
  • сетевые туннели;
  • lease и принудительная уборка VM.

Для Broker нужен узкий аутентифицированный HTTP API или HTTP MCP-обёртка над этими операциями. Произвольного host shell в этом API нет.

Callee и Codex — выполнение внутри VM

Callee исполняет workflow: фазы, ветвления, циклы, Human-паузы и запуск ролей.

implementer, reviewer, verifier — роли Callee. Каждая роль запускает новую Codex ACP-сессию с отдельным prompt и контекстом.

Codex изменяет код, запускает xcodebuild, тесты и другие команды внутри VM. Codex не запускает Callee и не управляет Story.

4. Prism и prism-callee

Официальный prism-callee — плагин к coding-agent host. В штатной схеме он делает coding agent владельцем Beads и запускателем Callee:

Codex → prism-callee skill → Callee → дочерние Codex sessions

Эта штатная топология не является целевой, потому что верхним оркестратором должен оставаться Balda.

В целевой схеме используются отдельно:

  • lifecycle и правила Prism — как основа skill/адаптера Balda;
  • Callee workflow pack — как версионируемые workflow-файлы внутри VM;
  • Beads — через отдельный Prism adapter;
  • Codex — только как исполнитель ролей Callee.

До реализации требуется проверить, какие части официального плагина можно импортировать без изменений, а какие нужно адаптировать для Balda.

5. Прямой data flow

  1. Пользователь ставит задачу Balda в Mattermost.
  2. Balda через Prism adapter создаёт Story и получает story_id.
  3. Balda выбирает workflow_id из статического allowlist и вызывает execution_start.
  4. Broker просит Virfield создать VM, затем запускает внутри неё VM runner и Callee.
  5. Callee выполняет граф и для каждой Role запускает локальный Codex через ACP stdio.

Минимальный запрос запуска:

{
  "idempotency_key": "story:bd-42:attempt:1",
  "story_id": "bd-42",
  "workflow_id": "prism/story",
  "workflow_version": "pinned-git-sha",
  "repository": "git@host:org/repo.git",
  "revision": "main",
  "vm_template": "macos-27-golden",
  "task": "Добавить CSV export"
}

Broker возвращает run_id сразу после надёжной записи команды. Подготовка VM продолжается асинхронно.

6. Обратный data flow

  1. Codex возвращает результат роли в Callee по ACP.
  2. Callee переводит workflow в следующее состояние и отдаёт структурированное событие VM runner.
  3. VM runner передаёт событие Broker; Broker сохраняет его до ответа Balda.
  4. Balda читает события через execution_events(run_id, after_event_id) и подтверждает курсор.
  5. Balda обновляет Story через Prism adapter и публикует значимые изменения в Mattermost.

События доставляются как минимум один раз. Повторная доставка безопасна благодаря уникальному (run_id, event_id).

Минимальное событие:

{
  "event_id": 17,
  "run_id": "run-123",
  "story_id": "bd-42",
  "type": "role_completed",
  "phase": "review",
  "role": "reviewer",
  "status": "passed",
  "summary": "Tests pass",
  "artifacts": [
    {"kind": "git_commit", "ref": "abc123"},
    {"kind": "xcresult", "ref": "artifact://run-123/tests"}
  ]
}

Тяжёлые логи и .xcresult не помещаются в журнал. Broker хранит только ссылки, checksum, размер и срок жизни.

7. Human approval

  1. Callee доходит до Human node и приостанавливает workflow.
  2. VM runner отправляет human_required с вопросом и вариантами.
  3. Broker фиксирует состояние waiting_human.
  4. Balda показывает вопрос в Mattermost и получает ответ в том же session/topic.
  5. Balda вызывает execution_respond; Broker доставляет ответ в конкретный paused run.

Связка обязательна: chat_id/topic_id ↔ story_id ↔ run_id ↔ human_request_id.

Ответ должен быть идемпотентным: повторный human_request_id не возобновляет workflow дважды.

8. Execution Broker: контракт

Где живёт

Отдельный контейнер в одном Docker network с Balda. У Broker собственный persistent volume с SQLite.

Northbound: HTTP MCP для Balda.
Southbound: узкий HTTP API Virfield и SSH к выданной VM.
Внутри VM: VM runner → Callee → Codex ACP stdio.

MCP tools

  1. execution_start(request) → run_id
  2. execution_status(run_id) → state, phase, last_event_id
  3. execution_events(run_id, after_event_id) → events, next_cursor
  4. execution_respond(run_id, human_request_id, answer)
  5. execution_cancel(run_id, reason) и execution_artifacts(run_id)

Состояния run

accepted
→ provisioning
→ booting
→ running
→ waiting_human
→ running
→ succeeded | failed | canceled | expired

Каждый переход записывается транзакционно вместе с событием. После рестарта Broker продолжает незавершённые run или переводит их в явно диагностируемое состояние.

Внутреннее состояние Broker

Broker хранит только технические данные:

  • run_id, story_id, idempotency key;
  • VM id, IP, lease deadline;
  • workflow id/version и process/session id;
  • event cursor, terminal status и error code;
  • artifact references и cleanup status.

VM runner

Нужен небольшой процесс внутри образа VM. Он отделяет Broker от консольного формата Callee.

Runner:

  • проверяет входной manifest и allowlist workflow;
  • запускает Callee в рабочей директории репозитория;
  • преобразует lifecycle/output в стабильные JSON events;
  • принимает cancel и Human response;
  • возвращает terminal result и artifact manifest.

Broker не должен парсить человекочитаемый ANSI/TTY-вывод Callee. Если Callee уже имеет стабильный machine-readable API, runner становится тонким адаптером.

9. Изоляция и секреты

Основная граница безопасности — одноразовая macOS VM.

  • исходный проект клонируется в VM без host bind mounts;
  • Codex, Callee, Xcode и тесты работают внутри VM;
  • Broker получает только scoped SSH key для конкретной VM;
  • Git credentials выдаются на один репозиторий и ограниченный срок;
  • VM удаляется после выгрузки результатов или по lease timeout.

Хостовый Virfield API разрешает только операции жизненного цикла VM. Balda и Broker не получают docker.sock, пользовательский ~/.ssh или произвольный shell на Mac.

10. Неподтверждённое

Блокирует прототип

  1. Есть ли у Callee стабильный machine-readable event stream и программный resume Human node.
  2. Можно ли запустить workflow pack prism/story отдельно от stock plugin host.
  3. Как Codex ACP получает workspace/cwd и сохраняет его между Role visits.
  4. Как передавать cancel в Callee без повреждения terminal result.
  5. Какой минимальный Virfield API можно безопасно открыть Broker.

Требует проверки до production

  • установка и авторизация Codex внутри golden VM;
  • доступность Dolt/Beads из Prism adapter после рестартов;
  • формат и размер Xcode артефактов;
  • восстановление Broker после падения во время waiting_human;
  • параллельные Story и лимиты VM/CPU/RAM на Mac.

11. Варианты

A. Sidecar Broker + VM runner — выбран

Balda остаётся оркестратором, Broker изолирует инфраструктуру, Callee владеет workflow, Codex работает в VM. Это целевая схема.

B. Broker как host daemon

Меньше сетевых переходов к Virfield и SSH, но Broker получает более широкую поверхность хоста. Использовать только если контейнерный sidecar не может надёжно управлять VM.

C. Stock prism-callee plugin

Codex → plugin → Callee → Codex. Быстрее для проверки Prism, но Balda перестаёт быть владельцем lifecycle. Подходит как временный reference test, не как production topology.

D. Native remote ACP

Будущая transport abstraction в runtime + acpagent позволит Balda или Callee подключаться к ACP по WebSocket/Streamable HTTP. Она может заменить SSH-транспорт, но не заменяет Broker, VM lifecycle, durable events и cleanup.

12. Pitfalls

Архитектура

  1. Смешивание двух топологий: stock Codex → Callee и целевой Balda → Broker → Callee.
  2. Перенос workflow-логики в Broker превращает его во второй оркестратор.
  3. Прямая запись Broker/Callee/Codex в Beads создаёт несколько владельцев состояния.
  4. Запуск Callee вне VM переносит Script nodes и часть команд на хост.
  5. Парсинг консольного вывода Callee вместо стабильного event protocol ломает resume и диагностику.

Надёжность

  1. Потеря события между Callee и Balda без durable event log.
  2. Двойной запуск VM без idempotency key.
  3. Повторный Human response возобновляет workflow дважды.
  4. Падение Broker оставляет VM без lease и cleanup.
  5. Большие build-логи забивают SQLite или MCP-ответы.

Безопасность

  1. Непроверенный workflow_id, repository URL или revision превращается в выполнение произвольного ввода.
  2. Общий SSH/Git credential между VM расширяет последствия компрометации.
  3. Секреты в prompt, events или build logs попадают в Mattermost/Beads.
  4. Host path, переданный как ACP cwd, не существует или указывает не туда внутри VM.
  5. VM с доступом в локальную сеть может атаковать хостовые сервисы; egress и host API нужно ограничить.

13. План реализации Broker

Этап 1 — spike контрактов, 4–8 часов

  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 на основании фактов.

Результат: подтверждённый протокол Callee/runner без предположений.

Этап 2 — Virfield control API, 4–8 часов

  1. Обернуть существующий vm_prepare_session в узкий authenticated HTTP API.
  2. Добавить операции lease status, stop и delete.
  3. Ограничить templates, TTL и число параллельных VM.
  4. Добавить idempotency key и audit log.
  5. Проверить cleanup после таймаута и падения клиента.

Результат: Broker может безопасно получить и освободить VM без host shell.

Этап 3 — VM runner, 1–2 дня

  1. Описать versioned JSON protocol command/event.
  2. Реализовать start, events, Human response и cancel.
  3. Подключить Callee workflow pack и Codex ACP.
  4. Сформировать artifact manifest для git diff, commit, logs и .xcresult.
  5. Добавить terminal result и гарантированное завершение дочерних процессов.

Результат: одна команда запускает workflow в VM и возвращает структурированные события.

Этап 4 — Broker MVP, 1–2 дня

  1. Реализовать SQLite schema для runs, events, responses и artifacts.
  2. Реализовать state machine и транзакционный event journal.
  3. Подключить Virfield API и SSH/runner transport.
  4. Опубликовать MCP tools из §8.
  5. Добавить restart recovery, lease renewal и cleanup worker.

Результат: Balda управляет долговечным run через HTTP MCP.

Этап 5 — Balda + Prism, 1–2 дня

  1. Подключить Broker MCP к runtime Balda.
  2. Развернуть Prism adapter и Dolt/Beads container.
  3. Реализовать отображение events → Story phases.
  4. Связать Human request с Mattermost session/topic.
  5. Сформировать финальный отчёт Result/Artifacts/Confidence/Next action.

Результат: Story ведётся в Beads, выполнение и approvals видны в Mattermost.

Этап 6 — сквозная приёмка, 4–8 часов

  1. Создать Story из реального сообщения Mattermost.
  2. Пройти specify/design/approval/implement/review/verify.
  3. Собрать Xcode-проект и запустить тесты внутри VM.
  4. Перезапустить Broker во время run и проверить восстановление.
  5. Проверить terminal cleanup VM и доступность артефактов.

Результат: воспроизводимый end-to-end прогон без исполнения агентских команд на хосте.

Оценка MVP после spike: 4–7 рабочих дней. Production hardening зависит от возможностей Callee API и обычно добавит 3–7 дней.

14. Критерии готовности

  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.

Связанные заметки