8831 Commits
Author SHA1 Message Date
Rafael Melgaço efed1d5745 Merge pull request #2071 from melgarafael/ci/cache-playwright-e2e
ci(e2e): cacheia os .deb do --with-deps — o espelho do apt deixa de comer o teto das partes
2026-10-01 13:07:32 -03:00
Rafael Melgaço bc81c0dbb5 Merge pull request #1987 from melgarafael/feat/org-operante
fix(suspensão): suspender uma empresa passa a calar a IA, os envios e a API dela
2026-10-01 12:14:32 -03:00
melgarafaelandClaude Opus 5.5 fe7a5442bf ci(e2e): cacheia os .deb do --with-deps — o espelho do apt deixa de comer o teto das partes
"Instalar o browser" levou de 27 s a 425 s por parte no run 36757657107
(main e8e291217). Os downloads do Playwright custaram 8-9 s em todas as
seis partes; a variação inteira era o apt-get baixando os mesmos 32-35 MB
de .deb do azure.archive.ubuntu.com a velocidades de 87 kB/s a 14 MB/s.

O apt passa a guardar os .deb numa pasta do usuário, restaurada e salva
por actions/cache (chave: imagem do runner + versão do Playwright). O
--with-deps roda igual; o apt confere o hash de cada arquivo restaurado e
só baixa o que mudou. Só em máquina do GitHub. Sem mudança em partição,
teto ou orçamento.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VcGP2iHbB4Jaw9T1PAbA4c
2026-10-01 12:08:53 -03:00
Rafael Melgaço bbee6bdbc5 Merge pull request #1978 from melgarafael/fix/hook-migration-populacao-em-arquivo
fix(hooks): população de migrations em arquivo — o hook não termina com 12 mil refs
2026-10-01 11:51:11 -03:00
Rafael Melgaço 24177d1a40 Merge pull request #2058 from melgarafael/fix/agenda-virada-do-mes
fix(agenda): o calendário de marcação não abre mais num mês que acabou
2026-10-01 11:51:07 -03:00
melgarafaelandClaude Opus 5.5 e0dd43574d refactor(agenda): a abertura decide no render, sem pintar o mes morto
O ajuste de estado vai para o proprio render (padrao "you might not need
an effect"): o mes sem vaga nem chega a ser pintado antes de o painel
passar ao seguinte, e sai o setState-em-efeito que o lint apontava.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 17:42:22 -03:00
melgarafaelandClaude Opus 5.5 b44fcf19c0 fix(agenda): o calendario de marcacao nao abre mais num mes que acabou
No ultimo dia util do mes, depois do ultimo horario, "Novo agendamento"
abria no mes de hoje com todo dia apagado e "Nenhum horario livre", e o
proximo horario (amanha) ficava atras da seta. Foi o que reprovou o e2e de
todos os PRs em 30/09 a partir de ~16h BRT (16 casos da agenda).

- Na abertura, quando os horarios do mes de hoje chegam e nenhum dia tem
  horario publicado, o painel passa ao mes seguinte. Uma vez so: quem volta
  a mao (encaixe hoje) fica onde voltou; sem jornada publicada, nao mexe.
- Os dias so acendem com os horarios DO mes em tela (`mesCarregado`): a
  janela de um mes vai ate endOfMonth + 1 dia, e o dia 1o do mes novo
  acendia com a sobra do velho no quadro entre trocar e carregar.

Teste com relogio congelado em 30/09 17h, 31/10, 31/12 e 26/02/2027.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 17:36:59 -03:00
melgarafaelandClaude Opus 5.5 66cc8d468f test(ia): a conversa simulada do Jev tem o status que a empresa real sempre tem
O teste do worker de clima (Jev, #1747) nasceu na main sem o embed
organizations(status) na conversa simulada. Com o portão de elegibilidade do
PR 1, que lê esse status e falha fechado, os 21 casos passaram a ver a empresa
como parada e o Jev não perguntava nada. A simulação ganha o status "active"
que toda linha real tem, e um caso novo prova o outro lado: empresa suspensa,
turno vetado, nenhum pedido perguntado.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 17:04:56 -03:00
melgarafaelandClaude Opus 5.5 6179868241 docs(spec): a spec diz o que o PR 1 entrega sobre MCP e rotas de API
A tabela da §4 separava Bearer e MCP numa linha só com 403; pela decisão do
dono de 30/09, a consulta de pedidos de LGPD pelo MCP responde com a empresa
suspensa e as demais ferramentas recusam. E o risco residual das "15 rotas com
307 HTML" deixou de existir: as 20 rotas respondem 403 JSON, com cerca — a
frase vira o comando que conta.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 16:33:06 -03:00
melgarafaelandClaude Opus 5.5 55def8727c Merge da main no PR 1: a 0501 passa a carregar os avisos do Jev (0500)
A main recebeu a 0500 (avisos do Jev na Central), que acrescenta
jev_pedido_de_humano e jev_parar_de_receber ao CHECK de agent_inbox_items.kind.
A 0501 reconstrói esse CHECK com a lista inteira e roda DEPOIS da 0500 na
cadeia do CLI: sem os dois tipos, ela apagaria o vocabulário da 0500 (ou
falharia com avisos do Jev já gravados). A lista da 0501 e o bloco único do
baseline levam os três tipos. Nos testes, os dois lados ficam.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 16:32:29 -03:00
melgarafaelandClaude Opus 5.5 584f666f99 chore(tipos): as funções da suspensão vão para a ordem em que o gerador as põe
fn_org_operante, fn_suspender_organizacao, fn_reativar_organizacao e
fn_followup_turno_descartado estavam coladas nos blocos escritos à mão, fora
da ordem alfabética e com os argumentos na ordem da assinatura. Passam ao
trecho gerado, na posição alfabética e com os argumentos ordenados, como o
`supabase gen types` escreve: a próxima regeneração não as move de lugar.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 16:21:57 -03:00
melgarafaelandClaude Opus 5.5 358e73ffe0 chore(db): o apêndice da 0501 volta a ser cópia byte a byte da migration
O cabeçalho do bloco no baseline afirma "cópia byte a byte das seções A, B,
C0a, C0, C, E, F e G"; havia três linhas em branco antes da seção B no
baseline (uma na migration) e duas antes da D na migration (uma no
baseline, onde a D não entra). Sem efeito no SQL; agora a frase é exata:
da seção A ao fim, tirando a D, as 441 linhas dos dois lados são iguais.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 16:21:12 -03:00
melgarafaelandClaude Opus 5.5 1062dd91dd test(suspensao): o hub de conta suspensa cobre a instalação sem SUPPORT_EMAIL, o dono da plataforma e quem não tem empresa ativa
Três ramos do page.tsx que nenhum caso exercitava: sem e-mail de suporte a
tela manda falar com quem administra o sistema (sem link) e a LGPD segue;
o dono da plataforma com papel de atendente vê o painel de admin, e em modo
suporte não; e sem empresa ativa a página manda para /app.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 16:15:24 -03:00
melgarafaelandClaude Opus 5.5 b739d35a21 docs(release): a nota da suspensão condiciona o contato do suporte ao SUPPORT_EMAIL
O fragmento prometia o contato do suporte a quem administra, sem condição,
e fechava com "nenhuma configuração é necessária"; SUPPORT_EMAIL vem vazio
por padrão, e sem ele a tela manda falar com quem administra o sistema. A
nota também passa a dizer o que os lotes seguintes mudaram: a API responde
403 org_suspended em vez de devolver a página, e o link do e-mail de prazo
de LGPD abre o pedido no hub.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 16:14:49 -03:00
melgarafaelandClaude Opus 5.5 a959b13d24 test(suspensao): o e2e clica na volta para a outra empresa e prova a recusa pelo 403
Três coisas que a prova afirmava sem fazer: a volta da admin para a empresa
que opera agora é clicada e chega ao inbox dela (antes só se via o botão); a
recusa a quem só tem leitura confere a resposta 403 forbidden_scope, já que
o toast é o mesmo para qualquer falha; e a foto do hub espera o pedido de
LGPD carregar, em vez de sair com o esqueleto da tabela. No mapa de
jornadas, a atomicidade da suspensão passa a apontar o test:db, que é quem a
prova.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 16:14:02 -03:00
melgarafaelandClaude Opus 5.5 3196d6016d docs(suspensao): os cabeçalhos da régua e do teste de campanhas dizem o que o código faz
O cabeçalho de operante.ts tinha perdido a rota global de entrada do canal,
sem token, que continua fora do bloqueio de propósito. O do teste de
campanhas repetia "a mesma decisão da fila do agente", frase que o próprio
rodada.ts já desmente: a fila nunca olhou status; a régua é operante.ts.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 16:10:34 -03:00
melgarafaelandClaude Opus 5.5 449e5858f0 test(suspensao): a cerca da porta da empresa suspensa reconhece a chave entre aspas
`{ "permiteOrgSuspensa": true }` é a mesma chave e não era contada: numa
rota fora de LGPD/cobrança passaria sem acusação, e numa rota de LGPD seria
lida como porta fechada. As duas direções agora usam o mesmo reconhecedor.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 16:09:51 -03:00
melgarafaelandClaude Opus 5.5 c40661b702 test(admin): a cerca do só-leitura passa a ver a rota embrulhada e a exportada com outro nome
`export const POST = comX(handle)` e `export { h as POST }` deixavam um
handler que chama requirePlatformAdmin sem a de escrita passar verde: o
primeiro porque a função passada como argumento não era seguida, o segundo
porque ExportDeclaration nunca virava handler exportado. Hoje nenhuma rota
do app é escrita assim; o instrumento agora acusaria a que for.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 16:09:50 -03:00
melgarafaelandClaude Opus 5.5 31abf73480 fix(campanhas): busca de campanhas que falha deixa de se passar por rodada vazia
A rodada descartava o `error` da busca das campanhas em andamento e
respondia "nada_a_fazer" — uma falha do banco era indistinguível de uma
rodada sem trabalho, e nada ficava registrado. Agora o erro vai para o
logger (como promoverAgendadas já fazia) e a rodada devolve
`detalhe: "busca_falhou"`. Trocar a lista de ids de orgs paradas por um
filtro no banco fica para uma issue própria.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 15:59:08 -03:00
melgarafaelandClaude Opus 5.5 099fac569c fix(followup): o turno que rodava na hora da suspensão não mata mais o follow-up na volta
A suspensão descarta o turno de envio `pending` e grava `turn_discarded`,
que faz o motor enfileirar um turno novo na reativação. O turno que JÁ
rodava naquele segundo seguia, tinha o envio barrado (OrgNaoOperanteError)
e era cancelado sem o evento: na reativação os rechecks esgotavam o
dead-man e a inscrição morria com `action_turn_never_completed` — um
follow-up morto na Central com motivo falso, e o lead sem a mensagem.

Uma regra só para "o turno saiu sem enviar": `fn_followup_turno_descartado
(org, job)` (seção C0a da 0501, invoker, só service_role). A C0 passa a
chamá-la em vez de repetir o INSERT, e os dois donos de turno em voo a
chamam antes de devolver o job: o agent-worker (createFollowupTurnHandler,
só purpose send_message) e o envio inline (enviarTextoFixoPendente). Erro
que não é suspensão não grava nada — o dead-man segue valendo.

Prova: tests/invariants/followup-org-suspensa.test.ts reproduz a sequência
(turno running → suspende → cancela → reativa) com controle que mostra a
morte sem o evento; tests/unit/turno-rodando-na-suspensao.test.ts e
lib/followup/enviar-texto-fixo.test.ts cobrem as duas chamadas.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 15:59:03 -03:00
melgarafaelandClaude Opus 5.5 f9df965345 fix(suspensao): a data de anonimização da empresa entra na trava do banco
O gatilho que impede a sessão (tela/PostgREST) de mexer no estado da
organização cobria status, suspensão e autoria, mas não `redacted_at`: um
platform admin só-leitura ainda gravava uma data de anonimização falsa. A
coluna entra na comparação da migration 0501 e, byte a byte, no apêndice do
baseline; o único escritor legítimo (lgpd-redact-worker, service_role)
segue passando. Caso novo em org-suspensa.test.ts para os dois scopes de
platform admin, e o controle do service_role passa a gravar a data como o
worker grava.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 15:58:46 -03:00
melgarafaelandClaude Opus 5.5 7d19a4bac0 test(suspensao): a reativação prova que o job remanescente virou falha, não só que saiu da fila
O caso de reativação conferia apenas que não sobrou job 'pending' — o que
também passaria se o job tivesse sido apagado ou marcado 'done' por engano.
O job agora nasce com id fixo (JOB_REMANESCENTE, no padrão de JOB_A/JOB_B)
e o teste afirma 'failed|org_nao_operante' por esse id, como o caso irmão
da suspensão já fazia.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 15:57:45 -03:00
Rafael Melgaço e8e2912178 Merge pull request #2025 from melgarafael/release/1.69.0
Release 1.69.0
v1.69.0
2026-09-30 15:18:36 -03:00
melgarafaelandClaude Opus 5.5 0938e8d8f5 fix(lgpd): o link do e-mail de prazo decide no clique, não no envio
O e-mail enviado com a empresa ativa e clicado depois da suspensão
ainda caía na lista do hub, sem o pedido: o link escolhia a porta
(/app ou o hub) no momento do envio, e a empresa pode mudar de estado
antes do clique.

Agora o link é sempre /lgpd/pedido/<id>, uma porta neutra fora de
/app que entrega o pedido ao hub; o hub já decide com as duas réguas
do layout de /app: empresa parada vê o pedido ali, empresa que opera
é devolvida a /app/lgpd/requests/<id>. A porta não é pública, então
quem abre o e-mail sem sessão passa pelo login com next= e volta ao
pedido (o hub, público, mandava ao login sem next).

Sai o que o conserto anterior precisava para escolher no envio: o
status da org no cron e no alarme, lib/lgpd/caminho-do-pedido.ts e a
entrada dele em NAO_E_FILTRO da cerca de crons, que volta ao que era.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 15:09:35 -03:00
deskcomm-release[bot] d6a42aef27 release(1.69.0): a versão montada a partir dos fragmentos declarados 2026-09-30 18:01:10 +00:00
Rafael Melgaço fa9071c90c Merge pull request #1772 from melgarafael/feat/jev-onda-4
feat(ia): o Jev lê a resposta ao follow-up ao lado da IA de sempre, só observando (onda 4.1)
2026-09-30 14:59:45 -03:00
melgarafaelandClaude Opus 5.5 e05b42dc93 feat(mcp): empresa suspensa ainda consulta os pedidos de LGPD pelo MCP
Decisao do dono (30/09): a ferramenta de privacidade do MCP fica liberada
para empresa suspensa, porque LGPD nunca e bloqueada. Antes o token de
empresa parada morria no /api/mcp inteiro com 403.

O /api/mcp agora valida o token com permiteOrgSuspensa e o recebe marcado
(orgSuspensa). O servidor recusa com org_suspended toda ferramenta que nao
declara permiteOrgSuspensa - hoje so crm_list_privacy_requests, que e
leitura. A recusa fica depois do teto (a integracao em laco nao escreve
auditoria sem freio) e dentro do try que audita. O token de API nas rotas
REST (auth-dual, /api/v1/contacts) segue 403: so quem passa a opcao abre
a porta.

A cerca org-suspensa-so-nas-rotas-permitidas passa a admitir a chave nos
dois arquivos do MCP e exige que o /api/mcp e a ferramenta de privacidade
a passem; o fragmento diz o que continua respondendo.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 14:36:01 -03:00
melgarafaelandClaude Opus 5.5 42dcc6fd22 test(e2e): evidência do jev-followup no caminho versionado (evidence/jev/)
A spec gravava em .superpowers/evidence/, que o .gitignore ignora; a cerca
evidencia-no-caminho-versionado reprovou o verify do #1772. Mesma pasta das
irmãs jev-pedidos (evidence/jev/).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 14:33:53 -03:00
melgarafaelandClaude Opus 5.5 efd1356f90 fix(lgpd): o e-mail de prazo abre o pedido mesmo com a empresa suspensa
O link do alarme de SLA apontava para /app/lgpd/requests/<id>; com a
empresa suspensa o layout de /app desviava para o hub sem dizer qual
pedido era, e o DPO caia na lista com o prazo legal correndo.

Agora quem monta o link escolhe a porta (lib/lgpd/caminho-do-pedido.ts):
empresa parada recebe /account-suspended?pedido=<id>. E o hub, quando a
empresa voltou a operar antes do clique, devolve ao pedido em vez de a
/app. As duas pontas usam a mesma funcao, entao o link vale nos dois
estados do clique; status ilegivel cai no hub, que redireciona certo.

A cerca de crons ganha caminho-do-pedido.ts em NAO_E_FILTRO: escolher a
porta de um link nao e filtro, e o alarme segue saindo para a empresa
parada, de proposito.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 14:31:11 -03:00
melgarafael 15a1a30ec0 Merge remote-tracking branch 'origin/main' into feat/jev-onda-4
# Conflicts:
#	.github/workflows/e2e.yml
#	docs/architecture/escalacao-ciclo-humano.architecture.json
#	docs/white-label.en.md
#	docs/white-label.es.md
2026-09-30 14:23:42 -03:00
Rafael Melgaço 0d231b5a0a Merge pull request #1766 from melgarafael/fix/followup-classificar-espera-a-resposta
fix(followup): "Classificar resposta" espera o cliente responder — e lê a resposta ao envio do fluxo
2026-09-30 14:19:20 -03:00
melgarafaelandClaude Opus 5.5 858541085f fix(suspensao): a tela de conta suspensa diz qual empresa parou
Quem participa de mais de uma empresa via só "Conta suspensa" e ficava sem
saber qual — a própria tela oferece trocar para as outras. O nome da
empresa ativa aparece logo abaixo do título (é dado, então não passa pelo
dicionário).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 13:58:26 -03:00
melgarafaelandClaude Opus 5.5 cc62928d09 fix(admin): admin só-leitura que tenta salvar lê o motivo, não a tela de erro
As server actions do painel (marca, e-mail, Google, Meta, destinos internos,
módulos, comportamento, cadastro, pedidos de cadastro e configuração da
instalação) chamavam requirePlatformAdminEscrita sem try/catch: a recusa de
support_readonly ou de MFA pendente subia ao error boundary, e a pessoa não
lia "seu acesso é somente leitura" nem "confirme a verificação em duas
etapas". Nada era gravado — a perda era a explicação.

Agora todas passam por escritaDeAdminOuRecusa(), que devolve
{ok:false, error:'forbidden_scope'|'mfa_required'} e deixa o redirect de
quem não é platform admin subir como antes. As telas leem a frase da mesma
tabela que o servidor usa (lib/auth/recusa-de-escrita-de-admin.ts, sem
next/*), com espanhol. A cerca admin-escrita-exige-scope-full ganha a regra
D: arquivo "use server" não chama o helper que lança.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 13:56:56 -03:00
Rafael Melgaço c3805f1514 Merge pull request #2018 from melgarafael/release/1.68.0
Release 1.68.0
v1.68.0
2026-09-30 13:49:58 -03:00
melgarafaelandClaude Opus 5.5 ec8f52a8c6 fix(admin): suspender ou reativar sem efeito avisa "nada mudou", não "sucesso"
As rotas respondem 200 {changed:false, motivo} quando a empresa já estava
no estado pedido — outro admin agiu antes e a tela estava velha. Os hooks
ignoravam a resposta e mostravam "Tenant suspenso/reativado com sucesso";
na suspensão por cobrança o admin leria "reativado" com a empresa parada.
Agora changed:false vira toast.info "Nada mudou" com o motivo traduzido
(pt/es), e motivo desconhecido não inventa causa.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 13:47:25 -03:00
melgarafaelandClaude Opus 5.5 d0aaa8761f fix(suspensao): reativar só fala de cobrança com empresa suspensa de fato
O pré-check do 409 suspensao_de_cobranca perguntava "a empresa está
parada?" em vez de "está suspensa?". Uma empresa redigida pela LGPD é
parada e guarda o tipo residual 'cobranca' (o redact não limpa a coluna),
e o admin receberia a instrução errada de negociar pagamento. Agora a
régua é status = 'suspended'; a função responde nao_suspensa como sempre.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 13:45:05 -03:00
melgarafaelandClaude Opus 5.5 41da980e6a fix(suspensao): empresa suspensa recebe 403 claro na API, e a tela a leva ao hub
Quem estava com o CRM aberto na hora da suspensão ficava com listas vazias
e erros até recarregar: 20 rotas de app/api resolviam a org com
resolveActiveOrg, que faz redirect("/account-suspended"); o fetch seguia o
307 e entregava o HTML da página à tela como se fosse o dado.

- orgAtivaDaApi (lib/auth/require-role.ts): a org ativa para Route Handler
  que não passa por requireRole; org não operante vira o MESMO 403
  org_suspended em JSON de requireRole (mensagem única, traduzida).
- As 20 rotas passam a usá-la; páginas e server actions seguem com o
  redirect de resolveActiveOrg.
- lib/api/client.ts: 403 org_suspended leva a janela a /account-suspended
  (sem navegar de novo quando já está lá).
- Cerca por AST (tests/unit/api-nao-redireciona-org-suspensa.test.ts):
  resolveActiveOrg não volta a app/api, e orgAtivaSemPortao só onde ver a
  org parada é o objetivo (allowlist que só encolhe: impersonate).
- Teste de comportamento por 4 rotas reais e casos de orgAtivaDaApi.

Acabamentos do PR 1, itens 6 e 23.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 13:40:02 -03:00
Rafael Melgaço d54f4b13c8 Merge pull request #1956 from melgarafael/docs/spec-cobranca-do-revendedor
docs(adr): ADR-0004 — cobrança do revendedor, e a spec que a detalha
2026-09-30 13:31:44 -03:00
melgarafaelandClaude Opus 5.5 95f848cc82 docs(release): créditos da 1.68.0 — @arodalves (#2006) e o relato de @aerosuiteapp (#1998)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 13:30:47 -03:00
deskcomm-release[bot] ef30bf4bc7 release(1.68.0): a versão montada a partir dos fragmentos declarados 2026-09-30 16:29:47 +00:00
Rafael Melgaço 47a25b2ed0 Merge pull request #2008 from webtecnica/fix/1998-backfill-0068-duplicate-pricing
fix(baseline): deduplica backfill 0068 por model_id
2026-09-30 13:26:24 -03:00
melgarafael 3d4c2842a1 Merge remote-tracking branch 'origin/main' into fix/followup-classificar-espera-a-resposta 2026-09-30 13:16:35 -03:00
Rafael Melgaço b46e320c7f Merge pull request #1747 from melgarafael/feat/jev-onda-3
feat(ia): o Jev percebe pedidos de pessoa e de parar de receber que a regra deixa passar, e pode avisar a equipe (onda 3)
2026-09-30 13:16:13 -03:00
melgarafaelandClaude Opus 5.5 b095c7969e chore(suspensao): renumera a migration para 0501, acima do que está na main e em voo
A main recebeu 0497–0499 (carimbos até 20260930160000) e dois PRs abertos
usam 0500@20260930170000. A 0496@20260930130000 ficaria abaixo de migrations
já aplicadas pela cadeia do Supabase CLI. Passa a 20260930180000_0501; o
apêndice do baseline, o COMMENT da coluna, o MANIFEST e a prosa acompanham.
Os UUIDs de fixture c0de0496 são identificadores e ficam.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 13:11:47 -03:00
melgarafael 390cc9e884 Merge remote-tracking branch 'origin/main' into feat/org-operante 2026-09-30 13:09:33 -03:00
melgarafael 06900e9bfd Merge remote-tracking branch 'origin/main' into docs/spec-cobranca-do-revendedor 2026-09-30 13:08:58 -03:00
melgarafael 203ecef5a4 Merge remote-tracking branch 'origin/main' into fix/followup-classificar-espera-a-resposta 2026-09-30 12:48:29 -03:00
melgarafaelandClaude Opus 5.5 08921dc839 test(db): planta o mesmo model_id em dois provedores no update-com-dados (#1998)
O test:db reaplica sobre banco vazio, onde openai/gpt-4o-mini só existe
sob requesty, e por isso o defeito do backfill 0068 passou verde da
v1.63 à v1.67. Agora o seed planta a mesma linha sob openrouter, uma
guarda de vacuidade confere 2 modelos e 0 preços antes do update, e
depois da reaplicação com ON_ERROR_STOP=1 exige UMA linha de preço com
o menor preço de entrada (1/14).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 12:47:19 -03:00
melgarafaelandClaude Opus 5.5 627050fcfb fix(baseline): desempate total no backfill 0068 (#1998)
O order by do distinct on desempatava só pelo preço de entrada: dois
provedores com a mesma entrada e saída diferente escolhiam uma linha
arbitrária. Agora desempata por saída e depois por provedor.
Acrescenta a quebra de linha final do fragmento.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 12:47:17 -03:00
melgarafael 86db2b47a4 Merge remote-tracking branch 'origin/main' into tri-2008 2026-09-30 12:46:18 -03:00