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+ проєктах:

Рішення: Федерація

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.

Вердикт: Правильне рішення. Більше інфраструктурної складності, але вирішує ВСІ проблеми.

Чому Федерація виграє

  1. Ізоляція контексту — вирішальний фактор. Одна Claude-сесія на 3+ проєкти = переповнення контексту за 30 хвилин активної роботи. Федерація дає кожному проєкту чисті 200K токенів.
  2. Готовність до multi-user — це не «фіча на майбутнє», це фундамент. Без неї Arc OS не стане продуктом.
  3. 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. Explicit команда /exit Якщо 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 Є

Чим Master Bot НЕ Є

Протокол Child Bot

Кожен child-бот має:

  1. Зареєструватися в config/bot_registry.json при старті
  2. Надсилати heartbeat (кожні 60с) у Master через файл: state/heartbeat_<name>.json
  3. Обробляти reply_to_message → інжект CONTEXT у GSD
  4. Зберігати останні 50 повідомлень у state/thread_history.json
  5. Реагувати на сигнал emergency-stop (graceful Ctrl+C → /exit → kill)
  6. Використовувати структурований логер (shared/logger.ts) — логи у /var/log/citadel/<name>/
  7. Приймати env-змінну BOT_NAME для динамічного іменування
  8. Виставляти /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

20.2 — Child Bot Protocol (перший Child)

20.3 — Onboarding Engine (DONE)

20.4 — Skill Library & Project Removal (DONE)

20.5 — Phantom-Ready Infrastructure (DONE)

Команди 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+)


Архітектура Phase 20 — Rick (Lead Architect). Фази 20.1–20.5 завершені. Затверджено CEO 2026-04-02.