Phase 20: Федерована архітектура ботів
Arc OS — від «одного офісу» до «командного центру для всіх проєктів» Автор: Rick (Lead Architect) | Дата: 2026-04-02 Статус: 20.1–20.5 COMPLETE Затверджено: CEO
Проблема
CEO керує кількома проєктами (Arc OS, Msolution, RTS_001) з телефону. Поточна архітектура: один Telegram-бот → одна Claude-сесія → одне контекстне вікно. Це ламається на 3+ проєктах:
- Забруднення контекстного вікна (200K токенів діляться між непов'язаними проєктами)
- Немає ізоляції проєктів (код msolution просочується у промпти citadel)
- Немає multi-user (не можна запросити дизайнера в чат проєкту)
- Зламаний reply-контекст (відповідь на повідомлення з не того проєкту = хаос)
Рішення: Федерація
CEO ↔ @citadel_master_bot (Master) ← лише глобальні команди
│
├── /status → опитує всіх children
├── /emergency-stop → kill-сигнал усім
├── /deploy all → каскадний deploy
│
├── @citadel_v2_bot (Child 1) ← окремий чат, окремий контекст
│ └── Claude session #1, cwd=/opt/repos/citadel-v2
│
├── @msolution_bot (Child 2) ← можна додати дизайнера до чату
│ └── Claude session #2, cwd=/opt/repos/msol
│
└── @rts_bot (Child 3) ← можна додати агента Morty
└── Claude session #3, cwd=/opt/repos/rts-001
Аналіз рішення: Single Bot vs Federation
Варіант A: Один бот + перемикач проєктів
| Критерій | Оцінка | Деталі |
|---|---|---|
| Складність коду | Низька (1 бот) | Додати змінну activeProject, /switch змінює cwd |
| Ізоляція контексту | СЛАБКА | Одна Claude-сесія = одне контекстне вікно для всіх проєктів. Перемикання забруднює контекст. |
| Зручність для CEO | Середня | Треба пам'ятати /switch. Ризик: надіслати задачу не в той проєкт. Немає візуального розділення. |
| Multi-user | НЕМОЖЛИВО | Один чат = один CEO. Не можна запросити людей у проєктний чат. |
| Reply-контекст | ЗЛАМАНО | Відповідь на повідомлення з іншого проєкту = Claude плутається. |
Вердикт: Працює для соло-CEO з 1-2 проєктами. Ламається на 3+.
Варіант B: Федеровані боти (Master + Children) — ОБРАНО
| Критерій | Оцінка | Деталі |
|---|---|---|
| Складність коду | Середня (N+1 ботів) | Кожен бот = окремий tmux + Claude-сесія. Master = легкий координатор. |
| Ізоляція контексту | ІДЕАЛЬНА | Кожна Claude-сесія = власне контекстне вікно, власний CLAUDE.md, власний cwd. Нуль забруднення. |
| Зручність для CEO | ВИСОКА | Окремі Telegram-чати = окремі «кімнати». Свайп між проєктами. Нативний mobile UX. |
| Multi-user | НАТИВНО | Додаєш @designer у чат @msolution_bot. Вона бачить лише свій проєкт. |
| Reply-контекст | ІДЕАЛЬНИЙ | Reply у чаті @citadel_v2_bot = 100% citadel-контекст. Telegram нативно зберігає thread. |
Вердикт: Правильне рішення. Більше інфраструктурної складності, але вирішує ВСІ проблеми.
Чому Федерація виграє
- Ізоляція контексту — вирішальний фактор. Одна Claude-сесія на 3+ проєкти = переповнення контексту за 30 хвилин активної роботи. Федерація дає кожному проєкту чисті 200K токенів.
- Готовність до multi-user — це не «фіча на майбутнє», це фундамент. Без неї Arc OS не стане продуктом.
- Reply = нативний RAG — Telegram уже вирішив проблему контексту. Ми просто мапимо reply → GSD prompt.
Архітектура Emergency Stop
CEO тапає /emergency-stop у Master-чаті
│
▼
Master Bot (Node.js/Bun, легкий, НЕ Claude-сесія)
│
├── 1. Читає config/bot_registry.json
│ { "children": [
│ { "name": "citadel-v2", "tmux": "citadel", ... },
│ { "name": "msolution", "tmux": "msolution", ... }
│ ]}
│
├── 2. Для кожного child (паралельно):
│ a) tmux send-keys -t $SESSION "C-c" Enter ← graceful: Ctrl+C
│ b) sleep 2
│ c) tmux send-keys -t $SESSION "/exit" Enter ← явний exit
│ d) sleep 2
│ e) tmux kill-session -t $SESSION ← force kill, якщо ще живий
│
├── 3. Оновлює office-state.json: всі агенти → idle
│
└── 4. Відповідає в Master-чат:
"EMERGENCY STOP executed.
citadel-v2: STOPPED (was: working on hooks)
msolution: STOPPED (was: idle)
All agents reset to idle."
Kill-протокол (3 рівні)
| Рівень | Дія | Timeout | Коли |
|---|---|---|---|
| 1. Graceful | Ctrl+C через tmux |
2с | Завжди першим |
| 2. Explicit | команда /exit |
2с | Якщо graceful не спрацював |
| 3. Force | tmux kill-session |
миттєво | Останній шанс |
Failsafe
Cron-job кожні 5 хвилин перевіряє /tmp/emergency-stop.flag. Якщо файл існує і свіжий (<10 хв), виконує kill-послідовність. Покриває випадок, коли сам Master Bot впав.
Smart Context Recall
Проблема
CEO відповідає на повідомлення 3-денної давнини і пише «зроби так само, але для іншого модуля». Claude не має жодної гадки про згадане повідомлення.
Рішення: трансформація Reply → GSD Prompt
Telegram Bot API віддає об'єкт reply_to_message з повним оригінальним текстом.
CEO відповідає на: "I deployed hooks to VPS, everything works"
CEO пише: "do the same for msolution"
│
▼
Child Bot отримує:
{
"message": {
"text": "do the same for msolution",
"reply_to_message": {
"text": "I deployed hooks to VPS, everything works",
"date": 1743580800,
"message_id": 847
}
}
}
│
▼
Bot будує GSD prompt для Claude:
┌─────────────────────────────────────┐
│ CONTEXT (from reply): │
│ > [2026-04-02] "I deployed hooks │
│ > to VPS, everything works" │
│ │
│ TASK (new message): │
│ "do the same for msolution" │
│ │
│ PROJECT: msolution (from bot scope) │
└─────────────────────────────────────┘
Deep Recall (старіші повідомлення)
Layer 1: Thread History (швидкий)
Bot зберігає останні 50 повідомлень у state/thread_history.json на чат.
Reply → бот знаходить оригінал → інжектить у блок CONTEXT.
Layer 2: Library Recall (fallback)
Якщо повідомлення немає у thread history (>50 повідомлень тому) →
бот запускає /citadel-recall з текстом reply →
витягує контекст із library-export/ → інжектить у prompt.
Flow: reply_to_message → thread_history → library-export/ → GSD prompt
Ключовий принцип
Claude НІКОЛИ не знає про Telegram replies напряму. Bot middleware ЗАВЖДИ трансформує reply у чистий блок CONTEXT + TASK перед тим, як надсилати у Claude-сесію.
Специфікація Master Bot
Чим Master Bot Є
- Легкий Bun/Node.js-сервіс (~300 рядків)
- Telegram Bot API (long-polling)
- Читає
config/bot_registry.jsonяк реєстр children - HTTP health-ендпоінт:
/api/master/health - Docker-контейнер у спільному compose
Чим Master Bot НЕ Є
- НЕ Claude-сесія (немає AI, немає LLM-викликів)
- НЕ проксі повідомлень (не форвардить повідомлення дітям)
- НЕ сховище стану (читає стан із файлів children)
Протокол Child Bot
Кожен child-бот має:
- Зареєструватися в
config/bot_registry.jsonпри старті - Надсилати heartbeat (кожні 60с) у Master через файл:
state/heartbeat_<name>.json - Обробляти
reply_to_message→ інжект CONTEXT у GSD - Зберігати останні 50 повідомлень у
state/thread_history.json - Реагувати на сигнал emergency-stop (graceful Ctrl+C → /exit → kill)
- Використовувати структурований логер (
shared/logger.ts) — логи у/var/log/citadel/<name>/ - Приймати env-змінну
BOT_NAMEдля динамічного іменування - Виставляти
/api/child/healthдля health-перевірок Watchdog
Оцінка ресурсів
| Ресурс | Зараз | Phase 20 |
|---|---|---|
| VPS RAM | ~4ГБ used / 11ГБ total | ~5.5ГБ (+ ~500МБ на кожну child-сесію) |
| Docker-контейнери | 2 (bridge + frontend) | 4-5 (+ master + 2 children) |
| Telegram bot-токени | 1 | 3-4 (@BotFather, безкоштовно) |
| tmux-сесії | 1 (citadel) | 3-4 (master + children) |
| Порти | 18889, 19200 | + 19201-19203 (child API) |
Підфази Phase 20
20.1 — Master Bot Foundation
- Bun + TypeScript Telegram-бот (long-polling)
config/bot_registry.json— реєстр children- Команди:
/status,/emergency-stop,/list,/health - Docker-контейнер у
docker/docker-compose.yml - Health-ендпоінт:
/api/master/health - Без AI, без Claude-сесії — чистий оркестратор
20.2 — Child Bot Protocol (перший Child)
- Визначити протокол реєстрації child-бота
- Message middleware:
reply_to_message→ інжект CONTEXT у GSD - Thread history: останні 50 повідомлень у
state/thread_history.json - Протокол graceful shutdown (реакція на emergency-stop)
- Pilot: мігрувати
@citadel_v2_botіз Claude Channel на кастомного бота - Heartbeat у Master (кожні 60с через файл)
20.3 — Onboarding Engine (DONE)
/new_project <name>— 4-кроковий інтерактивний інтерв'ю- Метчинг скілів (registry + library), визначення blueprint
- Авто-провіжн: директорії, CLAUDE.md, MANIFEST.md, .env, registry, tmux
20.4 — Skill Library & Project Removal (DONE)
/remove_project <name>— потрійне підтвердження + захищені імена- Library-скіли авто-метчаться та копіюються під час onboarding
- Registry reload hook для in-memory оновлень
20.5 — Phantom-Ready Infrastructure (DONE)
shared/logger.ts— JSONL структуроване логування, denne розбиття файлівshared/vault.ts— AES-256-GCM зашифровані секрети (токени у vault, не в .env)master-bot/watchdog.ts— Watchdog із self-healing та exponential backoff- Команда
/watchdogдля real-time статусу children - Logrotate-конфіг + VPS setup script
- Усі console.log → структурований логер
Команди Master Bot (фінальні)
| Команда | Дія | Відповідь |
|---|---|---|
/status |
Читає стан + health + heartbeat усіх children | Зведений dashboard |
/emergency_stop |
3-рівнева kill-послідовність на всіх children | Підтвердження зі статусом по кожному child |
/list |
Показує зареєстрованих children | Ім'я, статус, tmux-сесія |
/deploy <name|all> |
Тригерить deploy для child(ren) | Deploy-лог по кожному child |
/health |
Перевіряє health-ендпоінти всіх children | Health-матриця |
/new_project <name> |
Стартує onboarding-інтерв'ю | 4-кроковий діалог |
/remove_project <name> |
Видаляє проєкт із підтвердженням | Triple-confirm + cleanup |
/watchdog |
Показує статус Watchdog | По кожному child: fails, restarts, backoff |
/cancel |
Скасовує активну операцію | Abort onboarding/removal |
Не у скоупі (Phase 21+)
- SaaS multi-tenancy (JWT, Stripe billing)
- Web-дашборд як альтернатива Telegram
- Голосові команди через Telegram
- Редактор спрайтів агентів та кастомізація офісу
- Механізм ротації ключів Vault
- Multi-VPS peer health monitoring
Архітектура Phase 20 — Rick (Lead Architect). Фази 20.1–20.5 завершені. Затверджено CEO 2026-04-02.