[2026-09-26] eagle: personal/projects/balda/balda-mm-delegation-plan.md personal/projects/balda/balda-valera.md personal/projects/balda/fast-rlm-integration.md
This commit is contained in:
1 parent
9eb5cf001e
commit
335478ef65
3 files changed
+268
No files matched your search
@@ -0,0 +1,243 @@
|
||||
# Balda 2.0 — Mattermost + распределённое делегирование (план)
|
||||
|
||||
> Создан 2026-09-25. Статус: **черновик, ждёт апрува Alex**.
|
||||
> Задача: поднять свежую Балду из `normahq/balda` (без наших коммитов), завязать на Mattermost,
|
||||
> построить распределённое делегирование (дешёвый оркестратор + подписочные CLI в VM).
|
||||
|
||||
---
|
||||
|
||||
## 0. Ключевые находки разведки (факты, проверено в коде и доках)
|
||||
|
||||
### 0.1 Апстрим Балды
|
||||
- Апстрим переехал: `normahq/balda` → **`baldaworks/balda`**. Релиз: `ghcr.io/baldaworks/balda:latest`, npm `@baldaworks/balda`.
|
||||
- Наш форк `~/Developer/balda` отстал на **900 файлов** (+135k/−28k строк).
|
||||
- Архитектура переписана полностью: `handlers/*` → `handlersfx/*`, Zulip вынесен в `internal/apps/balda/channel/zulip/*`, добавлены backoffice (встроенный web UI + админ/логин/аудит), Slack Agent, unified user security state, sessionmemory на Badger.
|
||||
- Наши коммиты (промежуточные статусы Zulip) в апстрим **не влиты** — `05159d15` есть только у нас.
|
||||
|
||||
### 0.2 Mattermost — в апстриме НЕТ
|
||||
- `grep -i mattermost` по всему `upstream/main` → **0 совпадений**. Ни кода, ни доков.
|
||||
- Каналы в апстриме: `telegram`, `zulip`, `slackagent`, `webhook` + `channel/router.go`.
|
||||
- Значит MM = **новый транспортный адаптер**, писать самим.
|
||||
- Хорошая новость: есть явный контракт для этого — `docs/architecture/transport-presentation-boundary.md`.
|
||||
Требование: shared-пакеты владеют семантикой, транспортные пакеты владеют рендерингом/ingress/delivery,
|
||||
регистрация через DI в composition root. Образец для копирования: `channel/zulip/adapter.go` (331 стр.) + `client.go` (289 стр.) — по объёму это 2-4 дня работы.
|
||||
|
||||
#### MM — это НОВЫЙ chat surface, а не просто «ещё один webhook»
|
||||
В README апстрима заявлены ровно три chat surface: **Telegram, Zulip, Slack Agent**. MM не входит.
|
||||
Значит адаптер затрагивает не только `channel/mattermost/*`, но и весь слой, где перечисляются транспорты.
|
||||
Найденные touchpoints (проверять при реализации):
|
||||
- `channel/router.go` — регистрация/диспетчеризация транспорта
|
||||
- `handlersfx/module.go` — composition root (DI-вайринг)
|
||||
- `internal/apps/balda/state/` — `channel_type` в каноническом locator (`channel_type:address_key`)
|
||||
- `docs/commands.md` — таблица доступности команд по транспортам (Telegram/Zulip/Slack — колонки)
|
||||
- `docs/reference/messaging.md`, `docs/architecture/multi-channel-token-auth.md` — контракты auth/доставки
|
||||
|
||||
**Следствие:** в MM-адаптере сразу закладывать полный набор: `/start owner=`, `/start invite=`,
|
||||
`/topic`, `/goalkeeper`, `/auto`, `/reset`, `/skill`, `/cancel`, `/locator`, `/user`.
|
||||
Scheduler/webhook-таргеты (`balda.scheduler.jobs` → `target: locator`) должны резолвиться в MM-локатор.
|
||||
|
||||
### 0.2.1 Что именно есть только у нас (инвентаризация перед «начать с чистого»)
|
||||
|
||||
Решение «поднять чистую Балду без наших коммитов» — обосновано. Инвентаризация:
|
||||
|
||||
**`~/Developer/balda`** (наши уникальные коммиты):
|
||||
- `05159d15` — промежуточные статусы Zulip (правит `internal/apps/balda/handlers/balda.go` +25). В `main` нашего форка.
|
||||
- `bc5fd03c` — то же + Telegram + `messageID` для threading. Лежит на `backup/our-main-before-upstream` и `feat/zulip-transport-intermediate`, в `main` не попала.
|
||||
- `5ad65955` — **не фича**, а `replace normahq/norma => ./norma-local` в `go.mod`. При переезде удалить.
|
||||
- `feat/zulip-events-polling` — `c619731d` Events API long-poll + stream_only_with_session фильтр; плюс два коммита про valera Dockerfile/compose.
|
||||
|
||||
**`~/Developer/norma-local`** (наши уникальные коммиты):
|
||||
- `56a6e1e` = `91c2c0a` (дубли) — DeepSeek tool_calls: `pkg/runtime/hostedagent/openai.go` (+286),
|
||||
`pkg/runtime/agentfactory/agentfactory.go` (+3), `openai_test.go` (+312).
|
||||
- **Критично:** в `norma v2` (`f8a7336`) эти файлы **удалены целиком**; модуль стал
|
||||
`github.com/normahq/norma/v2`, апстрим использует `github.com/normahq/runtime/v2 v2.0.11`.
|
||||
Наш патч не переносится — либо он уже есть в `normahq/runtime/v2`, либо пишется заново.
|
||||
- `norma-local` отстал от `origin/master` на **26 коммитов** (включая теги `v0.0.11`–`v0.0.13`, `v2.0.0`, `v2.0.1`).
|
||||
|
||||
**Проверить перед началом:** есть ли в `normahq/runtime/v2` поддержка tool_calls для OpenAI-совместимых
|
||||
провайдеров. Если да — наш DeepSeek-фикс не нужен вообще, и потерь нет. Если нет — фикс надо
|
||||
переписать в новый модуль (см. скилл `adk-hostedagent-openai-mcp`).
|
||||
|
||||
### 0.3 Провайдеры Балды (ACP)
|
||||
Реестр в `cmd/balda/init.go`:
|
||||
|
||||
| id | type | model | binary |
|
||||
|---|---|---|---|
|
||||
| codex | `codex_acp` | gpt-5-codex | `codex` |
|
||||
| opencode | `opencode_acp` | opencode/big-pickle | `opencode` |
|
||||
| copilot | `copilot_acp` | gpt-5-codex | `copilot` |
|
||||
| gemini | `gemini_acp` | gemini-3-flash-preview | `gemini` |
|
||||
| claude_code | `claude_code_acp` | claude-sonnet-4-6 | `claude` |
|
||||
|
||||
- Балда говорит с CLI через **ACP (Agent Client Protocol)** — через `github.com/normahq/go-adk-acpagent/v2 v2.2.6`.
|
||||
- Это ровно то, что нужно для «подписочных CLI»: Балда запускает **настоящий** `claude`/`codex` бинарь, а не дёргает API.
|
||||
- **Мультипровайдерность есть:** несколько провайдеров в `runtime.providers`, переключение через `profiles.<name>.balda.provider`. Но у **одной сессии один провайдер** — переключается профилем, не внутри сессии.
|
||||
|
||||
### 0.4 GoalKeeper — уже готовая база для делегирования
|
||||
- `/goalkeeper <objective>`: цикл work → validate до `verdict: pass` или `max_iterations`.
|
||||
- Отдельные ADK-сессии для worker и validator (изоляция контекста).
|
||||
- При workspace mode: изолированный worktree, автогенерация Conventional Commit, squash-merge в `base_branch`, удаление workspace.
|
||||
- Артефакты в финале: изменённые файлы, ветка, коммит, вывод валидации, next step.
|
||||
- **Вывод:** это уже «оркестратор + исполнитель», просто оба на одном провайдере.
|
||||
|
||||
### 0.5 Auto mode — автономное продолжение
|
||||
- `/auto on|off` — сессионный режим: после каждого turn планируется внутренний synthetic turn со стирингом.
|
||||
- Сентинелы `AUTO_DECISION:DONE` / `AUTO_DECISION:WAIT_FOR_USER`.
|
||||
- Наш прошлый кейс (агент сам не продолжал) — в апстриме закрыт этой фичей.
|
||||
|
||||
### 0.6 Юридическая граница по подпискам — КРИТИЧНО
|
||||
Проверено по официальным докам Anthropic (`code.claude.com/docs/en/legal-and-compliance`) и разбору Zylos (2026-07-13):
|
||||
|
||||
**Разрешено:**
|
||||
- Запуск **немодифицированного** официального бинаря `claude`, залогиненного **под своим** аккаунтом, для своих задач и автоматизации. Claude Code сам является «explicit permission» для автоматизации.
|
||||
- `claude setup-token` → `CLAUDE_CODE_OAUTH_TOKEN` на headless-машине (Pro/Max). Это документированный путь, не дыра.
|
||||
- Provisioning своих API-ключей для своих авторизованных пользователей.
|
||||
|
||||
**Запрещено:**
|
||||
- Извлекать OAuth-токен подписки и **переиспользовать его в другом клиенте** (прокси, ре-серв как OpenAI-совместимый API). Anthropic реализовал блокировки на сервере и банит аккаунты. Февраль 2026: OAuth-токены consumer-планов «in any other product, tool, or service — including the Agent SDK» не разрешены.
|
||||
- Спуфить идентичность клиента Claude Code.
|
||||
|
||||
**Следствие для архитектуры:** Балда через ACP = хорошо (запускает настоящий бинарь). Прокси-мост, отдающий подписочный токен наружу как API = бан.
|
||||
Дополнительно: лимиты Pro/Max рассчитаны на «ordinary, individual usage» — параллельные агенты под одним аккаунтом это серая зона даже с официальным бинарём. Codex CLI от OpenAI в этом смысле либеральнее (инженер OpenAI публично поддержал использование подписочного токена в сторонних харнессах); Gemini CLI — как Anthropic, вплоть до закрытия аккаунта.
|
||||
|
||||
---
|
||||
|
||||
## 1. Где разворачивать — решение
|
||||
|
||||
Требование Alex: постоянная доступность + сборка проектов + подписочные CLI без токенов.
|
||||
|
||||
Вывод: **не «или-или», а разделение ролей между двумя контейнерами.**
|
||||
|
||||
| Роль | Где | Почему |
|
||||
|---|---|---|
|
||||
| Mattermost + оркестратор Балда (DeepSeek) | **Kraken** | 24/7, уже есть docker stack, Zulip-подобный топиковый UX, дешёвый по CPU/RAM |
|
||||
| Исполнитель (codex/claude CLI по подписке) | **Mac (Eagle)**, в VM | нужен доступ к `~/Developer`, git, тяжёлые сборки; подписка залогинена на маке |
|
||||
|
||||
### Почему не всё на Mac
|
||||
Постоянная доступность Mac не гарантирована (сон, ребуты), а оркестратор должен жить в чате 24/7.
|
||||
|
||||
### Почему не всё на Kraken
|
||||
- RPi5 ARM64: тяжёлые сборки/macOS-таргеты невозможны, `~/Developer` не там.
|
||||
- Подписочный CLI на Kraken = логин подписного аккаунта на чужом хосте, вне зоны контроля → лишний риск бана.
|
||||
|
||||
### Почему VM, а не голый Mac
|
||||
Изоляция: агент-исполнитель получает полный доступ к файлам и сети. VM даёт откат, снапшоты, ограничение диска. Плюс чистая авторизация (`claude setup-token` внутри VM, вне основного профиля Mac).
|
||||
|
||||
### Вариант, который стоит рассмотреть вместо VM
|
||||
**Одноразовый Docker-контейнер на Mac** (не VM): том с проектом, `CLAUDE_CODE_OAUTH_TOKEN` из env. Плюсы: запуск за минуты, изоляция не хуже, легко убить. Минус: на macOS Docker работает через VM — доступ к хостовому диску только через bind-mount, производительность FS ниже.
|
||||
**Рекомендация: начать с Docker-контейнера; если понадобится полный desktop/gui или сложный toolchain — переехать в UTM/Parallels VM.** Это на порядок быстрее в запуске.
|
||||
|
||||
### Транспорт между оркестратором и исполнителем
|
||||
- Вариант A: **общий Mattermost-канал** — Балда на Kraken и исполнитель в VM оба боты. Просто, но грязно (лишний шум, конфликты сессий).
|
||||
- Вариант B: **Мост на Mac**: небольшой сервис (FastAPI), который принимает задачи от Kraken по HTTP/Webhook и запускает CLI внутри. Идемпотентность, очередь, статусы.
|
||||
- Вариант C: **вторая Балда в VM** и связка через webhooks Балды (в апстриме есть `balda.webhooks.*`).
|
||||
- **Рекомендация: начать с B**, потому что он не требует ни форка Балды, ни второго канала. Позже можно перейти на C.
|
||||
|
||||
---
|
||||
|
||||
## 2. Сценарий делегирования (как это работает для Alex)
|
||||
|
||||
```
|
||||
Mattermost (Alex)
|
||||
│ «почини баг X в проекте Y»
|
||||
▼
|
||||
Балда-оркестратор (Kraken, DeepSeek — дёшево)
|
||||
│ 1. собирает контекст: читает Obsidian, ищет в web, формирует ТЗ
|
||||
│ 2. /goalkeeper → цикл work→validate
|
||||
│ 3. на этапе work вызывает мост → задание в VM
|
||||
▼
|
||||
Мост (Mac, FastAPI) ──► codex/claude CLI (VM, подписка)
|
||||
│ делает: код, сборка, тесты
|
||||
│◄──── возврат: diff, вывод тестов, коммит
|
||||
▼
|
||||
Балда-оркестратор
|
||||
│ 4. валидирует результат, обновляет доку в Obsidian,
|
||||
│ трекает исполнение, отвечает в Mattermost
|
||||
▼
|
||||
Mattermost (Alex) — итог + артефакты
|
||||
```
|
||||
|
||||
Ключевое разделение расходов:
|
||||
- **оркестратор** — DeepSeek (дёшево) — контекст, поиск, документирование, трекинг, коммуникация.
|
||||
- **исполнитель** — подписочный CLI (фикс-цена) — код, сборка, тесты.
|
||||
|
||||
---
|
||||
|
||||
## 3. Фазы
|
||||
|
||||
### Фаза 0 — подготовка (бэкапы, ~30 мин)
|
||||
1. `backup/pre-normahq-sync` в `~/Developer/balda` и `~/Developer/norma-local`.
|
||||
2. Сохранить стэш `whale-20260623` в отдельную ветку (не в stash — стэши теряются).
|
||||
3. Снять текущий compose Валерии/Клавдия в бэкап (`~/Docker/balda-agent/`, `~/Docker/claudio-agent/`).
|
||||
|
||||
### Фаза 1 — Mattermost (Kraken, ~2-3 ч)
|
||||
1. Решить вопрос лицензии MM (free self-hosted Team Edition — ограничения по числу пользователей смотреть на момент установки).
|
||||
2. Развернуть MM на Kraken (`docker-compose`, postgres, volume на USB-HDD-разделе с учётом mount-race).
|
||||
3. Настроить: reverse proxy / порт, вход, создать команду + канал для агентов.
|
||||
4. Создать бота (Personal Access Token / bot account) для Балды.
|
||||
|
||||
### Фаза 2 — адаптер Mattermost в Балде (~2-4 дня)
|
||||
1. Склонировать чистый `baldaworks/balda` в **новую** директорию (`~/Developer/balda-mm`) — наши коммиты не переносим.
|
||||
2. Изучить `channel/zulip/*` как образец: adapter, client, inbound, server, presentation.
|
||||
3. Написать `channel/mattermost/*` по контракту `transport-presentation-boundary.md`:
|
||||
- ingress: WebSocket events (или outgoing webhook) → семантические типы;
|
||||
- delivery: рендеринг (Markdown MM), треды/посты;
|
||||
- registration через DI в composition root.
|
||||
4. Собирать локально на Mac (arm64) и/или на Kraken (arm64) — проверить целевую платформу.
|
||||
|
||||
### Фаза 3 — оркестратор на Kraken (~1-2 дня)
|
||||
1. Развернуть Балду с MM-адаптером на Kraken, провайдер — **DeepSeek** (через API-ключ, не подписка).
|
||||
2. Настроить `balda.mcp_servers` (Obsidian MCP + Knowl при необходимости).
|
||||
3. Проверить `/goalkeeper`, `/auto`, `/topic`, `/skill` в MM.
|
||||
4. Верификация Alex в UI MM (не по логам).
|
||||
|
||||
### Фаза 4 — исполнитель в VM/Docker на Mac (~2-3 дня)
|
||||
1. Docker-контейнер (или UTM VM) с Node 24 + `codex` + `claude` + `git`.
|
||||
2. Авторизация: `claude setup-token` на Mac → `CLAUDE_CODE_OAUTH_TOKEN` в контейнер; для codex — свой flow.
|
||||
3. Bind-mount проектной директории (не весь `~`).
|
||||
4. Мост: FastAPI-сервис, принимает задачу от Kraken, запускает CLI headless, возвращает diff/тесты.
|
||||
5. Идемпотентность + таймауты + лимит параллельных задач (не более 1-2, чтобы не ловить «unusual traffic patterns»).
|
||||
|
||||
### Фаза 5 — связка и приёмка
|
||||
1. Сквозной тест: сообщение в MM → Балда → мост → CLI → результат обратно в MM.
|
||||
2. Проверить расходы: DeepSeek-токены оркестратора + подписочные лимиты исполнителя.
|
||||
3. Записать в Obsidian: как работает, где логи, как откатить.
|
||||
|
||||
---
|
||||
|
||||
## 4. Риски
|
||||
|
||||
| Риск | Оценка | Митигация |
|
||||
|---|---|---|
|
||||
| Бан подписочного аккаунта за «unusual traffic» | средний | только официальный бинарь; не более 1-2 параллельных задач; не проксировать токен; мониторить письма Anthropic |
|
||||
| MM-адаптер разъедется с апстримом | высокий | держать как отдельный fork-патч, ребейзить на каждый релиз; либо предложить в апстрим PR |
|
||||
| Kraken: USB-диск нестабилен, mount-race | известный | учесть в compose (см. `docker-data-root-mount-race`), volume не на data-root |
|
||||
| RPi5 не тянет сборку Балды | средний | собирать образ на Mac arm64, на Kraken только `pull`/`up` |
|
||||
| Утечка секретов в MM-канал | средний | `balda.permissions.mode: ask`; redaction в job-events уже есть в апстриме |
|
||||
| Mattermost free-лицензия ограничивает нужное | низкий | проверить лимиты до установки |
|
||||
|
||||
---
|
||||
|
||||
## 5. Открытые вопросы к Alex
|
||||
|
||||
1. **Mattermost:** поднимаем self-hosted Team Edition (free) или есть платный/облачный аккаунт?
|
||||
2. **VM vs Docker:** начинаем с Docker-контейнера на Mac (быстро) или сразу VM (UTM/Parallels)?
|
||||
3. **Kraken:** MM на USB-HDD-разделе или на SD (риск износа)? Учитывая нестабильность USB-диска — возможно, вынести MM на SD с бэкапом.
|
||||
4. **Провайдер оркестратора:** DeepSeek (как сейчас у Валеры) или другой дешёвый?
|
||||
5. **Судьба текущей Валеры/Клавдия:** гасим или держим параллельно на время миграции?
|
||||
|
||||
---
|
||||
|
||||
## 6. Что понадобится прочитать перед реализацией
|
||||
|
||||
- `docs/architecture/transport-presentation-boundary.md` — контракт транспортов
|
||||
- `docs/architecture/runtime-contract.md` — инварианты рантайма
|
||||
- `docs/reference/configuration.md` — конфиг провайдеров и MCP
|
||||
- `docs/reference/plugins.md` — расширения
|
||||
- `docs/goal-workflow.md` — контракт GoalKeeper
|
||||
- `docs/architecture/auto-mode.md` — автономное продолжение
|
||||
- `docs/reference/job-runtime.md` — durable jobs, scheduler, webhooks
|
||||
- `internal/apps/balda/channel/zulip/*` — образец адаптера
|
||||
|
||||
## История
|
||||
- **2026-09-25**: создан по итогам разведки апстрима и юридической проверки подписок.
|
||||
@@ -1,5 +1,19 @@
|
||||
# Балда / Валера — эксплуатация & MCP debug
|
||||
|
||||
> ## ⚠️ УСТАРЕЛО (2026-09-25) — читать с оговоркой
|
||||
> Этот док описывает **старый форк-стек**: свой патч `norma-local` (`hostedagent/openai.go`),
|
||||
> `go.mod replace` на локальную норму, DeepSeek через OpenAI-совместимый рантайм.
|
||||
>
|
||||
> **Апстрим ушёл далеко вперёд.** Актуально: `normahq/balda` → **`baldaworks/balda`**,
|
||||
> архитектура переписана (`handlers/*` → `handlersfx/*`, Zulip → `channel/zulip/*`),
|
||||
> провайдеры теперь **ACP** (`claude_code_acp`, `codex_acp`, ...) вместо hostedagent/openai.
|
||||
>
|
||||
> Планируется поднять **чистую Балду без наших коммитов** → см.
|
||||
> [[personal/projects/balda/balda-mm-delegation-plan|balda-mm-delegation-plan]].
|
||||
>
|
||||
> Что здесь всё ещё верно: грабли эксплуатации (NATS, owner, `DOCKER_OPTS`, `stream_only_with_session`),
|
||||
> бранчи/стэши, диагностика молчания. Что мертво: раздел про `openai.go`/`norma-local` replace как «текущее».
|
||||
|
||||
## Расположение
|
||||
- **Валера** = `balda-agent-valera-1`, конфиг: `~/Docker/balda-agent/.config/balda/config.yaml`
|
||||
- **Клавдий** = `claudio-agent-claudio-1`, конфиг: `~/Docker/claudio-agent/.config/balda/config.yaml`
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
# fast-rlm MCP HTTP integration with Balda
|
||||
|
||||
> ## ⚠️ СТАТУС (2026-09-25)
|
||||
> Док описывает интеграцию с **прежней Балдой** (`balda-agent-valera-1` на нашем форке).
|
||||
> Планируется переезд на чистый апстрим `baldaworks/balda` — см.
|
||||
> [[personal/projects/balda/balda-mm-delegation-plan|balda-mm-delegation-plan]].
|
||||
>
|
||||
> **Что переносится:** сама идея MCP HTTP sidecar в сети Балды (`runtime.mcp_servers` +
|
||||
> `balda.mcp_servers`) и `OPENAI_BASE_URL`/`OPENAI_API_KEY` для fast-rlm — в апстриме MCP-механика
|
||||
> сохранилась (`docs/reference/configuration.md`: `runtime.mcp_servers.<id>` c `type: http|sse|stdio`).
|
||||
> **Что перепроверить:** в апстриме у Балды встроенная fact-memory (`balda.memory.remember`) и
|
||||
> опциональная Knowl-сайдкар — возможно, RLM-сжатие частично закрывается ими, оценить перед переносом.
|
||||
|
||||
## Цель
|
||||
Дать Балде (`balda-agent-valera-1`) инструмент рекурсивного сжатия контекста (RLM) через MCP **HTTP** сервер в отдельном Docker контейнере.
|
||||
|
||||
|
||||
Reference in new issue
Block a user