Inconsistências do protótipo dc-runtime replicadas por fidelidade

TLDR: sete comportamentos do protótipo original foram replicados no app React para manter paridade visual, mas não são regra de negócio — são mock, simplificação ou bug. Este é o registro para que nenhum deles vire requisito por engano.

O que aconteceu

Ao portar Sistema de Cobrança.dc.html e Ficha Unificada.dc.html para o app React, encontramos comportamentos do protótipo que foram replicados propositalmente — mas que, se lidos como especificação, produziriam requisitos falsos.

# Quirk Natureza Ação futura
1 Quatro valores do Painel são strings fixas Mock Precisam de fonte de dados real
2 “Cléber Santana Farias” duplicado entre Negativação e Clientes Duas fontes de verdade Unificar a fonte, não replicar
3 pgDupForma/avForma não afetam o pagamento gerado Simplificação Mudança de escopo, não correção de bug
4 vencBase indefinida em emitir() Bug do protótipo Corrigir ao portar a Ficha Unificada
5 Roster do Detalhe do lote não reflete o total do lote Limitação de mock Aceito como amostra
6 Ordem de mutação ao compor duas escritas no mesmo Context Bug nosso, já corrigido Regra prática registrada abaixo
7 jcDica (Jurídico) não tem caso especial por id Divergência real entre telas Não copiar o padrão ao portar a Ficha Unificada

1. Valores estáticos não computados (Painel)

No Painel, os seguintes valores são strings fixas no protótipo original, não derivadas dos filtros de período/atendente:

  • KPI “Reincidência”: sempre 47,7% (REINCIDENCIA_PAINEL em hooks/painel/painel.constants.ts).
  • “Casos ativos”: 6.442 quando “todos” e ~2.147 para um atendente específico (CASOS_ATIVOS_TODOS / CASOS_ATIVOS_UM_ATENDENTE).
  • “Tempo médio de resposta” quando “todos”: sempre 8 min (TEMPO_MEDIO_TODOS), mesmo variando o período.
  • Régua de disparos → “Respostas até agora”: sempre 893 (29,6%) (RESPOSTAS_ATE_AGORA em mocks/painel.ts).

Quando o back-end real existir, esses quatro números precisam de uma fonte de dados própria — hoje são apenas mocks fixos, não cálculos.

2. Dado duplicado entre Negativação e Clientes

No protótipo original, a tela Negativação tem um item “Remoções pendentes” com o nome “Cléber Santana Farias” hardcoded diretamente no template, enquanto o mesmo cliente já existe (com os mesmos dados) no array clientes usado pela tela Clientes. São duas fontes de verdade para a mesma pessoa. Replicado assim na Fase 2 por fidelidade (mocks/negativacao.ts tem seu próprio REMOCAO_PENDENTE_INICIAL com o nome fixo, independente de mocks/clientes.ts) — não é uma junção real de dados, só coincide o nome.

Se algum dia isso virar um problema real (ex.: editar o cliente em Clientes não reflete em Negativação), a correção é unificar a fonte, não replicar a duplicação para novas telas.

3. pgDupForma/avForma existem na UI mas não afetam o pagamento gerado

Tanto o painel “Duplicar pagamento” (Pagamentos) quanto o formulário de “Pagamento avulso” (Detalhe do cliente) têm um seletor de forma de pagamento (Boleto/Pix, Cartão de crédito, etc.), mas no protótipo original nenhuma das duas funções de geração (pgDupGerar/avGerar) lê esse valor — o pagamento gerado não registra a forma escolhida.

Replicado assim (useDuplicarPagamento.forma e usePagamentoAvulso.forma existem como estado selecionável, mas não entram na função gerar()). Se a forma de pagamento precisar afetar o registro gerado, é uma mudança de escopo, não uma correção de bug.

4. Bug: vencBase indefinida em unified_record.dc.html

Na função emitir() do simulador de acordo (aba Financeiro → “Simular acordo”), o protótipo referencia vencBase[s.simVenc], mas vencBase não é definida em nenhum lugar do arquivo (não é state, prop nem constante local). Isso quebra em tempo de execução no protótipo original ao clicar em “Emitir acordo”.

