Architektura Ewoluującej Inteligencji

Phase 21.5–40.12 — System samodoskonalących się skilli dla Arc OS. Status: Gotowy produkcyjnie. Sage Worker (autonomiczne doskonalenie) + benchmarki (testowanie A/B) + odkrywanie marketplace + wyszukiwanie semantyczne NotebookLM.


Ogólny opis

Arc OS operuje federowaną architekturą botów, gdzie child boty pośredniczą między wiadomościami użytkownika a Claude CLI. Phase 21.1 wprowadziła śledzenie jakości (logi wykonania, przyciski feedbacku). Phase 21.5 zamyka pętlę: system teraz waliduje własne wyniki, zapamiętuje korekty, skupia kontekst i autonomicznie proponuje ulepszenia.

Siedem filarów tworzy warstwę inteligencji:

Wiadomość użytkownika
    │
    ├─► Context Router ──► SKILLS_HINT (top 5 trafnych skilli)
    │
    ├─► Learnings ──► blok LEARNINGS (przeszłe korekty)
    │
    ▼
buildGsdPrompt() ──► Claude CLI ──► Odpowiedź
                                        │
                                        ├─► Binary Evals ──► Przypisy z ostrzeżeniami
                                        │
                                        └─► Quality Tracker ──► Metryki
                                                                   │
                                                          Nightly Improve ──► Zatwierdzenie CEO

Filar 1: Silnik Binary Evals

Moduł: shared/evals.ts Pliki spec: skills/<nazwa>/<nazwa>.evals.json

Co robi

Każdy skill może deklarować reguły walidacji w pliku JSON. Po wygenerowaniu odpowiedzi przez Claude, silnik evals sprawdza ją względem wszystkich obowiązujących reguł. Niepowodzenia generują nieblokujące przypisy z ostrzeżeniami dołączane do wiadomości Telegram.

Typy reguł

Typ Sprawdza Przykładowe zastosowanie
string_contains Odpowiedź zawiera dosłowny ciąg Weryfikacja że wyjście JSON ma pole "verdict"
string_not_contains Odpowiedź NIE zawiera ciągu Blokuj --force w instrukcjach git
regex_match Odpowiedź pasuje do wzorca regex Upewnij się, że audyt systemu wspomina o dysku/RAM/CPU
regex_not_match Odpowiedź NIE pasuje do regex Zapobiegaj wzorcom wycieku danych uwierzytelniających
max_length Długość odpowiedzi <= N znaków Zachowaj zwięzłość wyjścia
min_length Długość odpowiedzi >= N znaków Zapewnij merytoryczne odpowiedzi

Poziomy ważności

Jak evals wpływają na metryki

Wyniki evals logowane są obok zdarzeń jakościowych. Gdy nocna pętla doskonalenia wykryje skill z niskim wskaźnikiem sukcesu, wzorce niepowodzeń evals pomagają zidentyfikować przyczynę bez potrzeby analizy AI.

Przykładowy plik eval

{
  "version": 1,
  "skill": "code-review",
  "rules": [
    { "id": "cr-001", "name": "Must return JSON verdict", "type": "string_contains", "value": "\"verdict\"", "severity": "warning" },
    { "id": "cr-002", "name": "No console.log debug", "type": "regex_not_match", "pattern": "console\\.log\\(", "severity": "warning" }
  ]
}

Zasada projektowania

Inspirowane frameworkiem evals Anthropic Skill Creator: deklaratywne asercje nad wyjściami, bez AI w pętli walidacyjnej. Binarne pass/fail eliminuje niejednoznaczność.


Filar 2: Context Router

Moduł: shared/context-router.ts Źródło danych: skills/_registry.json (pola triggers + keywords)

Co robi

Przed zbudowaniem promptu GSD, router ocenia każdy zarejestrowany skill względem wiadomości użytkownika. Top 5 dopasowań wstrzykiwanych jest jako blok SKILLS_HINT, nakierowując Claude na odpowiednie możliwości.

Algorytm oceniania

Dla każdego skilla:
  score = 0
  dla każdego triggera:   jeśli wiadomość zawiera trigger  → score += 2
  dla każdego słowa kluczowego:   jeśli wiadomość zawiera słowo kluczowe  → score += 1

