mozak.tech Engenharia de IA Corporativa 63%

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

4.1 — Definição e Decomposição de Escopo com Suporte de IA (Escopo + IA)

Objetivo da Aula

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

Calcular RICE score para priorizar user stories com múltiplos critérios

Implementar decomposição automática de user story em tasks técnicas via LLM

Usar LLM para identificar ambiguidades em requisitos antes de estimar

Completar os 2 TODOs do starter: calcularRICE e decomporEmTasks

Aplicar o framework RICE em situações onde critérios são incompletos

Por que isso importa

PMs e tech leads gastam horas discutindo priorização sem critérios objetivos. RICE (Reach, Impact, Confidence, Effort) transforma opiniões subjetivas em números comparáveis — e LLMs podem preencher gaps quando o PM não tem dados precisos.

Decomposição de user story em tasks é onde estimativas erram: “Adicionar login com Google” parece 1 sprint mas esconde 8 tasks (OAuth config, callback handler, session, testes, mobile, error states, etc.). LLMs que conhecem o stack identificam essas tasks ocultas.

Conceitos Fundamentais

Fundamento: Frameworks de PM para Arquitetos

RICE prioriza por Reach (quantos usuários impacta) × Impact (intensidade) × Confidence (certeza) / Effort (esforço). WSJF (SAFe) adiciona urgência temporal: Cost of Delay / Duration — uma feature que perde valor rápido tem prioridade maior mesmo com RICE similar. MoSCoW classifica por Must/Should/Could/Won't — define o escopo mínimo viável. O cone de incerteza formaliza que estimativas iniciais podem errar por fator de 4× para cima ou para baixo — o único jeito de reduzir o cone é dividir em entregas menores e aprender com cada uma. Estimativa como distribuição de probabilidade (intervalo de confiança) é mais honesta que número único: "2 a 4 sprints com 80% de confiança" comunica melhor risco do que "3 sprints".

Framework RICE

RICE = (Reach × Impact × Confidence) / Effort



- Reach: quantos usuários afeta por mês? (número)

- Impact: o quanto melhora para eles? (0.25=mínimo, 0.5=baixo, 1=médio, 2=alto, 3=massivo)

- Confidence: confiança na estimativa? (0-100%)

- Effort: pessoas×mês para completar

RICE mais alto = prioridade mais alta

TODO 1: calcularRICE(historia)

function calcularRICE(historia) {

  const { reach, impact, confidence, effort } = historia

  

  if (!reach || !impact || !confidence || !effort) {

    return null  // dados insuficientes para calcular

  }

  

  const rice = (reach * impact * (confidence / 100)) / effort

  

  return {

    ...historia,

    rice_score: Math.round(rice * 10) / 10,

    interpretacao: rice > 100 ? 'alta prioridade' : rice > 50 ? 'média prioridade' : 'baixa prioridade',

  }

}

Exemplos:

calcularRICE({ reach: 1000, impact: 2, confidence: 80, effort: 2 })

// → rice_score: 800  ← alta prioridade



calcularRICE({ reach: 100, impact: 1, confidence: 60, effort: 3 })

// → rice_score: 20  ← baixa prioridade

TODO 2: decomporEmTasks(historia) via LLM

async function decomporEmTasks(historia, client) {

  const response = await client.messages.create({

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

    max_tokens: 600,

    system: `Você é um tech lead experiente. Decomponha user stories em tasks técnicas específicas.

Para cada task, estime: nome, descrição, dias_estimados, tipo (backend/frontend/infra/teste/docs).

Retorne JSON: {"tasks": [{...}, ...]}`,

    messages: [{

      role: 'user',

      content: `User Story: ${historia.titulo}\nDescrição: ${historia.descricao || ''}\nStack: ${historia.stack || 'Node.js, React'}`,

    }],

  })

  

  const texto = response.content[0].text

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

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

  

  const total_dias = parsed.tasks.reduce((acc, t) => acc + (t.dias_estimados || 1), 0)

  return { ...parsed, total_dias, confianca_estimativa: total_dias < 5 ? 'alta' : 'media' }

}

Aprofundamento Técnico

Quando RICE Falha

Impact subjetivo: “massivo” para o VP de vendas é “médio” para o time de produto. Calibre Impact com dados históricos: quais features com Impact=2 geraram +X% de engajamento?

