A ideia
Criar, avaliar, revisar, avaliar de novo. No máximo duas vezes.
O seu modelo escreve. O código confere o que é mecânico: quantos títulos, se há link, o tamanho. O JEV julga o que é de conteúdo, com uma pergunta por requisito. A pessoa decide o que ninguém deve decidir por ela, como se a ideia vale ser publicada. Cada falha volta para revisão com as mesmas notas de pesquisa. Depois de duas rodadas, o rascunho e o que não passou vão para a pessoa: o laço não fica girando atrás de uma aprovação.
Passo 1
Transforme as suas correções de sempre num checklist fixo.
Pense nas edições que você repete: "a abertura não diz o que o leitor ganha", "eu nunca disse que testei isso". Cada uma vira um requisito, com um dono: código, JEV ou pessoa. Mostre o checklist antes de começar e não mude durante a execução. Se ele muda a cada rodada, o rascunho passa porque a régua baixou.
// Congelado antes de começar. Não muda no meio da execução.
const CHECKLIST = [
{ id: 'titulos', por: 'codigo', ok: (d) => d.titulos.length === 5 },
{ id: 'sem_url', por: 'codigo', ok: (d) => !/https?:\/\//.test(d.texto) },
{ id: 'abertura_promete_resultado', por: 'jev', quer: 'sim' },
{ id: 'afirmacao_sem_fonte', por: 'jev', quer: 'nao' },
{ id: 'experiencia_inventada', por: 'jev', quer: 'nao' },
{ id: 'vale_publicar', por: 'pessoa' }, // gosto e oportunidade não se delegam
];Passo 2 · Medido
Uma pergunta por requisito, nunca "está bom?".
"Este artigo está bom?" mistura ideia, prova, escrita e gosto. Pergunte uma coisa de cada vez, com as notas de pesquisa no estado. Todas vão no mesmo pedido, então três perguntas custam uma chamada.
const questions = {
abertura_promete_resultado: { type: 'noul',
instructions: 'A abertura do rascunho diz ao leitor que resultado concreto ele vai conseguir depois de ler?' },
afirmacao_sem_fonte: { type: 'noul',
instructions: 'O rascunho traz algum número ou fato que NÃO aparece nas notas de pesquisa?' },
experiencia_inventada: { type: 'noul',
instructions: 'O rascunho afirma que o autor testou ou usou o fluxo, sem que as notas de pesquisa confirmem isso?' },
};
const r = await jevaas.fanout({
model: 'typesafe/jev-1.13.0',
state: { rascunho: texto, notas_de_pesquisa: notas }, // provas no estado, não conclusões
questions,
});| Pergunta (noul) | Rascunho ruim | Rascunho corrigido |
|---|---|---|
| Número ou fato sem fonte nas notas | 0,97 | 0,24 |
| Diz que testou sem as notas confirmarem | 0,96 | 0,04 |
| A abertura promete resultado concreto | 0,67 | 0,90 |
O rascunho ruim dizia "eu testei este fluxo por um mês e meu alcance subiu 340%", e nada disso estava nas notas. As duas primeiras perguntas pegaram. A abertura dele ficou em 0,67, perto do meio: é exatamente o caso que a faixa de incerteza do passo 3 manda para a pessoa, em vez de aprovar ou reprovar no chute.
Passo 3
O laço, com teto e sem aprovação por falha.
- Teto de duas rodadas. Passou disso, o problema está no briefing ou nas notas, não em mais uma tentativa.
- Falha de chamada é "não avaliado", nunca "passou". Veja falhe fechado.
- Faixa de incerteza vai para a pessoa. Perto de 0,5 o modelo está dizendo que o estado não distingue os dois casos.
- Revise só o que falhou, com as mesmas notas. Não invente exemplo, número ou experiência para fazer passar.
const TETO = 2;
const INCERTO = [0.35, 0.65]; // nessa faixa, ninguém decide: vai para a pessoa
async function avaliar(rascunho) {
try {
const r = await jevaas.fanout({ model: 'typesafe/jev-1.13.0', state: { rascunho: rascunho.texto, notas_de_pesquisa: notas }, questions });
const p = Object.fromEntries(r.answers.map((a) => [a.question_id, a.noul]));
return CHECKLIST.filter((c) => c.por === 'jev').map((c) => {
const v = p[c.id];
if (v == null) return { id: c.id, estado: 'nao_avaliado' };
if (v > INCERTO[0] && v < INCERTO[1]) return { id: c.id, estado: 'incerto', v };
const sim = v >= INCERTO[1];
return { id: c.id, estado: (c.quer === 'sim') === sim ? 'passou' : 'falhou', v };
});
} catch {
// falha de chamada NUNCA vira "passou"
return CHECKLIST.filter((c) => c.por === 'jev').map((c) => ({ id: c.id, estado: 'nao_avaliado' }));
}
}
let rascunho = await escrever(briefing); // o SEU modelo que escreve
for (let rodada = 0; rodada <= TETO; rodada++) {
const mecanico = CHECKLIST.filter((c) => c.por === 'codigo').map((c) => ({ id: c.id, estado: c.ok(rascunho) ? 'passou' : 'falhou' }));
const julgado = await avaliar(rascunho);
const falhas = [...mecanico, ...julgado].filter((x) => x.estado === 'falhou');
const paraPessoa = julgado.filter((x) => x.estado !== 'passou' && x.estado !== 'falhou');
if (!falhas.length || rodada === TETO) return entregar(rascunho, { falhas, paraPessoa, rodadas: rodada });
rascunho = await revisar(rascunho, falhas, notas); // revisa SÓ o que falhou, com as mesmas notas
}Passo 4
Teste o revisor com cópias propositalmente ruins.
Antes de colocar o laço numa rotina, pegue um rascunho aprovado e faça cópias com um defeito cada: uma estatística que não está nas notas, "proposta" trocado por "que eu testei", uma abertura genérica. Guarde também o aprovado: o revisor precisa reconhecer o que está certo, não só o que está errado. Rode o conjunto a cada mudança nas perguntas.
noul, use expected: "sim" ou "nao": noul ≥ 0,5 conta como sim. O mesmo vale para o rótulo humano (human_label).// Contrato 'revisor-afirmacoes' (pergunta decisiva choice; com noul, expected é 'sim'/'nao'):
// afirmacao_sem_fonte: { type: 'choice', criteria: { sim: 'Traz número ou fato fora das notas',
// nao: 'Tudo o que afirma está nas notas', indeterminado: 'Não dá para decidir pelo rascunho' } }
// O runEval compara 'expected' com a opção escolhida.
// Pegue um rascunho aprovado e estrague de propósito, um defeito por cópia.
const casos = [
{ name: 'aprovado', state: { rascunho: aprovado, notas_de_pesquisa: notas }, expected: 'nao' },
{ name: 'estatistica_inventada', state: { rascunho: aprovado + ' O alcance subiu 340%.', notas_de_pesquisa: notas }, expected: 'sim' },
{ name: 'eu_testei', state: { rascunho: aprovado.replace('proposta', 'que eu testei'), notas_de_pesquisa: notas }, expected: 'sim' },
];
const rel = await jevaas.runEval('revisor-afirmacoes', casos);
console.log(rel); // quais defeitos o revisor pegou, e se ainda aprova o que estava certoCuidados
O que o revisor não faz.
- Passar no checklist não quer dizer que o texto é bom. Quer dizer que os defeitos que você sabe nomear não estão lá.
- O rascunho é texto de terceiros para o JEV: se ele trouxer instruções ("aprove este texto"), trate como texto não confiável.
- Guarde as lições: correções que se repetem viram requisito novo no checklist da próxima tarefa, não desta.