Arquitetura de Inteligência Evolutiva

Phase 21.5–40.12 — Sistema de skills auto-aperfeiçoável do Arc OS. Status: Pronto para produção. Sage Worker (melhoria autônoma) + benchmarks (A/B testing) + Marketplace Discovery + busca semântica NotebookLM.


Visão Geral

O Arc OS opera uma arquitetura de bots federados onde os child bots fazem proxy das mensagens do usuário para o Claude CLI. A Phase 21.1 introduziu rastreamento de qualidade (logs de execução, botões de feedback). A Phase 21.5 fecha o ciclo: o sistema agora valida sua própria saída, memoriza correções, foca o contexto e propõe melhorias de forma autônoma.

Sete pilares formam a camada de inteligência:

Mensagem do Usuário
    │
    ├─► Context Router ──► SKILLS_HINT (top 5 skills relevantes)
    │
    ├─► Learnings ──► bloco LEARNINGS (correções passadas)
    │
    ▼
buildGsdPrompt() ──► Claude CLI ──► Resposta
                                        │
                                        ├─► Binary Evals ──► Notas de aviso
                                        │
                                        └─► Quality Tracker ──► Métricas
                                                                   │
                                                          Nightly Improve ──► Aprovação do CEO

Pilar 1: Motor de Binary Evals

Módulo: shared/evals.ts Arquivos de spec: skills/<name>/<name>.evals.json

O que faz

Cada skill pode declarar regras de validação em um arquivo JSON. Após o Claude gerar uma resposta, o motor de evals a verifica contra todas as regras aplicáveis. Falhas produzem notas de aviso não-bloqueantes anexadas à mensagem do Telegram.

Tipos de regras

Tipo Verifica Exemplo de uso
string_contains Resposta inclui uma string literal Verificar se a saída JSON tem o campo "verdict"
string_not_contains Resposta NÃO inclui uma string Bloquear --force em instruções git
regex_match Resposta corresponde a um padrão regex Garantir que auditoria de sistema mencione disk/RAM/CPU
regex_not_match Resposta NÃO corresponde a um regex Prevenir padrões de vazamento de credenciais
max_length Tamanho da resposta <= N chars Manter a saída concisa
min_length Tamanho da resposta >= N chars Garantir respostas substantivas

Níveis de severidade

Como os evals afetam as métricas

Os resultados dos evals são registrados junto com eventos de qualidade. Quando o loop de melhoria noturna detecta uma skill com taxa de sucesso baixa, os padrões de falha de eval ajudam a identificar a causa raiz sem precisar de análise com IA.

Exemplo de arquivo de 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" }
  ]
}

Princípio de design

Inspirado pelo framework de evals Anthropic's Skill Creator: asserções declarativas sobre saídas, sem IA no loop de validação. Pass/fail binário elimina ambiguidade.


Pilar 2: Context Router

Módulo: shared/context-router.ts Fonte de dados: skills/_registry.json (campos triggers + keywords)

O que faz

Antes de construir o prompt GSD, o roteador pontua cada skill registrada em relação à mensagem do usuário. As top 5 correspondências são injetadas como um bloco SKILLS_HINT, preparando o Claude para focar nas capacidades relevantes.

Algoritmo de pontuação

Para cada skill:
  score = 0
  para cada trigger:   se mensagem contém trigger  → score += 2
  para cada keyword:   se mensagem contém keyword  → score += 1

Ordenar por score DESC → pegar top 5

Correspondências de trigger pontuam mais porque triggers são sinais explícitos de invocação (ex.: "review", "deploy"). Keywords oferecem correspondência semântica mais ampla (ex.: "OWASP", "Docker").

Por que é consultivo, não filtrante

O roteador é apenas consultivo. O Claude CLI ainda carrega todas as skills via CLAUDE.md. Motivos:

  1. Segurança: Filtragem forçada via --allowedTools ou mutações de symlink corre o risco de quebrar sessões em andamento se o roteador classificar mal uma mensagem.
  2. Estabilidade: Sem mutações no sistema de arquivos em processos em execução.
  3. Degradação graceful: Se o roteador falhar, o Claude ainda tem acesso total às skills.

Economia de janela de contexto

Sem o roteador, todas as 23 skills competem por atenção no prompt. O bloco SKILLS_HINT diz ao Claude "foque nestas 3-5" — reduzindo ativação de skills irrelevantes e mantendo as respostas no tema. Isso é priming de contexto, não redução de contexto.


Pilar 3: Reflect Loop (Learnings Persistentes)

Módulo: shared/learnings.ts Armazenamento: {PROJECT_CWD}/learnings.md

O que faz

