From a5535382174dbad8e380ab1dd5dfad28029b0fae Mon Sep 17 00:00:00 2001 From: Alexey Martemyanov Date: Tue, 29 Sep 2026 01:48:30 +0600 Subject: [PATCH] [2026-09-29] eagle: personal/plans/balda-callee-prism-plan.md personal/tech/callee-prism.md --- personal/plans/balda-callee-prism-plan.md | 47 +++++--- personal/tech/callee-prism.md | 138 ++++++++++++++++++++-- 2 files changed, 158 insertions(+), 27 deletions(-) diff --git a/personal/plans/balda-callee-prism-plan.md b/personal/plans/balda-callee-prism-plan.md index 983ace34..9614a165 100755 --- a/personal/plans/balda-callee-prism-plan.md +++ b/personal/plans/balda-callee-prism-plan.md @@ -1,7 +1,12 @@ # Балда → Callee + Prism: делегирование -> Обновлён 2026-09-29. Статус: **C0 закрыта, C1-C5 не начаты.** +> Обновлён 2026-09-29. Статус: **C0 закрыта. Топология пересмотрена: стек переезжает +> на Mac, на Kraken остаётся только MM-сервер.** C1-C5 не начаты. > Часть [[personal/projects/balda/balda-mm-delegation-plan]]. +> Опорная заметка по контрактам инструментов: [[personal/tech/callee-prism]]. +> +> 🔴 **Открытая развилка (§6.7):** как давать доступ к `xcodebuild` / `lume` / `docker build` — +> узкий контейнер (три операции недоступны) или гибрид с хост-исполнителем. Определяет объём C1a. --- @@ -664,19 +669,26 @@ scoped-пакеты так не индексируются. ## 7. Питфоллы -1. ⚠️ **`PROVIDERS` в мосте — argv-список.** Промпт должен остаться **одним** - последним элементом, иначе передача рвётся. -2. ⚠️ **`.env` не перебивает plist.** `--host` жёстко в `ProgramArguments`; смена - аргументов требует `bootout` + `bootstrap`. Проверка: - `lsof -nP -iTCP:8790 -sTCP:LISTEN` → должно быть `*:8790`. -3. ⚠️ **`prism/lifecycle` должен быть `Router`** — `Sequential` означает устаревший +1. 🔴 **Два инстанса Балды на один MM-бот = рвут WebSocket друг другу.** Симптом — + `bad_seq`, события не приходят. Mac-инстансу нужен **отдельный бот и токен**. +2. 🔴 **`docker.sock` в контейнер не монтировать никогда** — эквивалент root на хосте + (через сокет запускается контейнер с `-v /:/host`). +3. 🔴 **`~/.ssh` целиком не монтировать** — один ключ даёт доступ ко всем хостам. + Только конкретные ключи + `command=` в `authorized_keys`. +4. 🔴 **ACP-провайдер — дочерний процесс callee.** Движок на хосте + callee в контейнере + невозможны: один процесс-тред. Где callee, там и движки, и Script'ы. +5. 🔴 **Гейт `Human` защищает действие, но не возможность.** Права определяет процесс и + монтирование, не граф (§1.1a). +6. ⚠️ **`prism/lifecycle` должен быть `Router`** — `Sequential` означает устаревший импорт, лечится `--force`. -4. ⚠️ **Provider `cmd` — одно имя файла, не shell-строка.** Аргументы — только +7. ⚠️ **Provider `cmd` — одно имя файла, не shell-строка.** Аргументы — только в `extraArgs`. -5. ⚠️ **Никогда не маршрутизировать вывод модели в `cmd`/`extraArgs`.** -6. ⚠️ **Установки в контейнере не переживают пересборку** — том или `Dockerfile`. -7. ⚠️ **`docker-compose` (дефис) на Mac, `docker compose` (пробел) на Kraken.** -8. ⚠️ **Node `>= 22.15`** требуется адаптером (в образе 24.21.0). +8. ⚠️ **Никогда не маршрутизировать вывод модели в `cmd`/`extraArgs`.** +9. ⚠️ **Установки в контейнере не переживают пересборку** — том или `Dockerfile`. +10. ⚠️ **`docker-compose` (дефис) на Mac, `docker compose` (пробел) на Kraken.** +11. ⚠️ **Node `>= 22.15`** требуется адаптером (в образе 24.21.0). +12. ⚠️ **Динамических маунтов на macOS Docker нет** — только `up -d` с пересозданием. + Доступ к проектам — через рабочую копию в `~/agents` + git, не через маунт под задачу. --- @@ -684,9 +696,13 @@ scoped-пакеты так не индексируются. | Риск | Оценка | Митигация | |---|---|---| +| 🔴 **Mac спит → бот не отвечает** | **высокий** | `caffeinate` / Energy Saver; MM-сервер на Kraken жив всегда, Mac переподключается | +| 🔴 **Развилка доступа к Xcode/lume/docker не решена** | **высокий** | решить до C1a (§6.7) | +| Хост-исполнитель = дыра в изоляции | средний | узкий набор операций (3 шт.), явный и названный | +| Два инстанса Балды конфликтуют по MM | средний | отдельный бот/токен для Mac-инстанса | | Импорт `prism/*` устаревает при обновлении | средний | проверять `kind: Router` после каждого импорта | | callee обновляется и меняет контракт | средний | пиннить версию в ресурсах | -| Мост теряет работоспособность после смены argv | низкий | бэкап `executor.py`, откат одной правкой | +| Переезд стека с Kraken не оправдается | средний | оставить Kraken-инстанс живым как запасной (§6.11) | | Стоимость DeepSeek растёт | низкий | исполнитель-роли — короткие визиты | | Установка в контейнер не переживёт пересборку | низкий | том или `Dockerfile` | @@ -694,7 +710,7 @@ scoped-пакеты так не индексируются. ## 9. Порядок и запреты -**Порядок:** C1 → C2 → C3 → C4 → C5. +**Порядок:** C1 → C1a → C2 → C4 → C5. (C3 отменена.) **НЕ трогать в `~/Developer/balda`:** `go.mod`, `Dockerfile.release`, `go.sum`, `internal/apps/balda/app.go`, `internal/apps/balda/preflight.go` — вне PR-дерева, @@ -702,7 +718,8 @@ scoped-пакеты так не индексируются. См. [[personal/plans/balda-mm-pr-plan]] §5. **НЕ начинать работу** без явного «поехали». -**Ничего не удалять** без отдельного подтверждения. +**Ничего не удалять** без отдельного подтверждения. В частности: Kraken-инстанс Балды, +образы для отката, диагностические контейнеры, старые теги. --- diff --git a/personal/tech/callee-prism.md b/personal/tech/callee-prism.md index 0b0d7e4b..03490afb 100755 --- a/personal/tech/callee-prism.md +++ b/personal/tech/callee-prism.md @@ -228,7 +228,115 @@ bd where --- -## 4. DeepSeek как ACP-провайдер +## 3.5 Роли: что это и как ими управляют + +**Роль — YAML/MD-файл в каталоге**, не право и не токен. Описание листа графа: провайдер, +промпт, параметры, таймаут. + +```yaml +apiVersion: callee.metalagman.dev/v1alpha1 +kind: Role +spec: + description: Собирает Xcode-проект + provider: + type: generic_acp + cmd: dsh-acp + model: deepseek-chat + timeout: 20m +--- +Собери проект {{ .Params.project }} и верни отчёт об ошибках. +``` + +| Источник ролей | Что даёт | +|---|---| +| Каталог по умолчанию | 6 стартовых ресурсов (`callee setup`) | +| Импорт из git | `callee agent import baldaworks/prism-callee --prefix prism` | +| Собственные | файлы в каталоге проекта или `~/.callee/` | + +🔴 **Ролей в рантайме не выдают.** Роль = наличие файла в каталоге. Рантайм-механизма +«выдать роль на задачу» **не существует**. + +### Что динамическое, а что нет + +| Сущность | Динамически? | Чем регулируется | +|---|---|---| +| Роль (файл графа) | ❌ статично | наличие файла в каталоге | +| Провайдер (`type`, `cmd`) | ❌ или из `State` через `DynamicRole` | автор графа | +| Файлы | ❌ | монтирование + рабочая копия | +| SSH-ключ | ❌ | наличие файла у процесса | +| **Разрешение модели внутри ACP-сессии** | ⚠️ **да** | `allow_all` / `ask` / `deny_all` | + +🔴 **Единственное, что реально запрашивается в рантайме — разрешение модели внутри +ACP-сессии** (`ask` → вопрос в чат). + +--- + +## 4. Права: формула и границы + +**`права = права процесса × смонтированное × разрешённое в графе`** + +| Уровень | Кто задаёт | +|---|---| +| Чем запущен процесс | вы, при старте (контейнер / хост-юзер / отдельный юзер) | +| Что смонтировано | compose | +| Что разрешено в графе | автор воркфлоу | + +🔴 **`permissions.mode: allow_all` — это про права модели ВНУТРИ ACP-сессии** (править +файлы, запускать команды). Оно **не** расширяет, что процесс видит в файловой системе. +Два разных ограничения. + +### Где callee — там и движки, и Script'ы + +🔴 **ACP-провайдер — дочерний процесс callee.** Движок на хосте + callee в контейнере +технически невозможны. Следствие: «callee на хосте» = **всё исполнение на хосте целиком**. + +### Гейт `Human` защищает действие, но не возможность + +Доступ у роли есть **всегда** — он определён тем, чем запущен callee и что смонтировано. +Апрув **не выдаёт доступ**, он разрешает выполнить операцию, которая уже технически +возможна. + +``` +Роль лежит в каталоге → доступ ЕСТЬ + ▼ +Узел Human («собрать Xcode в VM macos-27?») → пауза + ├─ апрув → Script исполняется (права у процесса УЖЕ были) + └─ отказ → граф останавливается +``` + +🔴 **Изоляцию даёт только то, чем процесс запущен и что смонтировано — не граф.** + +### Динамических маунтов не существует + +На macOS Docker маунты задаются **при создании контейнера**; live `mount --bind` +контейнер не видит; симлинк на внешний путь битый. **«Как модель запросит доступ к папке» +не решается через маунты.** + +| Подход | Оценка | +|---|---| +| A. Смонтировать всё заранее (`~/Developer:ro`) | запись нельзя | +| B. Пересоздание контейнера (`up -d`, ~3 с) | нужен механизм вне контейнера | +| C. Хост-агент ставит права сам | полный доступ, ноль изоляции | +| **D. Проект = рабочая копия** ✅ | модель работает в `~/agents/<проект>`, результат в проект через git | + +**Решение: D** — доступ задаётся наличием репозитория, а не маунтом. + +### Доступ выбирается маршрутом, а не запросом + +Модель **не просит** прав и **не может эскалировать**: нет доступа — задача падает. + +``` +Роутер в графе + ├─ задача требует ~/agents → роль в контейнере + ├─ задача требует Xcode/lume → роль на хост-исполнителе + └─ задача требует хоста по ssh → роль со ssh-ключом (command=) +``` + +**Разграничение = статический роутинг по типам задач**, не динамические права. + +--- + +## 5. DeepSeek как ACP-провайдер Провайдер callee — `generic_acp`, `cmd: dsh-acp`, пакет **`@openma/deepseek-harness-acp@0.4.33`** (Apache-2.0, Node `>= 22.15`, @@ -250,25 +358,31 @@ bd where --- -## 5. Питфоллы +## 6. Питфоллы 1. 🔴 **`Human` требует TTY** — non-interactive режим отвергает граф целиком, включая невыбранные ветки Router. Запуск через `docker exec` без `-t` = non-interactive. 2. 🔴 **`cmd` — одно имя файла.** Аргументы только в `extraArgs`, иначе провайдер не стартует. 3. 🔴 **Не подавать вывод модели в `cmd`/`extraArgs`** — исполнение произвольного кода. -4. ⚠️ **`prism/lifecycle` обязан быть `Router`** — иначе устаревший импорт. -5. ⚠️ **Непустой stderr ≠ провал** — судить по exit status. -6. ⚠️ **Таймаут Script валит весь воркфлоу** — не «продолжает с ошибкой». -7. ⚠️ **Concurrency группы `Parallel`** используют один живой shared state. -8. ⚠️ **Поиск npm по `scope:normahq` / `scope:baldaworks` даёт пусто** — эти scoped-пакеты - через search-API не индексируются. Искать прямыми URL - `registry.npmjs.org/%2f`. +4. 🔴 **ACP-провайдер — дочерний процесс callee** — движок и callee не могут быть на + разных хостах. +5. 🔴 **Гейт `Human` не выдаёт доступ** — только разрешает уже возможное действие. +6. ⚠️ **`prism/lifecycle` обязан быть `Router`** — иначе устаревший импорт. +7. ⚠️ **Непустой stderr ≠ провал** — судить по exit status. +8. ⚠️ **Таймаут Script валит весь воркфлоу** — не «продолжает с ошибкой». +9. ⚠️ **Concurrency группы `Parallel`** используют один живой shared state. +10. ⚠️ **Поиск npm по `scope:normahq` / `scope:baldaworks` даёт пусто** — эти scoped-пакеты + через search-API не индексируются. Искать прямыми URL + `registry.npmjs.org/%2f`. +11. ⚠️ **Динамических маунтов на macOS Docker нет** — только пересоздание контейнера. --- ## Связанные заметки -- [[personal/plans/balda-callee-prism-plan]] — план внедрения +- [[personal/plans/balda-callee-prism-plan]] — план внедрения (топология: стек на Mac) +- [[personal/projects/balda/balda-mm-delegation-plan]] — общий план Фаз 1-5 - [[personal/plans/balda-mm-phase4-agents]] — Фаза 4 (мост, приёмка) -- [[personal/tech/agents-bridge]] — мост :8790 -- [[personal/tech/balda-executor-mcp]] — MCP-сервер делегирования +- [[personal/tech/agents-bridge]] — мост :8790 (демонтируется в новой топологии) +- [[personal/tech/balda-executor-mcp]] — MCP-сервер делегирования (демонтируется) +- [[personal/tech/macos-docker-virtiofs-mount-limits]] — почему нет динамических маунтов