Pular para o conteúdo
0%

Artefatos

Artefatos

O inventário do que precisa existir em disco, em banco e em rede para uma empresa rodar como Cognitive Enterprise. Não é lista de ferramentas — é lista de arquivos, tabelas e endpoints que alguém tem que criar e manter.

Os caminhos abaixo seguem uma organização de apadrinhamento — o mesmo caso que atravessa o treinamento. Em outra empresa mudam os nomes, não a estrutura.

01

Contexto raiz

O que todo agente lê antes de qualquer tarefa

Se um agente só pudesse ler três arquivos antes de trabalhar, seriam estes. É a camada mais barata de construir e a que mais muda o resultado.

  • mdCLAUDE.md

    O contexto que todo agente carrega antes de qualquer tarefa: o que a organização é, como se trabalha aqui, o que nunca se faz.

    Exemplo real · Declara que a organização atende crianças em vulnerabilidade, que dado de menor não sai da sede, e que o tom nunca é de pena.

    Ver exemplomd
    # Organização de apadrinhamento — contexto para agentes
    
    ## O que somos
    Conectamos padrinhos a crianças em comunidades atendidas. O produto não é a doação:
    é o vínculo. Ele se sustenta na correspondência anual entre criança e padrinho.
    
    ## Como se trabalha aqui
    - Toda afirmação sobre uma criança vem de um relatório de campo. Nunca de inferência.
    - Quando faltar dado, escale. Não complete.
    - Specs em `specs/`. Prompts em `agentes/`. Nada de instrução solta em conversa.
    
    ## O que nunca se faz
    - Publicar endereço, nome da escola ou sobrenome de criança. Sem exceção.
    - Enviar qualquer coisa a um padrinho sem passar pelo gate de `gates.yaml`.
    - Representar uma criança pela carência dela. Ver `tom-de-voz.md`.
    
    ## Onde olhar primeiro
    `ontologia.md` para saber o que as palavras significam · `politicas/` para as regras
    duras · `skills/` para o passo a passo de cada tarefa.
  • mdAGENTS.md

    A mesma coisa em formato neutro, para agentes de outros fornecedores. Um arquivo, vários leitores.

    Exemplo real · Aponta para o CLAUDE.md em vez de duplicar conteúdo.

    Ver exemplomd
    # Agentes neste repositório
    
    Este arquivo existe para agentes que não leem `CLAUDE.md`.
    O conteúdo canônico é o `CLAUDE.md` — mantenha um só, referencie o outro.
    
    @CLAUDE.md
    
    ## Comandos
    - `python3 evals/rodar.py` — suíte de qualidade (obrigatória antes de qualquer merge)
    - `python3 build.py` — regera artefatos derivados
    
    ## Limites deste repositório
    Sem credencial de produção. Sem acesso a `dados/financeiro/`.
    Ações irreversíveis exigem aprovação humana registrada.
  • config.claude/settings.json

    Permissões, hooks, modelo padrão e limites. O harness em formato de configuração, versionado.

    Exemplo real · Bloqueia escrita no cadastro, exige aprovação para envio, teto de 6 iterações.

    Ver exemplojson
    {
      "permissions": {
        "allow": ["Read(./**)", "Bash(python3 evals/*)", "WebFetch(domain:docs.internos)"],
        "deny": ["Read(./dados/financeiro/**)", "Bash(curl:*)", "Write(./producao/**)"]
      },
      "hooks": {
        "PreToolUse": [
          { "matcher": "Write|Edit",
            "hooks": [{ "type": "command", "command": "python3 guardrails/sem_dados_sensiveis.py" }] }
        ]
      },
      "env": { "MAX_ITERACOES": "6", "MODELO_PADRAO": "modelo-rapido" }
    }
  • mdidentidade.md

    Missão, princípios e o que a organização recusa fazer. É o System 5 do VSM em arquivo.

    Exemplo real · "Nunca representamos uma criança pela carência dela."

    Ver exemplomd
    # Identidade
    
    ## Missão
    Que cada criança apadrinhada tenha um adulto no mundo acompanhando o crescimento dela.
    
    ## Princípios
    1. A criança é sujeito, não beneficiária. Ela aparece pelo que faz, não pelo que falta.
    2. O padrinho merece a verdade. Carta bonita e imprecisa é pior que carta simples e exata.
    3. Dado de menor de idade é responsabilidade, não ativo.
    
    ## O que recusamos
    - Usar imagem ou história de criança em campanha de captação sem consentimento vigente.
    - Prometer ao padrinho qualquer resultado sobre a vida da criança.
    - Automatizar qualquer etapa cujo erro a criança pague.
  • mdtom-de-voz.md

    Como a organização escreve, com exemplos aprovados e reprovados lado a lado.

    Exemplo real · Três cartas exemplares e três reprovadas, cada uma com o motivo da reprovação.

    Ver exemplomd
    # Tom de voz na correspondência
    
    Escrevemos na voz da criança, em primeira pessoa, com vocabulário compatível com a idade.
    
    ## Aprovado
    > "Este ano entrei para o time de vôlei da escola. Ainda erro muito o saque,
    > mas a professora disse que eu melhorei bastante."
    
    Por quê: fato do relatório, voz da criança, progresso sem exagero.
    
    ## Reprovado
    > "Graças à sua generosidade, hoje eu tenho a oportunidade de estudar."
    
    Por quê: coloca o padrinho como salvador e a criança como carente. Fere o princípio 1
    de `identidade.md`.
    
    ## Reprovado
    > "A Ana adora jogar futebol e sonha em ser jogadora profissional."
    
    Por quê: nada disso está no relatório. Invenção, mesmo que simpática, é erro grave.
  • mdmemoria/*.md

    O que os agentes aprenderam e vale para as próximas sessões. Um fato por arquivo.

    Exemplo real · "Irmãos só são mencionados se aparecerem no relatório do ano corrente."

    Ver exemplomd
    ---
    tema: correspondencia
    registrado_em: 2026-03-14
    por: marina
    ---
    
    Irmãos só são mencionados na carta se aparecerem no relatório de campo **do ano corrente**.
    
    Motivo: em março de 2026 uma carta citou um irmão que havia saído do programa,
    e o padrinho perguntou por ele. Não temos como responder.
    
    Vale para: todas as tarefas de redação. Já está refletido em
    `skills/carta-apadrinhamento/SKILL.md`.

02

Fundação semântica

O que a empresa é, num formato que máquina lê

Esta é a camada que trava projeto em empresa tradicional. O conteúdo não é difícil, mas ninguém nunca escreveu.

  • mdontologia.md

    O mapa das entidades do negócio e como se relacionam.

    Exemplo real · Estabelece que "criança apadrinhada", "criança atendida" e "criança de família atendida" são três entidades diferentes que o relatório chama igual.

    Ver exemplomd
    # Ontologia
    
    ## Criança
    Três entidades distintas que o relatório de campo chama pelo mesmo nome:
    
    | Entidade | Definição | Tem padrinho? |
    |---|---|---|
    | `crianca_apadrinhada` | Vinculada a um padrinho ativo | sim |
    | `crianca_atendida` | Participa dos programas, sem vínculo | não |
    | `crianca_familia` | Irmão de atendida, alcance indireto | não |
    
    Só `crianca_apadrinhada` gera correspondência.
    
    ## Padrinho
    Pessoa física com apadrinhamento ativo. **Todo padrinho é doador; nem todo doador
    é padrinho.** Doador sem vínculo nunca recebe carta.
    
    ## Apadrinhamento
    Relação entre `padrinho` e `crianca_apadrinhada`, com início, status e (às vezes) fim.
    É a entidade que morre quando o vínculo acaba — a criança continua existindo.
    
    ## Relatório de campo
    Registro anual feito pelo educador. **É a única fonte de fato sobre a criança.**
    Nada entra numa carta sem estar aqui.
  • mdglossario.md

    Termos, sinônimos e — o mais importante — o que eles não significam.

    Exemplo real · Todo padrinho é doador; nem todo doador é padrinho.

    Ver exemplomd
    # Glossário
    
    **Padrinho** — pessoa com apadrinhamento ativo.
    *Não confundir com:* doador (contribui sem vínculo), mantenedor (pessoa jurídica).
    
    **Carta** — peça anual da criança para o padrinho.
    *Não confundir com:* comunicado (institucional), recibo (fiscal).
    
    **Desligamento** — fim do vínculo por mudança, idade ou decisão da família.
    *Não confundir com:* inadimplência (o padrinho parou de pagar; o vínculo segue 90 dias).
    
    **Educador de campo** — quem visita e escreve o relatório.
    *Não confundir com:* voluntário de sede (transcreve, não observa).
  • dadosschema.sql

    A ontologia materializada em tabelas, com chaves, restrições e histórico.

    Exemplo real · crianca, padrinho, apadrinhamento, relatorio_campo, carta, envio.

    Ver exemplosql
    create table crianca (
      id            uuid primary key,
      nome          text not null,
      nascimento    date not null,
      comunidade_id uuid not null references comunidade(id),
      tipo          text not null check (tipo in ('apadrinhada','atendida','familia')),
      status        text not null check (status in ('ativa','desligada')),
      desligada_em  date
    );
    
    create table apadrinhamento (
      id          uuid primary key,
      crianca_id  uuid not null references crianca(id),
      padrinho_id uuid not null references padrinho(id),
      inicio      date not null,
      fim         date,
      unique (crianca_id, padrinho_id, inicio)
    );
    
    create table relatorio_campo (
      id          uuid primary key,
      crianca_id  uuid not null references crianca(id),
      ano         int  not null,
      educador_id uuid not null references educador(id),
      frequencia_escolar numeric(4,1),
      observacoes text,
      unique (crianca_id, ano)          -- um relatório por criança por ano
    );
  • mdpoliticas/*.md

    Uma regra de negócio por arquivo, estruturada: campo, motivo, exceção, responsável.

    Exemplo real · lgpd-menores.md — endereço, escola e sobrenome nunca saem da sede.

    Ver exemplomd
    ---
    politica: lgpd-menores
    versao: 3
    responsavel: juridico
    vigente_desde: 2025-08-01
    ---
    
    # Dados de menor não saem da sede
    
    ## Regra
    Os campos abaixo **nunca** aparecem em conteúdo que sai da organização:
    
    | Campo | Onde vive | Motivo |
    |---|---|---|
    | `crianca.endereco` | cadastro | localização de menor |
    | `crianca.escola` | relatório | localização indireta |
    | `crianca.sobrenome` | cadastro | identificação |
    
    ## Exceção
    Uma só: intimação judicial, respondida pelo jurídico. Nunca por agente.
    
    ## Como isto é cumprido
    Não por prompt. Por código: `guardrails/sem_dados_sensiveis.py` recusa a saída.
  • mdcatalogo-de-dados.md

    Onde cada dado mora, quem é o dono e qual a classificação de sensibilidade.

    Exemplo real · Foto da criança: bucket privado, dona é a coordenação de programa, sensibilidade alta.

    Ver exemplomd
    # Catálogo de dados
    
    | Dado | Onde mora | Dono | Sensibilidade | Quem lê |
    |---|---|---|---|---|
    | Cadastro da criança | `postgres.crianca` | Coord. de programa | alta | agente redator (campos públicos) |
    | Foto anual | `s3://fotos/` (privado) | Coord. de programa | alta | ninguém automatizado |
    | Relatório de campo | `postgres.relatorio_campo` | Coord. de campo | média | agente redator |
    | Dados do padrinho | `postgres.padrinho` | Captação | alta | agente de envio |
    | Financeiro | `postgres.doacao` | Financeiro | alta | nenhum agente |
    | Cartas geradas | `postgres.carta` | Coord. de programa | média | agente verificador |
    
    Classificação **alta** implica: acesso nominal, registro em audit log, revisão trimestral.
  • configeventos.yaml

    O vocabulário de eventos do negócio: o que acontece e o que cada coisa dispara.

    Exemplo real · relatorio.recebido, carta.gerada, carta.aprovada, carta.enviada.

    Ver exemployaml
    eventos:
      relatorio.recebido:
        payload: { crianca_id: uuid, ano: int, origem: enum[app_campo, digitalizacao] }
        dispara: [tarefa.triar-relatorio]
    
      carta.gerada:
        payload: { carta_id: uuid, crianca_id: uuid, agente: string, versao_prompt: string }
        dispara: [tarefa.verificar-carta]
    
      carta.reprovada:
        payload: { carta_id: uuid, criterio: string, detalhe: string }
        dispara: [tarefa.reescrever-carta, gate.revisao-humana]
    
      carta.enviada:
        payload: { carta_id: uuid, enviada_em: timestamp, aprovada_por: string }
        dispara: []          # terminal e irreversível

03

Dados

Onde a verdade mora

Agente não inventa quando tem onde consultar. Cada linha aqui existe para responder a uma pergunta que o agente vai fazer.

  • dadosBanco transacional

    A verdade operacional, com histórico e não só o estado atual.

    Exemplo real · 12 mil crianças, 8 mil padrinhos, 40 mil relatórios de campo acumulados.

    Ver exemplosql
    -- A pergunta que o agente faz antes de escrever qualquer carta.
    select c.id, c.nome, extract(year from age(c.nascimento)) as idade,
           r.frequencia_escolar, r.observacoes,
           a.inicio as apadrinhado_desde
    from crianca c
    join apadrinhamento a on a.crianca_id = c.id and a.fim is null
    join relatorio_campo r on r.crianca_id = c.id and r.ano = 2026
    where c.id = $1 and c.status = 'ativa';
    
    -- Sem linha de retorno, o agente NÃO escreve: ele escala.
    -- Criança desligada, relatório ausente e vínculo encerrado caem todos aqui.
  • dadosÍndice vetorial

    O acervo pesquisável: documentos, políticas, histórico por entidade.

    Exemplo real · Os relatórios dos últimos três anos de cada criança, indexados para recuperação.

    Ver exemplopython
    # Indexação: um documento por relatório, com metadado que permite filtrar antes de buscar.
    colecao.upsert(
        id=f"relatorio:{r.crianca_id}:{r.ano}",
        texto=r.observacoes,
        metadados={"crianca_id": str(r.crianca_id), "ano": r.ano,
                   "sensibilidade": "media", "tipo": "relatorio_campo"},
    )
    
    # Recuperação: SEMPRE filtrada por criança. Busca semântica solta,
    # num acervo de 40 mil relatórios, traz a criança errada com texto convincente.
    trechos = colecao.buscar(
        consulta="progresso escolar e atividades",
        filtro={"crianca_id": str(crianca_id), "ano": {"$gte": 2024}},
        k=5,
    )
  • dadosObject storage

    O que não cabe em banco: fotos, PDFs, digitalizações, áudios.

    Exemplo real · As fotos anuais de cada criança e os relatórios manuscritos escaneados.

    Ver exemplotext
    s3://apadrinhamento/
    ├── fotos/
    │   └── {crianca_id}/{ano}.jpg          privado · url assinada · 15 min
    ├── relatorios-digitalizados/
    │   └── {crianca_id}/{ano}.pdf          privado · entrada de OCR
    └── cartas/
        └── {carta_id}/
            ├── rascunho.md                 versão do agente
            ├── evidencia.json              claim → fonte, da auto verificação
            └── final.pdf                   gerado só após o gate
    
    Regra: nada aqui é público. Toda leitura passa por URL assinada e fica no audit log.
  • dadosgolden/

    Os pares entrada / saída-esperada que servem de gabarito oficial.

    Exemplo real · 200 cartas aprovadas com o relatório que as originou, sendo 30 casos difíceis escolhidos de propósito.

    Ver exemplotext
    golden/
    ├── 001-padrao-simples/
    │   ├── entrada.json        relatório de campo completo, criança ativa
    │   ├── esperado.md         carta aprovada pela coordenação em 2024
    │   └── porque.md           "caso base: se este falhar, tudo falhou"
    ├── 031-mudou-de-cidade/
    │   ├── entrada.json        relatório aponta comunidade diferente do cadastro
    │   ├── esperado.md         carta que não menciona a mudança
    │   └── porque.md           "o agente inventava despedida. Incidente #14, mar/2026"
    └── 047-relatorio-contraditorio/
        ├── entrada.json        frequência 95% e observação "faltou muito"
        ├── esperado.md         ESCALAR — nenhuma carta é resposta correta aqui
        └── porque.md           "aceitar contradição em silêncio é o pior modo de falha"
    
    30 dos 200 casos são difíceis de propósito. São eles que dão valor ao conjunto.
  • dadosbaseline/

    A medição do processo antes da automação, datada e assinada.

    Exemplo real · 80 cartas manuais: 25 min cada, 3,2% de erro factual, 8% de retrabalho, 11 dias de fila.

    Ver exemplocsv
    medido_em,amostra,metrica,valor,unidade,fonte
    2026-01-20,80,tempo_por_carta,25.0,minutos,cronometragem em 4 turnos
    2026-01-20,80,erro_factual,3.2,percentual,revisão cega por 2 coordenadoras
    2026-01-20,80,retrabalho,8.0,percentual,cartas devolvidas pela revisão
    2026-01-20,80,fila_alta_temporada,11.0,dias,fila média de novembro/2025
    2026-01-20,80,custo_por_carta,9.30,BRL,horas × custo médio da hora
  • dadosCamada analítica

    Tabelas de leitura para painel e para o agente que analisa a própria operação.

    Exemplo real · Cartas por mês, custo por carta, taxa de escalada por idioma.

    Ver exemplosql
    create view v_cartas_mes as
    select date_trunc('month', c.criada_em)          as mes,
           c.idioma,
           count(*)                                   as cartas,
           avg(c.custo_brl)                           as custo_medio,
           sum(case when c.escalou then 1 else 0 end)::float / count(*) as taxa_escalada,
           avg(extract(epoch from (c.aprovada_em - c.criada_em))/3600)  as horas_ate_aprovacao
    from carta c
    group by 1, 2;
    
    -- É desta view que sai o painel de custo e a comparação com o baseline.
    -- O agente que analisa a própria operação lê daqui, não da tabela crua.

04

Interfaces

Como o software da empresa é alcançado

Sistema sem interface programática não participa da operação agêntica. Aqui é onde a maioria das empresas descobre a própria dívida técnica.

  • apiGET /criancas/{id}

    Leitura da ficha, devolvendo só o mínimo necessário para o perfil que pediu.

    Exemplo real · Devolve nome, idade e status no programa — nunca endereço nem escola.

    Ver exemplohttp
    GET /criancas/9f3c…?perfil=redacao
    Authorization: Bearer <token do agente redator>
    
    200 OK
    {
      "id": "9f3c…",
      "nome": "Ana",
      "idade": 11,
      "tipo": "apadrinhada",
      "status": "ativa",
      "apadrinhada_desde": "2023-03-01",
      "comunidade": "Vale Verde"
    }
  • apiGET /relatorios?crianca=&ano=

    O insumo da carta, filtrado por criança e período.

    Exemplo real · Traz frequência escolar, atividades e observações do educador de campo.

    Ver exemplohttp
    GET /relatorios?crianca=9f3c…&ano=2026
    
    200 OK
    {
      "crianca_id": "9f3c…",
      "ano": 2026,
      "educador": "e-221",
      "visitado_em": "2026-02-20",
      "frequencia_escolar": 94.0,
      "atividades": ["vôlei na escola", "oficina de leitura"],
      "observacoes": "Melhorou muito a leitura em voz alta. Entrou para o time de vôlei.",
      "completo": true
    }
  • apiPOST /cartas

    Cria a carta em rascunho. Nunca envia.

    Exemplo real · Separar criação de envio é o que torna possível existir gate humano entre as duas.

    Ver exemplohttp
    POST /cartas
    { "crianca_id": "9f3c…", "ano": 2026, "idioma": "pt-BR",
      "agente": "redator@v12", "texto": "...", "evidencia": [...] }
    
    201 Created
    { "id": "c-8812", "status": "rascunho", "criada_em": "2026-03-03T14:02:11Z" }
  • apiPOST /cartas/{id}/enviar

    Ação irreversível: exige gate, chave de idempotência e registro.

    Exemplo real · Rodar duas vezes por engano entrega uma carta, não duas.

    Ver exemplohttp
    POST /cartas/c-8812/enviar
    Idempotency-Key: c-8812-envio-1
    { "aprovada_por": "marina@org", "gate": "revisao-primeira-carta" }
    
    200 OK
    { "id": "c-8812", "status": "enviada", "enviada_em": "2026-03-05T09:14:00Z" }
    
    # Repetir a mesma chave devolve 200 com o MESMO enviada_em. Nunca envia duas vezes.
    # Sem Idempotency-Key: 400. Sem aprovada_por: 403.
  • apiServidor MCP do cadastro

    O sistema interno exposto por protocolo comum, para qualquer agente plugar.

    Exemplo real · Trocar o sistema de cadastro troca o servidor MCP; os agentes não mudam.

    Ver exemplojson
    {
      "name": "cadastro-apadrinhamento",
      "version": "2.1.0",
      "tools": [
        { "name": "buscar_crianca",
          "description": "Ficha da criança no perfil do agente que chamou.",
          "inputSchema": { "type": "object",
            "properties": { "crianca_id": { "type": "string" } },
            "required": ["crianca_id"] } },
        { "name": "relatorio_do_ano",
          "description": "Relatório de campo. Devolve completo:false se faltar campo.",
          "inputSchema": { "type": "object",
            "properties": { "crianca_id": {"type":"string"}, "ano": {"type":"integer"} },
            "required": ["crianca_id","ano"] } }
      ]
    }
  • config.mcp.json

    A lista de servidores MCP que os agentes deste repositório enxergam — inclusive o de documentação de bibliotecas.

    Exemplo real · Cadastro, doações e a documentação atualizada dos frameworks usados no código.

    Ver exemplojson
    {
      "mcpServers": {
        "cadastro":  { "command": "npx", "args": ["-y", "@org/mcp-cadastro"],
                       "env": { "PERFIL": "redacao" } },
        "doacoes":   { "command": "npx", "args": ["-y", "@org/mcp-doacoes"] },
        "docs-libs": { "command": "npx", "args": ["-y", "@upstash/context7-mcp"] }
      }
    }
  • apiPOST /webhooks/relatorio-recebido

    O campo avisa quando chega relatório novo.

    Exemplo real · O agente acorda por evento em vez de varrer o banco de hora em hora.

    Ver exemplohttp
    POST /webhooks/relatorio-recebido
    X-Assinatura: sha256=8f21…            <- verificada antes de qualquer processamento
    
    { "evento": "relatorio.recebido",
      "id_evento": "ev-77120",             <- dedupe: reentrega não reprocessa
      "crianca_id": "9f3c…", "ano": 2026, "origem": "app_campo" }
    
    202 Accepted

05

Procedimentos executáveis

Como o trabalho é feito

O manual descreve o trabalho; o artefato executa. Tudo aqui é lido por agente.

  • mdskills/carta-apadrinhamento/SKILL.md

    O procedimento completo de uma tarefa, carregado sob demanda.

    Exemplo real · Padrão da carta, estrutura, proibições e o que fazer quando falta dado no relatório.

    Ver exemplomd
    ---
    name: carta-apadrinhamento
    description: Escreve a carta anual da criança para o padrinho a partir do relatório de campo.
    ---
    
    # Carta de apadrinhamento
    
    ## Antes de começar
    1. Busque o relatório do ano. Se `completo: false`, **escale** e pare.
    2. Busque o resumo dos dois anos anteriores (para não repetir assunto).
    3. Confira o status: criança desligada não recebe carta.
    
    ## Estrutura
    1. Saudação com o nome do padrinho
    2. Um parágrafo de escola
    3. Um parágrafo de atividade ou conquista
    4. Uma pergunta da criança para o padrinho
    5. Despedida
    
    ## Restrições
    - 180 a 320 palavras · idioma do padrinho · voz da criança em primeira pessoa
    - Toda afirmação precisa de linha correspondente no relatório
    - Nunca: endereço, escola, sobrenome, promessa, agradecimento por caridade
    
    ## Ao terminar
    Rode `validar.py`. Se falhar, corrija e rode de novo. Duas falhas seguidas: escale.
  • dadosskills/carta-apadrinhamento/exemplos/

    Saídas exemplares aprovadas e reprovadas, com o motivo de cada reprovação.

    Exemplo real · Seis cartas: três que passariam, três que não, e por quê.

    Ver exemplotext
    exemplos/
    ├── aprovado-01.md      + motivo: fato → fonte em cada frase, voz natural
    ├── aprovado-02.md      + motivo: criança com pouca informação; carta curta e honesta
    ├── aprovado-03.md      + motivo: padrinho espanhol, idioma correto sem tradução literal
    ├── reprovado-01.md     − motivo: "graças à sua generosidade" — padrinho como salvador
    ├── reprovado-02.md     − motivo: inventou hobby que não está no relatório
    └── reprovado-03.md     − motivo: citou o nome da escola (violação de LGPD)
    
    Os reprovados valem mais que os aprovados: eles delimitam a fronteira.
  • codigoskills/carta-apadrinhamento/validar.py

    O script que confere a saída antes de ela sair da skill.

    Exemplo real · Tamanho, idioma e varredura de dados proibidos.

    Ver exemplopython
    import re, sys, json
    
    PROIBIDO = [
        (r"\bRua\b|\bAv\.|\bAvenida\b", "endereço"),
        (r"\bEscola\s+[A-ZÁ-Ú]", "nome de escola"),
        (r"gra[çc]as? [àa] sua", "padrinho como salvador"),
    ]
    
    def validar(texto: str, idioma: str) -> list[str]:
        erros = []
        n = len(texto.split())
        if not 180 <= n <= 320:
            erros.append(f"extensão: {n} palavras (esperado 180–320)")
        for padrao, nome in PROIBIDO:
            if re.search(padrao, texto, re.I):
                erros.append(f"conteúdo proibido: {nome}")
        if idioma == "es" and " você " in texto:
            erros.append("idioma: trechos em português numa carta em espanhol")
        return erros
    
    if __name__ == "__main__":
        d = json.load(sys.stdin)
        e = validar(d["texto"], d["idioma"])
        print(json.dumps({"ok": not e, "erros": e}, ensure_ascii=False))
        sys.exit(1 if e else 0)
  • mdspecs/correspondencia.md

    A especificação do processo: entrada, saída, critérios de aceite, o que escala.

    Exemplo real · É dela que derivam prompt, testes e documentação — não o contrário.

    Ver exemplomd
    # Spec — correspondência anual
    
    ## Outcome
    O padrinho renova o apadrinhamento porque sente que acompanha a vida de uma criança real.
    
    ## Tarefa
    `escrever-carta` — uma execução por criança apadrinhada ativa, por ano.
    
    ## Entrada
    `relatorio_campo` do ano (obrigatório, `completo: true`) · resumo dos 2 anos anteriores ·
    idioma do padrinho · políticas vigentes.
    
    ## Saída
    Carta em markdown + `evidencia.json` com claim → fonte.
    
    ## Critérios de aceite
    | # | Critério | Como se mede | Exigência |
    |---|---|---|---|
    | 1 | Fidelidade factual | toda afirmação tem fonte | 100% |
    | 2 | LGPD | nenhum campo proibido | 100% |
    | 3 | Idioma | o do padrinho | 100% |
    | 4 | Extensão | 180–320 palavras | 100% |
    | 5 | Tom e dignidade | LLM-as-judge, rubrica | ≥ 4,0 |
    
    ## Escala para humano quando
    Relatório incompleto ou contraditório · criança desligada · menção a situação de risco ·
    duas falhas seguidas na validação.
  • mdtemplates/carta.md

    O esqueleto da saída, com os campos fixos e os livres explicitamente marcados.

    Exemplo real · Fato e LGPD são fixos; voz, ordem e ênfase são livres.

    Ver exemplomd
    {{! Campos FIXOS: validados em código. Campos LIVRES: variam a cada geração. }}
    
    Olá, {{padrinho.primeiro_nome}}!      {{! FIXO — vem do cadastro }}
    
    {{escola}}                             {{! LIVRE — voz, ordem e ênfase do agente }}
    
    {{atividade_ou_conquista}}             {{! LIVRE }}
    
    {{pergunta_ao_padrinho}}               {{! LIVRE }}
    
    Com carinho,
    {{crianca.primeiro_nome}}              {{! FIXO — nunca o sobrenome }}
    
    {{! Proibidos por guardrail, não por instrução: endereco, escola_nome, sobrenome }}
  • mdprogresso.md

    O estado de uma tarefa longa entre execuções: o que já foi feito, o que falta, onde parou.

    Exemplo real · A migração de 12 anos de correspondência avança 20 registros por iteração, sem perder o lugar.

    Ver exemplomd
    ---
    tarefa: migrar-correspondencia-historica
    iniciado: 2026-03-02
    atualizado: 2026-03-19T14:22Z
    ---
    
    ## Onde parei
    Lote 34 de 61. Último registro convertido: `carta:2019:8841`.
    
    ## Feito
    - [x] 2014–2018 · 12.408 cartas · sem pendência
    - [x] 2019 · 2.100 de 3.980 cartas
    
    ## Falta
    - [ ] 2019 · 1.880 cartas restantes
    - [ ] 2020–2025
    
    ## Aprendido no caminho
    - Cartas anteriores a 2016 não têm `crianca_id`; casar por nome + comunidade + ano.
    - 41 registros com data inválida foram para `duvidas.md`. Não invente data.
    
    ## Próximo passo
    Retomar em `carta:2019:8842`.
  • mdrunbooks/carta-errada-enviada.md

    O que fazer quando o erro já saiu. Passo a passo, com dono de cada etapa.

    Exemplo real · Quem avisa o padrinho, quem registra o incidente, quem transforma em caso no gabarito.

    Ver exemplomd
    # Runbook — carta errada enviada
    
    **Gatilho:** erro factual, de LGPD ou de tom identificado após o envio.
    **Dono:** DRI da correspondência (hoje: Marina). **Prazo do passo 1:** 4 horas.
    
    ## 1. Conter (0–4 h)
    - [ ] Suspender o lote: `./scripts/parar.sh correspondencia`
    - [ ] Levantar quantas cartas saíram com o mesmo defeito (query em `runbooks/consultas.sql`)
    
    ## 2. Comunicar (4–24 h)
    - [ ] Padrinho afetado: contato por pessoa, nunca por agente
    - [ ] Se houver LGPD envolvida: acionar o jurídico no mesmo dia
    
    ## 3. Registrar (até 48 h)
    - [ ] Abrir `incidentes/AAAA-MM-DD-descricao.md` com causa raiz
    - [ ] Criar o caso em `golden/` — **o incidente não fecha sem isto**
    - [ ] Adicionar critério na suíte se o eval não pegaria o defeito
    
    ## 4. Retomar
    - [ ] Suíte inteira verde, incluindo o caso novo
    - [ ] Religar com o nível de autonomia rebaixado por 2 semanas

06

Agentes e tarefas

Quem faz o quê

Um agente sem arquivo só existe na cabeça de quem o criou. Estes arquivos funcionam como o organograma da força de trabalho.

  • configtarefas.yaml

    O catálogo das unidades delegáveis: entrada, goal, ferramentas, custo esperado e dono.

    Exemplo real · escrever-carta, triar-relatorio, traduzir-carta, revisar-lote.

    Ver exemployaml
    tarefas:
      escrever-carta:
        entrada:   [relatorio_campo, resumo_historico, idioma_padrinho]
        goal:      "Carta de 180 a 320 palavras, na voz da criança, com toda afirmação
                    rastreável ao relatório do ano."
        tools:     [buscar_crianca, relatorio_do_ano, criar_carta]
        escala_se: [relatorio_incompleto, contradicao, crianca_desligada, risco]
        custo_esperado_brl: 0.42
        dono: marina
    
      triar-relatorio:
        entrada:   [relatorio_campo]
        goal:      "Classificar em completo / incompleto / contraditório."
        tools:     [relatorio_do_ano]
        escala_se: [contradicao]
        custo_esperado_brl: 0.03
        dono: marina
  • mdagentes/redator/agent.md

    O harness de um agente: papel, tarefas que executa, ferramentas, limites e critério de escalada.

    Exemplo real · Redige a carta; não consulta dado financeiro; escala se o relatório for contraditório.

    Ver exemplomd
    ---
    nome: redator
    tarefas: [escrever-carta]
    modelo: modelo-capaz
    max_iteracoes: 6
    ---
    
    # Agente redator
    
    ## Papel
    Transformar um relatório de campo em uma carta. Não decide nada além do texto.
    
    ## Ferramentas
    `buscar_crianca` · `relatorio_do_ano` · `criar_carta` (rascunho)
    **Não tem:** envio, escrita no cadastro, leitura de financeiro.
    
    ## Limites
    - 6 iterações. Estourou, escala.
    - Falhou duas vezes em `validar.py`, escala — não tenta uma terceira.
    
    ## Escalada
    Chama `gate.revisao-humana` com o motivo em uma frase e a evidência parcial anexada.
  • mdagentes/redator/prompt.md

    O prompt de sistema, versionado como código e alterado junto com a suíte.

    Exemplo real · Cada mudança aqui dispara a suíte inteira de evals.

    Ver exemplomd
    Você escreve a carta anual de uma criança apadrinhada para o padrinho dela.
    
    REGRAS INVIOLÁVEIS
    1. Toda afirmação sobre a criança vem do relatório de campo fornecido. Nada de inferência.
    2. Se faltar informação, escreva uma carta mais curta. Nunca invente para preencher.
    3. Nunca cite endereço, nome de escola ou sobrenome.
    4. A criança é sujeito. Ela aparece pelo que faz — nunca pelo que falta.
    
    PROCESSO
    1. Leia o relatório e liste os fatos disponíveis.
    2. Escreva a carta usando apenas esses fatos.
    3. Monte `evidencia.json`: cada frase da carta → a linha do relatório que a sustenta.
    4. Sobrou frase sem fonte? Reescreva antes de entregar.
    
    # versão: v12 · alterado em 2026-03-14 · suíte rodada: sim (98,5%)
  • mdagentes/verificador/agent.md

    O agente que confere o trabalho do outro contra a fonte.

    Exemplo real · Não escreve nada: devolve a tabela de afirmação → fonte → ok/falha.

    Ver exemplomd
    ---
    nome: verificador
    tarefas: [verificar-carta]
    modelo: modelo-rapido
    ---
    
    # Agente verificador
    
    ## Papel
    Conferir a carta contra a fonte. **Não escreve nem corrige** — só julga e devolve evidência.
    
    ## Saída obrigatória
    ```json
    { "aprovado": false,
      "claims": [
        { "frase": "Entrei para o time de vôlei.", "fonte": "relatorio:2026:atividades", "ok": true },
        { "frase": "Sonho em ser jogadora.",        "fonte": null,                       "ok": false }
      ],
      "motivo": "1 afirmação sem fonte" }
    ```
    
    ## Por que é um agente separado
    O mesmo turno que escreveu tende a aprovar o que escreveu. Contexto limpo é o ponto.
  • configorquestracao.yaml

    Que tipo de tarefa vai para qual modelo, e quando escala direto para humano.

    Exemplo real · Relatório completo → modelo barato. Contraditório → modelo caro. Criança fora do programa → humano.

    Ver exemployaml
    rotas:
      - quando: { tarefa: triar-relatorio }
        modelo: modelo-rapido
        max_iteracoes: 2
    
      - quando: { tarefa: escrever-carta, relatorio: completo }
        modelo: modelo-rapido
    
      - quando: { tarefa: escrever-carta, relatorio: [incompleto, contraditorio] }
        modelo: modelo-capaz
    
      - quando: { crianca_status: desligada }
        destino: humano
        motivo: "Não existe carta correta para criança fora do programa."
    
    padrao: { modelo: modelo-capaz }
  • mdagentes/README.md

    O organograma dos agentes: quem chama quem, com que protocolo e em que ordem.

    Exemplo real · Extrator → redator → verificador, com o coordenador decidindo escalada.

    Ver exemplomd
    # Time de agentes — correspondência
    
    ```
    relatorio.recebido
            │
            ▼
      [ triador ]  ── incompleto ──▶  gate.revisao-humana
            │ completo
            ▼
      [ redator ] ──▶ rascunho + evidencia.json
            │
            ▼
      [ verificador ] ── reprovado ──▶ volta ao redator (máx. 2×)
            │ aprovado
            ▼
      gate.envio (humano, quando exigido por gates.yaml)
            │
            ▼
         carta.enviada
    ```
    
    Protocolo: cada agente recebe e devolve JSON com esquema fixo. Nenhum agente chama
    outro diretamente — quem coordena é o orquestrador, por evento.

07

Qualidade

Como se sabe que está certo

Sem esta camada, nada do que vem antes pode subir de nível de autonomia, porque subir de nível exige evidência.

  • dadosevals/casos/*.json

    Os casos de teste, um por arquivo, com o motivo de existirem registrado.

    Exemplo real · Criança que mudou de cidade; relatório contraditório; padrinho que escreve em espanhol.

    Ver exemplojson
    {
      "id": "047-relatorio-contraditorio",
      "porque_existe": "Aceitar contradição em silêncio é o pior modo de falha do sistema.",
      "entrada": {
        "crianca_id": "9f3c…",
        "relatorio": {
          "ano": 2026,
          "frequencia_escolar": 95.0,
          "observacoes": "Faltou muito no segundo semestre por problema de transporte."
        },
        "idioma": "pt-BR"
      },
      "esperado": { "acao": "escalar", "motivo_contem": "contradi" },
      "criterios": ["fidelidade", "lgpd", "idioma", "extensao", "tom"]
    }
  • mdevals/criterios.md

    As rubricas: o que é nota 1 e o que é nota 5, critério por critério.

    Exemplo real · Dignidade, fidelidade factual, tom, extensão e idioma.

    Ver exemplomd
    # Rubricas
    
    ## Tom e dignidade (1 a 5) — avaliado por LLM-as-judge
    
    **Nota 5**
    > "Este ano entrei para o time de vôlei. Ainda erro o saque, mas melhorei."
    Criança como sujeito. Progresso sem exagero. Nenhuma menção ao padrinho como provedor.
    
    **Nota 1**
    > "Graças a você, hoje eu posso sonhar. Sem sua ajuda eu não teria nada."
    Criança definida pela carência. Padrinho como salvador. Gratidão performática.
    
    **Penalize:** linguagem de pena · comparação que diminui a criança · foco no que falta ·
    promessa que a organização não pode cumprir.
    
    ## Fidelidade factual (0 ou 1) — automático
    1 se toda frase da carta tem entrada correspondente em `evidencia.json` com `ok: true`.
  • codigoevals/rodar.py

    Um comando que roda a suíte inteira e imprime o percentual por critério.

    Exemplo real · 200 casos, 6 minutos, R$ 4 por execução.

    Ver exemplopython
    #!/usr/bin/env python3
    """Roda a suíte inteira. Falhar aqui bloqueia o deploy."""
    import json, pathlib, sys
    from criterios import fidelidade, lgpd, idioma, extensao, tom_por_juiz
    
    CRITERIOS = {"fidelidade": fidelidade, "lgpd": lgpd, "idioma": idioma,
                 "extensao": extensao, "tom": tom_por_juiz}
    MINIMO = {"fidelidade": 1.0, "lgpd": 1.0, "idioma": 1.0, "extensao": 1.0, "tom": 0.80}
    
    def main() -> int:
        casos = [json.loads(p.read_text()) for p in pathlib.Path("evals/casos").glob("*.json")]
        placar, falhou = {}, False
        for nome, fn in CRITERIOS.items():
            passou = sum(fn(c) for c in casos if nome in c["criterios"])
            total  = sum(1     for c in casos if nome in c["criterios"])
            taxa   = passou / total
            placar[nome] = taxa
            marca = "ok " if taxa >= MINIMO[nome] else "FALHA"
            if taxa < MINIMO[nome]: falhou = True
            print(f"  {marca} {nome:14} {taxa:6.1%}  (mínimo {MINIMO[nome]:.0%})")
        pathlib.Path("evals/resultados").mkdir(exist_ok=True)
        return 1 if falhou else 0
    
    if __name__ == "__main__":
        sys.exit(main())
  • dadosevals/resultados/

    O histórico por versão. É a comparação entre execuções que revela a regressão.

    Exemplo real · Percentual por critério, semana a semana, versionado junto com o prompt.

    Ver exemplocsv
    data,versao_prompt,fidelidade,lgpd,idioma,extensao,tom,casos
    2026-03-01,v10,0.985,1.000,1.000,1.000,0.86,200
    2026-03-08,v11,0.990,1.000,1.000,1.000,0.87,200
    2026-03-14,v12,0.990,1.000,1.000,1.000,0.71,200
  • codigo.github/workflows/evals.yml

    O gate automático: falhar na suíte bloqueia o deploy.

    Exemplo real · Sem isto, a suíte é decoração.

    Ver exemployaml
    name: evals
    on:
      pull_request:
        paths: ["agentes/**", "skills/**", "politicas/**", "evals/**"]
      schedule:
        - cron: "0 6 * * 1"        # segunda de manhã: pega mudança de modelo do fornecedor
    
    jobs:
      suite:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v4
          - run: python3 evals/rodar.py          # sai != 0 se algum critério ficar abaixo
          - uses: actions/upload-artifact@v4
            with: { name: resultado, path: evals/resultados/ }
  • mdanalise/variedade.md

    O inventário das exceções que o processo real produziu, confrontado com o que o gabarito cobre.

    Exemplo real · 14 tipos de exceção observados no ano; 9 estão no golden dataset. Os 5 restantes são a exposição atual.

    Ver exemplomd
    # Variedade observada × variedade coberta — 2026-Q1
    
    | # | Tipo de exceção | Vezes no ano | No gabarito? |
    |---|---|---|---|
    | 1 | Relatório incompleto | 210 | sim |
    | 2 | Criança mudou de comunidade | 88 | sim |
    | 3 | Padrinho em espanhol | 74 | sim |
    | 4 | Relatório contraditório | 31 | sim |
    | 5 | Criança desligada no meio do ano | 24 | sim |
    | 6 | Homônimas na mesma comunidade | 12 | sim |
    | 7 | Relatório digitalizado ilegível | 9 | sim |
    | 8 | Dois relatórios para o mesmo ano | 7 | sim |
    | 9 | Padrinho falecido | 5 | sim |
    | 10 | Criança com dois apadrinhamentos | 4 | **não** |
    | 11 | Menção a situação de risco | 3 | **não** |
    | 12 | Padrinho pede idioma diferente do cadastro | 3 | **não** |
    | 13 | Relatório de educador desligado | 2 | **não** |
    | 14 | Comunidade encerrada no meio do ano | 1 | **não** |
    
    **Cobertura: 9 de 14 tipos · 89% dos casos, 36% dos tipos.**
    
    Os 5 descobertos representam 13 casos por ano — pouco volume, alto risco. O tipo 11
    (situação de risco) nunca pode ser automatizado: vira gate obrigatório, não caso de teste.
    
    Regra: toda exceção nova observada entra nesta tabela **no mesmo dia**, mesmo antes de
    virar caso no gabarito. A tabela é o mapa da exposição.
  • mdevals/calibracao.md

    A conferência do juiz-modelo contra julgamento humano, datada.

    Exemplo real · 30 casos avaliados por gente e pelo juiz, com o percentual de concordância.

    Ver exemplomd
    # Calibração do juiz — 2026-03-10
    
    30 cartas avaliadas em `tom` por duas coordenadoras e pelo juiz-modelo, às cegas.
    
    | | Humano ≥4 | Humano <4 |
    |---|---|---|
    | **Juiz ≥4** | 17 | 2 |
    | **Juiz <4** | 1 | 10 |
    
    **Concordância: 90%** (27/30). Aceitável — mínimo interno é 85%.
    
    ## Os 3 desacordos
    - 2 casos: o juiz aprovou cartas que as coordenadoras acharam frias. Rubrica ajustada
      para penalizar ausência de voz da criança, não só presença de linguagem de pena.
    - 1 caso: humano reprovou por erro factual, que não é critério de tom. Descartado.
    
    Próxima calibração: junho/2026, ou antes se trocarmos de modelo.

08

Governança

O que não pode acontecer

Cada arquivo aqui responde à pergunta: se o agente errar da pior forma possível, até onde vai o estrago?

  • configpermissoes.yaml

    A matriz agente × acesso, com o mínimo necessário e o resto revogado.

    Exemplo real · O redator lê relatório e cadastro básico; não lê dado financeiro nem tem credencial de envio.

    Ver exemployaml
    agentes:
      redator:
        ler:      [crianca.publico, relatorio_campo, politicas, skills]
        escrever: [carta.rascunho]
        negado:   [doacao, padrinho.contato, crianca.endereco, crianca.escola, s3://fotos]
    
      verificador:
        ler:      [carta, relatorio_campo]
        escrever: [carta.parecer]
        negado:   ["*"]
    
      expedidor:
        ler:      [carta.aprovada, padrinho.contato]
        escrever: [envio]
        negado:   [relatorio_campo, crianca.*]
        exige_gate: true
    
    # Revisão trimestral obrigatória. Acesso não usado por 90 dias é revogado.
  • codigoguardrails/

    As regras críticas implementadas em código, fora do prompt.

    Exemplo real · sem_dados_sensiveis.py recusa qualquer saída que contenha endereço, escola ou sobrenome.

    Ver exemplopython
    # guardrails/sem_dados_sensiveis.py
    # Roda como hook PreToolUse. Não é conselho ao modelo: é impedimento.
    import re, sys, json
    
    PADROES = {
        "endereco":  r"\b(Rua|Av\.|Avenida|Travessa)\s+[A-ZÁ-Ú]",
        "escola":    r"\b(Escola|Colégio|E\.M\.)\s+[A-ZÁ-Ú]",
        "cpf":       r"\b\d{3}\.\d{3}\.\d{3}-\d{2}\b",
        "sobrenome": r"\b{nome}\s+[A-ZÁ-Ú][a-zá-ú]+",     # formatado com o nome da criança
    }
    
    def bloquear(texto, contexto):
        for nome, p in PADROES.items():
            if re.search(p.format(**contexto), texto):
                return f"bloqueado: {nome} — ver politicas/lgpd-menores.md"
        return None
    
    if __name__ == "__main__":
        ev = json.load(sys.stdin)
        motivo = bloquear(ev["conteudo"], ev["contexto"])
        if motivo:
            print(json.dumps({"decision": "block", "reason": motivo}))
            sys.exit(2)          # 2 = bloqueia a ferramenta e devolve o motivo ao agente
  • configgates.yaml

    Onde um humano aprova, com dono nomeado e prazo de resposta.

    Exemplo real · Primeira carta de cada criança nova; qualquer carta reprovada uma vez pelo verificador.

    Ver exemployaml
    gates:
      revisao-primeira-carta:
        quando: { primeira_carta_da_crianca: true }
        aprovador: coordenacao-programa
        prazo_horas: 48
        se_estourar: notificar_dri
    
      revisao-reprovada:
        quando: { verificador_reprovou: true }
        aprovador: coordenacao-programa
        prazo_horas: 24
    
      envio-em-lote:
        quando: { tamanho_lote: ">200" }
        aprovador: marina
        prazo_horas: 8
    
    # Renovação que passou limpa no verificador NÃO tem gate. O gate existe onde há risco,
    # não em todo lugar — senão vira carimbo e para de significar alguma coisa.
  • configautonomia.yaml

    O nível de cada tarefa por segmento, com a evidência que sustenta e a data.

    Exemplo real · Carta em português: nível 4 desde 12/03. Em espanhol: nível 3, faltam 40 casos.

    Ver exemployaml
    tarefas:
      escrever-carta:
        pt-BR:
          nivel: 4                    # age sozinho
          desde: 2026-03-12
          evidencia:
            - "6 semanas acima do baseline em todos os 5 critérios"
            - "0 incidentes de LGPD"
            - "kill switch acionado em treino em 2026-02-28"
        es:
          nivel: 3                    # age com aprovação
          falta: "40 casos em espanhol no golden dataset"
          revisar_em: 2026-06-01
    
      escrever-carta-crianca-desligada:
        todos:
          nivel: 2                    # só sugere
          motivo: "Não existe resposta correta automatizável."
  • dadosAudit log

    Registro append-only de quem decidiu o quê, quando e com base em quê.

    Exemplo real · Gerada pelo agente v12 em 3/3, com base no relatório de 20/2, aprovada por Marina, enviada em 5/3.

    Ver exemplosql
    create table audit (
      id          bigserial primary key,
      em          timestamptz not null default now(),
      ator        text not null,          -- 'agente:redator@v12' ou 'humano:marina@org'
      acao        text not null,          -- 'carta.gerada', 'carta.aprovada', 'carta.enviada'
      entidade    text not null,          -- 'carta:c-8812'
      base        jsonb not null,         -- com base em quê: fontes, versões, evidência
      resultado   text not null
    );
    revoke update, delete on audit from public;   -- append-only, inclusive para admin
  • codigoscripts/parar.sh

    O comando de parada, mais o gatilho automático por limite de custo ou de erro.

    Exemplo real · Para sozinho se o custo médio por carta passar de R$ 1,50.

    Ver exemplobash
    #!/usr/bin/env bash
    # Parada manual. Testada em treino todo trimestre — botão nunca acionado é suposição.
    set -euo pipefail
    PROCESSO="${1:?uso: parar.sh <processo>}"
    
    echo "pausando fila de $PROCESSO..."
    redis-cli SET "pausado:$PROCESSO" 1 EX 86400
    redis-cli SET "motivo:$PROCESSO" "parada manual por $(whoami) em $(date -Iseconds)"
    psql -c "insert into audit(ator,acao,entidade,base,resultado)
             values ('humano:$(whoami)','operacao.pausada','processo:$PROCESSO','{}','ok')"
    echo "pausado. Retomar: ./scripts/retomar.sh $PROCESSO"

09

Observabilidade

O que está acontecendo agora

Eval mede em laboratório; esta camada acompanha a produção. Sem ela, você descobre o problema pelo cliente.

  • painelTraces por execução

    Entrada, saída, ferramentas chamadas, tokens, custo, latência e versão do prompt.

    Exemplo real · Foi o trace que mostrou relatórios digitalizados entrando inteiros no contexto.

    Ver exemplojson
    {
      "trace_id": "tr-91ac",
      "tarefa": "escrever-carta",
      "crianca_id": "9f3c…",
      "agente": "redator@v12",
      "inicio": "2026-03-03T14:02:03Z",
      "duracao_ms": 38210,
      "passos": [
        { "tipo": "tool", "nome": "relatorio_do_ano", "ms": 210, "tokens_saida": 480 },
        { "tipo": "modelo", "nome": "modelo-rapido", "tokens_entrada": 5120,
          "tokens_saida": 610, "custo_brl": 0.31 },
        { "tipo": "tool", "nome": "validar", "ms": 40, "resultado": "falhou:extensao" },
        { "tipo": "modelo", "nome": "modelo-rapido", "tokens_entrada": 5900,
          "tokens_saida": 590, "custo_brl": 0.11 }
      ],
      "custo_total_brl": 0.42,
      "escalou": false
    }
  • painelPainel de custo

    Custo por tarefa e por resultado, em série temporal.

    Exemplo real · Mostrou o salto de R$ 0,42 para R$ 1,10 por carta, três horas antes de alguém perceber.

    Ver exemplosvg
    <svg viewBox="0 0 620 210" class="mock" role="img" aria-label="Painel de custo por carta">
      <text class="mk-t" x="0" y="14">CUSTO POR CARTA · ÚLTIMAS 8 SEMANAS</text>
      <text class="mk-n" x="0" y="52">R$ 0,71</text>
      <text class="mk-s" x="112" y="52">por carta entregue · baseline humano R$ 9,30</text>
      <g class="mk-grade">
        <line x1="0" y1="180" x2="620" y2="180"/><line x1="0" y1="140" x2="620" y2="140"/>
        <line x1="0" y1="100" x2="620" y2="100"/>
      </g>
      <polyline class="mk-linha" points="10,168 90,165 170,170 250,120 330,96 410,150 490,160 570,158"/>
      <circle class="mk-alerta" cx="330" cy="96" r="5"/>
      <text class="mk-s" x="300" y="84">pico: R$ 1,10</text>
      <g class="mk-eixo"><text x="10" y="198">jan</text><text x="250" y="198">fev</text>
        <text x="490" y="198">mar</text></g>
    </svg>
  • configalertas.yaml

    Os três alertas que pegam quase tudo.

    Exemplo real · Custo médio 2× a semana anterior; taxa de escalada subindo; latência p95 estourando.

    Ver exemployaml
    alertas:
      - nome: custo-dobrou
        consulta: "avg(custo_brl) últimas 24h > 2 × avg(custo_brl) semana anterior"
        severidade: alta
        destino: [dri, canal-operacao]
    
      - nome: escalada-subindo
        consulta: "taxa_escalada últimas 4h > 1.5 × mediana dos últimos 30 dias"
        severidade: media
        destino: [dri]
    
      - nome: latencia-p95
        consulta: "p95(duracao_ms) últimas 2h > 90000"
        severidade: baixa
        destino: [canal-operacao]
    
    # Três bastam. Alerta que dispara toda semana vira ruído e ninguém olha mais.
  • painelPainel de qualidade

    Percentual por critério ao longo do tempo, por versão.

    Exemplo real · É onde a regressão silenciosa fica visível.

    Ver exemplosvg
    <svg viewBox="0 0 620 210" class="mock" role="img" aria-label="Painel de qualidade por critério">
      <text class="mk-t" x="0" y="14">% POR CRITÉRIO · POR VERSÃO DE PROMPT</text>
      <g class="mk-grade"><line x1="120" y1="30" x2="120" y2="185"/></g>
      <g class="mk-rot">
        <text x="0" y="52">fidelidade</text><text x="0" y="82">lgpd</text>
        <text x="0" y="112">idioma</text><text x="0" y="142">extensão</text>
        <text x="0" y="172">tom</text>
      </g>
      <g class="mk-barra">
        <rect x="120" y="42" width="485" height="12"/><rect x="120" y="72" width="490" height="12"/>
        <rect x="120" y="102" width="490" height="12"/><rect x="120" y="132" width="490" height="12"/>
      </g>
      <rect class="mk-barra-ruim" x="120" y="162" width="348" height="12"/>
      <text class="mk-s" x="478" y="172">0,71 &#8594; era 0,87</text>
    </svg>
  • dadosincidentes/

    Um arquivo por incidente, com causa raiz e o caso que ele virou no gabarito.

    Exemplo real · Nenhum incidente é considerado fechado sem o caso correspondente.

    Ver exemplomd
    ---
    incidente: 2026-03-21-nome-trocado
    severidade: alta
    detectado_por: padrinho
    dri: marina
    ---
    
    # Carta com o nome de outra criança
    
    ## O que aconteceu
    Duas crianças homônimas na mesma comunidade. O agente buscou por nome, não por id,
    e escreveu a carta da Ana S. com os dados da Ana R.
    
    ## Causa raiz
    `buscar_crianca` aceitava nome como parâmetro. Nunca deveria ter aceitado.
    
    ## O que ficou permanente
    - [x] `buscar_crianca` só aceita `crianca_id` — parâmetro `nome` removido
    - [x] Caso `052-homonimas` no golden dataset
    - [x] Critério novo na suíte: id da carta bate com id do relatório
    - [x] Nota em `ontologia.md` sobre homônimos na mesma comunidade
    
    O incidente só fecha com os quatro marcados. Três deles não corrigem esta carta —
    corrigem todas as próximas.
  • painelPainel de fila e SLA

    Quanto tempo cada tarefa espera por aprovação humana.

    Exemplo real · Mostra quando o gate virou o gargalo do processo.

    Ver exemplosvg
    <svg viewBox="0 0 620 190" class="mock" role="img" aria-label="Fila de aprovação humana">
      <text class="mk-t" x="0" y="14">ESPERANDO APROVAÇÃO HUMANA</text>
      <text class="mk-n" x="0" y="52">34</text>
      <text class="mk-s" x="56" y="52">cartas na fila · prazo do gate: 48 h</text>
      <g class="mk-rot">
        <text x="0" y="92">revisao-primeira-carta</text><text x="0" y="122">revisao-reprovada</text>
        <text x="0" y="152">envio-em-lote</text>
      </g>
      <g class="mk-barra">
        <rect x="200" y="82" width="260" height="12"/><rect x="200" y="112" width="90" height="12"/>
      </g>
      <rect class="mk-barra-ruim" x="200" y="142" width="380" height="12"/>
      <g class="mk-s"><text x="470" y="92">21 · 12 h</text><text x="300" y="122">9 · 4 h</text>
        <text x="590" y="152">4 · 61 h</text></g>
    </svg>

10

Economia e responsabilidade

Quanto custa e quem responde

Aqui o projeto de tecnologia vira decisão de negócio: quanto custa e quem responde.

  • dadosunit-economics.csv

    Custo por token, por tarefa e por resultado, comparado ao baseline humano.

    Exemplo real · R$ 0,42 em tokens, R$ 0,71 por carta entregue, contra R$ 9,30 do processo manual.

    Ver exemplocsv
    etapa,unidade,valor,moeda,observacao
    tokens_entrada,por carta,0.29,BRL,média de 5.100 tokens
    tokens_saida,por carta,0.13,BRL,média de 600 tokens
    subtotal_modelo,por carta,0.42,BRL,custo direto de inferência
    retrabalho_agente,por carta,0.05,BRL,12% das cartas rodam 2×
    escalada_humana,por carta,0.24,BRL,8% × 25 min × custo/hora
    custo_por_resultado,por carta entregue,0.71,BRL,o número que decide
    baseline_humano,por carta entregue,9.30,BRL,medido em 2026-01-20
  • configdri.yaml

    Quem responde por cada processo agêntico. Pessoa com nome, não área.

    Exemplo real · Correspondência: Marina. Ela não revisa as 4.000; responde pelo sistema que as produz.

    Ver exemployaml
    processos:
      correspondencia:
        dri: marina@org
        substituto: joao@org
        responde_por: [qualidade, custo, incidentes, nivel de autonomia]
        nao_responde_por: [infraestrutura, contrato de modelo]
        revisa: { evals: semanal, selos_maturidade: trimestral, permissoes: trimestral }
    
      triagem-relatorios:
        dri: marina@org
        substituto: joao@org
    
    # Processo agêntico sem DRI não sobe de nível de autonomia. Regra sem exceção.
  • dadosspan-of-control.csv

    Quantos processos cada pessoa supervisiona e com que instrumentos.

    Exemplo real · Marina: 6 processos, todos com eval, painel de custo e gates definidos.

    Ver exemplocsv
    pessoa,processos,com_eval,com_painel,com_gate_definido,horas_semana_supervisao
    marina@org,6,6,6,6,7
    joao@org,2,2,1,2,4
  • mdmaturidade.md

    Onde a organização está em cada conceito, revisado por trimestre.

    Exemplo real · O mesmo selo que aparece nas fichas deste dicionário.

    Ver exemplomd
    # Maturidade — revisão de 2026-Q1
    
    | Conceito | Selo | Evidência | Próximo passo |
    |---|---|---|---|
    | Golden dataset | 🟢 em produção | 200 casos, 30 difíceis | manter: todo incidente vira caso |
    | Evals | 🟢 em produção | suíte bloqueia deploy desde jan/26 | adicionar critério de repetição |
    | Auto verificação | 🟡 experimentando | roda em pt-BR, não em es | estender ao espanhol |
    | Baseline humano | 🟢 em produção | medido em 2026-01-20 | remedir em jan/27 |
    | Ontologia | 🟡 experimentando | 12 entidades escritas | faltam as de captação |
    | Monitoramento | 🟢 em produção | traces + 3 alertas | painel de qualidade por versão |
    | Span of control | 🔴 não usamos | — | medir antes de opinar |
    
    Revisado por: Marina · Próxima revisão: 2026-06-30
  • mdroadmap-autonomia.md

    O que falta para cada tarefa subir de nível, com data e responsável.

    Exemplo real · Espanhol precisa de 40 casos a mais no gabarito antes de ir para o nível 4.

    Ver exemplomd
    # Roadmap de autonomia
    
    | Tarefa / segmento | Hoje | Alvo | O que falta | Quando | Dono |
    |---|---|---|---|---|---|
    | escrever-carta · pt-BR | 4 | 4 | — | — | marina |
    | escrever-carta · es | 3 | 4 | 40 casos em espanhol no golden | jun/26 | marina |
    | triar-relatorio | 3 | 4 | 4 semanas de eval acima do baseline | mai/26 | joao |
    | carta · criança desligada | 2 | 2 | permanece em 2 por decisão | — | marina |
    
    ## Regra
    Nenhuma linha sobe sem: evidência anexada, data e DRI. "Está indo bem" não é evidência.
  • mddecisoes/ADR-*.md

    As decisões de arquitetura, datadas, com as alternativas que foram descartadas e por quê.

    Exemplo real · Por que MCP em vez de integração ponto a ponto com cada sistema.

    Ver exemplomd
    # ADR-007 — MCP em vez de integração ponto a ponto
    
    **Data:** 2026-02-10 · **Status:** aceita · **Decisor:** time de plataforma
    
    ## Contexto
    Quatro sistemas internos (cadastro, doações, e-mail, campo) e três agentes previstos.
    Ponto a ponto seriam 12 integrações, cada uma refeita a cada troca de agente.
    
    ## Decisão
    Um servidor MCP por sistema. Agentes falam MCP, nunca a API interna diretamente.
    
    ## Alternativas descartadas
    - **SDK interno compartilhado** — resolveria hoje, mas amarra os agentes à nossa linguagem.
    - **Integração direta** — mais rápida na primeira, insustentável na terceira.
    
    ## Consequências
    - (+) Trocar o sistema de cadastro troca 1 servidor, não 3 agentes.
    - (−) Uma camada a mais para operar e monitorar.
    - (−) Latência adicional de ~40 ms por chamada. Aceita.
    
    ## Quando revisitar
    Se ficarmos com um único agente por mais de um ano, esta decisão perde a justificativa.