# Wiki Log

Chronological, append-only record of everything that's happened in this wiki.

**Format:**
```
## [YYYY-MM-DD HH:MM] <type> | <title>
<optional detail line>
```

**Types:** `session`, `ingest`, `query`, `lint`, `rebuild`

**Quick access:** `grep "^## \[" log.md | tail -5` gives you the last 5 entries.

---

## [2026-05-22 dia] session | Melissa UX overhaul + 5 docs saas (Fases 2-5)
Touched: none codigo durable; 5 docs saas novas em development/saas-docs/

Sessao longa (~12 commits codigo + 5 docs). 2 grandes blocos:

BLOCO 1 — Melissa UI overhaul (manha):
- Tray no canto inf. direito (substitui topbar band do topo): busca +
  plan-DEV + bell + ajuda + cog. Sibling de .melissa-dock (fora de
  .win11-summary) pra ficar interativa com secao aberta. Em <md (768px)
  collapse parcial — bell/help/cog/plan-DEV viram popup vertical no
  botao ⋮; dot vermelho no ⋮ quando ha notificacoes nao lidas.
- Busca global unificada: MelissaBusca ganha parser de data (hoje/
  amanha/ontem/DD/MM/YYYY) + card azul "Ir para [data]" + emit
  goto-date. Popover da agenda (MelissaAgendaSearchPopover) deletado;
  Ctrl+K so vive na MelissaBusca. Lupa unica fica so na .melissa-tray
  (removida das toolbars de secoes pra evitar pollution mobile).
- Dock: 4 builtins (Agenda · Pacientes · WhatsApp · Financeiro). MRU
  oculto em <md via @media (utility 'hidden' do tailwind perdia pro
  .dock-pin{display:grid} por carga).
- Hero resumo: contagem "(x foi cancelado, x foi remarcado)" depois
  do chip atendimentos com gramatica plural.
- Settings + Ajuda fecham ao clicar fora (mousedown capture + watch
  open). Cog ref + data-ajuda-toggle ignoram trigger pra evitar
  close+reopen.
- Cronometro: pre-selecao paciente + autostart quando aberto via
  botao ⏱ na timeline (sessao em curso) ou card "Proximo paciente".
  abrir(opts) com { pacienteId, autostart, sessionPlan }. sessionPlan
  exibe "Programado: HH:MM – HH:MM" + badge "atrasada X min"; NAO
  desconta atraso auto. Confirm fechar quando ha sessao rodando/
  decorrido sem salvar. Chip minimizado oculta nome do paciente em
  <md (so icone + tempo).
- Documents: linkage document_generated.documento_id agora preenchido
  no INSERT (era sempre NULL). Modo edit in-place via editingDocId:
  busca template+dados_preenchidos via loadGeneratedFromDocId, popula
  vars, pula pra step 'edit'; save substitui PDF no Storage e
  atualiza documents (preserva id+audit). Header amber "Editar
  documento" + botao "Substituir documento". Backfill SQL pra docs
  antigos (3 linkados, 5 orfaos no DB local).
- DocumentPreviewDialog: wire-up dos 5 botoes da sidebar (download/
  editar/share/sign/delete) que estavam caindo no vazio.

BLOCO 2 — saas-docs (tarde):
Padrao igual da 01-busca-global-melissa.json — JSON-fonte +
SQL de import direto via $HTML$/$FAQ$ dollar quoting. 5 docs novas
(03 a 07), cada uma com 12 FAQ itens:

- 03 Documentos do paciente — pagina_path /melissa/paciente,
  categoria Documentos
- 04 Templates de documentos — pagina_path /melissa/documentos-
  templates, categoria Documentos
- 05 Assinatura eletronica — pagina_path /melissa/paciente,
  categoria Documentos
- 06 Recibo profissional — pagina_path /melissa/agenda, categoria
  Financeiro (cobre fluxo do AgendaEventoFinanceiroPanel)
- 07 Relatorios e exportacao — pagina_path /melissa/relatorios,
  categoria Relatorios

Todas importadas no DB local via docker exec psql. Total acumulado:
7 docs ativas em saas_docs (busca + cronometro + os 5 novos).

PROXIMA SESSAO (retomar 23/05):
- Fase 6 RESTANTE: C12 UX iter (cronometro/sessao antecipar pgto —
  flow DB ja ok, UX obscura adiada em 20/05). Unico item de codigo
  da lista de ontem.
- Fase 7 RESTANTE: Regressao Agenda C7-C13 (validacao manual; eu
  nao executo, so listo plano de teste se quiser).
- Antes/depois: olhada no ROADMAP.md canonico pra panorama MVP
  real. Itens visiveis ainda no horizonte: #12 papel timbrado
  (bloqueado, codigo no UniaoApp), #15 NFS-e (esforco L), §1.5
  Sentry+qualidade, Asaas Fase B (bloqueado), M4 cutover billing
  (depende decisoes #2/#3/#6), validacao centralizada CPF/CNPJ/tel.

ITENS TESTADOS HOJE (✅): tray + busca unificada + cronometro
evento-aware + edicao in-place de docs gerados + Fase 2.7-2.9
(gerar PDF, vars CRP/UF, tipo_documento='outro').

PUSH: 12 commits pushados (c17c547..701d9f4) usando workaround SSL
(git -c http.sslVerify=false push). Credenciais pediram 1x, depois
cacheou pra sessao toda.

## [2026-05-20 18:30] session | C12 deferred + C13 prep (lock ja existia em Fase 6)
Touched: none (codigo + HANDOFF; memoria project_c12_antecipar_iterar)
Detalhes:

C12 (antecipar pagamento) — DB OK + watch sync resolveu snapshot
stale, mas UX ficou confusa em ciclos antecipar/revogar/re-antecipar.
Adiado pra iterar pos-Rail/Clinica. 5 bugs adicionais corrigidos:
- Re-antecipar reusava record cancelled (notes confusas). Fix: filter
  cancelled em existRec query
- Popover snapshot stale apos materializacao virtual->real. Fix:
  watch em M.eventos com lookup por id + recurrence_id/date
- normalizeForMelissa nao expunha owner_id/tenant_id/billing_contract_id
  -> RPC create_financial_record_for_session erro "null in owner_id".
  Fix: expor explicit + fallback em handler
- onAnteciparPagamento fechava popover -> agora mantem aberto e watch
  sincroniza
- Quick "Revogar pagamento" button alternando "Antecipar pagamento"
  quando isAntecipacaoAtiva (paid + agendado)

C13 — prep:
- Lock "edit cobrada imutavel" JA esta implementado (Fase 6 do
  commit 1feb711). Message azul com cadeado + AgendaEventoFinanceiro
  Panel embedded quando occFinancialRecord existe. Card "Aplicar
  alteracoes em" oculto pra simplificar.
- Pacientes pra testar: Joao Almeida (R$ 40 maquininha avulsa) ou
  Andre Green 20/05 (R$ 40 PIX, pacote saldo)
- User vai testar; sem mudanca de codigo prevista. Validacao visual.

Total acumulado no dia: 14 commits, ~14 bugs corrigidos, 3 features
novas (Agendada button, reverse trava, revogar antecipacao + watch
sync popover).

## [2026-05-20 16:00] session | C11 OK (A/B/C/D) + reverse trava + 5 bugs achados
Touched: none (codigo + HANDOFF; memoria project_billing_contracts_no_updated_at)
Detalhes:

CENARIO 11 (Status change pacote saldo) - 4/4 passaram com Andre Green:
- 11A: realizada + markPaid PIX (saldo 0->1, record paid R$ 40)
- 11B: falta + descontar (saldo 1->2, sem multa)
- 11C: falta + multa SEM consumir (saldo stays 2, multa pending R$ 30)
- 11D: cancelado >2h + default_consume_on_miss=true (saldo 2->3, sem multa)

ROOT CAUSE descoberto: billing_contracts NAO tem coluna updated_at.
Passar esse field em UPDATE falhava silently em Promise.allSettled
(ja documentado em memoria). Refatorado pra awaits sequenciais com
error handling explicito.

DIALOG UX (refator): bloco "Cobranca no pacote" antes tinha select
"Como cobrar?" com options "Ja recebi - PIX/Dinheiro" misturadas.
Confuso. Agora tem 2 sub-questions: "Ja recebi?" radio + select
condicional (sem prefixo ambiguo).

REVERSE TRANSITION TRAVA (antecipado pos-C13 pra C11): quando user
clica Agendada em sessao com artefatos (cobranca pending, paid,
ou saldo consumido em pacote), dialog reverse abre mostrando:
- Lista records pending + radio Cancelar/Manter
- Warning textual pra paid (sem auto-estorno)
- Radio devolver saldo se consumido
- Default: cancel + devolver (recovery flow)

Outros fixes acumulados:
- consumeSaldo amarra billing_contract_id (era omissao)
- link universal pre-forward (antes era so em consumeSaldo/generatePackageCharge)
- reverse decrement saldo: refetch FRESH antes do UPDATE (anti-race)
- label pacote saldo state=none: "Aguardando uso do pacote"
- badge $ amber suprimido em pacote saldo state=none
- lock total em sessao encerrada (Editar some, status disabled excepto Agendada)

DOC: addendum no HTML cenarios atualizado anteriormente cobre tudo.
Memorias: project_billing_contracts_no_updated_at (novo gotcha).

PROXIMO: Cenario 12 (antecipar pagamento) ou Cenario 13 (edit
cobrada). Depois replicar em Rail + Clinica.

## [2026-05-20 14:00] session | C10 OK (A/A2/B/C/C2) + lock sessao encerrada + addendum doc
Touched: none (codigo + HANDOFF + addendum HTML; memorias project_agenda_reverse_transitions e project_melissa_popover_snapshot)
Detalhes:

CENARIO 10 (Status change avulsa) - 5/5 sub-testes passaram:
- A: realizado sem markPaid -> record pending preservado (João Almeida)
- A2: realizado + markPaid maquininha -> paid + paid_at + payment_method
  (João Almeida; investigado false positive de "stale" - era confusao de
  query, sempre passou)
- B: faltou + multa fixed R$ 30 -> original cancelled + nova multa com
  description "Multa por falta · sessão dd/mm/aa" (Otto Rank)
- C: cancelado >2h antecedência -> original cancelled sem multa
  (Otto/Karen). Hint contextual no dialog explica POR QUE multa veio
  desmarcada.
- C2: cancelado tardio <2h full charge -> original cancelled + nova
  "Taxa de cancelamento tardio" (Karen Horney)

BUGS DESCOBERTOS + CORRIGIDOS durante bateria (3 commits acumulados):
- Cobranca dupla na multa: _applyStatusDecisions INSERIA multa mas
  deixava original pending. Fix: cancelar ctx.pendingRecord com nota
  de auditoria em notes.
- _reloadRange not defined: _buildHandlers nao destruturava do deps.
- Badge $ amber em sessao cancelada: gate sessaoEncerrada agora cobre
  status=cancelado/faltou em MelissaAgenda.vue.
- paymentLabel usava ev.price pra pending (R$ 150 enquanto multa real
  era R$ 30). Fix: paymentAmount tambem em pending.
- Botao "Gerar cobranca" no popover + AgendaEventoFinanceiroPanel
  permitia emitir fatura em sessao encerrada. Fix: gated por
  isSessaoEncerrada.
- Lock total em cancelado/faltou: Editar sessao some, Realizada/Falta/
  Reagendar/Cancelar disabled. So botao "Agendada" (novo, variante
  --info cyan) continua funcional pra recuperacao explicita.
- Bug dormente: useAgendaFinanceiro.js comparava 'fixed' em vez de
  'fixed_fee' do schema.

UX ADICIONS:
- Botao "Agendada" no popover (pi-calendar, --info cyan)
- Hint contextual sobre min_hours_notice no dialog ("Cancelou 18.5h
  antes -> sem multa por padrao")

DOC:
- Addendum C10 no topo de src/docs/agenda-compromisso-financeiro
  -cenarios.html capturando todas as divergencias + 3 pendencias.

PENDENCIAS POS-C13 (salvas em memoria):
- Reverse transitions com multa orfa (project_agenda_reverse_transitions)
- Popover Melissa snapshot stale (project_melissa_popover_snapshot)

PROXIMO: Cenario 11 (status change pacote saldo).

## [2026-05-20 06:00] session | C9 OK + rowGroup por paciente + bubble cobranca-atualizada
Touched: none (codigo + HANDOFF)
Detalhes:

CENARIO 9 (per_session):
- Michael Balint 12 sessoes R$ 150 modo "1 por sessao"
- DB conforme esperado: 1 rule, 12 events materializadas, 0 contracts,
  12 records pending (R$ 150 cada)
- Visual: 12 badges $ amber, todas pending. Sem linha de pacote no
  popover (per_session nao usa contract).

ROWGROUP NO /melissa/financeiro-lancamentos:
- DataTable com rowGroupMode='subheader' + groupRowsBy='patient_id'
- Default todos expandidos (watcher recalcula a cada recordsGrouped)
- Header de grupo: avatar + nome + badge "N lançamento(s)"
- Sort outer por nome de paciente, preserva ordem interna pai→filhos
- Click no chevron contrai/expande

BUBBLE @cobranca-atualizada:
- Bug: card na agenda nao atualizava badge/borda apos marcar como
  pago no dialog (so dava refresh ao trocar de view)
- Root cause: AgendaEventoFinanceiroPanel.@cobranca-atualizada
  disparava so loadOccFinancialRecord (interno do dialog). O
  _paymentStateMap da agenda ficava stale.
- Fix: AgendaEventDialog tem agora _onCobrancaAtualizada que faz
  loadOccFinancialRecord + emit('cobranca-atualizada'). MelissaLayout
  escuta nos 2 dialogs e chama M.refetch() + refetchEventosHoje().
  Card no FC passa pra borda verde imediatamente.

PROXIMO: Cenario 10 (status change avulsa — realizado/faltou/cancelado
+ STATUS_TO_EXCEPTION em financial_exceptions).

## [2026-05-20 03:00] session | C8 OK + Usar/Revogar saldo + UI pacote + ajustes UX
Touched: none (sem nova wiki page; mudancas em codigo + HANDOFF)
Detalhes: noite longa cobrindo C8 (pacote saldo) e principalmente
construindo a UI/UX de pacote saldo do zero — antes nao tinha
indicacao alguma no dialog/popover de que era saldo.

CENARIO 8 (Pacote SALDO):
- Criou Otavio 12 sessoes R$50 saldo
- DB conforme esperado: 1 rule, 0 events, 1 contract (saldo), 0 records
- Visual conforme esperado: 12 virtuais limpas

UI DE PACOTE (saldo + upfront):
- _ruleContractMap em useMelissaAgenda: bulk-load popula contract info
  por recurrence_id (query recurrence_rules.patient_id como fonte
  autoritativa, cobre saldo sem materializadas)
- Normalize injeta `contract` no evento
- Popover MelissaEventoPanel: linha colorida (violeta saldo, verde
  upfront) com "Pacote X · N/M usadas|realizadas" + botão Usar
  (verde, paymentState=none) OU Revogar (vermelho, paymentState=pending)
- AgendaEventDialog: info card mt-4 com header+body+hint explicando
  modelo, botão "Usar agora"/"Revogar uso" gateado por
  occFinancialLoading (spinner durante carga)

HANDLERS USAR/REVOGAR ATOMICOS:
- onUsarSessao: materializa virtual + status=realizado + record per-session
  + sessions_used++ + (se total) contract status=completed
- onRevogarSessao: cancela record + sessions_used-- + reativa contract
  + status=agendado. Bloqueia se record paid (estorno formal precisa)
- Ambos aceitam payload do popover OU do dialog

FIXES NA RODADA:
- Enum status_evento_agenda usa 'realizado' (masculino), nao 'realizada'
- determined_commitment_id backfill no materialize+revogar+update path
  (sem isso, dialog mostrava campo "Titulo" indevidamente)
- "Gerar fatura" do popover esconde quando ha contract (evita
  duplicacao em saldo)
- Race condition no dialog: spinner enquanto occFinancialLoading,
  botoes so renderizam apos carga

RECORRENCIAS APLICADAS — UI:
- Header stats coloridos por status (azul total, verde realizadas,
  amber faltaram, cinza canceladas, violeta remarcadas)
- Pills com badge solido por status (em vez de texto cinza)

DECISAO UX antes de codar (3 perguntas):
- Editar servico pago? NAO (cobranca fiscal imutavel)
- Alternar Particular/Convenio/Gratuito em serie cobrada? NAO
- Gerar fatura individual em pacote upfront? NAO (duplicacao)
Tudo isso o lock-edit (Fase 6) cobre.

DECISAO UX "Usar" vs "Confirmacao":
- Recomendei Revogar (undo) em vez de confirmacao toda vez
- Friction baixo no fluxo principal (usuario "Usa" 12x ao longo de 3 meses)
- Reversivel enquanto record pending; paid bloqueia

PROXIMO: Cenario 9 (Michael Balint per_session 12 x R$150).

## [2026-05-19 23:00] session | C7 OK + Fase 6 lock em Melissa + cross-week propagation
Touched: project_cross_week_propagation (nova)
Detalhes: rodada longa cobrindo C7 (pacote upfront, Ana Souza Ferreira 4xR$200=R$800),
ativacao do lock-edit (Fase 6) em Melissa e correcao de bug cross-week
na propagacao de estado de pagamento.

CENARIO 7 (Pacote UPFRONT):
- User criou Ana, pagou os R$800 em dinheiro pelo Financeiro
- Borda verde + popover "Pago R$800" no card materializado funcionou
- 4 pills no dialog da serie, todas com "Cobranca paga R$800 do pacote"
  ate as virtuais (via synthesized record em loadOccFinancialRecord)

LOCK-EDIT (Fase 6) ATIVADO EM MELISSA:
- Antes: loadOccFinancialRecord tinha guard occurrenceMode, so ativo
  em Rail/Clinica. Em Melissa havia sessionPaymentRecord paralelo so
  pro Resumo lateral (sem trigger de lock).
- Agora unificado: removido guard, occFinancialRecord carrega em ambos
  modos. Card Sessao/Honorarios ganha Tag em vez de Select billingType
  quando ha cobranca. Body mostra Message lock + cadeado.
  AgendaEventoFinanceiroPanel so renderiza se record real (nao
  sintetizado).
- Antes do codar, alinhei 3 perguntas de UX com user:
  1) Editar servico pago? NAO (cobranca fiscal imutavel)
  2) Alternar Particular/Convenio/Gratuito em serie cobrada? NAO
  3) Gerar fatura individual em upfront? NAO (duplicaria cobranca)

