Objetivo da Aula
Ao concluir esta aula, você será capaz de:
Implementar análise what-if para cenários adversos (dev saindo, feature maior que estimado)
Implementar balanceamento automático de carga quando dev tem >120% da carga média
Calcular caminho crítico em dependências de tasks
Completar os 2 TODOs: analisarWhatIf e balancearCarga
Usar LLM para sugestões de paralelização de tasks
Por que isso importa
Cronogramas falham por dois motivos: estimativas erradas (endereçado por RICE/WSJF) e eventos imprevistos. What-if automático responde “e se um dev sair no meio do sprint?” sem horas de reunião de replanejamento.
Balanceamento de carga é onde gerentes de projeto gastam mais tempo manualmente: João está em 150%, Maria em 80%. LLM pode sugerir redistribuição em segundos.
Conceitos Fundamentais
TODO 1: analisarWhatIf(cenario, sprint, client)
async function analisarWhatIf(cenario, sprint, client) {
// cenarios: 'dev_saiu', 'feature_maior', 'bug_critico', 'dependencia_atrasou'
const contextoSprint = {
tasks_pendentes: sprint.tasks.filter(t => t.status !== 'done').length,
dias_restantes: sprint.dias_restantes,
capacidade_total: sprint.devs.reduce((acc, d) => acc + d.horas_disponiveis, 0),
}
const response = await client.messages.create({
model: 'claude-haiku-4-5-20251001',
max_tokens: 500,
system: 'Você é um scrum master experiente. Analise o impacto do cenário e sugira ações de mitigação.',
messages: [{
role: 'user',
content: `Cenário: ${cenario}
Estado atual do sprint:
${JSON.stringify(contextoSprint, null, 2)}
Forneça:
1. Impacto estimado no prazo (dias de atraso)
2. Tarefas que devem ser descartadas do sprint se necessário (por prioridade)
3. Ações imediatas de mitigação (top 3)
4. Comunicação sugerida para stakeholders`,
}],
})
return response.content[0].text
}TODO 2: balancearCarga(sprint)
function balancearCarga(sprint) {
const devs = sprint.devs
// Calcular carga média
const total_pontos = sprint.tasks.reduce((acc, t) => acc + (t.pontos || 0), 0)
const media_por_dev = total_pontos / devs.length
const redistribuicoes = []
// Identificar devs sobrecarregados (>120% da média)
for (const dev of devs) {
const carga_dev = sprint.tasks
.filter(t => t.responsavel === dev.id)
.reduce((acc, t) => acc + (t.pontos || 0), 0)
const pct_carga = carga_dev / media_por_dev
if (pct_carga > 1.2) {
// Sobrecarregado: mover tasks menores para devs com menor carga
const tarefas_realocar = sprint.tasks
.filter(t => t.responsavel === dev.id && (t.pontos || 0) <= 2)
.slice(0, Math.ceil((pct_carga - 1.0) * media_por_dev / 2))
// Encontrar dev com menor carga
const dev_livres = devs
.filter(d => d.id !== dev.id)
.map(d => ({
dev: d,
carga: sprint.tasks.filter(t => t.responsavel === d.id).reduce((acc, t) => acc + (t.pontos || 0), 0),
}))
.sort((a, b) => a.carga - b.carga)
for (const tarefa of tarefas_realocar) {
const destino = dev_livres[0].dev
redistribuicoes.push({
task: tarefa.titulo,
de: dev.nome,
para: destino.nome,
pontos: tarefa.pontos,
})
}
}
}
return {
media_pontos_por_dev: Math.round(media_por_dev),
redistribuicoes,
sprint_balanceado: redistribuicoes.length > 0,
}
}Aprofundamento Técnico
Caminho Crítico
function calcularCaminhoCritico(tasks) {
// Tasks sem dependências começam em t=0
const sem_deps = tasks.filter(t => !t.dependencias || t.dependencias.length === 0)
// Para cada task, calcular o tempo mínimo de início
const tempo_inicio = {}
function calcularInicio(taskId) {
if (tempo_inicio[taskId] !== undefined) return tempo_inicio[taskId]
const task = tasks.find(t => t.id === taskId)
if (!task.dependencias || task.dependencias.length === 0) {
tempo_inicio[taskId] = 0
return 0
}
const max_dep = Math.max(...task.dependencias.map(depId =>
calcularInicio(depId) + (tasks.find(t => t.id === depId)?.duracao || 0)
))
tempo_inicio[taskId] = max_dep
return max_dep
}
tasks.forEach(t => calcularInicio(t.id))
// Caminho crítico = task com maior tempo_inicio + duracao
const critico = tasks.reduce((max, t) => {
const fim = (tempo_inicio[t.id] || 0) + (t.duracao || 0)
return fim > max.fim ? { task: t, fim } : max
}, { task: null, fim: 0 })
return { tempo_inicio, duracao_total: critico.fim, task_critica: critico.task }
}Exemplos Anotados
Exemplo 1: What-If Dev Saiu
Cenário: "dev_saiu" (Pedro saiu no meio do sprint)
Análise LLM:
1. Impacto: +5-7 dias de atraso (Pedro tinha 40% das tasks restantes)
2. Descartar: "Dark mode" (baixa prioridade), "Analytics refinements" (não comprometido)
3. Ações imediatas:
- Reatribuir tasks de Pedro por RICE (mais importantes primeiro)
- Comunicar PM sobre risco de data de entrega
- Verificar se alguma task pode ir para próximo sprint
4. Comunicação: "Sprint em risco por redução de 25% da capacidade..."Exemplo 2: Balanceamento
const sprint = {
devs: [
{ id: 'd1', nome: 'Ana', horas_disponiveis: 40 },
{ id: 'd2', nome: 'João', horas_disponiveis: 40 },
{ id: 'd3', nome: 'Maria', horas_disponiveis: 40 },
],
tasks: [
{ titulo: 'Auth', pontos: 8, responsavel: 'd1' },
{ titulo: 'Dashboard', pontos: 5, responsavel: 'd1' },
{ titulo: 'API', pontos: 3, responsavel: 'd1' }, // Ana: 16 pontos!
{ titulo: 'Testes', pontos: 5, responsavel: 'd2' }, // João: 5 pontos
{ titulo: 'Deploy', pontos: 3, responsavel: 'd3' }, // Maria: 3 pontos
]
}
balancearCarga(sprint)
// → redistribuicoes: [{task: 'API', de: 'Ana', para: 'Maria', pontos: 3}]
// Ana: 13, João: 5, Maria: 6 → mais balanceadoPadrões e Armadilhas
Padrões
Padrão 1: Threshold 120% configurável
const THRESHOLD_SOBRECARGA = process.env.THRESHOLD_CARGA || 1.2
if (pct_carga > THRESHOLD_SOBRECARGA) { ... }Padrão 2: What-if antes do sprint começar O melhor momento para análise what-if é no sprint planning, não quando o problema acontece.
Armadilhas
⚠️ Armadilha 1: Redistribuir tasks especializadas
// João é o único que conhece o sistema de pagamentos
// Redistribuir "Integrar gateway de pagamento" para Ana pode não funcionar
// Adicionar campo 'especialidade' nas tasks⚠️ Armadilha 2: LLM não conhece o contexto técnico
What-if: "feature_maior"
LLM sugere: "remova feature X e Y"
Realidade: X é bloqueante para Y e Z, que são committed para o clienteSempre revisar com o tech lead antes de aplicar sugestão de LLM.
Se não for realizar o laboratório, pule para o próximo capítulo.
Ponte para o Lab
TODO 1 — analisarWhatIf(cenario, sprint, client): Monte o contexto do sprint e passe para o LLM com estrutura clara de output (impacto, descartes, ações, comunicação).
TODO 2 — balancearCarga(sprint): Calcule média de pontos, identifique devs com >120%, mova tasks pequenas para devs com menor carga.
Agora você está pronto para o lab.