develop #19

Merged
jhony75 merged 11 commits from develop into main 2026-09-03 10:29:53 -03:00
Owner
No description provided.
docs: adiciona handoff da sessão de 25/08/2026
All checks were successful
EEG QA CI / validate-and-build (pull_request) Successful in 2m57s
EEG QA CI / Deploy production (pull_request) Has been skipped
EEG QA CI / Deploy development (pull_request) Has been skipped
f55854b1f3
Resumo do que foi feito (PRs #11-#14: deploy dev na VPS compartilhada,
vínculo Report<->TestRunStep + fix do clone, itens da Validação Técnica
editáveis, PDF alinhado ao template DOCX), decisões de arquitetura e
armadilhas descobertas (git push em sandbox, encoding de PR via curl,
conflito de branch com "ci/"). Complementa docs/BACKLOG.md e
docs/KNOWN_LIMITATIONS.md, que continuam sendo o estado vivo.
Merge pull request 'docs: adiciona handoff da sessão de 25/08/2026' (#16) from docs/session-handoff-2026-08-25 into develop
All checks were successful
EEG QA CI / validate-and-build (push) Successful in 2m12s
EEG QA CI / Deploy production (push) Has been skipped
EEG QA CI / Deploy development (push) Successful in 42s
cf9eac6b77
Reviewed-on: #16
Continua a decomposição do monólito modular (ADR-0013): Plans/Runs/Steps
(test_execution) e achados (issues) viram módulos Core de verdade (sem
depender de main/pdf_export/html_export/ai_client/hubspot_client, coberto
pelo teste de fronteira em test_architecture.py). reporting (CSV/HTML/PDF de
Report, resumo em PDF, /api/metrics) também sai de main.py, mas fica marcado
como ainda não-Core: continua lendo campos EEG do Report e usando os
builders de pdf/html, então fica fora da lista CORE_MODULES até esses campos
serem extraídos do Report.

main.py cai de 951 para 457 linhas. URLs, schemas e comportamento
inalterados — 36/36 testes de backend continuam passando.

Corrige também uma linha desatualizada em KNOWN_LIMITATIONS.md (Report e
TestRun já têm relação explícita desde o PR #12).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Primeiro corte real de separação Core/EEG a nível de schema (ADR-0013):
patient_code/has_photic/has_cardio/has_video saem da tabela reports para
report_eeg_profiles, com FK 1:1 (report_id é PK e FK ao mesmo tempo,
ondelete=CASCADE). Migration b4fc85244591 cria a tabela, faz backfill de
todo report existente (inclusive com os 4 campos vazios/False) e dropa as
colunas antigas via batch_alter_table; testada com round-trip
upgrade->downgrade->upgrade preservando os dados.

Para não quebrar CRUD/schemas/frontend de uma vez, Report ganhou @property
de compatibilidade para os 4 campos, delegando para Report.eeg_profile e
criando o perfil sob demanda no primeiro set. Isso mantém main.py (CRUD via
REPORT_SCALAR_FIELDS + setattr genérico), schemas.py (ReportOut/ReportCreate/
ReportUpdate/ReportListItem) e o payload JSON da API inalterados — o
frontend não precisou mudar nesta etapa.

Dois pontos que filtravam por essas colunas em nível de classe (não dá pra
usar property Python num WHERE de SQL) foram reescritos para juntar
ReportEegProfile explicitamente: channel_coverage em
modules/reporting/router.py::metrics() e o filtro de busca em
services/reports.py::apply_report_filters.

reporting continua fora da lista CORE_MODULES do teste de fronteira — ainda
depende de pdf_export/html_export e agora também de ReportEegProfile
diretamente, então segue não-Core (ver docs/MODULAR_ARCHITECTURE.md).

Falta o segundo corte, maior: mover a lógica que lê/escreve esses campos
para dentro de eeg_reports e decidir o contrato da API (campos soltos vs.
sub-objeto) — muda payload HTTP e toca o frontend, registrado no backlog.

36/36 testes de backend continuam passando.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
refactor: mover perfil EEG do Report pra eeg_reports e aninhar no contrato da API
Some checks failed
EEG QA CI / validate-and-build (pull_request) Failing after 1m44s
EEG QA CI / Deploy production (pull_request) Has been skipped
EEG QA CI / Deploy development (pull_request) Has been skipped
64859d3807
Segundo corte da separação Core/EEG do Report (depois do split de schema em
report_eeg_profiles): a lógica de ler/criar/clonar o perfil EEG agora mora em
modules/eeg_reports/report_profile.py (apply/clone/to_schema) — main.py só
orquestra (create_report/update_report/duplicate_report/list_reports), não é
mais dono da lógica. As @property de compatibilidade saíram do Report: ele
não expõe mais patient_code/has_photic/has_cardio/has_video como atributo
nenhum, só a relationship eeg_profile.

Contrato HTTP mudou de propósito: GET/POST/PUT /api/reports* agora usam
eeg: {patient_code, has_photic, has_cardio, has_video} em vez dos 4 campos
soltos (schemas.ReportEegProfile novo, ReportUpdate.eeg é Optional e
substitui os 4 de uma vez quando presente, mesma semântica de tags/
manufacturers). channel_coverage (reporting/router.py::metrics()) e o filtro
de busca (services/reports.py::apply_report_filters) já usavam join
explícito com ReportEegProfile desde o corte anterior, então não mudaram.

Frontend atualizado: ReportForm.jsx, ReportDetail.jsx e ReportList.jsx leem/
escrevem form.eeg.*/r.eeg?.* em vez dos campos soltos, com merge defensivo
no restore de rascunho do localStorage (formato antigo não quebra mais).

Validado com dev server rodando (.claude/launch.json novo, com backend e
frontend): criar, listar, buscar por patient code, editar, duplicar, CSV,
PDF, HTML e métricas, tudo conferido via network tab batendo com o novo
formato. 36/36 testes de backend continuam passando (test_report_duplicate_
and_run_link.py atualizado pro formato aninhado).

reporting continua fora do CORE_MODULES do teste de fronteira — ainda
depende de pdf_export/html_export e de ReportEegProfile diretamente.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
refactor: separar reporting genérico da especialização EEG via extension point
Some checks failed
EEG QA CI / validate-and-build (pull_request) Failing after 1m15s
EEG QA CI / Deploy production (pull_request) Has been skipped
EEG QA CI / Deploy development (pull_request) Has been skipped
ae968b6efe
reporting (CSV/HTML/PDF de Report, resumo em PDF, /api/metrics) e
services/reports.py ainda liam patient_code/has_photic/has_cardio/has_video
direto, mesmo depois do split anterior — o que os prendia à especialização
EEG apesar de serem, em espírito, código genérico de QA (uma vertical não-EEG
teria que duplicar ou reescrever esses módulos pra reportar sobre seus
próprios testes).

Introduzido um ponto de extensão explícito, injetado pela composition root
(sem módulo importar outro diretamente, respeitando a regra de dependências):

- pdf_export.py::build_report_pdf e html_export.py::build_report_html
  trocam a seção "Dados do exame" hard-coded (patient code + 3 canais) por um
  parâmetro opcional extra_exam_fields(report) -> list[(label, valor)]. Sem
  esse parâmetro, os dois arquivos não têm mais nenhuma referência a EEG.
- services/reports.py::apply_report_filters troca o join com
  ReportEegProfile hard-coded na busca textual por extra_search_filter(query,
  like) -> (query, condição|None).
- modules/reporting/router.py::create_router ganha o parâmetro eeg_extension
  (duck-typed: CSV_HEADERS, csv_values, exam_fields, channel_coverage_metric,
  search_filter), usado nos 5 pontos que antes tinham conhecimento de EEG.
- modules/eeg_reports/report_profile.py implementa esse contrato e é
  injetado por main.py: reporting.create_router(get_db,
  eeg_extension=eeg_report_profile).

Resultado: reporting, pdf_export.py, html_export.py e services/reports.py
não referenciam mais ReportEegProfile nem os 4 campos — servem igualmente
bem pra reportar sobre qualquer tipo de teste, não só EEG. reporting entra
de fato na lista CORE_MODULES do teste de fronteira, que também ganha
test_generic_report_exporters_stay_eeg_agnostic como guarda de regressão.

Validado com dev server: criar report, CSV, HTML, PDF, métricas
(channel_coverage) e busca por patient_code todos conferidos via
fetch/network, batendo byte a byte com o comportamento anterior. 37/37
testes de backend passando.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
docs: atualizar mapa Motor vs. EEG com o que já foi feito nesta sessão
Some checks failed
EEG QA CI / validate-and-build (pull_request) Failing after 1m6s
EEG QA CI / Deploy production (pull_request) Has been skipped
EEG QA CI / Deploy development (pull_request) Has been skipped
dbb31cb1a8
docs/ARCHITECTURE.md estava desatualizado desde antes dos 3 commits
anteriores desta branch: listava main.py como dono de endpoints "ainda não
extraídos" (já viraram test_execution/issues/reporting) e descrevia
pdf_export.py/html_export.py como só uma ideia futura de generalização —
já feita, parcialmente, via o extra_exam_fields injetado por
modules/eeg_reports/report_profile.py.

Deixa explícito o que falta pra separação motor/EEG: Report ainda embute
ReportScenario/ReportScenarioStep em vez de referenciar um TestRun (o maior
item pendente, schema-changing, listado como próximo passo #1 de propósito).
fix: atualizar head do Alembic esperado no restore drill do CI
All checks were successful
EEG QA CI / validate-and-build (pull_request) Successful in 2m50s
EEG QA CI / Deploy production (pull_request) Has been skipped
EEG QA CI / Deploy development (pull_request) Has been skipped
7020fde039
A pipeline falhava no passo "Backend tests" porque
scripts/sqlite-restore-drill.py roda com --expect-alembic fixo, e esse valor
não tinha sido atualizado depois da migration b4fc85244591 (separar campos
EEG do Report em tabela própria) — mesmo padrão já visto no PR #9
(commit 8bb6b96, quando a migration da Validação Técnica trocou o head).

Validado localmente rodando o mesmo passo do CI: init_db() do zero seguido
de sqlite-restore-drill.py --expect-alembic b4fc85244591.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Merge pull request 'refactor: decomposição de main.py em módulos Core + split EEG do Report' (#17) from refactor/backend-core-modules into develop
All checks were successful
EEG QA CI / validate-and-build (push) Successful in 2m19s
EEG QA CI / Deploy production (push) Has been skipped
EEG QA CI / Deploy development (push) Successful in 45s
ea6dcd6ba1
Reviewed-on: #17
refactor: Report referencia TestRun em vez de embutir ReportScenario/Step
All checks were successful
EEG QA CI / validate-and-build (pull_request) Successful in 2m11s
EEG QA CI / Deploy production (pull_request) Has been skipped
EEG QA CI / Deploy development (pull_request) Has been skipped
bed2408574
Último item pendente do mapa Motor vs. EEG (docs/ARCHITECTURE.md): Report
tinha ReportScenario/ReportScenarioStep próprios, uma cópia quase idêntica
de TestRunScenario/TestRunStep (funções de criação praticamente clonadas —
add_scenario_to_report vs add_scenario_to_run). Já existia a estrutura certa
pra isso; faltava Report referenciá-la.

TestRun ganha report_id (FK 1:1 pra reports.id, nullable, unique,
ondelete=CASCADE) — Report.run é um TestRun "de suporte" exclusivo daquele
report, criado sempre (mesmo sem cenários). Migration 573520d0fbe5 migra
report_scenarios/report_scenario_steps/anexos de step (images.step_id)
existentes pra test_run_scenarios/test_run_steps/run_images, com IDs
deslocados por offset pra nunca colidir com scenarios/steps de Runs "de
verdade" já existentes, e só então dropa as tabelas/coluna antigas.

Validação da migration foi além do padrão usado até aqui, dado o risco real
de mover BLOBs entre tabelas: testada com dados seedados direto no schema
antigo (não só banco vazio) incluindo um Run pré-existente pra garantir que
o offset de IDs não colide, round-trip upgrade->downgrade->upgrade
comparando BLOBs byte a byte, e validação end-to-end via API real (criar
report com cenário/passo/imagem, editar, duplicar, exportar PDF/HTML,
deletar e confirmar cascade limpo sem órfãos).

Contrato HTTP das rotas de cenário/step do Report não mudou: Report.scenarios
virou @property delegando pra Report.run.scenarios — como ReportScenarioOut/
ScenarioStepOut não declaram os campos extras que só TestRunScenario/
TestRunStep têm (template_id, reports), o Pydantic ignora essas colunas na
validação e o JSON fica idêntico ao de antes. add_report_scenario chama
modules.test_execution.router.add_scenario_to_run direto;
services/reports.py::add_scenario_to_report foi removida.
GET /api/runs passa a filtrar os runs de suporte (report_id IS NOT NULL).
Issue (achados) continua embutido em Report, sem equivalente no motor pra
reaproveitar — decisão documentada, não pendência.

Zero mudança de frontend. 37/37 testes de backend passando.

Também corrige o head do Alembic esperado no restore drill do CI (mesmo
padrão de manutenção já visto antes — precisa bump a cada nova migration).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Merge pull request 'refactor: Report referencia TestRun em vez de embutir cenários próprios' (#18) from refactor/report-run-scenarios into develop
All checks were successful
EEG QA CI / validate-and-build (push) Successful in 3m19s
EEG QA CI / Deploy production (push) Has been skipped
EEG QA CI / Deploy development (push) Successful in 50s
EEG QA CI / validate-and-build (pull_request) Successful in 2m49s
EEG QA CI / Deploy production (pull_request) Has been skipped
EEG QA CI / Deploy development (pull_request) Has been skipped
ebeb847a59
Reviewed-on: #18
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
jhony75/eeg-qa!19
No description provided.