CROSS-WEEK PROPAGATION (descoberto durante C7):
- Bug: virtuais isoladas em semanas futuras nao mostravam paid.
- Root cause: bulk-load tinha "if (realIds.length) { ... propagacao ... }
  else { _rulePaymentMap.value = {} }". Quando user navegava pra semana
  so com virtuais (sem reais), else zerava o ruleMap.
- Fix: maps inicializados SEMPRE, propagacao roda sempre, atribuicao
  final tambem fora do if. Propagacao tambem ficou cross-week — pega
  ruleIdsInView de TODOS eventos da view (real+virtual com recurrence_id),
  busca records de QUALQUER evento da rule (em qualquer semana). Memoria
  durador em project_cross_week_propagation.md.

OUTROS FIXES NA RODADA:
- Atalho "Gerar fatura" no popover (pill amber ao lado de "A cobrar R$ X").
- Info de pacote no header popover ("Sessao · Pacote · N sessoes").
- Botao "Excluir serie inteira" no popover (hard delete, bloqueia se
  algum record paid).
- Migration 20260519000001: RPC create_financial_record_for_session
  ignora cancelled na idempotencia. Memoria em
  project_rpc_idempotency_cancelled.md.
- cancel_session exception some da agenda (era visivel com status
  cancelado, doc dizia que sumia).
- recurrence_exceptions cancel agora upsert idempotente (nao quebra
  com unique violation em re-cancel).
- onVerLancamentos busca records via siblings da serie pra virtuais de
  upfront.
- Visualizacao: virtuais herdadas via propagacao agora mostram borda
  verde + linha verde no popover (showPaymentRow e isPaidSession
  relaxados pra paymentState !== 'none').

PROXIMO: Cenario 8 (Carl Jung pacote SALDO 4x R$40 = R$160).
Esperado: 0 records iniciais, 4 virtuais limpas (saldo NAO propaga —
cada sessao gera cobranca quando vira realidade).

## [2026-05-19 14:00] session | C5+C6 OK + atalho gerar fatura + RPC idempotencia fix
Touched: project_rpc_idempotency_cancelled (nova)
Detalhes: sessao longa cobrindo C5 e C6 ate green checkmark, com varios
fixes intermediarios:

CENARIO 5 (Sandor + Unimed convenio):
- 2 bugs no save: amount lia 'price' (null em convenio) e payment_method
  caia em 'asaas' por fallback. Fix: detecta convenio via insurance_plan_id,
  amount=insurance_value, payment_method='convenio'. markPaidNow ignorado
  pra convenio (sempre nasce pending).
- 2 bugs na visualizacao: popover so mostrava "Cobranca pendente" sem
  valor (lia ev.price) e /financeiro nao mostrava pill convenio.
  Fix: normalize expoe insurance_value; popover fallback price ?? insurance_value;
  /financeiro ganhou branch pra payment_method='convenio' (pill violeta).

CENARIO 6 (Maria Magali, recorrente sem pacote):
- chargeMode='none' nao materializava 1a (todas viravam virtuais, sem badge).
  Fix: adicionado bloco no fluxo de criacao recorrente que materializa 1a
  quando chargeMode='none' && paciente_id. Package/per_session ja
  materializam nos seus helpers; package saldo intencionalmente NAO.
- Primeira tentativa de fix usou paciente_id (Portuguese) mas
  agendaRepository dropa esse campo (legado). Corrigido pra patient_id
  (English DB column). Fallback `normalized.patient_id ?? normalized.paciente_id`.

ATALHO "Gerar fatura" no popover:
- Pill amber "Gerar fatura" ao lado de "A cobrar R$ X" no popover.
- Wire em MelissaLayout via emit gerar-cobranca + handler onGerarCobrancaQuick.
- Fecha popover apos sucesso pra impedir click duplicado.
- Tooltip simplificado: "Gerar fatura agora".

BUG RPC IDEMPOTENCIA (gravado em memoria):
- create_financial_record_for_session checava idempotencia por
  agenda_evento_id + deleted_at IS NULL, MAS sem filtrar status='cancelled'.
  User cancelava cobranca sem querer → todo regenerar retornava cancelado
  e nada inseria. Toast verde mentindo.
- Fix: migration 20260519000001 adiciona AND status != 'cancelled'.
- Memoria salva em project_rpc_idempotency_cancelled.md (padrao a aplicar
  em toda RPC futura com idempotencia por chave natural).

INFO PACOTE NO POPOVER:
- Header do popover agora mostra "Sessao · Pacote · N sessoes" ou similar
  (computed seriesLabel le do _raw). Visual: violeta sem caps lock.

TITULO DIALOG "Sessao do Pacote · Sessao":
- Quando commitment name eh "Sessao" (default), drop pra evitar duplicacao.
  Outros nomes (Avaliacao etc) permanecem com forma completa.

CSS:
- .aed-row-50 perdeu margin-bottom (user request).
- .field-card.mb-4 ganhou margin-top: 1rem (scoped via composer wrappers).

OUTROS BUGS RESOLVIDOS NO CAMINHO:
- AgendaEventoFinanceiroPanel.fetchRecord agora filtra cancelled.
- bulk-load do useMelissaAgenda agora filtra cancelled.
- recurrence_exceptions cancel agora usa upsert (idempotente, nao quebra
  com unique constraint quando user cancela 2x ou tem exception zumbi).
- "Excluir serie inteira" botao novo no popover (hard delete: rule +
  materializadas + financial_records pendentes; bloqueia se paid).
- cancel_session exception agora SOME da agenda (era visivel com status
  cancelado, doc dizia "some da agenda" mas codigo mantinha).
