[2026-09-29] eagle: personal/plans/balda-callee-prism-plan.md
This commit is contained in:
1 parent
afabb21c25
commit
1c2d734ace
1 file changed
+131
-32
@@ -7,49 +7,148 @@
|
||||
|
||||
## 1. Целевая архитектура
|
||||
|
||||
**Принцип: стек — единое целое по признаку «работает с файлами на Mac».** Всё, что трогает
|
||||
код, сборку, тесты, хосты, обязано быть рядом. Всё, что только принимает сообщения — может
|
||||
жить отдельно.
|
||||
|
||||
```
|
||||
Mattermost (Alex)
|
||||
│ «добавь CSV-экспорт в отчёт»
|
||||
▼
|
||||
Балда-оркестратор (Kraken, DeepSeek, balda-mm:0.1.13)
|
||||
│ приём сообщения, чтение Obsidian, контекст, ответ в чат
|
||||
│ MCP-инструмент executor_run
|
||||
▼
|
||||
MCP-сервер balda-executor-mcp (Kraken, :8890, сеть mattermost_mm-net)
|
||||
│ HTTP + X-Bridge-Secret
|
||||
▼
|
||||
Мост agents-bridge (Mac, :8790, launchd com.agents.bridge)
|
||||
│ запускает `callee agent run <resource> --message <prompt>`
|
||||
▼
|
||||
callee CLI (контейнер balda-executor, Mac)
|
||||
│ компилирует граф → валидирует ЦЕЛИКОМ до запуска
|
||||
│ общий state-объект через прогон → ОДИН артефакт в stdout
|
||||
├→ Role / DynamicRole → ACP-процесс → DeepSeek (generic_acp)
|
||||
├→ Script → локальные детерминированные проверки
|
||||
└→ Human → точка одобрения
|
||||
▼
|
||||
Beads (`bd`) — durable-состояние Story/Epic, переживает сессии
|
||||
▼
|
||||
артефакт → Балда → Mattermost
|
||||
┌─ Mac ─────────────────────────────────────────────┐
|
||||
│ Балда (оркестрация, планирование, крон) │
|
||||
│ callee (движок воркфлоу) │
|
||||
│ движки: codex / claude / dsh-acp │
|
||||
│ bd (Beads) — состояние задач │
|
||||
│ тулчейн: ~/Developer, xcodebuild, lume, docker │
|
||||
└───────────────────────────────────────────────────┘
|
||||
▲
|
||||
│ Mattermost API — ИСХОДЯЩЕЕ соединение с Mac
|
||||
│
|
||||
┌─ Kraken ──────────────────────────────────────────┐
|
||||
│ MM-сервер + postgres ← только это │
|
||||
└───────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Разделение ролей
|
||||
### Что это убирает
|
||||
|
||||
| Слой | Владелец |
|
||||
| Узел | Почему больше не нужен |
|
||||
|---|---|
|
||||
| Граф воркфлоу, валидация, state | **callee** |
|
||||
| Durable-состояние + одобрение | **coding agent** |
|
||||
| Исполнение модели | ACP-процесс |
|
||||
| `balda-executor-mcp` (:8890) | его работа — пропихнуть вызов к мосту. Балда на Mac → пропускать нечего |
|
||||
| мост `agents-bridge` (:8790) | был границей хостов. Границы нет — нет моста |
|
||||
| Cloudflare Tunnel для этого потока | нужен только для внешнего доступа к MM |
|
||||
| MCP-сервер `obsidian-mcp` на Kraken | Obsidian рядом с Балдой |
|
||||
|
||||
📌 **Соединение — исходящее с Mac к MM.** Никаких входящих портов, туннеля внутрь Mac,
|
||||
«Mac спит → мост недоступен». При недоступности MM — переподключение.
|
||||
|
||||
### Что остаётся на Kraken
|
||||
|
||||
Только **MM-сервер + postgres**. Доступность 24/7, один сетевой вход, ничего тяжёлого.
|
||||
Kraken разгружается: уходят Балда, MCP-сервер, obsidian-mcp (при load 8.03 на 4 ядрах это
|
||||
заметно).
|
||||
|
||||
### Разделение расходов
|
||||
|
||||
| Роль | Где | Провайдер |
|
||||
|---|---|---|
|
||||
| Оркестратор верхнего уровня | Kraken | DeepSeek `deepseek-chat` |
|
||||
| Исполнитель-роли callee | Mac, контейнер | DeepSeek |
|
||||
| Оркестратор | Mac | DeepSeek `deepseek-chat` |
|
||||
| Исполнитель-роли callee | Mac | DeepSeek |
|
||||
|
||||
📌 «DeepSeek с обоих концов» = обе стороны на DeepSeek. Подписочный Codex подключается
|
||||
позже заменой `State.provider` в `DynamicRole` — без правки графа.
|
||||
📌 «DeepSeek с обоих концов» = обе стороны на DeepSeek. Codex/Claude подключаются позже
|
||||
заменой провайдера в `DynamicRole` — без правки графа.
|
||||
|
||||
---
|
||||
|
||||
## 1.1 Балда на Mac: контейнер и границы доступа
|
||||
|
||||
### Где живёт
|
||||
|
||||
**В Docker-контейнере.** Причины те же, что были на Kraken: изоляция, воспроизводимость,
|
||||
образ уже собран (`balda-mm:0.1.13`), откат одним тегом.
|
||||
|
||||
### Проблема: контейнер изолирован, а нужен тулчейн
|
||||
|
||||
В контейнере нет и не должно быть по умолчанию:
|
||||
|
||||
| Чего нет | Почему это правильно |
|
||||
|---|---|
|
||||
| `~/.ssh` | ключи дают доступ ко всем хостам сразу |
|
||||
| `docker.sock` | **эквивалент root на хосте** |
|
||||
| пароли, `.env` с токенами | Балде они не нужны |
|
||||
| `~/.aws`, `~/.config/gh`, прочие креды | то же |
|
||||
|
||||
Но нужны: `xcodebuild`, `lume`, `docker build`, опционально `ssh`.
|
||||
|
||||
### Решение: три класса доступа
|
||||
|
||||
| Класс | Что | Как | Права |
|
||||
|---|---|---|---|
|
||||
| **1. Прямой** | файлы проектов, git | bind-mount `~/Developer` (только нужные проекты, не весь `~`) | чтение-запись в проекте |
|
||||
| **2. Через шлюз** | `docker build`, `lume` | **не давать `docker.sock` и бинарь** — вместо этого узкий сокет/скрипт-обёртка на хосте с белым списком команд | только разрешённые операции |
|
||||
| **3. Через ssh** | доступ к хосту, TrueNAS, Kraken | `ssh` с ключом **ограниченным** `command=` в `authorized_keys` | одноразовые команды, без шелла |
|
||||
|
||||
🔴 **`docker.sock` в контейнер не монтировать никогда.** Это тождественно выдаче root на
|
||||
хосте: через сокет можно запустить контейнер с `-v /:/host` и получить всё. Если нужны
|
||||
сборки — либо `docker build` через ограниченную обёртку на хосте, либо **вынести сборку в
|
||||
отдельный Script-узел, исполняемый на хосте**, а не в контейнере.
|
||||
|
||||
### Xcode и lume: где физически
|
||||
|
||||
| Задача | Где исполняется | Почему |
|
||||
|---|---|---|
|
||||
| `xcodebuild` | **не в Linux-контейнере** — в lume VM с macOS | контейнер Linux, Xcode только на macOS |
|
||||
| `lume` | **на хосте Mac** | бинарь на хосте, в контейнере недоступен |
|
||||
| `docker build` | **на хосте Mac** | `docker.sock` в контейнер не даём |
|
||||
|
||||
📌 **Это означает: часть ролей исполняется НЕ в контейнере Балды.** Значит нужен явный
|
||||
механизм «роль → хост-исполнитель». Вариант — callee запускается не только в контейнере,
|
||||
но и на хосте (для ролей, требующих Xcode/lume/docker); маршрутизация роли по хосту
|
||||
описывается в графе.
|
||||
|
||||
### Границы: что Балда НЕ должна получить
|
||||
|
||||
| Ресурс | Статус |
|
||||
|---|---|
|
||||
| пароли, токены в открытом виде | ❌ только через env-файл с ограниченным набором (DeepSeek-ключ) |
|
||||
| `~/.ssh` целиком | ❌ только конкретные ключи |
|
||||
| `docker.sock` | ❌ никогда |
|
||||
| весь `~` | ❌ только выбранные проекты |
|
||||
| root на хосте | ❌ |
|
||||
| host-шелл | ❌ только белый список команд |
|
||||
|
||||
---
|
||||
|
||||
## 1.2 Правила работы: Hermes-конфигурация в Балде
|
||||
|
||||
В Hermes у Alex накоплены: правила ведения документации (Obsidian — источник истины),
|
||||
правила работы (план → апрув → работа, бэкапы, запрет удаления), формат ответов
|
||||
(артефакт первой строкой, единица счёта, ADHD-friendly), правила приёмки (от учётки
|
||||
заказчика, а не подставной).
|
||||
|
||||
**Эти правила — не код, а контент.** Значит их надо переносить как контент, а не
|
||||
зашивать в Балду.
|
||||
|
||||
| Слой Hermes | Аналог в Балде | Как переносится |
|
||||
|---|---|---|
|
||||
| System prompt / SOUL | `balda.global_instruction` | текст в конфиг |
|
||||
| Память (`memory`) | session memory Балды + Obsidian | Obsidian MCP |
|
||||
| Скиллы (процедуры) | **callee-ресурсы** (`Role`/`Sequential`) | правила работы как воркфлоу |
|
||||
| Правила документирования | `global_instruction` + Role, обновляющий Obsidian | текст |
|
||||
| Формат ответов | `deliveryfmt` / `questionfmt` | рендеринг, не промпт |
|
||||
| Правила приёмки | `Script` + `Human` в графе | исполняемый граф |
|
||||
|
||||
🔴 **Ключевое различие:** в Hermes правила лежат в промпте и памяти — это **мягкое**
|
||||
принуждение (модель может нарушить). В callee часть правил становится **жёсткой**:
|
||||
валидация графа, `Human`-гейт, `Script`-проверка. Например «план → апрув → работа»
|
||||
превращается в узел `Human` между фазами, а не в просьбу в промпте.
|
||||
|
||||
**Что это значит на практике:** правила, которые важны как инвариант (апрув, бэкап,
|
||||
приёмка) — переносятся в граф как узлы. Правила, которые про стиль (формат ответа,
|
||||
тон) — остаются в `global_instruction`.
|
||||
|
||||
### Obsidian
|
||||
|
||||
Балда ходит в Obsidian по MCP. На Mac поднимается `obsidian-mcp` рядом (по образцу
|
||||
Kraken — контейнер `mcp-proxy --port 3101 -- mcpvault /vault`, `type: sse`), том
|
||||
`~/obsidian:/vault`.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in new issue
Block a user