Ao portar a Ficha Unificada (fase futura), essa lógica precisa ser corrigida — o valor provavelmente deveria vir de s.simVencData (a data de vencimento já escolhida no formulário), não de um array vencBase inexistente.

5. Roster sintético do Detalhe do lote não reflete o total do lote

loteDetalhes no protótipo gera sempre os mesmos 23 alunos sintéticos (NOMES_LOTE) para qualquer lote, embora o texto de meta do lote diga “2.987 alunos” ou “3.102 alunos”. Ou seja, o Detalhe do lote é uma amostra representativa, não a lista completa. Replicado assim intencionalmente (não é um bug, é uma limitação de protótipo/mock) em hooks/loteDetalhe/buildLotesDetalhe.ts.

6. Ordem importa ao compor duas mutações no mesmo Context

Este é um aprendizado nosso, não do protótipo. Ao implementar useDuplicarPagamento.gerar(), a primeira versão chamava adicionarPagamento(novo) (prepend) antes de atualizarStatus(idxOriginal, ...). Como adicionarPagamento desloca todos os índices em +1, a segunda chamada acabava marcando o pagamento recém-criado como regerado em vez do original.

O teste useDuplicarPagamento.test.tsx pegou isso antes de chegar em produção.

7. jcDica (Jurídico) não tem caso especial por id

Na tela Jurídico do arquivo principal, o texto de dica das ações (jcDica) depende só do status do caso (hooks/juridico/juridico.constants.ts → DICA_POR_STATUS), igual para qualquer caso naquele status. Isso é diferente do statusDica da Ficha Unificada (arquivo separado, ainda não portado), que tem um caso especial hardcoded para c.id === 'c2'.

São mecanismos parecidos (texto de ajuda contextual por status) em telas diferentes, com regras diferentes.

Causa raiz

O protótipo dc-runtime foi construído para demonstrar as telas, não para especificar o sistema. Números foram escritos à mão para parecerem plausíveis numa demo; dados foram duplicados onde duplicar era mais rápido que referenciar; e nada foi executado a ponto de o bug de vencBase aparecer. Nenhuma dessas escolhas está sinalizada no arquivo — do ponto de vista de quem lê o protótipo como fonte de requisito, um mock fixo e um cálculo real são indistinguíveis.

O risco concreto é de mão dupla: portar um mock como se fosse regra (congelando 47,7% no back-end), ou portar um bug como se fosse comportamento esperado.

Correção

Cada quirk foi replicado deliberadamente no port, para preservar paridade visual, e registrado aqui com a sua natureza explícita. As specs de back-end que tocam essas áreas já citam este documento e definem o comportamento real:

Quirk Onde o comportamento real é definido
1 — valores fixos do Painel USER-020 — Painel de KPIs, USER-017 — Régua de disparos
2 — Cléber duplicado USER-013 — Ficha unificada, USER-019 — Negativação (front)
3 — forma de pagamento ignorada USER-015 — Motor de negociação
4 — vencBase USER-015 — Motor de negociação: venc_primeira vem da regra (RN-REPARC-3)
6 — ordem de mutação USER-016 — Pagamentos (front)

Sobre o quirk 6, a regra prática que ficou: ao compor duas mutações de array no mesmo Context em que uma referencia um índice e a outra insere/remove itens, aplique primeiro a mutação que depende do índice antigo, depois a que muda o tamanho do array.

Como evitar

  • Protótipo não é spec. Ao portar uma tela, todo número que não é derivado de um input visível é suspeito de ser mock — confirmar antes de tratá-lo como cálculo.
  • Ao encontrar um quirk novo durante um port, registrar aqui na mesma entrega, com a natureza classificada (mock / simplificação / bug do protótipo / bug nosso). Foi o que as specs das Fases 2 e 3 exigiram explicitamente.
  • Ao portar a Ficha Unificada, reabrir o arquivo original: dois quirks (4 e 7) dependem dele e não podem ser inferidos do arquivo principal.