Confidence superestimado: Times iniciantes colocam 80-90% em tudo. Use regra: se não fez antes = 50%, se fez uma vez = 70%, se fez muitas vezes = 90%.

Effort subestimado: O LLM identifica tasks esquecidas. Regra de Hofstadter: sempre leva mais tempo do que você espera, mesmo quando você leva em conta a Lei de Hofstadter.

Identificação de Ambiguidades com LLM

async function identificarAmbiguidades(historia, client) {

  const response = await client.messages.create({

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

    max_tokens: 400,

    messages: [{

      role: 'user',

      content: `Analise esta user story e identifique:

1. Ambiguidades que precisam de resposta do PM antes de estimar

2. Casos extremos não cobertos

3. Dependências com outros times/sistemas



User Story: "${historia.titulo}"

Critérios de aceite: ${historia.criterios_aceite?.join('; ') || 'não especificados'}`,

    }],

  })

  return response.content[0].text

}

Exemplos Anotados

Exemplo 1: RICE Scoring Completo

const historias = [

  { titulo: 'Login com Google', reach: 5000, impact: 2, confidence: 80, effort: 3 },

  { titulo: 'Dashboard analytics', reach: 200, impact: 3, confidence: 60, effort: 5 },

  { titulo: 'Dark mode', reach: 8000, impact: 0.5, confidence: 95, effort: 1 },

]



const scored = historias.map(calcularRICE).sort((a, b) => b.rice_score - a.rice_score)

// → Dark mode: RICE 3800 (alta prioridade)

// → Login com Google: RICE 2667 (alta prioridade)

// → Dashboard analytics: RICE 72 (média prioridade)

Exemplo 2: Decomposição de “Login com Google”

User Story: "Como usuário, quero fazer login com Google para não criar senha"



Tasks geradas pelo LLM:

1. Configurar OAuth 2.0 no Google Cloud Console [infra, 1 dia]

2. Implementar endpoint /auth/google/callback [backend, 2 dias]

3. Criar sessão JWT após autenticação [backend, 1 dia]

4. Componente botão "Continuar com Google" [frontend, 0.5 dia]

5. Tratamento de erro (conta bloqueada, email já cadastrado) [backend, 1 dia]

6. Testes de integração OAuth [teste, 1 dia]

7. Docs de configuração para dev local [docs, 0.5 dia]



Total: 7 dias (estimativa alta confiança: 1.5 sprints)

Padrões e Armadilhas

Padrões

Padrão 1: RICE relativo, não absoluto RICE 2667 não significa nada sozinho. Significa “3.7x mais prioritário que Dashboard analytics (RICE 720)”. Compare sempre dentro do mesmo backlog.

Padrão 2: Decomposição com stack explícito

// Inclua o stack para tasks mais específicas

`Stack: Next.js 14, Prisma, PostgreSQL, AWS S3`

// → LLM gera tasks de migração de schema Prisma, não genérico "database migration"

Padrão 3: Confidence inversamente proporcional à novidade Feature nova para a empresa = Confidence 50%. Feature similar já feita = 80%.

Armadilhas

⚠️ Armadilha 1: Impact igual para tudo

// Se todas as historias têm Impact=2, RICE não diferencia

// Calibre: "Qual é a feature de maior impacto que já entregamos?" → Impact=3

// Calibre: "Qual teve menos impacto?" → Impact=0.5

⚠️ Armadilha 2: LLM decompõe sem conhecer dependências

LLM: "Task: implementar SSO com Okta [2 dias]"

Realidade: Okta não está configurado — precisa de 2 sprints de infra antes

Sempre revisar com quem conhece o ambiente.

⚠️ Armadilha 3: JSON malformado do LLM

try {

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

  return parsed

} catch {

  return { tasks: [], erro: 'LLM retornou JSON inválido' }

}
⚗ 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

2 TODOs no starter.js:

TODO 1 — calcularRICE(historia):

function calcularRICE(historia) {

  const { reach, impact, confidence, effort } = historia

  const rice = (reach * impact * (confidence / 100)) / effort

  return { ...historia, rice_score: Math.round(rice * 10) / 10 }

}

TODO 2 — decomporEmTasks(historia, client): Use client.messages.create com system prompt instruindo JSON de tasks. Extraia com texto.indexOf('{') e texto.lastIndexOf('}').

Rode com node starter.js e observe as histórias rankeadas por RICE e dekompostas em tasks.

Agora você está pronto para o lab.