# Dimensionamento e mudanças pós-aprovação

## Conteúdo

- Sizing — tiers, nunca horas
- Mudanças pós-aprovação — extensão grátis vs novo ciclo

## Sizing — tiers, nunca horas

Não existe benchmark público de "horas por widget"; qualquer número assim seria
inventado. O documento carrega **T-shirt sizes (S/M/L/XL)** derivados
deterministicamente das respostas da entrevista — o tier sai da tabela, não do
achismo, o que o torna defensável quando o cliente questiona. Converter tier em
dias/preço é decisão comercial de quem entrega (com calibração interna própria), nunca da skill.

Escala interna: S=1 · M=3 · L=5 · XL=8 (Fibonacci curto, só para somar inventário).

| Componente | Base | Modificadores |
|---|---|---|
| Flow (ETL) | Total=S · Temporal=M · Incremental=L | +1 tier: querySpec avançado (dedupe, windowColumns, filtros OR múltiplos); +1: ≥2 fontes/joins; API/HTTP paginada: base M |
| Tabela DW | dimensão conformada REUSADA=S (só relationship) · dimensão nova=M · fato=M | fato: +1 tier se ≥5 relacionamentos (ver linha Relationship abaixo) |
| Relationship (religação) | S por par fato↔dimensão | dashboard NOVO que reusa um par já existente ainda religa — custo por app, não por par (`limites-horus.md`); relationships não vivem em tabela |
| SCD2 (build manual) | L | não é feature nativa — surrogate key + fechamento de versão no ETL; tier PRÓPRIO, não modificador de +1 na dimensão |
| Expression/métrica | SUM/COUNT simples=S · razão/derivada=M · agregação filtrada=M · time-intelligence (YoY/YTD, `${}`)=L · paramétrica encadeada=XL | |
| Widget | Kpi=S · gráfico nativo=M · Table=M · Matrix=L · **Svelte custom=XL sempre** | +1 tier: cross-filter/drill além do padrão |
| Dashboard (montagem+validação) | M por tela (≤9 widgets) | +1 tier: público analista (denso) |

Regras:
- **Confirmação de lineage decide faixa vs comprometido**: componente com profiling
  validado entra no cronograma-faixa da fase; componente `a-perguntar` entra como
  "T-shirt bruto, a refinar no Marco N" (rolling wave) — nunca finja precisão.
- **Fechamento de fase recalibra, não só confirma escopo** (Hughes/current
  estimate): ao fechar cada fase, some os tiers efetivamente entregues (mesma
  escala S/M/L/XL, nunca hora) e compare com os comprometidos. Desvio relevante
  (>~20%, calibrável) ajusta a FAIXA da fase seguinte ANTES de comprometê-la —
  e o cliente é avisado do desvio na mesma mensagem, nunca só no fim. Registra
  em `log.md` como MINOR (reforecast com o mesmo escopo, sem nova assinatura).
- **Fases no PDF, por FATIA vertical de valor** (Collier): 1 fatia = 1 linha do
  bus matrix completa (tabelas + flow + dashboard dela), maior `prioridade`
  declarada em projeto.md primeiro (campo obrigatório quando há >1 dashboard).
  Fundação inteira antes do 1º dashboard rodar é exatamente o padrão que a
  fatia evita — o cliente vê dado real cedo. Faixa por fatia, **nunca data
  única**, nunca horas.
- **Trade-off quantificado na negociação**: pedido que sobe tier (Incremental em
  vez de Total, Svelte em vez de nativo) gera automaticamente a frase para
  `fora-de-escopo.md`: "X fica fora desta fase — adicionaria ~N tiers vs a opção
  padrão Y". Preço em esforço filtra pedido casual.
- **Discovery é orçado, não infinito**: registre em `log.md`, ainda na Fase 0,
  o nº de rodadas previsto para o discovery. Prospect estourando as rodadas
  previstas sem sinal de assinatura próxima → gate comercial (discovery vira
  etapa paga), nunca decisão silenciosa do analista.

## Mudanças pós-aprovação — extensão grátis vs novo ciclo

Versionamento do escopo: **MAJOR.MINOR** no `log.md` do bundle (append-only, nunca
reescrever versão aprovada). MINOR = extensão grátis (addendum, "ciente" leve do
cliente). MAJOR = novo ciclo formal (muda esforço/prazo/grain → nova aprovação
assinada ANTES de tocar o workspace). Na aprovação de cada versão: `git tag
scope-vX.Y` no workspace — é o único mecanismo de "o que mudou desde a aprovação"
(`git diff scope-v1.0 HEAD -- flows/ tables/ apps/`).

