//Caso de uso

Priorização de relatos de bug com decisão tipada

Prioridade de bug é uma discussão que se repete toda semana com os mesmos argumentos. Parte dela é julgamento; parte é aritmética mal colocada.

A reunião de triagem de bugs tem um formato conhecido: uma lista longa, uma pessoa lendo em voz alta, duas pessoas discordando sobre o que é P1, e a mesma discussão de novo na semana seguinte. O que torna a reunião cansativa não é o julgamento difícil — é que 80% da lista é óbvia e passa pela mesma cerimônia dos 20% que não são.

O Jev, modelo da TypeSafe AI que devolve decisões tipadas com probabilidade em vez de texto, resolve a parte óbvia. E, o que importa mais, obriga a equipe a escrever o que significa cada nível de severidade — que é a discussão que a reunião nunca termina.

O desenho das perguntas

Uma chamada por relato. No state, o texto do relato e os campos que a sua telemetria já sabe, já calculados.

{
  "state": {
    "titulo": "Pedido some do carrinho ao trocar de aba",
    "relato": "Quando eu deixo o carrinho aberto e volto depois de um tempo, os itens somem. Perdi um pedido de quase mil reais que eu tinha montado item por item. Não apareceu erro nenhum.",
    "plataforma": "web",
    "usuarios_afetados_7d": 412,
    "dias_desde_o_primeiro_relato": 3,
    "tem_contorno_documentado": false
  },
  "questions": {
    "area": {
      "type": "choice",
      "instructions": "Qual área do produto este relato aponta?",
      "criteria": {
        "carrinho_e_checkout": "Montagem do pedido, carrinho, pagamento, finalização.",
        "conta_e_acesso": "Login, cadastro, permissão, recuperação de senha.",
        "catalogo": "Busca, listagem, ficha de produto, estoque exibido.",
        "integracao": "API, webhook, importação e exportação de dados.",
        "indeterminada": "O relato não permite identificar a área."
      }
    },
    "severidade": {
      "type": "score",
      "instructions": "Qual a gravidade do comportamento descrito para quem usa o produto?",
      "criteria": [
        "Cosmético; não afeta o que dá para fazer.",
        "Funcionalidade degradada, com contorno possível.",
        "Funcionalidade bloqueada, sem contorno descrito.",
        "Perda de dados, de dinheiro ou risco de segurança."
      ]
    },
    "clareza_do_relato": {
      "type": "score",
      "instructions": "Quanto este relato permite reproduzir o problema?",
      "criteria": [
        "Só a queixa, sem contexto.",
        "Descreve o sintoma, sem passos.",
        "Descreve passos parciais ou condição de ocorrência.",
        "Passos completos e resultado esperado versus obtido."
      ]
    },
    "menciona_perda_de_dados": {
      "type": "noul",
      "instructions": "O relato descreve perda de dados, de trabalho salvo ou de dinheiro do usuário?"
    },
    "menciona_seguranca": {
      "type": "noul",
      "instructions": "O relato descreve acesso indevido, vazamento de dado de outra pessoa ou falha de autenticação?"
    }
  }
}

Os dois números do stateusuarios_afetados_7d e dias_desde_o_primeiro_relato — vêm prontos do seu sistema. Isso não é detalhe de implementação: é o que impede a arquitetura de pedir ao modelo duas coisas que ele declaradamente não faz bem.

O que o código faz com a resposta

Piso de confiança primeiro. Área com confiança baixa significa relato vago. Vai para uma fila de “pedir mais informação”, não para um time.

Regras determinísticas depois. menciona_seguranca acima do corte escala na hora para o time responsável, fora da fila normal. menciona_perda_de_dados força prioridade máxima. As duas são políticas de engenharia, e políticas não devem depender de pesos.

Combinação por último, com os números que vieram do seu banco.

a = r.answers["area"]

if r.answers["menciona_seguranca"].noul > 0.5:
    return escalar_seguranca(bug)            # corte baixo de propósito

if r.answers["menciona_perda_de_dados"].noul > 0.6:
    prioridade_base = 1.0
else:
    prioridade_base = r.answers["severidade"].score / 3

if a.confidence < PISO:
    return pedir_mais_informacao(bug)

alcance = min(bug["usuarios_afetados_7d"] / 1000, 1.0)   # aritmética no código
idade = min(bug["dias_desde_o_primeiro_relato"] / 30, 1.0)