Sortuj po score MALEJĄCO → weź top 5

Dopasowania triggerów punktują wyżej, bo triggery są jawnymi sygnałami wywołania (np. "review", "deploy"). Słowa kluczowe zapewniają szersze dopasowanie semantyczne (np. "OWASP", "Docker").

Dlaczego doradczy, nie filtrujący

Router jest wyłącznie doradczy. Claude CLI nadal ładuje wszystkie skille przez CLAUDE.md. Powody:

  1. Bezpieczeństwo: Twarde filtrowanie przez --allowedTools lub mutacje symlinków ryzykuje zepsuciem mid-sesji przy błędnej klasyfikacji wiadomości.
  2. Stabilność: Brak mutacji systemu plików na działającym procesie.
  3. Graceful degradation: Jeśli router zawiedzie, Claude nadal ma pełny dostęp do skilli.

Ekonomia okna kontekstu

Bez routera, wszystkie 23 skille konkurują o uwagę w prompcie. Blok SKILLS_HINT mówi Claude „skupi się na tych 3–5" — zmniejsza aktywację nieistotnych skilli i utrzymuje trafność odpowiedzi. To priming kontekstu, nie redukcja kontekstu.


Filar 3: Reflect Loop (Trwałe learnings)

Moduł: shared/learnings.ts Przechowywanie: {PROJECT_CWD}/learnings.md

Co robi

Gdy CEO naciska „Fix It" lub „👎", system przechwytuje regułę uczenia się i zapisuje ją do pliku markdown. Przy każdej kolejnej wiadomości, skumulowane learnings wstrzykiwane są do promptu GSD jako blok LEARNINGS.

Potok zdarzenie → learning

CEO naciska 🛠️ Fix It
    │
    ├─► addLearning(source: "fixit", rule: "Fix requested for: <kontekst>")
    │
    └─► projectLearnings przeładowane z dysku

CEO naciska 👎
    │
    ├─► addLearning(source: "negative", rule: "Negative feedback on: <kontekst>")
    │
    └─► qualityTracker.logFeedback(positive: false)

Format pliku learnings

# Learnings

> Auto-generowane. Wstrzykiwane do promptu GSD na początku sesji.

## Rules

- [2026-04-03T14:22:00Z] [fixit] Always use t-call for translations in Odoo QWeb
- [2026-04-03T15:10:00Z] [negative] Avoid sudo in deployment scripts

Wstrzykiwanie do promptu

Funkcja formatForPrompt() pobiera najnowsze learnings (do 2000 znaków), odwraca je (najnowsze pierwsze) i formatuje jako:

LEARNINGS (past corrections — follow these rules):
- Avoid sudo in deployment scripts
- Always use t-call for translations in Odoo QWeb

Zasada projektowania

Inspirowane systemem Claude Reflect: korekty nie naprawiają tylko bieżącej odpowiedzi — stają się trwałymi regułami zapobiegającymi regresji. System buduje „pamięć immunologiczną" z czasem.


Filar 4: Karpathy Loop (Nocne samodoskonalenie)

Moduł: scripts/nightly-improve.ts Harmonogram: Codziennie o 03:00 UTC przez cron Stan: mcp-server/state/improvement-proposals.json

Co robi

  1. Odczytuje config/bot_registry.json aby wyliczyć wszystkie child boty
  2. Dla każdego child bota: odczytuje quality-metrics.json z katalogu stanu
  3. Wywołuje findUnderperformingSkills() — filtruje skille gdzie:
    • applied_count >= 3 (minimalna próbka)
    • ORAZ success_rate < 80% LUB feedback_negative > feedback_positive
  4. Odczytuje learnings.md w poszukiwaniu powiązanych wzorców korekt
  5. Generuje propozycje oparte na szablonach (deterministyczne, bez AI)
  6. Wysyła raport podsumowujący do CEO na Telegram
  7. Wysyła indywidualne karty propozycji z przyciskami inline Zatwierdź/Odrzuć

Przepływ zatwierdzania przez CEO