### Árvore de decisão (primeira regra que bater decide)

0. Recursos-alvo ainda em draft, pré-corte? → ajuste de pré-produção; só logar.
1. Só cosmético (label, mask, descrição, layout de widget, expression nova usando
   colunas já existentes)? → **grátis**, nota leve no log — EXCETO edição de
   `formula_lumo`/inclusões/exclusões de métrica já `status: validado` (item 1b:
   isso NUNCA é cosmético, mesmo sem tocar grain).
1b. Edição de `formula_lumo`, inclusões ou exclusões de métrica já `validado`?
   → **MINOR sempre** (nunca grátis) — abre bloco `historico_formula: {data,
   formula_anterior, motivo, impacto_retroativo}` no card. Pedido de reversão
   chegando por canal ASSÍNCRONO (e-mail, chat, ticket — sem call) exige
   reafirmar por escrito a evidência que invalida a fórmula atual ANTES de
   aplicar a reversão, nunca só porque "pediram".
2. Aditivo dentro das "grace extensions" Kimball — novo fato consistente com o
   grain, nova dimensão via nova FK, novo atributo em dimensão existente, grain
   mais atômico preservando nomes — E não toca `key_type`/`key_columns`/
   `partition_column`? → **MINOR/addendum**, sem assinatura.
3. Remove/renomeia/retipa coluna usada por app/widget/expression existente? →
   **novo ciclo (MAJOR)** mesmo sem mudar grain — quebra resultado existente.
4. Muda `key_type`/`key_columns`/`partition_column` de tabela publicada com dados
   (= mudança de grain)? → **MAJOR sempre** + aviso cirúrgico abaixo.
5. Novo processo de negócio / fato não conformado (novo flow, credential, dashboard)?
   → **novo ciclo** — gate comercial (esforço), mesmo sendo tecnicamente seguro.

Classifique TAMBÉM iniciativa própria do time ("seria legal adicionar X") — gold
plating é overdelivery igual; passa pela mesma árvore.

**Troca de aprovador ou inatividade prolongada pausa execução:** troca do
aprovador NOMEADO em `projeto.md`, ou um período longo sem nenhuma atividade
no projeto, pausa a execução até reafirmação por escrito do escopo vigente —
nunca presuma que o sucessor herda silenciosamente o aceite do antecessor.

**Teto cumulativo de MINORs:** quando a soma dos MINORs aprovados (em tiers)
ultrapassa ~15-20% do inventário tier original, dispare um checkpoint MAJOR de
reconciliação — cada MINOR isolado pode ter sido grátis/leve, a SOMA não é.

**Regressão antes de fechar qualquer branch:** antes de marcar a mudança
(grátis/MINOR/MAJOR) como fechada em `log.md`, rerode os itens de `aceite.md`
que tocam o componente alterado e anexe o resultado ao log — sem regressão
anexada, a mudança não fecha. Ao reprocessar dado (reload, correção de
fórmula, mudança de load type), rerode o aceite TAMBÉM contra um período JÁ
assinado anteriormente e compare com o histórico registrado — divergência
bloqueia o fechamento, mesmo que o período novo passe sozinho.

### Mudança de grain — aviso cirúrgico

Criar tabela DW em cima de hipótese de grão (ainda sem profiling validado) é
**permitido** — a Regra 1 não bloqueia a construção por causa disso. O aviso é
cirúrgico, não um bloqueio: confirmar o grain ANTES de criar evita um
retrabalho caro, porque no Lumo o schema de uma tabela DW congela na criação —
ajustar grain depois é sempre drop + recreate + reload, com perda dos dados já
carregados. Avise nisso; seguir com a hipótese registrada ou esperar a
confirmação é decisão do analista/dono, não automática.

Se a decisão for mudar o grain de uma tabela **já publicada com dados**,
registre no log, antes de aplicar:
1. Aprovação MAJOR assinada, com esforço incluindo reprocessamento histórico e
   revalidação de cada app afetado.
2. Confirmação de que os dados serão **reconstruídos do zero da fonte** (no Lumo
   é sempre drop+create+reload) e de que **a fonte ainda retém o histórico
   necessário** — checar ANTES (fontes com purga/lookback curto = perda
   irrecuperável).
3. Blast-radius anexado: saída real de `app change-table --dry-run` / relatório
   `affected:` do publish — nunca estimativa manual.

Sequência segura é sempre blue-green (mudança no clone/draft, validar completo,
só então publish-replace) — o momento destrutivo nunca acontece primeiro no
recurso publicado.