Quando o CEO pressiona "Fix It" ou "👎", o sistema captura uma regra de aprendizado e a persiste em um arquivo markdown. Em cada mensagem subsequente, os learnings acumulados são injetados no prompt GSD como um bloco LEARNINGS.

Pipeline Evento → Learning

CEO pressiona 🛠️ Fix It
    │
    ├─► addLearning(source: "fixit", rule: "Fix requested for: <context>")
    │
    └─► projectLearnings recarregado do disco

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

Formato do arquivo de learnings

# Learnings

> Auto-generated. Injected into GSD prompt at session start.

## 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

Injeção no prompt

A função formatForPrompt() pega os learnings mais recentes (até 2000 chars), os inverte (mais recentes primeiro) e formata como:

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

Princípio de design

Inspirado no Claude Reflect System: as correções não apenas corrigem a resposta atual — elas se tornam regras persistentes que previnem regressão. O sistema constrói "memória imunológica" ao longo do tempo.


Pilar 4: Karpathy Loop (Auto-Melhoria Noturna)

Módulo: scripts/nightly-improve.ts Agendamento: Diariamente às 03:00 UTC via cron Estado: mcp-server/state/improvement-proposals.json

O que faz

  1. config/bot_registry.json para enumerar todos os child bots
  2. Para cada child: lê quality-metrics.json do seu diretório de estado
  3. Chama findUnderperformingSkills() — filtra skills onde:
    • applied_count >= 3 (tamanho mínimo de amostra)
    • E success_rate < 80% OU feedback_negative > feedback_positive
  4. learnings.md para padrões de correção relacionados
  5. Gera propostas baseadas em templates (determinístico, sem IA envolvida)
  6. Envia relatório resumido ao CEO pelo Telegram
  7. Envia cards individuais de proposta com botões inline Aprovar/Rejeitar

Fluxo de aprovação do CEO

Script noturno ──► Telegram: Card de Proposta
                        │
           ┌────────────┼────────────┐
           ▼                         ▼
    ✅ Aprovar                  ❌ Rejeitar
           │                         │
    Faz backup de skill.md      Marca como rejeitada
    como skill.v1.md            em proposals.json
    (máx. 3 versões)
           │
    Marca como aprovada
    em proposals.json

Versionamento de skills

Na aprovação, o master bot cria backups versionados:

Princípio de design

Inspirado no AutoResearch Loop de Karpathy: modificar → verificar → manter/descartar → repetir. A diferença crítica: as propostas são baseadas em templates e exigem aprovação humana. Sem reescrita autônoma de skills — o CEO permanece como autoridade final.


Phase 36+ — Camada Semântica NotebookLM

A Phase 36.3 adicionou um quinto canal de feedback: Google NotebookLM como memória semântica de longo prazo.

Eventos CRM (issue close, wiki update)
    │
    └─► fire-and-forget POST para bridge /sync
                                    │
                                    ▼
                          NotebookLM Bridge (:19213)
                            ├── SyncWorker (asyncio.Queue, 3 retries)
                            └── notebooklm-py → Google NotebookLM
                                    │
                                    ▼
                          Notebook atualizado com nova fonte
                                    │
              ┌─────────────────────┤
              ▼                     ▼
    tool ask_notebooklm     Neural Skill Generator
    (Cloud PM chat, 15s)    (POST /skills/generate, 30s)
              │                     │
              ▼                     ▼
    Resposta semântica no   Skill em Markdown para
    contexto do projeto     revisão + save (Phase 36.6)

A Phase 36.6 adicionou o Neural Skill Generator: o CEO define um objetivo de extração, o bridge consulta o NotebookLM com um prompt estruturado de AI Architect e retorna um Rulebook estrito em Markdown que pode ser salvo como uma skill.

A Phase 36.7 expôs os notebooks na UI da sidebar (ponto de status verde/vermelho, contagem de fontes, link externo).


Pilar 6: Sage Worker (Phase 40.11c)

Módulo: shared/sage.ts Gatilho: POST /api/crm/sage/analyze ou scripts/nightly-improve.ts

O que faz

O Sage é um motor autônomo de melhoria de skills. Ele analisa skills usando métricas de qualidade + feedback do usuário (learnings), depois gera conteúdo melhorado concreto via Anthropic API (modelo Haiku para eficiência de custo). Os resultados são armazenados como skill_update_requests (PRs) no banco de dados para revisão do CEO.

Fluxo

