mirror of
https://github.com/melgarafael/DeskcommCRM.git
synced 2026-10-02 01:28:34 +08:00
Ondas 4 e 5, que fecham o conserto: o controle da tela passa a valer, o sistema paralelo morto sai, e um bloqueio deixa de abandonar o lead. `DESKCOMM_GOV_INVARIANTS_EDIT=1` — dois invariantes MODIFICADOS, e a razão: `vocabulario-banco-x-typescript` ganhou o par `ModoDeOrcamento` (coluna nova com CHECK precisa de par no TypeScript, senão o job `invariants` reprova), e `orcamento-apos-backfill` acompanhou a mudança do piso. O invariante NOVO (`orcamento-nasce-desarmado`) não precisa da flag. ## Os três achados que valeram mais que a feature **1. A escolta era inalcançável no caso dominante.** `classifyStage` roda em todo turno e estourava ANTES da escolta — que, portanto, nunca protegia o caminho normal. Movida para `runAgentTurn`, que envolve o turno inteiro. A guarda antiga contava `runModelCall(` no texto e era cega para helpers; agora conta call sites e a fronteira dos auxiliares. **2. A escada era contornável pela REST do Supabase** (migration 0160). O PATCH exige `off → avisar → bloquear`, mas `ai_budgets` aceitava escrita direta de `authenticated` — qualquer cliente com a anon key pulava a escada e armava bloqueio imediato. `revoke insert/update/delete`, SELECT fica. **3. O texto mandava clicar num botão que não existe.** A mensagem que o cliente lê quando a IA para dizia "Retomar atendimento automático"; o componente renderiza **"Devolver ao automático"**. Corrigido em 7 arquivos, e a guarda nova **lê o rótulo do componente** em vez de guardar uma cópia — cópia de rótulo é a próxima mentira esperando envelhecer. ## O dropdown decorativo saiu "Ação ao atingir 100%" oferecia "Pausar" vs "Desabilitar" e o produto entregava sempre a mesma coisa. Era o defeito que este trabalho existe para matar, sobrevivendo dentro do conserto — um juiz reprovou um desenho inteiro por mantê-lo. Ou entrega os dois futuros, ou sai. Saiu. ## O lead não fica mais no vácuo Quando o orçamento barra, o turno vai para `performHumanHandoff` com contexto, e o job é **cancelado** (`cancelJob`), não falhado com retry: repetir uma chamada que o teto recusa é gastar de novo para receber a mesma recusa. O caminho legado ganhou o mesmo veto — e depois dos gates que reconhecem "quero falar com um atendente", não antes, senão pedir humano viraria silêncio. ## Sabotagem: 10 previsões, 10 acertos escolta fora do turno 3×3 · piso só para bloquear 3×3 · não zerar a carência 2×2 · veto antes dos gates 1×1 · sem handoff 1×1 · ressalva de medição sumida 1×1 · rótulo do período revertido 2×2 · flag de gasto incompleto fixa 1×1 · janela do mês removida 1×1 · botão renomeado 3×3. ## Uma discordância mantida, com evidência O KPI de plataforma fica na coluna acumulada. A alternativa barata seria um `group by` inline — a segunda régua de gasto que `orcamento-uma-regua-de-gasto` existe para impedir, e o gate provou o ponto reprovando o próprio comentário do implementador quando ele escreveu a query em PROSA. Mitigado: nunca `critical`, rótulo "acumulado", divergência escrita no arquivo e link para a tela que tem a régua certa. ## Bateria typecheck 0 · lint 0 erros · lint:channels 0 · test:shell 0 · build 0 · test:unit **3347 passam**, 1 falha — a baseline do `.env.local` deste worktree, que não cita orçamento, budget, handoff nem money. ## NÃO MEDIDO, declarado - `tests/invariants/orcamento-nasce-desarmado.test.ts` é **novo e nunca foi executado** (15 casos, e é a primeira vez que `SQL_ORCAMENTO` roda contra Postgres em todo o repo). É o maior risco de CI vermelho desta entrega, e está escrito aqui porque dívida declarada não é defeito — dívida presumida é. - O `revoke` da 0160 não foi provado contra PostgREST vivo: o achado veio de leitura de grants. - **DoD 12 (prova pela tela): NÃO MEDIDO.** Radio, kill switch e badge estão provados por unidade em jsdom e por `build`, não por browser em ambiente fresco estilo VPS. - `test:db`, `e2e` e `build-and-size`: quem prova é o CI. Nota de release em `docs/release/teto-de-orcamento.md`; mapa vivo em `docs/architecture/teto-de-orcamento.architecture.json` (26 nós, 43 arestas). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TCiffR3ugjQbxsfceQE2GB