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.

Checklist
// 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.

TypeScript
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,
});
Medido na API em 28/09/2026, typesafe/jev-1.13.0, 454 tokens por chamada
Pergunta (noul)Rascunho ruimRascunho corrigido
Número ou fato sem fonte nas notas0,970,24
Diz que testou sem as notas confirmarem0,960,04
A abertura promete resultado concreto0,670,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.
TypeScript
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.

Com pergunta decisiva noul, use expected: "sim" ou "nao": noul ≥ 0,5 conta como sim. O mesmo vale para o rótulo humano (human_label).
TypeScript · runEval
// 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 certo

Cuidados

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.

Cookbook de ponta a ponta: contrato, sombra e calibração →