AI Forge Eval
Validação comportamental para skills e agentes. A pontuação por rubrica (ai-forge-judge) informa se um artefato está bem escrito. O Eval informa se ele funciona.
Funciona para SKILL.md (skills) e .agent.md (agentes). Mesmo fluxo de 5 fases; a configuração da Fase 2 difere conforme o tipo de artefato.
Fase 0 — Carregar ou Escrever a Suíte
OBRIGATÓRIO — LEIA references/eval-suite.md para o formato em disco, o protocolo de gatilho e a tabela de discriminação de asserções.
Verifique se existe evals/evals.json ao lado do artefato.
- Presente — carregue e pule para a Fase 2. Adicione casos se a cobertura for escassa; nunca substitua silenciosamente os existentes, ou a tendência se quebra.
- Ausente — crie na Fase 1 e escreva em
evals/evals.jsonantes de gerar qualquer coisa.
Uma suíte que vive apenas nesta conversa não consegue detectar uma regressão no mês seguinte. Persisti-la é o que faz a diferença entre uma opinião e um teste.
Fase 1 — Escrever Evals
Escreva 2–3 casos de eval. Cada eval é um prompt realista mais 3–5 asserções.
Prefira prompts extraídos de uma sonda de base (Fase 1b do ai-forge-create) em vez dos gatilhos declarados pelo próprio artefato — asserções escritas a partir do artefato só podem confirmar que ele faz o que afirma. Carregue cada captura no campo baseline_failure do cenário.
Para skills: prompts que devem ativar a skill naturalmente. Asserções verificam comportamentos específicos da skill (ex.: "a saída inclui um resumo da Fase 1", "o formato da regra NUNCA tem PORQUE e EM VEZ DISSO").
Para agentes: prompts que cobrem o escopo declarado do agente. Asserções verificam comportamentos observáveis — arquivos criados, ferramentas chamadas, restrições de tom, limites de escopo (ex.: "não modificou arquivos fora de src/lib/", "abriu um PR", "a mensagem de commit começa com 'refactor:'").
Regras para asserções:
- Verificáveis: o avaliador pode verificar apenas com a saída
- Específicas: "saída inclui o cabeçalho 'Fase 1'" é melhor que "saída é bem estruturada"
- Falseáveis: deve ser possível falhar
Registre os evals:
Eval 1: <prompt>
Expectativas:
- <asserção 1>
- <asserção 2>
- <asserção 3>
Fase 2 — Gerar em Paralelo
Para cada eval, gere as execuções com artefato e de base na mesma mensagem (nunca sequencialmente). No modo de benchmark, isso se torna N pares de tentativa por eval — veja Modo de benchmark abaixo.
Execução com artefato: forneça o prompt do eval. Para skills: adicione "Use a skill <nome-da-skill> para esta tarefa." Para agentes: cole as instruções completas do agente como contexto do sistema.
Execução de base: depende do que está sendo medido.
- Artefato novo — mesmo prompt de eval, sem instrução de skill, sem contexto de agente. Resposta simples do assistente.
- Melhorando um artefato existente — tire um snapshot da versão atual primeiro (
cp -r <caminho> <scratch>/snapshot/), depois aponte a base para o snapshot. "Sem artefato" é o controle errado quando a questão é se a mudança ajudou; ele mede a existência do artefato, não a edição.
Capture imediatamente ao concluir: quando cada notificação de tarefa chegar, registre qual execução foi (mais o índice da tentativa no modo de benchmark) e leia duration_ms e subagent_tokens do bloco <usage> — exatos, não estimados. Sem bloco <usage> significa registrar null; nunca substitua por um palpite de tempo real. Esses dados existem apenas no momento da notificação e não podem ser reconstruídos depois.
Armazene por eval: texto de saída with_artifact e baseline, mais duration_ms e tokens para cada braço.
Fase 3 — Avaliar
LEITURA OBRIGATÓRIA: agents/assayer.md
Para cada eval, invoque o assayer em ambas as saídas. Passe:
Saída: <texto da saída>
Expectativas:
- <asserção 1>
- <asserção 2>
O assayer retorna por expectativa:
{ "text": "...", "passed": true, "evidence": "..." }
Calcule taxa_de_acerto = passou / total por execução.
Calcule delta = taxa_de_acerto_com_artefato - taxa_de_acerto_base.
Em seguida, classifique cada asserção conforme seu comportamento em ambos os braços — passa em ambos (mede o modelo, não o artefato), falha em ambos (quebrada ou fora de alcance), passa com e falha sem (sinal real), falha com e passa sem (o artefato está prejudicando), ou alta variância (instável). Veja a tabela em references/eval-suite.md. Uma suíte cujas asserções passam em ambos os braços relata uma taxa de acerto saudável e não informa nada.
Leia também a transcrição, não apenas a saída: a execução realmente seguiu o artefato ou chegou à resposta correta apesar dele? Trabalho causado pelo artefato que não produziu nada é candidato a corte.
Fase 3b — Revisão Humana
Antes de analisar qualquer coisa, coloque as saídas brutas diante do usuário.
Preencha assets/eval-review.html — substitua __ARTIFACT_NAME__ e __EVAL_DATA__ (um array JSON de {id, name, prompt, with_artifact, baseline, assertions}) e escreva-o ao lado da suíte de eval. Apresente-o com uma ferramenta de entrega de arquivos se disponível; caso contrário, forneça o caminho ao usuário. Leia o feedback.json exportado quando terminarem.
A avaliação do modelo sobre a saída de seu próprio artefato é o sinal mais fraco aqui — um olhar humano capta o que nenhuma asserção foi escrita para captar. Pule apenas se o usuário recusar.
Fase 4 — Comparar (opcional)
LEITURA OBRIGATÓRIA: agents/arbiter.md — carregue apenas quando a Fase 4 for executada.
Execute a Fase 4 quando: delta > 0,1 em qualquer eval, ou as taxas de acerto conflitarem entre evals.
Pule quando: as taxas de acerto forem idênticas, ou o usuário solicitou apenas notas.
Entrada do árbitro: Saída A (não identificada), Saída B (não identificada), lista de expectativas. Registre qual era qual para a Fase 5.
O árbitro retorna: pontuação de conteúdo (1–5), pontuação de estrutura (1–5), vencedor (A/B/empate), justificativa, pontos fortes/fracos por lado.
Portão de liberação ao comparar duas versões: libere apenas se a nova versão vencer ou empatar em todos os cenários, e vencer em pelo menos um. Uma versão que vence bem em um caso e perde em outro trocou uma falha por outra diferente — isso não é uma melhoria, e o delta agregado esconderá isso.
Fase 5 — Analisar + Relatar
LEITURA OBRIGATÓRIA: agents/refiner.md — carregue apenas se a Fase 4 foi executada.
Se a Fase 4 foi pulada: vá diretamente para a tabela de benchmark.
Entrada do refiner: saída do árbitro + mapeamento de rótulos { "A": "with_artifact", "B": "baseline" } (ou invertido). O refiner explica por que o vencedor venceu o perdedor e apresenta 1–3 melhorias priorizadas.
Renderize a tabela de benchmark — uma linha por eval mais uma linha Média, colunas Eval | with_artifact | baseline | delta | duration_ms (com / base), contagens e porcentagens de acerto por braço. Acrescente quaisquer asserções não discriminantes ou prejudiciais sinalizadas na Fase 3, depois as sugestões de melhoria do refiner, se executado.
Se o delta for negativo em qualquer eval, sinalize: "O artefato pode estar prejudicando o desempenho — revise a redação do gatilho ou as restrições de escopo."
Fase 6 — Verificação de Gatilho
Evals comportamentais respondem "funciona quando invocado." Isso responde "ele é invocado" — a falha mais comum e invisível para todas as fases acima.
Execute quando a suíte tiver um bloco triggers, ou ofereça após a Fase 5. OBRIGATÓRIO — LEIA references/eval-suite.md para o protocolo, a divisão de retenção 60/40 e o padrão de qualidade da consulta. NÃO carregue para uma execução puramente comportamental.
Relate recall e precisão por divisão (treino e retido), além dos erros específicos (falsos negativos e falsos positivos). Baixo recall com alta precisão significa que a descrição é muito restrita — amplie-a. O inverso significa que ela está usurpando tarefas adjacentes — adicione gatilhos negativos.
Modo de Benchmark
Ative quando o usuário pedir para executar benchmark, rastrear regressão ou bloquear por tendência. O modo de benchmark estende as cinco fases com tentativas repetidas e um armazenamento de tendências persistido.
LEITURA OBRIGATÓRIA: references/benchmarking.md antes de executar — protocolo de tentativa, fórmulas de agregação, limites de bloqueio e os esquemas de resultados de tentativa + benchmark.json estão lá. NÃO carregue para uma execução única simples de eval.
- Tentativas — cada eval executa N vezes (padrão 3). Por eval, gere todos os N pares de tentativa (2N subagentes) em UMA mensagem, processe as notificações desse eval capturando
<usage>conforme a Fase 2, depois passe para o próximo eval. Nunca gere todas as tentativas de todos os evals de uma vez. - Agregar —
node scripts/aggregate-benchmark.cjs --trials <scratch.json> --prior benchmarks/<nome-do-artefato>.json --artifact <caminho>retorna média/desvio padrão por eval, sinalizadores de instabilidade e discriminação, deltas em relação à execução anterior e um veredito de bloqueio. Se não puder executar (semnode, script ausente, erro de uso), relate os resultados brutos por tentativa com⚠ sem agregado — validador indisponível: <motivo>e não calcule manualmente um veredito de bloqueio; um veredito de bloqueio é uma alegação sobre significância estatística e não deve ser estimado. Um veredito de FALHA sempre bloqueia. - Persistir — salve o payload retornado em
benchmarks/<nome-do-artefato>.json(versionado) como a nova linha de base de tendência. - Relatar — tabela da Fase 5 com colunas de média±desvio padrão mais o veredito de bloqueio. Em caso de falha no bloqueio, o veredito é "regrediu — não pronto".
NUNCA
-
NUNCA execute as execuções com artefato e de base de uma tentativa sequencialmente Em vez disso: Ambos os braços de cada tentativa na mesma mensagem. No modo de benchmark, todos os N pares de tentativa para um eval vão em uma mensagem; evals diferentes podem ser processados em lote sequencialmente. Por quê: Braços sequenciais serializam o feedback paralelo; mas gerar todas as tentativas de todos os evals de uma vez inunda as notificações e torna a captura por chegada de
<usage>não confiável. -
NUNCA adie a captura de uso até que outras execuções terminem Em vez disso: Leia o bloco
<usage>de cada notificação (duration_ms,subagent_tokens) no momento em que chegar. Por quê: Os dados de<usage>existem apenas no momento da notificação e não podem ser reconstruídos depois. -
NUNCA relate uma única tentativa como um benchmark Em vez disso: Execute pelo menos N=3 tentativas para que média e desvio padrão sejam significativos. Por quê: Uma taxa de acerto isolada parece precisa, mas esconde instabilidade — uma skill que realmente passa um terço das vezes pode parecer 100% ou 0% em uma única tentativa.
-
NUNCA enfraqueça um cenário que uma execução com artefato falhou Em vez disso: Reforce o corpo até que a execução passe no cenário como escrito. Por quê: O cenário é o registro de uma falha real. Suavizá-lo torna o eval verde enquanto a falha para a qual foi construído sobrevive intocada.
-
NUNCA ajuste uma descrição com base nas consultas de gatilho retidas Em vez disso: Itere na divisão de treino; olhe para a retida apenas para selecionar a versão final. Por quê: Uma descrição ajustada em seu próprio conjunto de teste obtém boa pontuação e generaliza pior — você perde a única estimativa não enviesada que tinha.
-
NUNCA escreva asserções subjetivas ("saída é clara", "bem formatada", "completa") Em vez disso: Verificável a partir do texto: "saída inclui o cabeçalho 'Fase 1'", "nenhuma regra NUNCA sem uma cláusula PORQUE" Por quê: Asserções subjetivas não dão verdade fundamental ao avaliador; aprovação/reprovação se torna arbitrária e irrepetível.
-
NUNCA use prompts diferentes para as execuções com e sem artefato Em vez disso: Prompt idêntico — apenas a instrução do artefato difere. Por quê: Variação de prompt confunde o delta; ele mede qualidade do prompt, não efeito do artefato.
-
NUNCA aceite saída do assayer com nomes de campos não padrão Em vez disso: Exija exatamente
text,passed,evidence— rejeitename,met,detailsou outros. Por quê: A agregação da Fase 5 depende de nomes de campos exatos; nomes incorretos silenciosamente produzem taxas de acerto erradas.