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',
}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.