prioridade = 0.55 * prioridade_base + 0.35 * alcance + 0.10 * idade
enfileirar(bug, time=TIMES[a.choice], prioridade=prioridade,
           clareza=r.answers["clareza_do_relato"].score)

A nota de clareza não entra na prioridade: ela vira uma etiqueta. Bug prioritário com clareza baixa é o primeiro da fila de “pedir passos ao usuário”, o que é uma ação diferente de “corrigir”.

Onde entra a pessoa

O limiar acompanha o risco. Segurança tem corte baixo, em 0,5, porque um falso positivo custa a leitura de um engenheiro e um falso negativo custa um incidente. Área e prioridade têm corte alto, porque errar o time custa um ciclo de sprint.

A revisão humana continua existindo — mas muda de objeto. Em vez de discutir a lista inteira, a reunião discute a faixa de confiança baixa e a fronteira entre os dois níveis mais altos da régua. Quando essa discussão acontece, a saída dela é uma frase melhor no criteria, não uma decisão sobre aquele bug específico. É assim que a régua melhora com o tempo; o assunto está em critérios que separam.

Custo

Assumindo dez mil relatos por mês — suposição deste artigo, típica de um produto grande com canal aberto de feedback — e um state de cerca de dois mil tokens: ao preço oficial de US$ 0,042 por milhão de tokens de entrada, com saída gratuita, e o dólar estimado em R$ 5,40, cada relato sai por cerca de R$ 0,00045 e o mês por cerca de R$ 4,54. A fórmula está em quanto custa uma decisão.

Onde isso quebra

Este caso esbarra em três dos nove modos de falha declarados do jev-1.13, e por isso o desenho acima empurra tanta coisa para o código.

Contagem. “Quantos usuários relataram isso?” não é pergunta para o modelo. A documentação diz que ele reconhece a forma de uma resposta em vez de contar, e que o erro cresce com o tamanho da coisa contada. O número vem da telemetria.

Comparação de datas. “Este bug está aberto há mais de duas semanas?” é aritmética sobre datas, e o modelo lê data como texto, não como quantidade ordenada. Calcule os dias no seu sistema e passe o inteiro.

Numérico versus semântico. A documentação observa que perguntas com representação semântica funcionam melhor que com representação numérica, e cita o caso de valores hexadecimais contra nomes de cor. Em bug, isso significa não pedir ao modelo para julgar um código de erro ou um stack trace como se fosse texto comum — mande o trecho relevante e pergunte sobre o comportamento descrito, não sobre o número.

Não confunda severidade com reprodução. O modelo pontua o texto do relato. Ele não executa o sistema, não confirma o bug e não sabe se o problema já foi corrigido em outra branch. A lista completa dos limites está em limites do Jev, e os outros fluxos desta família em casos de uso.

Perguntas frequentes

O modelo consegue estimar severidade de bug?

Consegue pontuar contra níveis que você descreve, que é diferente de adivinhar um número. Um Score com quatro níveis — cosmético, degradado com contorno, bloqueante e perda de dados — dá uma nota reprodutível sobre o texto do relato. Ele não avalia o código nem reproduz o erro.

Por que perda de dados é Noul e não um nível da régua?

Porque perda de dados costuma ser uma regra de escalonamento imediato, não algo que se pondera com outras dimensões. Um Noul responde uma condição binária que dispara política no seu código; o Score serve para ordenar o resto.

Ele conta quantos usuários foram afetados?

Não. A documentação oficial diz que o jev-1.13 não conta de forma confiável e que o erro cresce com o tamanho da coisa contada. A contagem vem da sua telemetria e entra pronta no state, como número.

E o tempo aberto do bug, entra na prioridade?

Entra, mas calculado em código. O modelo lê data como texto, não como quantidade ordenada, então comparar datas é um dos limites declarados. Calcule os dias no seu sistema e some o peso na fórmula.

Quanto custa triar dez mil relatos?

Assumindo um state de cerca de dois mil tokens, que cobre o relato e os campos técnicos, ao preço oficial de US$ 0,042 por milhão de tokens de entrada e com o dólar estimado em R$ 5,40, dez mil relatos saem por cerca de R$ 4,54.

Quer dominar decisões com IA em português? O curso da comunidade está em pré-venda.

Garantir pré-venda por R$ 499,00

Pré-venda: R$ 499,00 · Após o lançamento: R$ 799,00