O lint recusava ler ref no render dos cartões de lembrete — e isso escondia a suíte unitária. A leitura de contacts.email estourava nos invariantes (cliente só com rpc) e o Meet nascia failed. O rótulo 'Quem será atendido' não apontava para o input com o id do contato.
O `tests/e2e/global-teardown.ts` deste PR IMPORTA
`scripts/cleanup-e2e-channel-sessions.ts`, e o Playwright transpila o teardown
para CommonJS — onde `import.meta` é erro de SINTAXE.
O sintoma no CI não é o teardown reprovar. Os testes passam:
134 passed (10.1m) · 2 skipped
SyntaxError: Cannot use 'import.meta' outside a module at global-teardown.ts:1
1 error was not a part of any test
##[error]Process completed with exit code 1
A rodada inteira sai vermelha DEPOIS de tudo passar, sob uma linha que não nomeia
teste nenhum — e a `e2e-parte (1)` reprova o agregador `e2e`.
A forma escolhida tem precedente medido neste repo: `scripts/cortar-release.ts`
usa `require.main === module` e é invocado por `tsx` em `release:conferir`, que
roda no CI. O `package.json` não declara `"type": "module"`, então o pacote é CJS.
Controle rodado nos dois ramos, sob `tsx`: executar o arquivo direto entra no if
("RAMO: CLI"); importá-lo não entra ("RAMO: importado").
NÃO PROVADO LOCALMENTE: o controle negativo NÃO reproduziu a falha — com
`import.meta` de volta, o `tsx` importa sem estourar. Quem quebra é o
transpilador do Playwright, e reproduzir isso exige uma rodada de Playwright.
A sonda local não distingue os dois estados, então ela não vale como prova.
Quem prova é o `e2e` do CI.
Crédito do PR: @joaopaulomirandamatias.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
O PR conserta um laço real: o processo morria antes de o handler devolver erro,
`attempts` não subia, e o evento envenenado tinha tentativas infinitas — 313
reinícios do worker em produção. A contagem na volta conserta isso.
O backoff junto da contagem, porém, colide com o invariante
`tests/invariants/event-log-drain.test.ts` caso 9, que afirma — com a razão
escrita lá — que o órfão volta para a fila E É PROCESSADO NO MESMO TIQUE. Com
`backoffAt(1)` = agora + 2 min, o evento sai do tique e o caso reprova.
Esta é a opção (A) que a triagem ofereceu a @Gervanno: o backoff entra a partir
da SEGUNDA volta (`preso.attempts >= 1`). O laço quebra igual — o envenenado
volta uma vez de graça e da segunda em diante paga 2, 4, 8… min até
`MAX_ATTEMPTS` —, e o órfão legítimo de deploy não passa a pagar espera.
A escolha entre (A) e (B) era do autor e ele não respondeu em dois dias, com um
P0 parado. Escolhi a (A) e a razão mudou desde o parecer: a (B) exigiria EDITAR
`tests/invariants/event-log-drain.test.ts`, e o caminho sancionado pelo hook de
congelamento é acrescentar arquivo, não editar (issue #1161). @Gervanno pode
vetar — é o desenho dele.
Guarda, em par, no arquivo de teste que já existia:
· primeira volta ⇒ `next_attempt_at` NULO (elegível no mesmo tique)
· segunda volta ⇒ `next_attempt_at` no futuro
O par importa: sem o segundo caso, trocar a condição por "nunca dar backoff"
passaria verde e traria os 313 reinícios de volta.
Crédito do PR: @Gervanno.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Conflito único, em `supabase/baseline.sql`: os dois lados acrescentaram bloco no
mesmo ponto de inserção — a 0277 (país da organização, desta branch) e a 0266
(transferência entre funis não é perda, que entrou na main pelo #1057).
Resolução: ficam os DOIS, em ordem de número — 0266 antes de 0277, e os dois
antes do bloco da VARREDURA anon, que segue sendo o último do arquivo.
Provado por md5, não por leitura:
bloco 0266 resolvido == bloco 0266 da main .......... df5a9869… idêntico
bloco 0277 resolvido == bloco 0277 do head anterior . 4397f359… idêntico
cabeçalho do bloco 0266 aparece 1x (as outras 2 ocorrências são os
comentários de filtro DENTRO de fn_atrito_metrics e fn_attendant_metrics)
ordem no arquivo: 0266 < 0277 < VARREDURA anon
DUAS válvulas de governança foram usadas, e as duas por disparo fora do objeto
do guard. Um merge IMPORTA o que a main já decidiu; ele não escolhe nem edita.
DESKCOMM_GOV_MIGRATION_EDIT=1 — o hook acusou colisão de 0276 entre a main e a
branch local `triagem/resgate-gyanu2507`. As duas migrations que este commit
encena (0266 e 0276) JÁ ESTÃO na main: `git cat-file -e origin/main:<arquivo>`
passa nas duas, com controle negativo num caminho inventado. Nenhum número foi
escolhido aqui. A colisão real é da branch local (main venceu o 0276).
DESKCOMM_GOV_INVARIANTS_EDIT=1 — o merge encena UM invariante,
`tests/invariants/automation-actions-crud.test.ts`, e ele é byte a byte igual
ao da main (md5 idêntico, controle: md5 de arquivo inexistente difere). A
versão veio do #1057, já mesclado. Nenhum invariante foi editado aqui.
Consequência que vale mais que este commit: com os dois hooks como estão, a
doutrina de higiene de branch ("atualize a branch com a main ANTES de trabalhar")
é impossível nesta máquina sempre que a main tiver tocado em migration ou
invariante. Reportado na issue #1161.
Crédito do PR: @webtecnica.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
O `gov-5d-queue-assign-unread` afirma a coerência ordem↔posição com a própria
cópia do ORDER BY (`last_inbound_at asc`) — a régua ANTERIOR à #990. Com a
régua deste PR (`awaiting_since`) ele segue VERDE afirmando uma pergunta que o
produto deixou de fazer, porque calcula a ordem em SQL e não consulta nada.
Ele é o eval congelado do épico de governança e não se edita
(`loop/hooks/freeze-invariants.sh` bloqueia M/D/R; acrescentar é permitido).
Então a proteção que faltava entra como arquivo NOVO, sem driblar a guarda.
Duas propriedades, e a segunda sustenta a primeira:
1. A coluna vem de `ORDEM_DA_ESPERA`, a mesma constante que o handler pede ao
banco e que numera a posição na tela. Ela não se reescreve aqui.
2. A fixture SEPARA `awaiting_since` de `last_inbound_at` e semeia o defeito da
#990 — a conversa mais antiga acabou de insistir. Com os dois campos iguais,
o caso passaria com qualquer uma das duas colunas: verde sem guardar nada. O
terceiro caso afirma que as duas réguas DIVERGEM nesta fixture, para que
igualá-las um dia reprove em vez de esvaziar o teste em silêncio.
Commit da triagem, não do autor — o parecer dizia "é a gente que encosta", e
isto não pode entrar antes deste PR porque a coluna nasce na 0267.
Crédito do PR: @webtecnica.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
O 'próximo livre' era calculado só em BASE ∪ HEAD: branch local de outra
sessão e head de outro PR aberto ocupavam número invisíveis ao conselho —
num único dia a 0275 nasceu em dois PRs e numa branch local (issue #1155).
Agora mede-se também refs/heads e refs/remotes, excluindo refs que resolvem
para o MESMO commit da base ou do HEAD (o alvo não mede a si mesmo). Quando
outra ref levanta o teto, a saída nomeia QUEM tem o número; onde não há
outras refs (clone raso do CI), a saída declara que não as mediu.
A cerca de `organizations` acusava escrita irregular num arquivo CORRETO
(PR #1017, `lib/ai/pontos/padrao-da-organizacao.ts`): ele faz
`p.admin.from("organizations").update(...)` com
`admin: ReturnType<typeof createAdminClient>` declarado no próprio arquivo, e
a cerca via "cliente `p`". Dois mecanismos, os dois medidos em origin/main:
`raizDaCadeia` devolve a RAIZ da cadeia e a propriedade se perde; e
`nomesDoClienteAdmin` só coleta cliente CRIADO no arquivo, então cliente que
chega por parâmetro nunca entra na conta.
Não era furo antigo: 21 arquivos já recebem o cliente por parâmetro e quatro
deles tocam `organizations`, mas todos os quatro só `.select()`. O #1017 é o
primeiro a MUTAR assim, e `MUTACOES` é o que esta cerca olha.
O reconhecimento é prova de TIPO, nunca de nome. Aceitar qualquer `x.admin`
seria trocar a prova por uma senha: bastaria batizar de `admin` um parâmetro
com o cliente de SESSÃO para escrever por baixo da cerca — e essa falha
devolve SUCESSO com zero linhas, então ninguém a descobre pelo sintoma. O que
autoriza é a anotação resolvida no arquivo em
`ReturnType<typeof <fábrica importada de lib/supabase/admin>>`, direto, por
`type` local, por membro de `interface`/tipo literal, ou por desestruturação.
Só PARÂMETRO entra. Variável anotada fica de fora de propósito: o cliente
criado no arquivo já é medido pela ORIGEM, e aceitar a anotação de uma
variável trocaria essa origem por uma promessa que um cast desfaz em silêncio.
`raizDaCadeia`, `ehClienteDeServico` e `passosDaCadeia` não mudam de
comportamento — `admin-client-exige-filtro-de-tenant.test.ts` mede o mesmo
conjunto de cadeias de antes (6/6 verde).
A sabotagem não ficou na minha sessão: dois CONTROLE novos alimentam a
varredura com fonte sintética e cobram as duas direções — as cinco formas
tipadas passam, e `admin` de sessão / `any` / sem anotação continuam
reprovados. Trocar a prova de tipo por prova de nome no helper deixa o
segundo vermelho.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Os outros dois PRs do mesmo contribuidor nesta rodada creditam no corpo do fragmento
("Credito: @joaopaulomirandamatias.") e este nao creditava — conferido nos tres:
#1042 credita, #1047 credita (commit 9d53141fb), #1051 nao.
Isto tambem TORNA VERDADEIRA a mensagem do commit 9d53141fb, que afirmava que "os outros
dois PRs do mesmo contribuidor nesta rodada creditam no corpo do fragmento". A afirmacao
estava falsa quanto a este PR, e reescrever a mensagem exigiria reescrever historico da
branch do autor, o que nao se faz. Consertar o mundo em vez do texto e o caminho certo aqui:
o credito no changelog e o que o projeto quer de qualquer forma.
Impacto segue `nada_mudou`: nenhuma frase nova sobre quem ja instalou.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Isto NÃO traz código: é o registro de proveniência para o GitHub fechar o #939 como
MERGED, no nome do autor, em vez de CLOSED — que para quem contribui lê como recusa.
Medido antes, arquivo por arquivo contra `origin/main`: dos 11 que o PR toca, **10 são
IDÊNTICOS** ao da main (incluindo `lib/leads/origem-do-site.ts`, `lib/channels/pos-entrada.ts`,
`lib/leads/nascimento-do-lead.ts` e os três testes). O único que diverge é
`lib/i18n/dicionario.ts`, o dicionário compartilhado que quase todo PR toca — divergência ali
é acúmulo de outras entradas, não trabalho dele que faltou.
O único commit fora da main na branch dele é o merge da main que ele próprio fez
(`9f3d85fc3`), não trabalho novo. Por isso `-s ours` aqui não descarta nada.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
O texto dizia que "o historico da regra mostra a mensagem do erro da consulta". Medido em
`origin/main`, isso nao acontece: `detail.erro` tem ZERO ocorrencias em
`app/app/webhooks/_components/ActivityTab.tsx`, e `membro_indeterminado` nao esta no mapa
`MOTIVO_DA_PARADA` (:73), cujo `explicacaoDe` (:95) devolve o codigo CRU quando a chave falta.
Ou seja: o operador le `membro_indeterminado`, nao a mensagem do erro.
O PR continua melhorando de verdade, e o texto novo diz exatamente isso: antes o historico
dizia que o responsavel escolhido estava FORA da organizacao — acusava a configuracao e mandava
mexer no que estava certo. Agora nao acusa. A frase amigavel na aba Atividade e outro trabalho,
que corre a parte (issue #1090).
Fragmento que promete tela inexistente vira changelog falso na mao de quem opera a VPS: ele
procura a mensagem do erro, nao acha, e conclui que a atualizacao nao pegou.
Autoria do conserto de codigo permanece com @webtecnica; este commit toca so o texto do fragmento.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
O mantenedor pediu o conserto das duas linhas "mais um caso que vermelhece se a
linha sair". O caso afirma as duas metades: a coluna `last_inbound_at` no
`select` da conversa e o `awaiting_since` no update da resposta — a régua que a
Fila usa para posição e para a média que o cliente ouve.
Os três consertos do review, todos com prova:
- O fio. `ler_rodada_do_banco` passa a imprimir as três chaves PLANAS e com os
nomes que a rota lê (`disputa_de_banco`, `retentativas_do_banco`,
`passada_do_banco`), e o `agent.sh` as manda no corpo do `run_result`. Antes
ele aninhava um objeto em `rodada_do_banco` com `disputa`/`retentativas`/
`passada`: o `z.object` descarta chave desconhecida em SILÊNCIO, os três campos
opcionais chegavam `undefined` e as colunas eram gravadas NULAS em toda rodada
— a tela ficava calada, que é exatamente o silêncio que este PR veio tirar.
Trava: caso em `route.test.ts` com o corpo literal do kit, e caso de unidade
que amarra os mesmos nomes nos três arquivos (kit, agent.sh e rota).
- O desfecho. Rodada que NÃO fechou o banco não registra mais nada: o esgotamento
gravava os MESMOS números do sucesso, e o erro fatal gravava um `0 0 1` que
ninguém mediu. As frases da tela são todas escritas como "…até a atualização do
banco fechar", então silêncio é o degrau certo. Trava: seção 10 da prova de
shell — o arquivo fica vazio, com controle positivo de que a rodada aconteceu.
- O ramo morto. `disputa: false` com `retentativas >= 1` é impossível por
construção (os dois saem do mesmo contador de passadas: `disputa = passadas > 1`
e `retentativas = passadas - 1`), então virou `null` em vez de uma frase para um
estado que ninguém produz — e o teste que o cobria saiu junto.
A coluna da rodada também deixa de poder derrubar o desfecho: ela sai numa escrita
própria, antes da que fecha o run, e best-effort. Na escrita única de antes, um
42703 (banco anterior à migration da rodada) ou a CHECK recusando o número virava
500, o `post` do agente voltava vazio e o run ficava preso em `dispatched` para
sempre — o desfecho que ninguém detecta.