Skrypt nocny ──► Telegram: Karta propozycji
                        │
           ┌────────────┼────────────┐
           ▼                         ▼
    ✅ Zatwierdź                 ❌ Odrzuć
           │                         │
    Backup skill.md              Oznacz jako odrzuconą
    jako skill.v1.md             w proposals.json
    (maks. 3 wersje)
           │
    Oznacz jako zatwierdzoną
    w proposals.json

Wersjonowanie skilli

Przy zatwierdzeniu, master bot tworzy kopie zapasowe z wersjami:

Zasada projektowania

Inspirowane AutoResearch Loop Karpathy'ego: modyfikuj → weryfikuj → zachowaj/odrzuć → powtarzaj. Kluczowa różnica: propozycje oparte są na szablonach i wymagają zatwierdzenia człowieka. Brak autonomicznego przepisywania skilli — CEO pozostaje ostatecznym autorytetem.


Phase 36+ — Warstwa semantyczna NotebookLM

Phase 36.3 dodała piąty kanał feedbacku: Google NotebookLM jako długoterminową pamięć semantyczną.

Zdarzenia CRM (zamknięcie zgłoszenia, aktualizacja wiki)
    │
    └─► fire-and-forget POST do bridge /sync
                                    │
                                    ▼
                          NotebookLM Bridge (:19213)
                            ├── SyncWorker (asyncio.Queue, 3 próby)
                            └── notebooklm-py → Google NotebookLM
                                    │
                                    ▼
                          Notatnik zaktualizowany nowym źródłem
                                    │
              ┌─────────────────────┤
              ▼                     ▼
    narzędzie ask_notebooklm    Neural Skill Generator
    (chat Cloud PM, 15s)        (POST /skills/generate, 30s)
              │                     │
              ▼                     ▼
    Semantyczna odpowiedź     Skill w Markdown do
    w kontekście projektu     przeglądu + zapisu (Phase 36.6)

Phase 36.6 dodała Neural Skill Generator: CEO definiuje cel ekstrakcji, bridge odpytuje NotebookLM ze strukturowanym promptem AI Architect, zwraca ścisły Markdown Rulebook, który można zapisać jako skill.

Phase 36.7 udostępniła notatniki w UI sidebara (zielona/czerwona kropka statusu, liczba źródeł, link zewnętrzny).


Filar 6: Sage Worker (Phase 40.11c)

Moduł: shared/sage.ts Wyzwalacz: POST /api/crm/sage/analyze lub scripts/nightly-improve.ts

Co robi

Sage to autonomiczny silnik doskonalenia skilli. Analizuje skille używając metryk jakości + feedbacku użytkownika (learnings), następnie generuje konkretną ulepszoną treść przez Anthropic API (model Haiku dla opłacalności). Wyniki przechowywane są jako skill_update_requests (PR-y) w bazie danych do przeglądu przez CEO.

Przepływ

Żądanie analizy Sage
    │
    ├─► Załaduj aktywne skille z DB (skillQueries)
    ├─► Skrzyżuj z metrykami jakości (readMetrics)
    ├─► Priorytetyzuj słabsze (findUnderperformingSkills)
    │
    ▼ Dla każdego docelowego skilla (maks. 5):
    ├─► Załaduj treść skilla + fork (jeśli scoped do projektu)
    ├─► Załaduj metryki jakości (wskaźnik sukcesu, liczniki feedbacku)
    ├─► Załaduj powiązane learnings (korekty użytkownika)
    ├─► Pomiń jeśli istnieje oczekujący PR
    ├─► Zbuduj prompt (treść + metryki + learnings)
    ├─► Wywołaj Anthropic API (Haiku, timeout 30s)
    ├─► Parsuj odpowiedź (NO_CHANGE = pomiń)
    ├─► Wstaw skill_update_request (proposed_by: 'sage')
    └─► Auto-uruchom benchmark (Filar 7) dla nowego PR

Dlaczego endpoint CRM, nie worker

Sage potrzebuje bezpośredniego dostępu do DB (skillQueries, benchmarkQueries) — workerzy działają jako podprocesy bez połączenia z DB. Sage nie otrzymuje wiadomości użytkownika; to analizator działający w tle, którego wynik = wiersze DB, nie tekst czatu.


