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
- warning: Exibido como
⚠️na nota. Indica um problema de qualidade. - info: Exibido como
ℹ️na nota. Informativo, não crítico.
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:
- Segurança: Filtragem forçada via
--allowedToolsou mutações de symlink corre o risco de quebrar sessões em andamento se o roteador classificar mal uma mensagem. - Estabilidade: Sem mutações no sistema de arquivos em processos em execução.
- 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
- Lê
config/bot_registry.jsonpara enumerar todos os child bots - Para cada child: lê
quality-metrics.jsondo seu diretório de estado - Chama
findUnderperformingSkills()— filtra skills onde:applied_count >= 3(tamanho mínimo de amostra)- E
success_rate < 80%OUfeedback_negative > feedback_positive
- Lê
learnings.mdpara padrões de correção relacionados - Gera propostas baseadas em templates (determinístico, sem IA envolvida)
- Envia relatório resumido ao CEO pelo Telegram
- 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:
skill.md→skill.v1.md(atual → backup)skill.v1.md→skill.v2.md(rotação)- Máximo de 3 versões de backup por skill
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:
- Carregamento lazy por PR (busca ao expandir)
- Resumo: vitórias/derrotas/empates/verdict/improvement_pct
- Por cenário: Antigo vs Novo lado a lado, estrela de vencedor, score/10, motivo do julgamento
- Botão "Run Benchmark" na aba Content (azul céu)
- Botão de âncora por PR para reexecutar benchmarks
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