mozak.tech Engenharia de IA Corporativa 82%

Parte IV — Gestão de Projetos e Produto com Suporte de IA

4.8 — Rastreabilidade e Controle de Qualidade em Projetos de IA (QA Governance)

Objetivo da Aula

Ao concluir esta aula, você será capaz de:

Implementar controle de versão de artefatos (PRD, spec, decisões) com rastreabilidade

Registrar changelog automático de mudanças via LLM

Implementar versionarArtefato(artefato, conteudoNovo, client) com diff e histórico

Implementar verificarConformidade(artefato, criterios, client) para gate de qualidade

Completar os 2 TODOs do starter

Por que isso importa

“Quem mudou os requisitos?” é a pergunta mais comum em post-mortems de projetos falhos. Sem versionamento de artefatos, não há resposta. Com versionamento + LLM, cada mudança tem: quem, quando, o quê mudou, e por quê (gerado pelo LLM a partir do diff).

Conceitos Fundamentais

TODO 1: versionarArtefato(artefato, conteudoNovo, client)

async function versionarArtefato(artefato, conteudoNovo, client) {

  const versao_anterior = artefato.versoes?.[artefato.versoes.length - 1]

  

  // Gerar changelog via LLM comparando conteúdo anterior e novo

  let changelog = 'Criação inicial'

  if (versao_anterior) {

    const response = await client.messages.create({

      model: 'claude-haiku-4-5-20251001',

      max_tokens: 200,

      messages: [{

        role: 'user',

        content: `Compare estes dois textos e descreva as mudanças em 1-3 bullets objetivos:



ANTES:

${versao_anterior.conteudo}



DEPOIS:

${conteudoNovo}`,

      }],

    })

    changelog = response.content[0].text

  }

  

  const nova_versao = {

    numero: (versao_anterior?.numero || 0) + 1,

    conteudo: conteudoNovo,

    changelog,

    timestamp: new Date().toISOString(),

    hash: Buffer.from(conteudoNovo).toString('base64').slice(0, 8),

  }

  

  return {

    ...artefato,

    versao_atual: nova_versao.numero,

    versoes: [...(artefato.versoes || []), nova_versao],

    ultima_modificacao: nova_versao.timestamp,

  }

}

TODO 2: verificarConformidade(artefato, criterios, client)

async function verificarConformidade(artefato, criterios, client) {

  const criterios_str = criterios.map((c, i) => `${i+1}. ${c}`).join('\n')

  const conteudo = artefato.versoes?.[artefato.versoes.length - 1]?.conteudo || ''

  

  const response = await client.messages.create({

    model: 'claude-haiku-4-5-20251001',

    max_tokens: 400,

    system: 'Você é um analista de qualidade. Avalie se o artefato atende aos critérios listados. Seja objetivo e específico.',

    messages: [{

      role: 'user',

      content: `Artefato (${artefato.tipo}):

${conteudo}



Critérios de conformidade:

${criterios_str}



Para cada critério, diga: APROVADO / NÃO ATENDE / PARCIALMENTE.

Retorne JSON: {"resultados": [{"criterio": "...", "status": "...", "observacao": "..."}], "aprovado": true/false}`,

    }],

  })

  

  const texto = response.content[0].text

  const i = texto.indexOf('{'), f = texto.lastIndexOf('}') + 1

  const resultado = JSON.parse(texto.slice(i, f))

  

  return {

    artefato: artefato.nome,

    versao: artefato.versao_atual,

    ...resultado,

    data_verificacao: new Date().toISOString(),

  }

}

Aprofundamento Técnico

Rastreabilidade: Requisito → Código → Teste

function gerarMatrizRastreabilidade(requisitos, tasks, testes) {

  return requisitos.map(req => ({

    requisito: req.id,

    descricao: req.titulo,

    tasks_relacionadas: tasks.filter(t => t.requisito_id === req.id).map(t => t.id),

    testes_relacionados: testes.filter(t => t.requisito_id === req.id).map(t => t.id),

    cobertura: testes.some(t => t.requisito_id === req.id) ? 'testado' : 'sem_teste',

  }))

}

Requisitos sem task = não implementado. Requisitos sem teste = risco de regressão.

Hash para Integridade

// Hash simples para detectar modificações não registradas

const hash = Buffer.from(conteudo).toString('base64').slice(0, 8)

// Verificação posterior:

const hash_atual = Buffer.from(artefato_em_disco).toString('base64').slice(0, 8)

if (hash_atual !== versao.hash) console.error('⚠️ Artefato modificado fora do sistema de versão!')

Exemplos Anotados

Exemplo 1: PRD com 3 Versões

let prd = { nome: 'PRD-001', tipo: 'requisito', versoes: [] }



prd = await versionarArtefato(prd, 'v1: Usuário pode fazer login com email', client)

// → versao 1: changelog "Criação inicial"



prd = await versionarArtefato(prd, 'v2: Usuário pode fazer login com email ou Google', client)

// → versao 2: changelog "• Adicionado suporte a login com Google OAuth"



prd = await versionarArtefato(prd, 'v3: Usuário pode fazer login com email, Google ou Apple', client)

// → versao 3: changelog "• Adicionado suporte a login com Apple Sign In"



// Auditoria

prd.versoes.forEach(v =>

  console.log(`v${v.numero} (${v.timestamp.split('T')[0]}): ${v.changelog}`)

)

Padrões e Armadilhas

Padrões

Padrão 1: Versionar antes de editar Nunca sobrescreva o conteúdo sem criar nova versão. O histórico é o único audit trail.

Padrão 2: Critérios de conformidade por tipo de artefato

const CRITERIOS = {

  prd: ['Define o problema do usuário', 'Tem critérios de aceite', 'Inclui métricas de sucesso'],

  spec_tecnica: ['Descreve a arquitetura', 'Lista APIs', 'Inclui diagramas'],

  plano_teste: ['Cobre casos de sucesso', 'Cobre casos de falha', 'Define ambiente de teste'],

}

Armadilhas

⚠️ Armadilha 1: Changelog gerado por LLM pode ser vago “• Atualizado conteúdo” — sem valor. Instrua: “Seja específico: o que exatamente mudou, não que algo mudou.”

⚠️ Armadilha 2: Versionar sem autor

const nova_versao = {

  // ...

  autor: req.user || process.env.USER || 'sistema',

}
⚗ Laboratório prático — mozak.tech
Se não for realizar o laboratório, pule para o próximo capítulo.

Ponte para o Lab

TODO 1 — versionarArtefato(artefato, conteudoNovo, client): compare com versão anterior via LLM, gere changelog, adicione nova versão ao array versoes.

TODO 2 — verificarConformidade(artefato, criterios, client): passe conteúdo e critérios para LLM, peça JSON com resultados[] e campo aprovado.

Agora você está pronto para o lab.