Arc OS — Przegląd Architektury

Ogólny opis

Arc OS zastępuje 11 321 linii niestandardowej infrastruktury Python/JS natywnymi narzędziami Claude Code. Agent AI staje się backendem.

Architektura systemu (Phase 52.1)

graph TB
    User[👤 Przeglądarka :18888]
    TG[📱 Telegram]
    Local[💻 Lokalne IDE]

    subgraph "Edge"
      Nginx[Nginx :18888<br/>basic-auth + deny-list]
      FE[React CRM + Phaser<br/>kontener frontend]
    end

    subgraph "Master Bot Bun :19210 — tylko 127.0.0.1"
      ApiSrv[api-server.ts<br/>196 LOC]
      Routes[master-bot/routes/<br/>auth · internal · cli · websocket]
      Router[shared/routes/router.ts<br/>dispatcher 373 LOC]

      subgraph "19 modułów domenowych — Phase 48"
        D1[auth · projects · workers]
        D2[skills · sage · chat]
        D3[wiki · files · onboarding]
        D4[billing · invites · analytics]
        D5[+ 7 kolejnych]
      end
    end

    subgraph "Federacja botów"
      Master[Master Bot<br/>orkiestrator]
      Child[Child Boty<br/>per-projekt]
      Claude[claude -p CLI]
    end

    subgraph "Warstwa inteligencji"
      Eval[Binary Evals]
      Ctx[Context Router top-5]
      Learn[Wstrzykiwanie Learnings]
      Karp[Pętla Karpathy'ego – nocna]
    end

    NB[NotebookLM Bridge<br/>FastAPI :19213 localhost]
    Google[(Google NotebookLM)]

    DB[(SQLite WAL<br/>21+ tabel<br/>migracje 001-021)]
    Vault[(Vault AES-256-GCM<br/>config/vault.json)]
    Bridge[Local Bridge CLI<br/>przekaźnik WebSocket]

    User -->|HTTPS| Nginx
    Nginx --> FE
    Nginx -->|/api/crm/*| ApiSrv
    Nginx -->|/api/sse/*| ApiSrv
    Nginx -->|/ws/terminal| ApiSrv
    ApiSrv --> Routes
    Routes --> Router
    Router --> D1 & D2 & D3 & D4 & D5

    TG --> Master
    TG --> Child
    Master -.uruchamia przez tmux.-> Child
    Child --> Claude
    Claude --> Eval & Ctx & Learn

    Router -.zapytania.-> NB
    Child -.auto-sync.-> NB
    NB --> Google

    Router --> DB
    Router --> Vault
    Child --> Vault

    Local --> Bridge
    Bridge -.ws relay.-> ApiSrv
    Karp -.nocna.-> DB

Kluczowe fakty:

LEGACY (v1):
Użytkownik → Bot Telegram (Python 111KB) → HybridEngine → command_queue.json
       → bridge_processor.sh → Claude → command_responses.json
       → FastAPI EventBus → WebSocket → Phaser UI

V2 (NATYWNY):
Użytkownik → Oficjalny kanał Telegram → sesja Claude Code
       ↓                                ↓
       reply/edit_message          Zespoły agentów (TaskCreate/SendMessage)
                                        ↓
                                   Zapisz stan → pliki JSON
                                        ↓
                                   Arc OS Bridge MCP → HTTP/SSE → Phaser UI

Redukcja: 11 321 linii → ~3 700 linii (67% mniej kodu)

Komponenty

1. Sesja Claude Code (Mózg systemu)

Sesja Claude Code zastępuje:

Cała orkiestracja odbywa się natywnie przez Zespoły Agentów.

2. Arc OS Bridge MCP Server (Adapter stanu)

Serwer MCP w TypeScript (Bun) — most między stanem Claude Code a frontendem.

Narzędzia MCP (strona Claude Code):

Narzędzie Kierunek Opis
get_office_state odczyt Odczyt state/office-state.json
update_agent_state zapis Aktualizacja pozycji, statusu i bąbelka agenta
get_tasks odczyt Odczyt plików zadań Zespołów Agentów
get_knowledge odczyt Odczyt indeksu wiedzy

HTTP API (strona frontendu):

Endpoint Metoda Opis
/api/state GET Pełny stan biura
/api/tasks GET Lista zadań
/api/knowledge GET Indeks wiedzy
/api/events GET Strumień SSE

3. Frontend Phaser (Warstwa wizualna)

Phaser 3.80 + Vite. Łączy się z serwerem MCP przez HTTP/SSE.

Kluczowa różnica od v1: brak WebSocket — zastąpiony SSE z serwera MCP. Brak interfejsu do wpisywania poleceń — Telegram pełni rolę interfejsu sterowania.

4. Interfejs poleceń Telegram (Taktyczna warstwa UI — Phase 21.0)

Telegram to główny panel sterowania całego Arc OS. Dwa poziomy botów:

Master Bot (@citadel_ceo_bot):

Child Boty (@cv2_pt_bot itp.):

Integracja CRM (development):

CRM_BASE_URL = http://62.171.128.248:18888  (dev)
               https://crm.citadel.v2       (przyszły prod)

Wszystkie układy klawiatur zdefiniowane w shared/ui_templates.ts — jedno źródło prawdy dla zmian UI.

Protokół danych callback: akcja:cel (maks. 64 bajty)

Przepływ danych

1. Użytkownik wysyła "/status" przez Telegram
2. Sesja Claude Code odbiera przez kanał Telegram
3. Rick odczytuje state/office-state.json + TaskList()
4. Rick odpowiada przez Telegram (edit_message dla aktualizacji na żywo)
5. Rick wywołuje update_agent_state() przez MCP
6. Serwer MCP zapisuje do state/office-state.json
7. File watcher wykrywa zmianę → wysyła zdarzenie SSE
8. Frontend odbiera SSE → aktualizuje sprite'y agentów

Zarządzanie stanem

Cały stan przechowywany jest w plikach JSON w katalogu state/:

Plik Schemat Aktualizowany przez Odczytywany przez
office-state.json Pozycje, statusy, bąbelki agentów Claude (przez MCP) Frontend (przez HTTP)
knowledge.json Indeksowane metadane plików Agent Squanchy Frontend, Beth
reports/*.json Wyniki analiz Beth, Summer Frontend

Zadania Zespołów Agentów zarządzane natywnie przez Claude Code pod ~/.claude/tasks/citadel-v2/.

Agenci (6)

Agent Rola Model Aktywacja
Rick CEO/Orkiestrator opus-4.6 Zawsze aktywny (lider zespołu)
Morty SRE/Monitoring haiku-4.5 Kontrole zdrowia, cron
Summer Pamięć/Przegląd sonnet-4.5 Code review, bezpieczeństwo
Jerry Utrzymanie haiku-4.5 Porządki, dokumentacja
Squanchy Archiwista haiku-4.5 Indeksowanie plików
Beth Analityk sonnet-4.5 Badania, analiza

Łańcuch dostaw

CEO → Rick (dekompozycja) → Zespół Agentów (wykonanie)
                          → Wzajemny przegląd (Summer waliduje)
                          → Rick (synteza)
                          → CEO (wynik końcowy)

Wymuszone przez:

Stos technologiczny

Warstwa v1 v2
Backend FastAPI + Python 3.12 Sesja Claude Code
Baza danych SQLite (8 tabel) Pliki JSON + Zespoły Agentów
Komunikacja WebSocket + EventBus Zespoły Agentów SendMessage
Stan SQLite + bridge JSON Pliki JSON (state/)
Frontend Phaser 3.86 + WebSocket Phaser 3.80 + SSE
Telegram Własny bot (111 KB) Oficjalny plugin kanału
Bridge bash + jq (19,6 KB) Wyeliminowany
MCP Brak Arc OS Bridge (TypeScript)
Deploy Docker Compose Docker Compose

Hooki cyklu życia

Hooki Claude Code (~/.claude/settings.json) automatycznie synchronizują stan agenta:

Zdarzenie SubagentStop → subagent-stop.sh → office-state.json (agent=idle)
                                              ↓
                                   StateManager (fs.watch) → SSE → Phaser UI

Zdarzenie Stop → session-end.sh → latest_wrapup.txt + wszystkie agenty=idle

Skrypty: scripts/citadel-hooks/subagent-stop.sh, scripts/citadel-hooks/session-end.sh

Kluczowe pola: subagentName (SubagentStop), stopReason (Stop), cwd (oba).

NotebookLM Bridge (Phase 36.3)

Prawdziwe wyszukiwanie semantyczne przez Google NotebookLM, zastępujące ręczne przesyłanie plików:

Cloud PM Chat → Bun Master Bot (:19210)
                    │
         executeAskNotebooklm()
                    │
         HTTP → FastAPI Bridge (:19213, tylko localhost)
                    │
              notebooklm-py async client
                    │
              Google NotebookLM (darmowe wyszukiwanie semantyczne)

         Fallback: lokalne wyszukiwanie słów kluczowych (istniejący kod)

Eksport oparty na plikach (/citadel-wrapup, /citadel-recall) nadal działa jako fallback.

Polityka routingu danych i zadań

System trzywarstwowy. Każda warstwa ma ściśle określone przeznaczenie. Mieszanie warstw = chaos.

┌─────────────────────────────────────────────────────────────────┐
│  WARSTWA 1: Pamięć robocza (gorąca)                             │
│  office-state.json + state/tasks/                               │
│  CLI: /citadel-task, /citadel-status                            │
│                                                                 │
│  Codzienne zadania agentów. Żyje w trakcie sesji. Ginie po.    │
│  Ukończone zadanie → /citadel-wrapup → Warstwa 3.              │
├─────────────────────────────────────────────────────────────────┤
│  WARSTWA 2: Strategiczny backlog (ciepły)                       │
│  GitHub Issues (repozytoria Claude-CEO + citadel-v2)            │
│                                                                 │
│  Tylko epiki: Phase 20, Phase 21, globalne błędy.              │
│  Bez zadań codziennych. Bez zgłoszeń "popraw literówkę".       │
│  Jedno zgłoszenie = jedna wielotygodniowa inicjatywa lub bug.  │
├─────────────────────────────────────────────────────────────────┤
│  WARSTWA 3: Pamięć długoterminowa (zimna)                       │
│  docs/library-export/ → Google Drive → NotebookLM              │
│  CLI: /citadel-wrapup, /citadel-recall                          │
│                                                                 │
│  Encyklopedia. Wyniki sesji, decyzje arch., RAG.               │
│  Archiwum tylko do odczytu. Brak aktywnych zadań.              │
└─────────────────────────────────────────────────────────────────┘

Zasady routingu

Typ danych Warstwa Przykład
„Napraw skrypt deploy" 1 — Pamięć robocza /citadel-task "Napraw skrypt deploy"
„Phase 20: Multi-Tenant SaaS" 2 — GitHub Issues gh issue create --title "Phase 20: ..."
„Podsumowanie sesji: hooki zaimplementowane" 3 — Biblioteka /citadel-wrapup → NotebookLM
„Decyzja arch.: wybrano SSE zamiast WS" 3 — Biblioteka Archiwizowane w wrapup po sesji
„Bug: SSE zrywa na VPS" 2 — GitHub Issues Tylko jeśli blokuje lub dotyczy wielu sesji
„Rick pracuje nad hookami" 1 — Pamięć robocza status agenta office-state.json

Cykl życia

CEO daje zadanie → Warstwa 1 (agent pracuje)
                       ↓ ukończone
                   /citadel-wrapup → Warstwa 3 (zarchiwizowane)
                       ↓ jeśli strategiczne
                   gh issue create → Warstwa 2 (śledzenie długoterminowe)

Antywzorce (NIE RÓB)

Infrastruktura (Phase 20.5)

Logowanie strukturalne (shared/logger.ts)

Format JSONL, podwójny output (plik + konsola), dzienne dzielenie plików według kategorii.

/var/log/citadel/
├── master/
│   ├── system-2026-04-02.log   ← cykl życia, config, zdrowie
│   ├── dialog-2026-04-02.log   ← (nie używany przez mastera)
│   └── error-2026-04-02.log    ← błędy (też w system)
├── citadel-v2/
│   ├── system-2026-04-02.log
│   ├── dialog-2026-04-02.log   ← wiadomości użytkownik ↔ Claude
│   └── error-2026-04-02.log
└── <nazwa-projektu>/           ← per onboardowany projekt

Rotacja logów: config/logrotate-citadel.conf/etc/logrotate.d/citadel (codziennie, retencja 7 dni).

Vault sekretów (shared/vault.ts)

Zaszyfrowane AES-256-GCM przechowywanie tokenów botów.

Źródło klucza: env SECRET_ENCRYPTION_KEY → plik config/vault-key → auto-generowany
Przechowywanie: config/vault.json (atomiczne zapisy: tmp + mv)
Cache:          In-memory po initVault() — brak I/O dysku per getSecret()
Fallback:       getSecret("FOO") → cache vault → process.env.FOO
Nazewnictwo:    child:<nazwa-projektu>:token

Własny token mastera pozostaje w .env (vault ładuje się wewnątrz procesu mastera).

Samoleczący Watchdog (master-bot/watchdog.ts)

Monitor działający w tle dla child botów. Działa wewnątrz procesu master bota.

Co 30s: kontrola zdrowia HTTP → /api/child/health (timeout 5s)
  Zdrowy → reset licznika błędów
  Niezdrowy → inkrementuj błędy
  3+ błędy + upłynął backoff → auto-restart (kill tmux → start nowy z tokenem z vault)
  Backoff: 30s → 1 min → 5 min → 15 min → 60 min (max)
  10 kolejnych błędów → trwałe wyłączenie + powiadomienie CEO

Stan przechowywany w config/watchdog-state.json (przeżywa restart mastera). Powiadomienia CEO przez Telegram: pierwszy restart, błąd restartu, trwałe wyłączenie. Komenda /watchdog: status w czasie rzeczywistym dla wszystkich dzieci.

Protokół usuwania projektu (Phase 20.4 + 21.0)

/remove_project <nazwa> → potrójna konfirmacja → pełne czyszczenie:

1. Zabij sesję tmux: child-<nazwa>
2. Masowe usuwanie duchów: ps aux | grep child-<nazwa> → kill -9 wszystkich PID
3. Sprawdzenie portu: ss -tlnp | grep :<port> → wymuś zwolnienie jeśli zajęty
4. Usuń z bot_registry.json + przeładuj in-memory
5. Usuń /opt/repos/<nazwa>/ (bezpieczeństwo: ścieżka musi być pod /opt/repos/, min 3 segmenty)
6. Usuń /var/log/citadel/<nazwa>/

Chronione nazwy: citadel-v2, citadel, claude-ceo, claude-CEO — usuwanie zablokowane.

Problem procesów-duchów (lekcja): po zabiciu tmux, osierocone procesy bun mogą trzymać porty. Masowe zabijanie + sprawdzenie portu zapobiega „phantom botom", które odpowiadają na kontrole zdrowia, ale ignorują Telegram.

Zarządzanie skillami (Phase 21.0)

Child boty ładują skille z dwóch źródeł przy starcie, deduplikowane przez Set:

Źródło 1: MANIFEST.md (JSON)
  → manifest.skills[]          (dopasowane podczas onboardingu)
  → manifest.library_skills[]  (dopasowane pliki .md z biblioteki)

Źródło 2: katalog skills/
  → pliki *.md → nazwa pliku bez rozszerzenia

Scalanie: Set<string>(manifest.skills + manifest.library_skills + skills/*.md)

Przykład (projekt PT): 5 z manifestu + 7 z skills/ = 12 unikalnych skilli.

Skille wyświetlane jako:

Bezpieczeństwo (Phase 42 — audyt Sentinel 2026-04-23, 4 przebiegi, 13 łatek)

Pełny przegląd: SECURITY.md. Raport z audytu: security/audit-2026-04-23.md.

Sekrety i przechowywanie:

Auth:

Multi-tenancy (Phase 42):

Perymetr sieci:

Bezpieczeństwo wejścia / ścieżek:

Pokrycie regresji: scripts/vps-sync.sh uruchamia 7+ testów dymnych po każdym deployu (bind loopback, path traversal, walidacja chat/save, kanarka proxy, SSE ?token=, walidacja fail-closed, blokada SSRF jeśli ustawione CEO_TOKEN).

Moduły Master Bota (Phase 25 — Rozwiązanie DEBT-1)

Master bot zorganizowany jest w skoncentrowane moduły:

master-bot/
├── bot.ts               ← Bootstrap: vault, rejestr, kontekst, okablowanie (106 linii)
├── context.ts           ← Typ MasterContext + interfejsy domenowe
├── api-server.ts        ← Bun.serve() — HTTP, WebSocket, SSE, trasy CRM
├── tg-api.ts            ← Wrapper Telegram Bot API (sendMessage, getUpdates itp.)
├── child-state.ts       ← Stan child bota, zdrowie, heartbeat, tmux, bridge
├── telegram-commands.ts ← Wszystkie handlery /komend, router callback query, router wiadomości
├── telegram.ts          ← Uproszczona pętla pollingu + re-eksporty dla wstecznej kompatybilności
├── watchdog.ts          ← Samoleczący monitor child botów
└── onboarding.ts        ← Interaktywny wizard tworzenia projektu

bot.ts importuje tylko z telegram.ts i api-server.ts. Wszystkie pozostałe moduły to szczegóły implementacji.

Bridge CLI (Phase 25 — Lokalna Brama)

bridge/
├── bin/citadel-bridge.ts    ← Wejście CLI (commander.js): connect, pull, push, status, disconnect
├── src/
│   ├── auth.ts              ← Walidacja JWT względem CRM
│   ├── config.ts            ← Trwałość ~/.citadel/bridge.json
│   ├── inject.ts            ← Markery <!-- CITADEL:START/END --> w CLAUDE.md
│   ├── sync.ts              ← Pull skills-bundle + learnings, push lokalnych learnings
│   └── heartbeat.ts         ← Reporter aktywności sesji
├── package.json
└── tsconfig.json

Endpointy CRM API (50+ łącznie)

Podstawowe CRM (Phase 22)

Endpoint Metoda Cel
/api/master/health GET Zdrowie master bota (publiczne)
/api/crm/projects GET Lista wszystkich projektów + zdrowie na żywo
/api/crm/projects/:name GET Szczegóły projektu
/api/crm/projects/:name/logs GET Ogon logów JSONL
/api/crm/projects/:name/files GET Bezpieczny listing katalogów
/api/crm/projects/:name/files/upload POST Upload plików
/api/crm/projects/:name/files/mkdir POST Tworzenie folderu
/api/crm/projects/:name/files/create POST Tworzenie pliku
/api/crm/projects/:name/files/delete DELETE Usunięcie pliku/folderu
/api/crm/projects/:name/files/clone POST Klonowanie repozytorium git
/api/crm/projects/:name/files/read GET Odczyt zawartości pliku
/api/crm/projects/:name/wiki/tree GET Lista plików .md w wiki
/api/crm/projects/:name/wiki/file GET Odczyt pliku wiki
/api/crm/projects/:name/skills GET Zainstalowane skille
/api/crm/projects/:name/metrics GET Szereg czasowy jakości
/api/crm/projects/:name/restart POST Restart child bota
/api/crm/projects/:name/specs GET Lista specyfikacji
/api/crm/projects/:name/specs/:id/approve POST Zatwierdź specyfikację
/api/crm/projects/:name/specs/:id/reject POST Odrzuć specyfikację
/api/crm/projects/:name/active-role GET/POST Rola agenta
/api/crm/projects/:name/message POST Kolejkuj wiadomość do workera
/api/crm/projects/:name/workers GET/POST CRUD rejestru workerów
/api/crm/projects/:name/workers/:id PUT/DELETE Aktualizuj/usuń workera
/api/crm/projects/:name/workers/generate-prompt POST AI-generuj prompt systemowy
/api/crm/projects/:name/skills-bundle GET Skille + evals dla bridge
/api/crm/projects/:name/learnings GET/POST Synchronizacja learnings
/api/sse/logs/:name GET Strumień SSE logów (?category=)

Pulpit i wiki (Phase 32)

Endpoint Metoda Cel
/api/crm/projects/:name/wiki/save PUT Zapisz/utwórz stronę wiki
/api/crm/projects/:name/skills/save PUT Zapisz plik skilla
/api/crm/projects/:name/skills/delete DELETE Usuń plik skilla

Multi-tenancy (Phase 33)

Endpoint Metoda Cel
/api/crm/account/settings GET/PUT Klucze API na poziomie konta
/api/crm/projects/create POST Lekkie tworzenie projektu
/api/crm/onboarding/setup POST Pełny wizard onboardingu

MCP i CLI (Phase 34)

Endpoint Metoda Cel
/api/mcp/issues/:project POST/GET CRUD zgłoszeń
/api/mcp/issues/:project/:id PUT Aktualizuj zgłoszenie
/api/mcp/wiki/:project PUT Synchronizacja wiki przez MCP
/api/mcp/roadmap/:project GET/PUT Odczyt/synchronizacja roadmapy
/api/cli/init/:project/:mode GET Kontekst chmurowy dla CLI
/api/mcp/skills/:project/:skill GET Pobierz skill dla MCP
/api/mcp/report/:project POST Raport misji
/api/mcp/learnings/:project GET Pobierz learnings dla MCP

Terminal na żywo (Phase 35)

Endpoint Metoda Cel
/api/crm/projects/:name/terminal/log POST Odbierz JSONL terminala z ARC CLI

Cloud PM i wiedza (Phase 36)

Endpoint Metoda Cel
/api/crm/projects/:name/chat POST Proxy chatu SSE do Anthropic API
/api/crm/projects/:name/skills/generate POST Generator Neuronowych Skilli (NotebookLM)
/api/crm/projects/:name/notebooks GET Powiązane notatniki NotebookLM

Auth i OAuth (Phase 37)

Endpoint Metoda Cel
/api/auth/register POST Rejestracja email/hasło
/api/auth/login POST Logowanie email/hasło
/api/auth/google GET Przekierowanie OAuth Google
/api/auth/callback/google GET Callback OAuth Google
/api/auth/github GET Przekierowanie OAuth GitHub
/api/auth/callback/github GET Callback OAuth GitHub
/api/auth/providers GET Dostępni providerzy OAuth

Przypięte notatki (Phase 41.8)

Endpoint Metoda Cel
/api/crm/projects/:name/pins GET Lista przypiętych notatek (najnowsze pierwsze)
/api/crm/projects/:name/pins POST Przypnij wiadomość workera do Context Rail (body: worker_id, body, opcjonalnie title, author)
/api/crm/projects/:name/pins/:id DELETE Usuń przypinkę

Backend: migracja 009 (tabela pinned_notes), pinnedNoteQueries w shared/db.ts. Frontend: ContextRail.jsx pobiera przy montowaniu, nasłuchuje zdarzenia CustomEvent crm-pin-created, optymistyczne DELETE.

Warstwa ochrony danych (Phase 45)

Hybrydowe szyfrowanie at-rest — fundament kryptografii po stronie klienta + szyfrowanie po stronie serwera.

Po stronie klienta (Przeglądarka)

Po stronie serwera (Bun + SQLite)

Nagłówki bezpieczeństwa

Sanityzacja PII

Endpointy klucza odzyskiwania

Endpoint Metoda Cel
/api/crm/account/recovery POST Utwórz klucz odzykiwania (przechowuje zaszyfrowany klucz główny)
/api/crm/account/recovery GET Lista aktywnych kluczy odzyskiwania
/api/crm/account/recovery DELETE Unieważnij klucz(e) odzykiwania
/api/crm/account/recovery/restore GET Pobierz zaszyfrowany klucz główny do odzyskiwania

Pełne szczegóły bezpieczeństwa: docs/SECURITY.md, docs/architecture/PHASE_45_E2EE.md.