- ConfiguracoesConveniosPage ganhou botao "+ Novo convenio" (faltava).
- goToConveniosConfig removida (dead code pos quick-create inline).
- Quick-create inline de procedimento (InsurancePlanServiceQuickCreateDialog).
- Hint contextual abaixo do card Sessao/Honorarios (convenio = "N guia
  opcional"; gratuito = "sem cobranca").

PROXIMO: Cenario 7 (Donald Winnicott · pacote UPFRONT · 4 × R$ 200).

## [2026-05-18 23:30] session | UX de convenio refinado (3 fixes) + hint contextual
Touched: none (sem nova wiki page; tudo em codigo + HANDOFF)
Detalhes: tarde inteira consumida em refinar UX de convenio antes do
save real do C5. User bateu em 3 problemas seguidos:

1) Botao "Cadastrar" do procedimento navegava pra /pages/notfound.
   Root cause: goToConveniosConfig prefixava com /therapist|/admin mas
   /configuracoes/* eh rota raiz sob AppLayout (sibling, nao filho). Em
   Melissa, convenios mora via secao=cfg-convenios sem URL propria.
   Fix descartado: user nao queria sair da agenda. Criamos quick-create
   inline (#2). Removi goToConveniosConfig (dead code).

2) InsurancePlanServiceQuickCreateDialog (novo componente). Mesmo pattern
   do InsurancePlanQuickCreateDialog. 2 campos: nome + valor que o
   convenio paga. Wiring em useAgendaEventLifecycle: planServiceQuickDlgOpen
   + openPlanServiceQuickCreate + onPlanServiceCreated. Apos criar:
   loadInsurancePlans + auto-seleciona SO se nada estava selecionado
   antes. UI refatorada: caixa cinza com botao "Cadastrar" SEMPRE
   visivel quando convenio selecionado, copy varia por contagem
   (0 procedimentos = chamada urgente; 1+ = "se quiser adicionar mais").

3) Botao "+ Novo convenio" faltando em ConfiguracoesConveniosPage.vue.
   addingNew=true sem botao pra setar. Empty state mandava clicar em
   botao inexistente. Fix: toolbar topo com Button label="Novo convenio"
   @click="addingNew = true". Empty state corrigida.

Hint contextual abaixo do card Sessao/Honorarios. User: "Nº da guia
eh obrigatorio?" — consegui salvar sem. Tentativa 1: coloquei em
v-if=occurrenceMode (errado, so Rail/Clinica). Tentativa 2: fluxo
principal Melissa (linha 2305). Copy: convenio = "Nº da guia eh
opcional…", gratuito = "Sessão gratuita…", particular = sem hint.
Label "Nº da Guia" tambem ganhou "(opcional)".

PROXIMO: rodar de fato o save do C5 (Sandor + Unimed + R$ 95). Tudo
preparado, agora eh testar end-to-end.

## [2026-05-18 21:45] session | Linha de cobranca no popover (3 estados) + Resumo do dialog
Touched: none (sem nova wiki page)
Detalhes: extensao do trabalho da sessao anterior (barra verde na agenda).
User pediu pra popover mostrar tambem o estado pago, nao so pendente.
Lembrava que "tinha algo assim mas talvez seja pra outra coisa" —
verifiquei: occFinancialRecord existia mas com guard de occurrenceMode,
servindo Fase 6 (lock-edit) em Rail/Clinica apenas. Decidi NAO unguardar
pra nao ativar lock prematuro em Melissa (isso eh C13).

MelissaEventoPanel.vue: showPaymentRow agora cobre paid tambem; novo
paymentVariant + paymentIcon (pi-check-circle quando pago, pi-dollar
nos outros); paymentLabel inclui "Pago · R$ X,XX"; CSS com 3
modificadores .evento-row--pay-{paid|pending|none} + dark mode.

AgendaEventDialog.vue + useAgendaEventLifecycle.js: novo ref
sessionPaymentRecord (independente do occFinancialRecord). Loader sem
guard, chamado no mesmo lifecycle. Computed paymentSummary cobre 5
estados (paid + verde + paid_at, overdue + vermelho + venceu, pending
+ amber + vence, sem cobranca c/ valor, sem cobranca s/ valor). Nova
linha summary-row entre pi-clock e pi-map-marker em ambas as copias do
Resumo (mobile inline + desktop floating). CSS com 4 classes
.aed-pay-summary-row--{paid|pending|overdue|none}.

@cobranca-atualizada do AgendaEventoFinanceiroPanel agora tambem
dispara loadSessionPaymentRecord pra a linha refrescar quando user
marca pago pelo panel inline.

PROXIMO: cenario 5 (Sandor + Unimed Nacional, R$ 95, convenio).

## [2026-05-18 21:00] session | Cenario 4 OK + barra esquerda verde pra sessao paga
Touched: none (decisao salva em memory/, doc HTML atualizado, sem nova wiki page)
Detalhes: cenario 4 (Joyce R$180 PIX "Ja recebi") testado e passou — toast,
record paid+pix+paid_at, badge $ removido. User pediu sinalizacao visual
pra sessao paga "olhar e saber". Brainstorm de 6 opcoes (check verde
canto, barra esquerda, fundo green-50, $ riscado, so popover, 3 canais
combinados). User escolheu #6 — 3 canais visuais distintos:
- pago: barra verde 4px borda esquerda (emerald-500)
- pendente: badge $ amber canto direito (como antes)
- neutro: nem um nem outro (sem cobranca / virtual)
Implementado em MelissaAgenda.vue (classe ma-evt--paid via classNames,
CSS forca border-left-color !important porque FC seta borderColor inline).
Doc HTML legenda "Indicadores visuais" expandida pros 3 estados (3 mocks
empilhados). Estado-alvo do C4 reescrito. Memoria persistida em
memory/project_agenda_payment_indicators.md (decisao + onde aplicar quando
replicar em Rail/Clinica). HANDOFF atualizado pra apontar C5 como
proximo.

## [2026-05-17 02:30] session | Testes C1-C3 + payment refactor + indicadores visuais + fix modalidade
Touched: agenda-compromisso-fluxo (implicit via HANDOFF.md, sem nova pagina)
Detalhes: rodada de testes manuais dos cenarios do doc viva
src/docs/agenda-compromisso-financeiro-cenarios.html. Cenarios 1, 2 e 3 ok.

CENARIO 1 (bloqueio):
- Fix `bloqueioCobrindo is not defined` em onSelectTime — funcao mora no
  escopo de useMelissaAgenda mas onSelectTime esta em _buildHandlers.
  Passada via deps, mesmo padrao do _openStatusDialog.
- Soft warn de bloqueio sobre slot agora vai DENTRO do dialog (Message
  warn no topo do step 1) em vez de toast atras do overlay. Novo ref
  dialogBlockOverlap no composable + nova prop blockOverlapWarning no
  AgendaEventDialog. Reset nos outros openers.
- Doc HTML cenario 1 expandido em 1a (criar) + 1b (agendar sobre
  bloqueio), com mock visual da Message + comparacao agendador publico.

CENARIO 2 (avulsa sem cobranca):
- Hint chargeMode fonte 0.72rem -> 0.8125rem.
- Card Frequencia avulsa refeito: era empty state convidando configurar,
  agora renderiza como "selecionado" com .aed-pay-summary (Tipo: Avulsa
  / Sessao unica, sem repeticao / botao Editar). Visual identico ao
  estado configurado de pacote.

CENARIO 3 (avulsa cobrar ao salvar):
- Refactor paymentSettlement -> paymentMethod + markPaidNow. UI antiga
  misturava metodo e status num Select unico ("Ja recebi - PIX"). Agora
  2 controles: Select forma (sem prefixo "Ja recebi") + SelectButton
  status (pendente / ja recebi). SelectButton oculto quando metodo='link'.
  Wire em 3 camadas (Dialog -> useAgendaEventActions -> useMelissaAgenda
  handler avulsa + _createPackageContract).
- Indicadores visuais de pagamento: bulk-load 1x em _reloadRange etapa 4
  (financial_records mapeado por agenda_evento_id -> paid|pending|none).
  normalizeForMelissa injeta paymentState + price. Badge $ amber 16px no
  canto superior direito do evento da agenda (so sessao+paciente+nao-
  virtual+!paid). Linha "A receber" amber abaixo do horario no popover
  (MelissaEventoPanel), texto adaptativo.
- BUG FIX pickDbFields whitelist faltando 'modalidade' — todas as sessoes
  avulsas criadas no Melissa ate hoje foram salvas como presencial no DB
  independente da escolha visual. Adicionado ao allowed[]. Gotcha durador
  salvo em memory/project_pickdbfields_whitelist.md.

DOC HTML AMPLAMENTE ATUALIZADO:
- Nova secao topo "★ Indicadores visuais de pagamento" com mocks (badge
  $ + linha popover) e link em violeta no TOC.
- Caixa violeta "Indicadores visuais" em cada cenario relevante (C2-C9)
  descrevendo o que aparece em cada caso.
- C4 ganhou caixa verde "estado-alvo" (sem badge, sem linha — pago).
- Receitas dos C2-C4 atualizadas pros 3 controles novos.

PROXIMO: cenario 4 (Joyce, "Ja recebi (dar baixa)"). Apos passar, seguir
ate C13. Quando todos passarem, replicar em AgendaTerapeutaPage (Rail) e
AgendaClinicaPage (Clinica). HANDOFF.md reescrito com tudo.

## [2026-05-05 23:45] session | Blueprint tabular Melissa + restore pacientes
Touched: none (sem mudança de wiki — handoff em HANDOFF.md)
Detalhes: criou `blueprints/melissa-table-page-blueprint.md` (~530L, 18 seções);
refatorou MelissaCadastrosRecebidos pro padrão (DataTable + frozen action +
view toggle list/grade); criou MelissaAgendamentosRecebidos nativa (substituindo
embed); MelissaPacientes ganhou subheader, sombras, status pills coloridas,
email/phone colunas próprias, mobile pencil+popover, view toggle, fix scroll
mobile (`min-height: 0` em `.mp-list`), botão Restaurar pra arquivados.
Repository: `restorePatient` novo. PatientsCadastroPage statusOpts: +Arquivado.
A66 V2 — user não gostou design, aguarda feedback específico.

## [2026-05-06 12:00] session | MelissaCompromissos refator blueprint
Touched: none (aplicacao direta do blueprint existente - sem mudanca de wiki)
Detalhes: refator de MelissaCompromissos pro melissa-table-page-blueprint preservando o design do row (color stripe + name+badges + descricao + meta inline). DataTable com 3 colunas (Compromisso flex / Atividade 220px / Acoes frozen 140px com toggle+pencil+trash). Sidebar com 2 grupos de filtros: Status (Ativos verde / Inativos amber) e Tipo (Nativos blue / Meus accent), cada um com Limpar filtro proprio. Grid view com cards (color stripe 28px + toggle topo + footer com edit/trash). Subheader explicativo. View toggle persistido em mc.viewMode.v1. Removeu Popover de actions (drawer mobile cobre). Stats: Total/Ativos/Inativos/Tempo total. ESLint 0 errors. UI nao testada em browser ainda.

## [2026-05-06 14:00] session | Melissa 6 Pages blueprint + WhatsApp drawer + commits
Touched: none (sem nova pagina de wiki - aplicacao do blueprint existente)
Detalhes: Sprint F entregue. Blueprint tabular aplicado em MelissaCompromissos
(row design preservado), MelissaGrupos, MelissaTags, MelissaMedicos,
MelissaConversas, MelissaRecorrencias. Dialogs de criar/editar harmonizados
(FloatLabel + IconField + section dividers espelhando PatientsCadastroPage
Identidade). Dialogs "Pacientes do grupo/tag/medico" com cor primary nos
avatares de letras + X de fechar igual .xx-close. ConversationDrawer redesign
estilo WhatsApp (avatar primary, bg papel de parede, bolhas com tail simulada,
time/status overlay no canto inferior direito, compose pill + send circular
verde #00a884). Bug fix em MelissaPacientes: g.cor->g.color em 20 lugares
(repository devolve camelCase, template lia PT-BR e cores nao apareciam).
5 commits criados: 957e912, 6d9b36d, 269b531, 98f7252, 15103ed. Working tree
limpa. HANDOFF.md atualizado.

## [2026-05-06 17:30] session | Melissa drawers: footer pattern AppMenu
Touched: none

## [2026-05-08 00:00] session | Melissa cfg-* nativas + temas + cronometro DB
Touched: none

## [2026-05-08 21:00] session | MelissaPaciente iteracao pos-Fase 8 + AgendaEventDialog reuse
Touched: none (iteracao de UX, sem novas paginas wiki)
Detalhes: 16 commits adicionais apos Fase 8 cobrindo ajustes de UX e
funcionalidades novas pedidas pelo user em sequencia:

LAYOUT/CHROME
- Full-width (removido right:max) — prontuario tem KPIs+tabelas+timeline,
  precisa espaco. Outras Melissa Pages mantem o constraint.
- Sidebar: substituido botao "Configuracoes" por "Voltar para Pacientes"
  (prontuario nao pertence a config). X faz history.back; sidebar btn
  forca /melissa/pacientes.
- Cards da sidebar com flex-shrink:0 (estavam encolhendo, cortando conteudo).
- .mpa-tab com display:flex+gap:12px (filhos estavam colados).

FUNCIONALIDADES NOVAS
- editPatient abre PatientCadastroDialog INLINE (antes redirecionava pra
  MelissaPacientes?edit=).
- openWhatsapp passa string id (era objeto) + detecta store.error pra
  toast warn quando paciente sem telefone.
- addFinancial: dialog inline com createRecord mutation no
  usePatientFinancial.
- goAgendar: dialog inline com createSession mutation, depois evoluiu
  pra usar AgendaEventDialog real via lockType/lockPatient props.
- Botao "Agendar" novo na sidebar Acoes Rapidas (antes so tinha Lancamento).

DIALOG NOVA SESSAO — evolucao em 4 etapas
1. Inline simples (createSession direto)
2. Frequencia integrando useRecurrence (recorrencia semanal)
3. Frequencia estilo AgendaEventDialog (chips Avulsa/Semanal/Quinzenal/
   diasEspecificos + qtd sessoes 4/8/12/personalizar)
4. Header custom (icon + Nova sessao + nome paciente)
5. **Decisao final**: trocar tudo por reuso do AgendaEventDialog real.
   User pediu pra ver dialog completo da Agenda dentro do prontuario.
   Caminho A escolhido: 2 props aditivas (lockType, lockPatient) + slot
   #headerLeft no AgendaEventDialog. 301 specs continuam passando — zero
   regressao nos 5 callsites legacy.

BLOCO DE RECORRENCIAS NA TAB AGENDA
- 5o KPI "Recorrencias" (count de ativas).
- Lista de cards mostrando regras com label legivel (fmtRecurrenceLabel)
  + meta (duracao/modalidade/fim/desde) + acoes inline (cancelar/reativar).
- Toggle "Ver canceladas".

DEBUGGING DIALOG (etapas finais)
- jornada/billing/freq sumiram: causa = lockType so setava step=2 sem
  inicializar form.commitment_id. Fix: watch chama selectCommitment(sessao).
- Resumo lateral sem nome paciente: causa = nao passar paciente_nome/
  avatar/status no eventRow. Fix: pre-popular dos computeds.
- Botao Salvar sumido: causa = footer tem v-if step=2; sem
  presetCommitmentId prop, lifecycle ia step=1. Fix: passar
  :preset-commitment-id no template.

TOTAL: 24 commits no branch. HANDOFF.md reescrito com estado completo +
historico + arquivos novos/modificados + decisoes arquiteturais +
hotspots de drift. Push pendente.

## [2026-05-08 19:30] session | MelissaPaciente Fase 8 — wire-up final (Dialog -> route)
Touched: none
Detalhes: PLANO DE 8 FASES COMPLETO. Os 2 callsites Melissa do
PatientProntuario.vue legacy (3593L Dialog) trocam por router.push pra
/melissa/paciente?id=X. PatientProntuario continua intocado pros 2
callsites legacy (TherapistDashboard, PatientsListPage) quando user nao
esta no layout Melissa.

MELISSAPACIENTE.VUE — wire-up
- useRouter + useConversationDrawerStore.
- close(): emit + router.push('/melissa/pacientes') (volta pra lista).
- editPatient(): emit + router.push('/melissa/pacientes', query: {edit: id})
  pra MelissaPacientes detectar e abrir o cadastroFullDialog automaticamente.
- openWhatsapp(): emit + conversationDrawerStore.openForPatient({id, name,
  phone, avatar_url}) — drawer global desce sobre Melissa sem fechar.
- addFinancial(): emit + toast "Em breve" (Fase 9 — dialog inline).

MELISSAPACIENTES.VUE — wire-up
- Removeu import PatientProntuario, refs prontuarioOpen/prontuarioPatient,
  template PatientProntuario.
- abrirProntuario(p): router.push('/melissa/paciente', query: {id}).
- onMounted: detecta route.query.edit -> abre cadastroFullDialog +
  router.replace pra limpar a query. Permite navegacao MelissaPaciente
  -> MelissaPacientes?edit=X -> auto-open do cadastro.
- Comentario header atualizado.

MELISSAAGENDA.VUE — wire-up
- Removeu import PatientProntuario, refs prontuarioOpen/prontuarioPatient,
  template PatientProntuario.
- abrirProntuarioPorId(id): router.push('/melissa/paciente', query: {id}).
- abrirProntuarioPaciente() / openProntuario(patient) / item kebab
  "Prontuario" todos delegam pra abrirProntuarioPorId.

MELISSALAYOUT.VUE
- Render do <MelissaPaciente> simplificado: so passa @close="fecharSecao".
  Acoes edit/open-whatsapp/add-financial agora ficam internas no MelissaPaciente.

ESLint: 0 errors da minha mudanca (9 errors pre-existentes nos arquivos
tocados, mesmos de antes do diff — confirmados via git stash baseline).

PLANO COMPLETO. Status final por fase:
1. Foundation (composables + skeleton)               — done (Fase 1)
2. Tab Visao Geral (KPIs ricos + timeline + msgs)    — done (Fase 2)
3. Tab Perfil (6 sections stacked + anchors)         — done (Fase 3)
4. Tab Prontuario MVP (evolucao via observacoes)     — done (Fase 4)
5. Tab Agenda (KPIs + filtros + grupos + acoes)      — done (Fase 5)
6. Tab Financeiro (KPIs + tabela + mark paid)        — done (Fase 6)
7. Tabs Documentos + Conversas (KPIs + embeds)       — done (Fase 7)
8. Wire-up final (Dialog -> route)                   — done (Fase 8)

PatientProntuario.vue (3593L) NAO foi deletado — continua usado pelo
TherapistDashboard.vue (homepage do role therapist) e PatientsListPage.vue
(rota /therapist/patients fora do Melissa). Quando user troca pra Melissa
em /account/profile, ele ve a versao nativa (MelissaPaciente).

## [2026-05-08 18:30] session | MelissaPaciente Fase 7 — Tabs Documentos + Conversas
Touched: none
Detalhes: Duas tabs entregues numa sessao (sao mais leves: KPIs + embed
de componentes existentes ja testados).

EXTENSAO patientFormatters.js:
- fmtSize(bytes): B/KB/MB/GB legivel
- DOC_TYPE_LABEL: atestado/receita/laudo/encaminhamento/termo/etc
- chConvLabel: whatsapp/sms/email -> WhatsApp/SMS/E-mail

EXTENSAO usePatientDocuments.js:
- topType computed: { tipo, count, label } do mais comum (DOC_TYPE_LABEL)
- pendentes computed: count de status_revisao === 'pendente'
- sizeTotalFormatted computed: fmtSize(totalBytes)
- Import patientFormatters dentro do composable.

EXTENSAO usePatientMessages.js:
- primeiraMensagem computed (mais antiga, [length-1])
- canais computed: Set de m.channel unicos

MELISSAPACIENTE.VUE — script
- Imports: DocumentsListPage, PatientConversationsTab, chConvLabel
- Removido kpiDocumentos (nao usado mais — substituido por
  documentsHook.total.value direto)

MELISSAPACIENTE.VUE — Tab Documentos (Fase 7)
- Loading state.
- 4 KPIs adaptativos (so renderizam quando ha dados):
  - 01 Total + sizeTotalFormatted
  - 02 Mais comum (label do tipo + count) — opcional
  - 03 Ultimo + relative + dateBR — opcional
  - 04 Revisao pendente (laranja) — opcional, so quando > 0
- DocumentsListPage embedded no card Melissa (mpa-embed) — reusa o
  componente existente que ja faz upload/preview/listagem completa.
  Wrapper ze-ra padding pra ele preencher tudo.

MELISSAPACIENTE.VUE — Tab Conversas (Fase 7)
- Loading state.
- 4 KPIs (so renderizam quando ha mensagens):
  - 01 Mensagens total + canais ("via WhatsApp, SMS")
  - 02 Recebidas + % do total
  - 03 Enviadas + % do total
  - 04 Ultima relative + direction + 1ª contato dim
- CTA "Abrir conversa no drawer" estilo WhatsApp (verde #25d366) que
  emite open-whatsapp pro parent (futuro: integra com
  conversationDrawerStore.openForPatient na Fase 8).
- PatientConversationsTab embedded no mesmo wrapper mpa-embed —
  thread completa com filter/scroll/media.

CSS: ~50L novos pros componentes (mpa-conv-cta + mpa-embed wrapper).
Padrao Melissa: CTA WhatsApp circular pill, embed wrapper transparente.

ESLint: 0 errors da minha mudanca.

PROXIMA: Fase 8 (wire-up final) — substituir Dialog do PatientProntuario
por router.push('/melissa/paciente?id=X') nos 4 callsites Melissa
(MelissaPacientes, MelissaAgenda); decidir se TherapistDashboard e
PatientsListPage tambem migram. PatientProntuario.vue pode ficar (legacy
fallback) ou deletar.

## [2026-05-08 17:30] session | MelissaPaciente Fase 6 — Tab Financeiro completa + mark paid mutation
Touched: none
Detalhes: Tab Financeiro espelha o legacy + adiciona mutation que o
legacy NAO tem (mark/unmark pago direto da tabela).

EXTENSAO patientFormatters.js:
- recordStatus(r): pago | vencido | pendente
- RECORD_STATUS_LABEL map.
- fmtPaymentMethod(v): PIX/Cartao/Dinheiro/Boleto/Transferencia/Convenio
  cobrindo variantes.

EXTENSAO usePatientFinancial.js:
- ref `busy` + `_lastPatientId` interno.
- recordsOrdenados computed (DESC por due_date com fallback created_at).
- markPaid(recordId): UPDATE financial_records SET paid_at=NOW() + auto-
  reload. Retorna {ok, error?}.
- markUnpaid(recordId): UPDATE SET paid_at=NULL + auto-reload (reverte).

MELISSAPACIENTE.VUE — script
- Imports: recordStatus, RECORD_STATUS_LABEL, fmtPaymentMethod.
- markRecordPaid(record) handler: chama markPaid + toast success/error.
- revertRecordPaid(record): chama markUnpaid + toast.

MELISSAPACIENTE.VUE — Tab Financeiro reescrita
- Loading state.
- Empty state com CTA "Novo lancamento" (botao mpa-quick-btn--cta).
- 3 KPIs (Pago / Pendente com proxVenc / Em atraso com cor adaptativa).
- Header "Lancamentos" com badge count + botao "+ Novo" no canto.
- Tabela 6-col: Vencimento (date mono+rel) | Descricao | Forma | Valor
  (mono right) | Status pill colorida (pago verde / vencido vermelho /
  pendente azul) | Action button.
- Action: pi-check (verde) pra marcar pago, pi-undo (amarelo) pra reverter.
- border-left adaptativa por status (verde pago / vermelho vencido /
  azul pendente).
- Mobile: tabela colapsa em cards 2-col 4-row (date|amount / desc /
  method|status / action).

CSS: ~190L novos pros componentes (mpa-fin__table/row/date/desc/method/
amount/status/action + responsive). Padrao Melissa: status pills com
color-mix, JetBrains Mono pra valores, header cell uppercase letter-
spacing.

ESLint: 0 errors da minha mudanca.

## [2026-05-08 16:30] session | MelissaPaciente Fase 5 — Tab Agenda completa
Touched: none
Detalhes: Tab Agenda com KPIs, filtros, agrupamento por mes e acoes
rapidas (mark realizada/falta/cancelar). Espelha o legacy.

EXTENSAO patientFormatters.js: +2 helpers
- fmtHourShort (HH:MM 24h pt-br) e fmtDayShort (DOW abbreviado pt-br
  sem ponto) — usados na coluna data dos cards.

EXTENSAO usePatientSessions.js: mutation + busy flag
- Novo ref `busy` pra disable de buttons durante mutation.
- _lastPatientId guardado pra auto-reload depois de mutation.
- Nova funcao `updateStatus(sessionId, novoStatus)` que faz
  supabase.from('agenda_eventos').update({status}) + auto-reload da
  lista. Retorna {ok, error?}.

MELISSAPACIENTE.VUE — script
- agendaFilter ref ('all' default) + AGENDA_FILTERS array com 6 opcoes
  (Todas, Proximas, Passadas, Realizadas, Faltas, Canceladas).
- agendaSessoesFiltradas computed: filtra sessoes por future/past/status.
- agendaAgrupadas computed: agrupa por "Mes de YYYY" mantendo ordem DESC.
- updateSessionStatus(ev, status, msg) handler que chama
  sessionsHook.updateStatus + toast de sucesso/erro.
- Removido `void toast` (toast usado de verdade agora).

MELISSAPACIENTE.VUE — Tab Agenda reescrita (substitui placeholder Fase 1)
- 4 KPI cards no padrao Visao Geral (numerados 01-04):
  - 01 Total + cap "sessoes registradas"
  - 02 Realizadas + cap "% do total"
  - 03 Faltas + cap "+ N cancel."  (cor vermelha quando > 0, cinza quando 0)
  - 04 Proxima + relative + datetime
- 6 filter chips redondas (estilo Melissa: cor primary quando active).
- Empty state contextual (sem sessoes vs filtro vazio).
- Grupos por mes com header (label + badge count).
- Cards com 3 colunas: data column (DOW + dia + hora curta) | main
  (status tag + chips modalidade/duracao + relative + titulo + note) |
  actions (3 buttons: ok/warn/danger com tooltip + cor adaptativa hover).
- Mobile: stack date+main em 2 cols; actions full-width abaixo.

CSS: ~150L novos pros componentes (mpa-ag__group/list/item/date/main/
actions). Padrao visual Melissa: data column estilo calendario, actions
hover muda cor por intent (verde realiz / amarelo falta / vermelho cancel).

ESLint: 0 errors da minha mudanca.

## [2026-05-08 15:30] session | MelissaPaciente Fase 4 — Tab Prontuario MVP
Touched: none
Detalhes: O legacy PatientProntuario.vue tem a aba Prontuario como
PLACEHOLDER ("Em breve"). MVP entregue aqui supera o legacy: usa
agenda_eventos.observacoes como nota evolutiva (pq nao tem schema de
anamnese/clinical_notes ainda).

ESTADO + COMPUTEDS adicionados:
- pronFilter ref ('com-evolucao' default) + PRON_FILTERS array com 5
  opcoes (Com evolucao, Todas, Realizadas, Faltas, Cancelamentos).
- pronSessions computed: filtra sessions por status/observacoes presentes.
- sessoesComEvolucao computed: count de sessoes com observacoes nao-vazia.

TEMPLATE Tab Prontuario (substitui placeholder Fase 1):
- Hint banner top: "Prontuario em construcao", explica que usa observacoes
  de sessoes como historico evolutivo.
- 4 mini-stats em grid responsivo: com evolucao / realizadas / faltas /
  total. Cada uma colorida + icone + value 800.
- 5 filter chips redondas (estilo Melissa): com-evolucao default; troca
  pra todas/realiz/falt/cancel.
- Empty state contextual:
  - Se nao tem sessoes: "Quando atender este paciente..."
  - Se filtro 'com-evolucao' e zero: "Use o campo Observacoes ao editar
    sessao..."
  - Outro filtro: "Tente outro filtro acima."
- Lista de sessoes (pron-list) com:
  - border-left colorida por status (verde realiz / vermelho falta /
    amarelo cancel / cinza default)
  - head com data + relative + chips status/modalidade/duracao
  - titulo opcional (titulo_custom || titulo)
  - block "Evolucao" quando tem observacoes (background medium, border-
    left primary, label uppercase com icone, texto pre-wrap)
  - mensagem "Sem evolucao registrada" italico cinza quando nao tem
- Roadmap card (border-dashed) listando 4 features futuras: anamnese
  estruturada / plano terapeutico / evolucao por temas / assinatura
  digital + LGPD Art. 18.

CSS: ~200L novos pros componentes (mpa-pron-hint/stats/filters/list/
item/roadmap). Padrao visual Melissa: chips redondas estilo MelissaTags,
border-left adaptativa, monospace inutilizado.

ESLint: 0 errors da minha mudanca.

## [2026-05-08 14:30] session | MelissaPaciente Fase 3 — Tab Perfil (6 sections stacked)
Touched: none
Detalhes: Substituiu o placeholder da aba Perfil por 6 sections stacked
com anchors no MelissaPaciente. Diferente do PatientProntuario legacy que
usava PrimeVue Accordion (1 painel aberto por vez), o Melissa nativo
mostra todos os 6 cards stacked com scroll suave do sidebar sub-nav pra
cada anchor. Mais legivel em desktop, mais rapido pra escanear.

EXTENSAO de patientFormatters.js: +5 formatters
- pickField (ja existia computed local; agora helper compartilhavel)
- onlyDigits, fmtCPF (000.000.000-00), fmtRG (passthrough), fmtPhoneMobile
  ((XX) 9XXXX-XXXX), fmtGender (Masculino/Feminino/Nao-binario/Outro),
  fmtMarital (Solteiro/Casado/Divorciado/Viuvo/Uniao estavel).

MELISSAPACIENTE.VUE — script:
- 30+ field computeds usando pickField (cobre snake_case + camelCase do
  schema): birthValue, telefone/Alternativo, email/Alternativo, genero,
  estadoCivil, naturalidade, ondeNosConheceu, encaminhadoPor, observacoes,
  notasInternas + 8 campos de endereco (cep/pais/cidade/estado/endereco/
  numero/bairro/complemento) + 5 dados adicionais (escolaridade/profissao/
  nomeParente/grauParentesco/telefoneParente) + 4 responsavel.
- groupNames/groupLabel/groupCountLabel pra Origem.
- scrollToProfileSection(key) que liga sidebar sub-nav -> nextTick ->
  scrollIntoView do anchor #mpa-perfil-XXX. Em mobile fecha o drawer.

MELISSAPACIENTE.VUE — template Tab Perfil:
- 1. Informacoes Pessoais: 2-col (Dados de cadastro: nome/data nasc com
  idade/genero/estado civil/CPF/RG/naturalidade) + (Contato: tel/tel-alt
  com tel: links + e-mail principal/alt com mailto: + Origem: grupos/tags
  chips/onde nos conheceu/encaminhado por). Observacoes full-width quando
  preenchido.
- 2. Endereco: grid 2-col com 8 fields (CEP/pais/cidade/estado/endereco/
  numero/bairro/complemento).
- 3. Dados Adicionais: grid 2-col com escolaridade/profissao/parente/grau/
  tel parente.
- 4. Responsavel: 1-col com nome/CPF/tel + observacao block textual.
- 5. Anotacoes Internas: card com hint lock + textblock min-height.
- 6. Sessoes: lista compacta scrollable (max-height 360px) com titulo/
  data/duracao/modalidade chips + tag status.

CSS: ~250L novos pros componentes (mpa-fields/field-row/field-grid-2/
field-block/sess/sess-list). Pattern visual Melissa: cards com label
uppercase, separadores horizontais sutis, links com cor primary, monospace
pra CPF/RG/CEP.

ESLint: 0 errors da minha mudanca.

## [2026-05-08 13:00] session | MelissaPaciente Fase 2 — Tab Visao Geral completa
Touched: none
Detalhes: Reescreveu a aba Visao Geral do MelissaPaciente substituindo o
placeholder por uma versao 1:1 do PatientProntuario.vue legado, mas com
estilo Melissa nativo.

NOVO: src/features/patients/utils/patientFormatters.js (~165L)
- Helpers compartilhaveis extraidos do PatientProntuario: parseDateLoose,
  fmtDateBR, fmtDateTimeBR, fmtCurrency, fmtRelative, sessionDuration,
  calcAge. STATUS_LABEL/SEVERITY pra sessoes. tagStyle com luminance auto
  (texto preto/branco baseado em contraste WCAG-ish). Sera usado pelas
  Fases 3-7 e finalmente pelo PatientProntuario tambem (Fase 8).

EXTENSAO de composables:
- usePatientSessions ganha computed `ultimasAtendidas` (top 6 sessoes
  realizadas/faltadas/canceladas pra Timeline). Refinou totalRealizadas/
  Faltas/Canceladas pra usar regex (cobre variantes pt-br).
- usePatientFinancial ganha computed `statusFinanceiro` ({ emDia, proxVenc,
  totalPendente, totalPago, vencidos }) pra alimentar o KPI 02 com info
  detalhada.

MELISSAPACIENTE.VUE — Visao Geral (Fase 2 done):
- 4 KPI cards ricos (era 4 simples na Fase 1):
  - 01 Sessoes: realizadas + total + faltas + cancel.
  - 02 Pagamento: emDia/atraso + proxVenc + pendente, com cor adaptativa
    (vermelho quando atrasado, primary quando ok).
  - 03 Proxima sessao: relative + datetime + modalidade.
  - 04 Mensagens: ultimaMensagem relative + direction + count.
- Grid 2-col abaixo: Timeline (1.4fr) + coluna direita (1fr) com
  Mensagens recentes + Notas/observacoes.
- Timeline com dot colorido por status (verde/vermelho/amarelo) +
  STATUS_LABEL/SEVERITY do utils + chips modalidade/duracao + nota
  observacoes inline.
- Mensagens recentes com border-left colorida (verde=in / azul=out) +
  meta direction + relative + body 3-line clamp.
- Notas e observacoes com card papel + label uppercase + icone lock
  pras internas.
- Removeu kpiEmAberto/Atrasado nao usados (statusFinanceiro encapsula).

ESLint: 0 errors. Working tree limpa antes do commit.

## [2026-05-08 11:30] session | MelissaPaciente Fase 1 (foundation: composables + skeleton + slug)
Touched: none (sem mudanca de wiki)
Detalhes: User escolheu "Full rewrite Melissa nativo" pra portar
PatientProntuario.vue (3593L Dialog) pro Melissa. Plano em 8 fases (2-8 sao
cada tab/wireup, sessao dedicada). Fase 1 entregue:

5 COMPOSABLES NOVOS em src/features/patients/composables/:
- usePatientDetail.js (108L) — patients + groups + tags via 4 queries
  (getPatientById, getPatientRelations, getGroupsByIds, getTagsByIds).
  Espelha 1:1 a logica de loadDetail() do PatientProntuario L893-953.
- usePatientSessions.js (83L) — agenda_eventos limit 100 ordenado desc +
  computeds proximaSessao/ultimaSessao/totalSessoes/totalRealizadas/
  totalFaltas/totalCanceladas.
- usePatientFinancial.js (82L) — financial_records (type=receita) limit 100
  + computeds totalRecebido/EmAberto/Atrasado/ultimoPago.
- usePatientMessages.js (64L) — conversation_messages limit 200 + computeds
  recentes (top 4)/totalIn/totalOut/ultimaMensagem.
- usePatientDocuments.js (70L) — documents (deleted_at IS NULL) limit 200
  + computeds total/totalBytes/tiposCount/ultimo.

MELISSAPACIENTE.VUE NOVO (1190L) em src/layout/melissa/:
- Prefixo CSS .mpa-* (Melissa PAciente). Chrome glass + drawer mobile +
  right: max(...) >=1024px (mesmo padrao MelissaAgendador/Negocio).
- Header: avatar + nome + ageLabel + pronomes + status/convenio Tag +
  risco-elevado pill + actions (Conversar / Editar / Close).
- Subheader condicional: banner risco elevado.
- Body 2-col: sidebar 320px (esquerda, drawer no mobile) + main flex 1.
- Sidebar contém 4 cards: Acoes Rapidas (Conversar/Editar/Lancamento) +
  Navegacao (7 tabs com icones coloridos) + Sub-nav Perfil (visivel so
  quando aba Perfil ativa, 6 secoes) + Vinculos (chips de grupos+tags).
- Main: 7 tabs com placeholders ("Em desenvolvimento — Fase X"). Aba
  Visao Geral ja mostra 4 KPIs reais via composables (sessoes totais,
  em aberto, mensagens, documentos).
- Props :patient-id; emits close/edit/add-financial/open-whatsapp.
- Watch immediate em props.patientId, dispara loadAll() via Promise.all
  dos 5 composables.

MELISSALAYOUT.VUE atualizado:
- Import MelissaPaciente.
- SECOES.paciente entry novo (label/icon/descricao).
- 'paciente' adicionado ao MELISSA_NON_CONFIG_SLUGS.
- Render condicional com :patient-id="String(route.query.id || '')" —
  navegacao via /melissa/paciente?id=xxx.

NAO ALTERADO: PatientProntuario.vue continua intocado nos 4 callsites
(TherapistDashboard, MelissaAgenda, MelissaPacientes, PatientsListPage).
Migration acontece nas Fases 2-8. Fase 8 troca os callsites no Melissa.

ESLint: 0 errors da minha mudanca. 2 errors pre-existentes em MelissaLayout
(duplicate key 'financeiro' L242, empty block L1130) — nao toquei aquelas
linhas. PatientProntuario tem 2 outros pre-existentes. Working tree:
MelissaLayout.vue + 6 arquivos novos.

## [2026-05-08 09:30] session | Chrome+preview em 7 paginas Melissa (LinkExterno preview novo)
Touched: none (sem mudanca de wiki - aplicacao do pattern existente)
Detalhes: Aplicou o chrome `right: max(6px, min(50%, calc(100% - 1006px)))`
em 6 paginas tabulares (CadastrosRecebidos .mcr / Recorrencias .mr / Grupos
.mg / Tags .mt / Compromissos .mc / Medicos .mm) - so o tamanho de janela,
sem preview, conforme pedido pelo user. Adicionou novo @media (min-width:
1024px) ao final de cada arquivo (cada um nao tinha esse breakpoint ainda).

MelissaLinkExterno (.ml) ganhou tratamento completo: chrome + sidebar
restruturada (2-col com aside agora a ESQUERDA, antes era a direita) +
mobile drawer pattern (Teleport pro #ml-mobile-drawer-target, transitions,
backdrop, botao Menu mobile-only) + 3-way teleport do preview (mobile=topo
do main / mid-desktop=bottom da sidebar / wide-desktop>=1340=floating glass).
Sidebar agora com Como funciona + Boas praticas (movidos da .ml-side direita)
+ scroll proprio. Sem cfg toggle (nao havia necessidade conceitual).

Componente novo: src/components/cadastro/CadastroExternoPreview.vue (~350L).
Phone-frame 260px estilo AgendadorPreview replicando o CadastroPacienteExterno
publico: nav (logo Psi + chip verificado), hero (avatar 38px + nome split
firstName/lastName em accent + work_description label + clinic name), stepper
4 dots (1 active), card etapa 1 (numero decorativo + tag "Etapa 1 de 4" +
title "Sobre voce" + 3 input bars + CTA "Continuar"), powered by. Recebe
:token prop e busca info do convite via mesma edge function que o publico
(get-intake-invite-info), watch refetcha quando token rotaciona. Sem token
ou sem dados, fallbacks pra "Profissional" + iniciais.

ESLint: 0 errors da minha mudanca. 2 errors pre-existentes em
MelissaRecorrencias.vue (totalDone unused L235, v-for/v-bind:key L584) -
nao toquei aquelas linhas. Working tree: 9 arquivos modificados +
src/components/cadastro/ (untracked). Nao commitado, nao testado em browser.

## [2026-05-08 07:55] session | MelissaAgendador preview celular teleport 3-way
Touched: none (aplicacao do padrao MelissaNegocio - sem mudanca de wiki)
Detalhes: Replicou o padrao floating preview do MelissaNegocio em
MelissaAgendador.vue (+145L). Importou AgendadorPreview (phone-frame ja
existente do legacy ConfiguracoesAgendadorPage). Adicionou ref isWideDesktop
+ matchMedia('(min-width: 1340px)') + computed previewTarget com 3-way
branching: mobile -> #mag-main-preview-target (topo do main, acima de tudo,
DIFERENTE do MelissaNegocio que vai pro drawer); mid-desktop (1024-1339) ->
#mag-sidebar-preview-target (dentro da sidebar apos Status/Resumos);
wide-desktop (>=1340) -> #mag-floating-preview-target (painel flutuante glass
fora do fake dialog, 320px de largura, ancorado a +14px do right edge da
.mag-page). Adicionou regra `right: max(6px, min(50%, calc(100% - 1006px)))`
em .mag-page no @media >=1024px (necessario pra abrir espaco a direita pro
floating). CSS: .mag-floating-preview com glass igual ao fake dialog;
placeholders com display:contents; hide rules por breakpoint. Card de preview
usa mag-w--side e perde fundo/borda no floating (glass do painel ja faz papel).
ESLint 0 errors. Working tree: src/auto-imports.d.ts (auto-gerado) +
MelissaAgendador.vue. Nao commitado, nao testado em browser ainda.

## [2026-05-11 10:50] session | Recorrencia: expandir + materializar + view lista
Touched: [[recorrencia-agenda]]
Detalhes: 6 commits criados e pushed (8b0e633..39cf017).

TIME PICKER do AgendaEventDialog (commit 988a4e5):
- Header dinamico (header-dot + "Nova {commitment.name}" + subtitulo
  "Inicio da sessao e duracao"). Inicio + Termino lado a lado (Termino
  readonly via fimDateTime). Card destacado de Termino removido.
- Picker virou DataTable (.aed-patient-dt) + Tags Arquivado/Inativo + sort
  Ativo>Inativo>Arquivado.
- Cadastro completo INLINE via PatientCadastroDialog (botao pi-id-card)
  em vez de redirecionar pra rota nova — nao vaza do layout Melissa.
  Usa prop hideViewListButton adicionada antes pra esconder "Salvar e
  ver pacientes".
- Mini calendar (.mc-mini) no time picker; chips de duracao rapida
  (30/50/60/90m); cards .aed-card; popovers de ajuda.

EXPANSAO DE RECORRENCIA cross-layout (commit 39cf017): 3 composables
compartilhados ganharam loadAndExpand — antes so AgendaTerapeutaPage
e AgendaClinicaPage expandiam, deixando widgets do Melissa com 1 sessao
de uma serie de 4. usePatientSessions.load (range -6mo a +12mo, filtra
por patient_id), useMelissaEventos._fetchRange (range visivel),
useMelissaTodasSessoesPaciente.fetch. normalizeEvent aceita shape de
virtual (paciente_nome/patient_name) alem de joined query.

MATERIALIZACAO em 4 caminhos: UPDATE em id virtual "rec::..." quebrava
com "invalid input syntax for type uuid". Corrigido em
usePatientSessions.updateStatus (aceita row inteira, materializa),
useAgendaEventActions watcher (emit updateSeriesEvent com row),
MelissaLayout.updateEventoStatus (detecta virtual, delega passando
row: ev — sem isso dialogEventRow ficava vazio e criava row orfa sem
patient_id), MelissaPaciente wire-up (@updateSeriesEvent aponta pro
handler certo agora), useMelissaAgenda.onUpdateSeriesEvent (aceita row
do chamador, guard contra rid null, error check no maybeSingle).

VIEW LISTA MelissaAgenda (commit 279b4f7): listWeek -> custom listAll
(duration { years: 2 }, centrada via gotoDate(hoje - 1 ano)). Banner
showRecurrenceHint aparece em day/week/month com botao "Ver na lista".
Sticky day header (.fc-list-day) com z-index 3 + bg opaco — antes
.fc-event passava por cima conforme scroll. View toggle dos botoes
manuais -> PrimeVue SelectButton.

VISUAL EVENTO INATIVO: classNames=['ma-evt--inactive-patient'] em
fcEvents quando paciente_status === Arquivado|Inativo (borda tracejada
+ opacidade 0.58 + italico em list view). useAgendaEventPickerBilling
+ AgendaEventDialogV2: picker mostra TODOS os pacientes ordenados
Ativo>Inativo>Arquivado, nao-Ativos com Tag colorida + disabled +
tooltip. selectPaciente bloqueia non-Ativo (defesa em camadas, 3
specs novas).

OUTROS: services nome unico por owner (case-insensitive); FC touch
defaults centralizados em src/features/agenda/utils/fcDefaults.js
aplicado em 4 calendars; props hideViewListButton em
ComponentCadastroRapido + PatientCadastroDialog pra uso in-flow.

Database backup gerado: backups/2026-05-11/ (138 tabelas, 141 FKs).
Dashboard regenerado.

## [2026-05-11 17:00] session | AgendaEventDialog redesign completo + 2º dialog WIP
Touched: HANDOFF.md (reescrito do zero)
Detalhes: sessao longa de refator visual + UX do AgendaEventDialog.
Headers dos 4 cards (Paciente, Data/Horario, Sessao/Honorarios, Frequencia)
com altura fixa 40px, label so mobile, acoes a direita. Card Paciente
ganhou toggle Presencial/Online com pi-pencil substituindo SelectButton;
mini-links Editar/Limpar no lugar dos botoes redondos. Card Data e
Horario com body em 2 linhas (Data · Duracao / Inicio → Termino). Card
Sessao/Honorarios (renomeado de Pagamento) com Select dropdown default
particular + 3 estados (gratuito/empty/configurado-resumo). Card Extras
renomeado, com botao ? abrindo popover educativo. Layout 50/50 via
.aed-row-50 (Paciente|Data e Sessao|Frequencia).

DIALOGS NOVOS:
- serviceDialogOpen: cada servico vira card individual com preco unit,
  total, botoes colapsaveis (Aplicar desconto, Alterar quantidade);
  desconto mostra calculo em vermelho; footer fixo com Valor desta
  sessao em pill tracejada primary; hint educativo Unidades vs
  Recorrencia
- freqDialogOpen: empty/resumo, 4 sub-cards (.aed-freq-section: Tipo,
  Dias, Quantidade, Proximas), chips renovados (.freq-tab borda solida
  + variant 2-line com 1 mes/4 sessoes), proximas ocorrencias com
  separador por mes + referencia relativa (em 2 semanas/em 1 mes).
  "Como interpretar o valor" REMOVIDO.

CONCEITO PACOTE (recorrencia >= 2):
- isPacote computed: criando >=2 OU editando hasSerie
- pacoteTotal = totalFromItems × totalOcorrencias
- Header dialog adapta: "Pacote · 4 Sessoes" / "Sessao do Pacote · Sessao"
  / "Editar Sessao" / "Nova Sessao"
- Resumo: modalidade vira "Presencial · Pacote"; wallet mostra total
  pacote; linha extra "4× R$ 40 = R$ 160"
- Status da Sessao escondido em pacote
- pluralCommitment PT-BR (Sessao→Sessoes, Analise→Analises, ão→ões)

MODO EDIÇAO:
- Cadastro Rapido NAO aparece
- Cadastro Completo + toggle Modalidade + Ajustar Horario: disabled
  com tooltip explicativo
- time-hero ganha --readonly (sem cursor pointer)

OUTROS: animacao de Dialog + backdrop blur REMOVIDOS (so nativo
PrimeVue); DataTable picker paciente coluna Acao agora frozen
alignFrozen=right; lista Recorrencias Aplicadas com numeracao 1/2/3
em badge primary; badge "atual" → "selecionado".

2º DIALOG EMPILHADO (WIP — BLOQUEIO PRA AMANHA):
- useMelissaAgenda.js: refs novos occDialogOpen/EventRow/StartISO/EndISO
- onEditSeriesOccurrence agora abre 2º dialog (em vez de mutar
  dialogEventRow in-place silenciosamente)
- _buildHandlers recebe occDialog* via deps (sem isso dava
  ReferenceError em runtime)
- MelissaLayout.vue: 2º AgendaEventDialog mountado paralelo, refs
  destruturados como agendaOccDialog* (refs aninhados nao auto-
  unwrappam no template — pattern conhecido do projeto)
- Status: ABRE, mas user reportou "nao é essa janela que tem de
  abrir" — investigar amanha. Provavelmente precisa de prop pra
  esconder Frequencia + Recorrencias Aplicadas no 2º dialog e
  ajustar titulo pra "Editar Ocorrencia"
- Pendente replicar em Rail (AgendaTerapeutaPage L1630 + L3080) e
  Clinica (AgendaClinicaPage L1119 + L2398) DEPOIS de estabilizar
  no Melissa

Mudancas NAO commitadas: 5 arquivos (AgendaEventDialog.vue + dois
QuickCreateDialog + MelissaLayout + useMelissaAgenda). HANDOFF.md
reescrito do zero documentando tudo.

## [2026-05-12 17:55] session | occurrenceMode no 2º dialog da agenda
Touched: recorrencia-agenda

## [2026-05-13 14:00] session | pesquisa fluxo agenda Cliniko SimplePractice TherapyNotes
Touched: none
nTouched: agenda-billing-pesquisa-mercado, index

## [2026-05-13 21:00] session | Pesquisa mercado agenda billing
Touched: agenda-billing-pesquisa-mercado, index

## [2026-05-14 sessao continua] session | AgendaEventDialog testes manuais + correcoes
Touched: none (apenas logs detalhados; sem nova pagina wiki)
Detalhes: User testou fluxo de criacao avulsa (Henrique Lima Souza) e
recorrente (Donald Winnicott, 4×R$40) passo-a-passo. Achados/correcoes:
(1) Bug badge financeiro "Despesa" — campo `type` faltava em BASE_SELECT
de useFinancialRecords.js (caia em else → "Despesa"). Fix: adicionar type
no SELECT. (2) E5 toggle Presencial/Online: removido :disabled="isEdit"
(habilitado em ediçao tambem). (3) E6 Ajustar Horario: trocado por
v-if="!isEdit || !hasSerie" — visivel em criacao E em avulsa em edicao;
escondido em série recorrente (politica "esconder em vez de disabled"
salva na memoria, vale apenas pra agenda). (4) Botao cog + popover sobre
horarios online no time picker — padrao espelhado do Card Extras, linka
pra /melissa/agenda-config (ou /configuracoes/agenda fora do Melissa).
(5) Bug visual: pill --current + --online-cfg perdia destaque selected
porque online-cfg !important ganhava da cascade. Fix: regra combo com
mais especificidade. (6) Time picker vazava dia/hora/duracao pro card
principal quando fechado sem confirmar — snapshot ao abrir + revert no
@hide se _tpCommitted=false (added Cancelar button no footer). (7)
Opção C1 implementada — checkbox bool gerarCobrancaAoSalvar substituido
por SelectButton chargeMode com opcoes dinamicas:
  - Avulsa: Não / Gerar cobrança
  - Recorrente: Não / Pacote único / 1 por sessão
Handler em useMelissaAgenda agora suporta 3 modos: 'session' (1
financial_record, igual Fase 1 original), 'package' (1 billing_contract
inline em vez de confirm.require pós-save), 'per_session' (materializa N
agenda_eventos + cria N financial_records via RPC, respeitando
recurrence_exceptions). _offerBillingContract removido (codigo morto).
useAgendaEventActions.gerarCobrancaAoSalvar → chargeMode. ESLint: 0
erros novos. Vitest useAgendaEventComposer.spec: 76/76 passed.

## [2026-05-13 22:00] session | Fase 1 — drop agenda_excecoes + render bloqueios cinza
Touched: agenda-compromisso-fluxo
Detalhes: Fase 1 da auditoria fase-a-fase concluida. Auditoria revelou
agenda_excecoes orfa (0 refs em src/, embora policies+trigger+enums
existissem) e bloqueios nunca renderizados no FullCalendar (so impediam
criacao). Aplicado: (1) migration 20260513000001_drop_agenda_excecoes.sql
dropa tabela+enums+trigger; (2) agendaMappers.buildBloqueioBackgroundEvents
renderiza dia-cheio/com-hora/recorrente como background event #6b728033;
(3) composable useAgendaBloqueios reusavel (load aceita owner unico OU
array); (4) wire nos 3 layouts (Melissa via useMelissaAgenda+MelissaAgenda,
Rail via AgendaTerapeutaPage, Clinica via AgendaClinicaPage com multi-owner);
(5) docs/schema_map.md e db.config.json limpos. ESLint 0 novos errors;
agendaMappers.spec 40/40 passed. Pendente: rodar migration no banco local
+ validacao visual nos 3 layouts. Plano de 8 fases salvo em
[[agenda-compromisso-fluxo]]; pesquisa de mercado em [[agenda-billing-pesquisa-mercado]].

## [2026-05-20 evening] session | Fase 0+0.5 sweep de padronização pré-MVP
Touched: none (durable em development/02-auditoria/ + blueprints/ + memory)
Entregue: 3 blueprints (repository, composable, quick-create universal) + AUDIT_BASELINE.md (51 divergências em 6 módulos) + PADRONIZACAO.md (estratégia 4 fases) + DESIGN_BILLING_ORCHESTRATOR.md + 4 migrations + 1 seed do schema clínico (NÃO executadas) + scaffold features/tenantship/ (7 arquivos). Próximo: Fase 1 Módulo 1 (Home/Components).

## [2026-05-20 evening] session | M1 padronização Home/Components concluído
Touched: none (durable em development/02-auditoria/PADRONIZACAO.md + AUDIT_BASELINE.md + memória)
Módulo 1 da Fase 1 fechado: features/medicos/, features/insurance/, ComponentCadastroRapido refatorado (8 callers preservados), TEST_ACCOUNTS extraído, .bak deletado, topbar dev button ganhou switcher de layout + atalhos M1. M1.6 (MelissaLayout 90 imports) deferida pra sessão dedicada. Próximo: M2 Pacientes.

## [2026-05-20 evening] session | M2 Pacientes refatorado em batch
Touched: none (durable em development/02-auditoria/PADRONIZACAO.md + AUDIT_BASELINE.md + memória)
Módulo 2 da Fase 1 fechado sem pausas de teste (estratégia revisada). patientsSelects.js criado com 11 constantes. patientsRepository.js estendido com 15 funções novas. 8 composables refatorados em paralelo (usePatients, usePatientDetail, usePatientFinancial, usePatientSessions, usePatientMessages, usePatientDocuments, usePatientRecurrences, usePatientSupportContacts). Zero supabase.from() em qualquer composable de patients. _lastPatientId DENTRO da function nos 3 composables que tinham. 9 audit items resolvidos. Aguarda teste batch do user antes de seguir M3.

## [2026-05-20 evening] session | M3+M4+M5+M6 foundation em batch único
Touched: none (durable em development/02-auditoria/PADRONIZACAO.md + memória)
Sweep da Fase 1 completa em foundation. M3 (prontuário): 6 files em patients/prontuario/, ativa quando migrations 0.5.B rodarem. M4 (financeiro): 9 files em features/financeiro/, old composables em paralelo, Fase C bloqueada pelas decisoes #2/#3/#6. M5 (tenantship): MembersPage criada, rota TODO. M6 (notificacoes): noticesSelects + conversations foundation, channel factory deferido. Total ~21 files novos nesta sessao. Aguarda teste batch consolidado.

## [2026-05-20 evening] session | M5 quick wins fechados
Touched: none
Rota /admin/members registrada em routes.clinic.js. Migration 20260520000005_accept_tenant_invite_rpc.sql criada (SECURITY DEFINER + lock FOR UPDATE). tenantInvitesRepository.acceptInvite real (nao mais stub). SaasTenantFeaturesPage refatorada via novo tenantFeatureAdminService.js. SetupWizardPage 2648 linhas deferido pra sessao dedicada.

## [2026-05-21 morning] session | Fase 2 hotspots Graphify
Touched: none
convertToPatient de-dup: nova funcao markIntakeConverted no patientsRepository, 2 pages refatoradas. Supabase client triplo: finding defasado, so 1 instancia. 348 nos fracos: graphify update rodou pra refresh apos M1-M6+Fase2. Setup Wizard cohesion: parcial (SaasTenantFeaturesPage feito em M5 quick win); SetupWizardPage 2648 linhas adiado.

## [2026-05-21 morning] session | Fase 3 Asaas Gateway Tier 1 — Fase A foundation
Touched: none
DESIGN_ASAAS_GATEWAY.md completo. 7 arquivos novos: 2 migrations (tables+RLS) + client service + 3 Edge Function stubs. Webhook existente trata WhatsApp credits — extensao pra financial_records eh Fase B. Decisao modelo negocio (A/B/C) pendente. User precisa: conta Asaas, API keys, webhook config, ENV vars no Supabase. Stops bem marcados pra Fase B (implementacao real).

## [2026-05-21 morning] session | Fase 3 — Compliance CFP #5/#8/#9
Touched: none
2 migrations (profiles registration + specialties+joinM:N+RLS) + 1 seed (33 specialties) + 1 service (specialtiesService.js). #8 nome social ja estava integrado. #6 consent forms e #7 assinatura adiados — schemas (document_templates+document_signatures) existem, falta UI workflow.

## [2026-05-21 afternoon] session | Compliance CFP #6 + #7 fechados
Touched: none (durable em development/02-auditoria/PADRONIZACAO.md + memoria padronizacao_sweep)

Fechou Fase 1.2 Compliance basico BR do ROADMAP. 5 commits tematicos.

#6 (consent forms) — biblioteca de templates LGPD-compliant:
- Migration 20260521000005 estende CHECK constraint de document_templates.tipo
  com 'termo_lgpd' + 'autorizacao_gravacao'
- Seed seed_060 insere 2 templates globais novos (Consentimento LGPD com
  Art. 18 direitos do titular + Autorizacao para Gravacao de Sessao) +
  UPDATE no tcle_online amend cláusula LGPD explicita
- Biblioteca completa pos-amend: TCLE, tcle_online (telehealth),
  autorizacao_menor (TCLE menores), termo_sigilo, termo_lgpd, autorizacao_
  gravacao + 9 outros tipos existentes

#7 (assinatura eletronica no portal) — fluxo end-to-end:
- Migration 20260521000006: 3 RPCs (sign_document_by_signature_id +
  sign_document_by_token + get_signable_document_by_token). IP/UA
  capturados SERVER-SIDE via inet_client_addr() e current_setting
  ('request.headers') — anti-spoof. Hash SHA-256 vem do cliente
  pra integridade
- Migration 20260521000007: RPC list_my_signatures que cruza auth.uid()
  por 3 caminhos (signatario_id, signatario_email, patient.user_id)
- DocumentSignatures.service ganha 4 wrappers: signByPortal,
  signByToken, getSignableDocumentByToken, listMySignatures
- useDocumentSignatures composable novo (Tipo A blueprint)
- PortalDocumentos.vue (nova) — lista pendencias do paciente logado
  com KPIs + filtro + botao "Assinar agora" que aponta pra share link
- portal.menu.js ganha item "Documentos > Para assinar"
- SharedDocumentPage.vue estendida: painel azul abaixo do preview
  com aviso LGPD/CFP + checkbox aceite + selecao multi-signatario
  + botoes Assinar/Recusar com loading + computa SHA-256 do PDF
  baixado antes do sign
- DocumentSignatureDialog (terapeuta-side, ja existia) ganha
  checkbox "Gerar link publico para assinatura" (default ON) +
  select validade (24h/3d/7d/30d) + bloco emerald com URL + copy

Fluxo end-to-end: terapeuta cria signature requests + share_link
no dialog -> copia URL -> envia via WA/email -> paciente abre
/shared/document/:token -> visualiza doc -> aceite -> assinatura
registrada via RPC sign_document_by_token (IP/UA/timestamp/hash
gravados server-side em document_signatures).

Pos-MVP nice-to-have: notificacao automatica do paciente quando
signature criada (depende de Modulo 6 notifications WA/email
channel factory). Por ora, terapeuta envia link manualmente.

PROXIMO: outras 5 secoes do ROADMAP Fase 1 (Asaas Fase B bloqueada,
UX §1.3, Fiscal §1.4, Qualidade §1.5).

## [2026-05-21 evening] session | ROADMAP #14 Recibo profissional PDF
Touched: none (durable em development/02-auditoria/PADRONIZACAO.md + memoria)

Fecha §1.4 Fiscal minimo (parcial — #15 NFS-e fica pra depois).

src/utils/valorExtenso.js — helper pt-BR completo ate 999 milhoes.
"R$ 1.234,56" -> "mil duzentos e trinta e quatro reais e cinquenta
e seis centavos".

DocumentGenerate.service estendido:
- loadTherapistData puxa professional_registration_type/numero/uf
  (#5 migration) e auto-formata terapeuta_registro: "CRP 12345/SP".
  terapeuta_crp legacy mantido pra compat.
- loadClinicData formata tenants.cpf_cnpj (11 dig CPF, 14 dig CNPJ).
- loadAllVariables aceita extras + computa valor + valor_extenso +
  forma_pagamento.
- saveGeneratedDocument ganha templateTipo + mapping
  TEMPLATE_TYPE_TO_DOC_TYPE (recibo_pagamento -> 'recibo', laudo ->
  'laudo' etc). Antes era hardcoded 'laudo' pra TUDO — bug.
- emitirReciboParaSessao(eventoId, opts) — quick path: busca
  template, carrega vars, gera PDF, salva, download. One-call.

Migration 20260521000008 substitui no template recibo_pagamento
"Psicologo(a) - CRP {{terapeuta_crp}}" por "{{terapeuta_registro}}".
Universal pra qualquer conselho (CRP/CRM/CRFa/CREFITO/CRESS/CRN).

DocumentTemplates.service.TEMPLATE_VARIABLES ganha 4 entries de
registro profissional. useDocumentGenerate passa templateTipo.

AgendaEventoFinanceiroPanel ganha botao "Emitir recibo" outlined
quando record.status === 'paid'. Toast + loading state.

PROXIMO: UX §1.3 (busca global + recently viewed + papel timbrado
+ relatorios export) OU sweep residual (M4 cutover billing decisoes
#2/#3/#6).

## [2026-05-21 evening] session | ROADMAP §1.3 UX 3/4 (#10/#11/#13)
Touched: none

3 commits fechando 3 dos 4 itens da Fase 1.3 UX:

#10 Busca global topbar — GlobalSearch.vue ja estava feito no Rail/
classic. **MelissaBusca promovida** de preview client-side pra RPC
search_global com debounce 200ms + searchSeq pra ignorar respostas
obsoletas. 3 grupos novos exibidos quando RPC retorna: sessoes,
documentos, cadastros recebidos. @paciente no MelissaLayout
corrigido (antes ignorava payload — bug). Emits novos: documento,
intake.

#11 Recently viewed — composables/useRecentPatients.js (localStorage
por user_id, max 5, dedup, eventos CustomEvent + 'storage' pra sync
entre instancias no mesmo browser). registerPatientVisit chamado
em MelissaPaciente.loadAll e PatientProntuario.loadDetail. Grupo
"Acessados recentemente" no GlobalSearch.vue + MelissaBusca.vue
quando query vazia. Decisao: localStorage > tabela user_recent_access
por simplicidade + zero round-trip por visita.

#13 Relatorios export PDF/Excel — services/reportExport.service.js
com exportSessionsToPDF (pdf.service HTML→PDF + KPIs + tabela A4),
exportSessionsToXLSX (exceljs com import dinamico, frozen header,
alternating rows, branded), exportSessionsToCSV (vanilla, BOM UTF-8,
separador ';'). 3 botoes pi-file-pdf/pi-file-excel/pi-table em
RelatoriosPage.vue (therapist) + MelissaRelatorios.vue. Respeita
filtro de status da tabela.

#12 Papel timbrado — BLOQUEADO: codigo no UniaoApp. Quando user
importar, plugar como cabecalho_html/rodape_html global em
document_templates ou setting tenants.letterhead_html.

PROXIMO: NFS-e (#15, esforco L), §1.5 Sentry (#18 nao-teste),
sweep residual (M4 cutover billing — bloqueado decisoes #2/#3/#6),
ou agenda Fase 4 residual.

## [2026-05-21 night] session | agenda Fase 4: C12 UX iter + utils extract
Touched: none (durable em memoria project_c12_antecipar_iterar atualizada)

Iniciou agenda Fase 4 residual. Auditoria revelou: popover snapshot
e reverse transition trava JA estavam done de fato (commits f83315b
+ 5684297 durante C11). Pendentes reais: C12 UX, replicacao Rail/
Clinica, doc ajuda.

3 commits:

1) agenda C12 UX: "Trocar metodo" em vez de Revogar+Antecipar
   MelissaEventoPanel ganha 2 botoes quando isAntecipacaoAtiva
   (antes era so "Revogar"). MelissaLayout: anteciparMode ref +
   onTrocarMetodoAntecipacao pre-seleciona metodo atual. confirm
   Antecipar Pagamento ramifica: mode='update' faz UPDATE no paid
   existente (sem cancel cycle). Result: trocar metodo gera 0
   records cancelled.

2) agenda C12 UX: filtrar cancelled do dialog Lancamentos
   lancamentosShowHistory ref (default false) + lancamentosFiltered
   computed. UI: badge "{N} cancelado(s) ocultos" + toggle
   Mostrar/Ocultar historico. Cards cancelled atenuados (opacity
   0.55, border-dashed, line-through na desc) quando expandidos.
   Combina com Trocar metodo — caso 99% so ve ativos.

3) agenda Fase A: extrai utils puros pra features/agenda/utils
   Decomposicao em prep pra Rail/Clinica adotarem. 4 arquivos novos:
   eventoTipo.js + dbFields.js + timeHelpers.js + colors.js.
   useMelissaAgenda.js: 2863L -> 2792L (-71L), imports via aliases
   pra nao mexer em 70+ callsites internos. Zero impacto comportamental.

C12 UX iter 3 (validar antecipar->Realizada nao duplica record) JA
estava implementado em commits 00c4168 + f83315b — comentario no
codigo de _loadStatusChangeContext confirma "ctx.existingPaidRecord"
pra evitar oferecer "Gerar cobranca nova".

PENDENTE replicacao Rail/Clinica:
- Fase B (service de billing): extrair _loadStatusChangeContext,
  _applyStatusDecisions, _createPackageContract, _materializeAndCharge
  PerSession num service reusavel. ~2-3h, risco medio (precisa nao
  quebrar 7 ciclos da agenda C7-C13).
- Fase C/D: adapter em AgendaTerapeutaPage/AgendaClinicaPage.

ATUAL: decidir entre Fase B agora ou pausar replicacao + atacar
outro residual (NFS-e, sweep, etc).

## [2026-05-21 late night] session | agenda Fase B (B1+B2) — agendaBilling.service
Touched: none

Continua decomposicao da agenda pra Rail/Clinica. 2 commits cobrindo
Fase B inteira (read-only + mutations):

Fase B1 (e7e3d1b): agendaBilling.service nasce com
- computeSeriePrice (puro)
- generateOccurrenceDates (puro)
- needsStatusConfirmDialog (puro)
- loadStatusChangeContext (read-only, 5 deps)
useMelissaAgenda: 2792L -> 2593L (-199L)

Fase B2 (049dd91): adiciona mutations
- applyStatusDecisions (~330L — todas as decisoes do dialog)
- createPackageContract (~140L — upfront/saldo)
- materializeAndChargePerSession (~90L — per_session)
useMelissaAgenda: 2593L -> 2042L (-551L)

TOTAL fases A+B1+B2: 3033L -> 2042L (-991L extraidas, ~33% reducao).
3 pages (Melissa/Rail/Clinica) agora podem reusar mesmo billing
core. Comportamento Melissa identico — codigo movido linha-a-linha,
so refactor de signature pra receber deps explicitas em vez de
closure.

Pendente: Fase C (adapter Rail) + Fase D (adapter Clinica) +
doc ajuda.

## [2026-05-21 dawn] session | migrations + seeds aplicados no banco local
Touched: none

Aplicou todas as 13 migrations pendentes do dia (clinical_notes
tables/rls/versioning + documents link + accept_invite RPC + asaas
tables/rls + profiles registration + specialties + document_templates
consent types + sign_document RPCs + list_my_signatures + recibo
amend) + 3 seeds novos (seed_040 clinical_note_templates 6 entries +
seed_050 specialties 34 entries + seed_060 consent forms 2 templates
LGPD/Gravacao + amend tcle_online).

Gotcha re-validado (memoria atualizada): migration 20260521000005
estendendo CHECK dt_tipo_check foi marcada aplicada pelo db.cjs mas
silenciosamente ROLLBACK (postgres nao e owner de document_templates).
Detectado quando seed_060 falhou com violates check constraint.
Re-rodada via `docker exec -i ... sh -c 'psql -U supabase_admin -h
127.0.0.1 -d postgres'` (trust pra 127.0.0.1/32 em pg_hba.conf).

db.config.json estendido com os 3 seeds novos (system group, ordem
seed_040 -> seed_050 -> seed_060) pra setup do zero rodar tudo.

Sanity check pos-aplicacao:
- 5 RPCs novas (accept_tenant_invite + 3 sign + list_my_signatures)
- 8 tabelas novas (clinical_notes + versions + templates + asaas
  customers/payments/webhook + profile_specialties + specialties)
- 17 document_templates global (15 existentes + 2 LGPD/Gravacao)
- 34 specialties seedadas
- 6 clinical_note_templates seedados
- 3 colunas professional_registration_* em profiles
- Backup automatico criado em backups/2026-05-21/

## [2026-05-21 deep night] session | agenda Fases C + D — Rail+Clinica adotam billing core
Touched: none

Replicacao Rail/Clinica fechada via composable reusavel
useAgendaStatusChange (Tipo A wrapper sobre agendaBilling.service).

3 commits:

1) Fase C (034c2c0): useAgendaStatusChange composable novo +
   AgendaTerapeutaPage onUpdateSeriesEvent refatorado pra usar
   applyStatusChange (load context + dialog se preciso + apply
   decisoes). AgendaStatusChangeConfirmDialog plugado no template.

   Antes: Rail fazia so update(id, { status }) cru. Zero das
   features C7-C13.

   Depois: Rail tem feature parity com Melissa pra status change.
   Multa por falta, taxa cancelamento tardio, consumir saldo,
   gerar cobranca pacote saldo, reverse transition trava.

2) Fase D (6807b44): AgendaClinicaPage espelha Fase C usando o
   mesmo composable. Diferencas adaptadas (updateClinic + createClinic
   recebem tenantId arg explicito).

3) Pendente residual:
   - Indicadores visuais (3 canais: barra esquerda verde / badge $
     amber / neutro) ainda nao replicados no Rail/Clinica — sao
     custom event classNames do FullCalendar, requerem _payment
     StateMap.
   - Antecipar/Revogar/Trocar metodo no popover do Rail — Rail
     nao tem popover separado, usa AgendaEventDialog direto;
     precisa refactor maior pra acomodar.
   - Doc ajuda completa.

ESTADO: agenda Fase 4 residual 70% fechada. C7-C13 core flow
(status change com billing) agora cobre os 3 layouts. UI fina
(popover antecipar, indicadores visuais) fica pra iter incremental
sob demanda.

TOTAL DA SESSAO (24/05 - 25/05, ~24 commits):
- CFP #6/#7 (Compliance Fase 1.2 ✅)
- #14 Recibo profissional PDF
- §1.3 UX 3/4 (#10 #11 #13)
- C12 UX iter (Trocar metodo + filtro cancelled)
- Agenda decomposicao A+B1+B2: -991L em useMelissaAgenda (~33%)
- Agenda Fases C+D: Rail+Clinica adotam billing core
- useAgendaStatusChange composable novo

## [2026-05-21 23:00] session | Melissa Fase 2 UX iter + bug isFinite(null)
Touched: feedback_isfinite_strict, feedback_teleport_body_styles
Detalhes:

Sessao de testes manuais Fase 2 (templates + paciente.documentos).
4 ajustes UX + 1 bug funcional resolvido. 5 commits, 0 push (SSL
self-signed Gitea — user faz manual amanha).

1) MelissaPatientDocuments (4e1ebeb, 6c39c58):
   Aba Documentos no /melissa/paciente?id=X foi convertida de embed
   <DocumentsListPage> pra pagina nativa 2-col Melissa. Drawer mobile
   bugava (transform/filter em ancestrais trapando position:fixed).
   Fix:
   - <Teleport to="body"> no drawer + backdrop pra escapar stacking
   - styles do drawer movidos pra <style> nao-scoped (teleport perde
     data-v attrs do scoped)
   - wrapper teleportado recebe class "win11-root" pra herdar vars
     --m-* (definidas nesse escopo no MelissaLayout)
   - cascata --mpd-bg/border/text: --m-* -> --p-* -> hardcoded

2) DocumentGenerateDialog (61bb0d9, 512bcc9):
   Inputs trocados pra FloatLabel variant="on". Adicionado map de
   ORIGEM dos campos (TEMPLATE_VARIABLES.source) — hint embaixo de
   cada campo vazio explica onde cadastrar (ex: "Perfil -> Registro
   Profissional"). Banner verde/amber no topo conta preenchidos.

3) Bug critico (4f05c2c) — RAIZ do "campos vem vazio mesmo com
   profile preenchido":
   loadAllVariables crashava com TypeError "Cannot read properties
   of null (reading toFixed)" quando NAO havia sessao vinculada
   (agendaEventoId=null) E sem extras.valor. Toda a Promise
   estourava, variables zerava.

   Causa: isFinite(null) global retorna TRUE (Number(null)===0),
   entrava no branch valorNum.toFixed e crashava.

   Fix: trocar por Number.isFinite (strict, nao coerce).
   Salvo como memoria feedback_isfinite_strict.

PROXIMA SESSAO (retomar amanha 22/05):
- Continuar Fase 2: 2.7-2.9 (gerar PDF dentro da aba Documentos
  do paciente, conferir vars CRP/UF preenchem, doc aparece como
  tipo_documento='outro')
- Gerar JSON docs Fase 2 (#6 + templates page)
- Fase 3: Portal assinatura #7
- Fase 4: Recibo profissional #14 testes
- Fase 5: Relatorios export #13
- Fase 6: C12 UX iter (deferred 20/05)
- Fase 7: Regressao Agenda C7-C13

PUSH PENDENTE: 35 commits ahead of origin/main; SSL self-signed
do Gitea exige `git -c http.sslVerify=false push origin main`
+ credenciais (user faz manual).

## [2026-06-12 10:47] session | F0 schema-per-tenant: varredura e categorizacao
Touched: Migracao Schema-per-Tenant, index

## [2026-06-12 11:49] session | F1 schema-per-tenant: template + helpers + clone
Touched: Migracao Schema-per-Tenant

## [2026-06-13 04:52] session | F3 schema-per-tenant: frontend tenantDb
Touched: Migracao Schema-per-Tenant

## [2026-06-13 09:10] session | F4 edge functions + F1b anon-tables-public
Touched: Migracao Schema-per-Tenant

## [2026-06-13 09:26] session | F5 PostgREST expoe schemas tenant (E2E HTTP)
Touched: Migracao Schema-per-Tenant

## [2026-06-13 12:53] session | F6.0+F6.1 clones + migracao dados; plano F6.2
Touched: Migracao Schema-per-Tenant

## [2026-06-13 13:34] session | F6.2 Lote A+B triggers (agnosticos + schema-aware)
Touched: Migracao Schema-per-Tenant

## [2026-06-13 14:10] session | F6.2 Lote C split notifications
Touched: Migracao Schema-per-Tenant

## [2026-06-13 14:37] session | F6.2 Lote D scoped (15 RPCs); checkpoint
Touched: Migracao Schema-per-Tenant

## [2026-06-13 15:13] session | F6.2 Lote D RPCs user-facing
Touched: Migracao Schema-per-Tenant

## [2026-06-13 15:26] session | F6.2 Lote E cron/global RPCs
Touched: Migracao Schema-per-Tenant

## [2026-06-13 15:51] session | F6.2 Lote F anon/token RPCs
Touched: Migracao Schema-per-Tenant

## [2026-06-13 16:01] session | F6.2 Lote G + F6.2 COMPLETA (66 funcoes)
Touched: Migracao Schema-per-Tenant

## [2026-06-13 16:26] session | F6 wiring no clone (tenants novos completos)
Touched: Migracao Schema-per-Tenant

## [2026-06-13 16:45] session | F6.3 preparada (nao-aplicada) + itens SaaS-admin
Touched: Migracao Schema-per-Tenant