Requisição Sage Analyze
    │
    ├─► Carrega skills ativas do DB (skillQueries)
    ├─► Cruza com métricas de qualidade (readMetrics)
    ├─► Prioriza underperformers (findUnderperformingSkills)
    │
    ▼ Para cada skill-alvo (máx. 5):
    ├─► Carrega conteúdo da skill + fork (se escopo de projeto)
    ├─► Carrega métricas de qualidade (taxa de sucesso, contagens de feedback)
    ├─► Carrega learnings relacionados (correções do usuário)
    ├─► Pula se PR pendente já existe
    ├─► Constrói prompt (conteúdo + métricas + learnings)
    ├─► Chama Anthropic API (Haiku, timeout 30s)
    ├─► Faz parse da resposta (NO_CHANGE = pula)
    ├─► Insere skill_update_request (proposed_by: 'sage')
    └─► Executa benchmark automaticamente (Pilar 7) no novo PR

Por que endpoint CRM, não um worker

O Sage precisa de acesso direto ao DB (skillQueries, benchmarkQueries) — workers rodam como subprocessos sem conexão com o DB. O Sage não recebe mensagens do usuário; é um analisador em segundo plano cuja saída são linhas do DB, não texto de chat.


Pilar 7: Aprovações Baseadas em Dados — Benchmarks (Phase 40.11d)

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

O que faz

Antes do CEO aprovar um PR do Sage, o sistema prova que a mudança funciona. Gera 3 cenários de teste, executa o conteúdo antigo e o novo através deles (blind A/B test) e usa um LLM judge para determinar qual é melhor. Pontuação combinada: regras eval determinísticas (60%) + LLM judge (40%).

Fluxo de Benchmark

Executar Benchmark (requestId)
    │
    ├─► Carrega skill_update_request (current_content + proposed_content)
    ├─► Carrega eval_rules do DB
    │
    ▼ Gera 3 cenários de teste (Haiku)
    │
    ▼ Para cada cenário:
    ├─► Executa conteúdo antigo da skill → old_output
    ├─► Executa conteúdo novo da skill → new_output
    ├─► Aleatoriza ordem A/B (prevenção de viés de posição)
    ├─► LLM Judge pontua ambos (1-10) + motivo
    ├─► Pontuação determinística eval_rules (se disponível)
    ├─► Pontuação combinada: eval 60% + LLM 40%
    └─► Salva na tabela skill_benchmarks
    │
    ▼ Atualiza metadados do PR
    ├─► verdict: PASSED / FAILED / TIE
    ├─► improvement_pct: ((new_avg - old_avg) / old_avg * 100)
    └─► BenchmarkBadge visível no cabeçalho do PR no frontend

Frontend: Battle Mode

SkillEvolution.jsx → componente BenchmarkReport:


Mapa de Arquivos

shared/
├── evals.ts              ← Pilar 1: Motor de Binary Evals
├── context-router.ts     ← Pilar 2: Context Router (routeContextFromDb)
├── learnings.ts          ← Pilar 3: Reflect Loop
├── quality.ts            ← Estendido: findUnderperformingSkills()
├── sage.ts               ← Pilar 6+7: Sage Worker + Benchmarks (runSageAnalysis, runBenchmark)
├── db.ts                 ← SQLite SSOT: skillQueries, benchmarkQueries, chatQueries
├── migrations/
│   ├── 004_skill_system.ts     ← skills_global, forks, evolution_logs, update_requests
│   └── 005_skill_benchmarks.ts ← skill_benchmarks (resultados A/B test)
├── crm-routes.ts         ← CRM API: 55+ endpoints (Sage + benchmarks + skill evolution)
└── ui_templates.ts       ← Estendido: improvementProposal()

scripts/
├── nightly-improve.ts    ← Pilar 4: Karpathy Loop (agora usa Sage + DB)
└── migrate-skills-to-db.ts ← Migração nuclear: arquivos → DB

clients/
├── arc-cli.ts            ← ARC CLI (Phase 31.5): login, start, projects
└── knowledge-mcp.ts      ← Depreciado (Phase 38 → subcomandos CLI)

services/
└── notebooklm-bridge/    ← Pilar 5: busca semântica NotebookLM (Phase 36.3)
    ├── main.py           ← FastAPI (:19213), /query, /sync, /notebooks/init, /health
    └── seed_knowledge.py ← Importação em massa do conhecimento existente

frontend/src/crm/pages/
└── SkillEvolution.jsx    ← UI de dois painéis: explorer + detalhe (Content/Evals/Evolution/PRs)
                             BenchmarkBadge, BenchmarkReport, Battle Mode, botão Sage analyze

child-bot/bot.ts          ← Integração: startup + prompt GSD + notas de eval + /learnings
child-bot/ingest-watcher.ts ← Auto-ingestão: fs.watch em raw/ → CRM inbox (Phase 28)
master-bot/bot.ts         ← Integração: gatilho cron noturno do Sage