Filar 7: Zatwierdzenia oparte na danych — Benchmarki (Phase 40.11d)

Moduł: shared/sage.ts (runBenchmark()) DB: shared/migrations/005_skill_benchmarks.ts API: POST /api/crm/sage/benchmark, GET /api/crm/skill-updates/:id/benchmarks

Co robi

Zanim CEO zatwierdzi PR Sage, system udowadnia, że zmiana działa. Generuje 3 scenariusze testowe, uruchamia stare i nowe treści skilla przez nie (ślepy test A/B) i używa sędziego LLM do oceny. Łączone punktowanie: deterministyczne eval_rules (60%) + sędzia LLM (40%).

Przepływ benchmarku

Uruchom Benchmark (requestId)
    │
    ├─► Załaduj skill_update_request (current_content + proposed_content)
    ├─► Załaduj eval_rules z DB
    │
    ▼ Generuj 3 scenariusze testowe (Haiku)
    │
    ▼ Dla każdego scenariusza:
    ├─► Uruchom starą treść skilla → old_output
    ├─► Uruchom nową treść skilla → new_output
    ├─► Randomizuj kolejność A/B (zapobieganie biasowi pozycji)
    ├─► Sędzia LLM ocenia oba (1-10) + uzasadnienie
    ├─► Deterministyczne eval_rules scoring (jeśli dostępne)
    ├─► Łączone punktowanie: eval 60% + LLM 40%
    └─► Zapisz do tabeli skill_benchmarks
    │
    ▼ Aktualizuj metadane PR
    ├─► verdict: PASSED / FAILED / TIE
    ├─► improvement_pct: ((new_avg - old_avg) / old_avg * 100)
    └─► BenchmarkBadge widoczny w nagłówku PR na froncie

Frontend: Tryb Battle

SkillEvolution.jsx → komponent BenchmarkReport:


Mapa plików

shared/
├── evals.ts              ← Filar 1: Silnik Binary Evals
├── context-router.ts     ← Filar 2: Context Router (routeContextFromDb)
├── learnings.ts          ← Filar 3: Reflect Loop
├── quality.ts            ← Rozszerzone: findUnderperformingSkills()
├── sage.ts               ← Filar 6+7: Sage Worker + Benchmarki (runSageAnalysis, runBenchmark)
├── db.ts                 ← SQLite jako SSOT: skillQueries, benchmarkQueries, chatQueries
├── migrations/
│   ├── 004_skill_system.ts     ← skills_global, forki, evolution_logs, update_requests
│   └── 005_skill_benchmarks.ts ← skill_benchmarks (wyniki testów A/B)
├── crm-routes.ts         ← CRM API: 55+ endpointów (Sage + benchmarki + ewolucja skilli)
└── ui_templates.ts       ← Rozszerzone: improvementProposal()

scripts/
├── nightly-improve.ts    ← Filar 4: Karpathy Loop (używa teraz Sage + DB)
└── migrate-skills-to-db.ts ← Migracja nuklearna: pliki → DB

clients/
├── arc-cli.ts            ← ARC CLI (Phase 31.5): login, start, projekty
└── knowledge-mcp.ts      ← Przestarzały (Phase 38 → podkomendy CLI)

services/
└── notebooklm-bridge/    ← Filar 5: wyszukiwanie semantyczne NotebookLM (Phase 36.3)
    ├── main.py           ← FastAPI (:19213), /query, /sync, /notebooks/init, /health
    └── seed_knowledge.py ← Masowy import istniejącej wiedzy

frontend/src/crm/pages/
└── SkillEvolution.jsx    ← Dwupanelowy UI: eksplorator + szczegóły (Content/Evals/Evolution/PRs)
                             BenchmarkBadge, BenchmarkReport, tryb Battle, przycisk analizy Sage

child-bot/bot.ts          ← Integracja: startup + prompt GSD + przypisy evals + /learnings
child-bot/ingest-watcher.ts ← Auto-ingest: fs.watch na raw/ → inbox CRM (Phase 28)
master-bot/bot.ts         ← Integracja: nocny trigger cron Sage