Fase 0 do roteiro de reestruturação (Engine/docs/10_MAPA_REESTRUTURACAO.md): move code/WHISPERX (2,6 GB de backups órfãos, sem uso ativo, sem .gitmodules) para ~/Archives/G-ART-WHISPERX-backup fora do workspace git; traz admin/ para o gate de lint de run_after_fix.sh; corrige fcpxml/writer/adjustment.py, que gerava um wrapper <adjustment> inexistente no DTD 1.13 (filtros agora vão direto no <clip>, na ordem exigida), com teste de regressão novo. Achado à parte: .gitignore tinha uma regra solta "models/" (pensada só para o cache do Whisper em code/models/) que também escondia do git todo o pacote fcpxml/models/ — nunca commitado, sem proteção nenhuma. Corrigida para /code/models/, ancorada na raiz. Docs atualizados no mesmo commit (02_MODULES, 09_MANUTENCAO, 10_MAPA_REESTRUTURACAO, 05_EXPERIENCIAS #34 e #36), conforme a regra do CLAUDE.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
10 KiB
09 — Manutenção: onde mexer, o que está aberto, o que dói
Escopo: Por onde começar cada tipo de tarefa, o que está aberto e onde dói. Não cobre: Como as coisas funcionam — este doc roteia para quem explica
Este é o documento de rota. Os outros descrevem o que é; este diz o que fazer e por onde começar quando chega uma implementação, uma melhoria ou uma correção.
Última varredura: 2026-09-22 · 1.543 testes passando (+1 falha pré-existente em test_forced_align.py e +1 erro pré-existente em test_refine_voice_timeline_tool.py, ver §2.6) · lint zerado em code/ e em admin/ (fora de server.py/ai_edit.py/fcpxml/analise.py, pré-existentes — outro trabalho em andamento na branch)
1. Chegou uma tarefa — por onde começo?
| A tarefa é… | Comece em | Não esqueça |
|---|---|---|
| Regra nova de edição (corte, zoom, legenda) | fcpxml/<módulo> + teste |
Expor na tool e na ponte, senão só metade dos usuários alcança |
| Corrigir XML que o FCP recusa | fcpxml/writer/ + dtd.py |
Validar contra o DTD real, não só o teste |
| Mudança visível na interface | MacApp/Sources/ |
Abrir a tela — compilar não prova nada (§4) |
| Comando novo para o app | admin/api/<assunto>.py |
Registrar na tabela de models_api.py |
| Ferramenta MCP nova | server_tools/<categoria>.py |
Schema Tool(...) + TOOL_HANDLERS |
| Ajuste de análise de voz | fcpxml/voice_*, emphasis.py |
Regerar os _voice_timeline.json de teste |
| "Está lento" / "está errado" e não sei onde | §5 (mapa de sintomas) | — |
A pergunta que resolve 90% das dúvidas de lugar: essa lógica precisa saber
o que é uma tool MCP ou uma tela? Se não precisa — e quase nunca precisa — ela
vai para fcpxml/.
2. O que está aberto agora
Ordenado por quanto atrapalha, não por esforço.
2.1 resolve_actions não tolera margem no encosto de zoom/marker contra um corte
Um zoom/marker cuja borda cai exatamente em cima do start/end de um
cut é descartado como "apontando para material cortado" — mesmo quando a
intenção era ficar bem ao lado. Contornado manualmente no projeto Mastopexia
(recuando as bordas na mão); a correção estrutural é dar a resolve_actions
uma margem de tolerância (meio frame) antes de considerar uma ação "dentro"
do corte. → fcpxml/voice_actions.py (resolve_actions/shift_after_cuts),
05_EXPERIENCIAS.md #27.
2.2 MacApp/ não tem teste automatizado
5.500 linhas de Swift sem uma asserção. A rede hoje é o harness manual (§4) e o olho do usuário. Não é para sair criando suíte de UI — mas lógica pura que foi parar na camada de tela (cálculo de trim, mapeamento de tempo) deveria descer para o Python, onde já existe rede.
2.3 admin/ fica fora do lint — resolvido em 2026-09-22
admin/ fica fora do lintrun_after_fix.sh agora roda um segundo passo (ruff check --config pyproject.toml ../admin/) com a mesma config do engine. Precisou de
# noqa: E402 em 6 imports de admin/models_api.py/admin/models_gui.py
(padrão sys.path.insert antes do import local, convenção já usada no
projeto). Lint de admin/ está zerado.
2.4 Confirmações visuais pendentes no FCP
Várias entradas do 05_EXPERIENCIAS.md estão marcadas como resolvidas no XML
— testes verdes, DTD válido — mas pendentes de importação real no Final Cut.
XML válido não é o mesmo que XML que renderiza como o esperado. Ao mexer em
legenda, zoom ou keyframe, a confirmação final é abrir no FCP.
2.5 remove_media_silence deixa fatias sub-segundo nas emendas entre clipes
Mesmo depois de corrigir o merge de cortes consecutivos (05_EXPERIENCIAS.md
#28), sobraram 4 clipes de 0,07-0,23s no projeto Mastopexia real, todos bem
na emenda entre dois clipes vizinhos — mesma família do #6 (clipe-fantasma de
1 frame por padding sem vizinho na borda), mas não confirmado se é a mesma
causa raiz. Não investigado a fundo ainda.
→ fcpxml/writer/cut.py (cut_clip_ranges, min_keep_seconds), padding do
remove_media_silence.
2.6 fcpxml/writer/adjustment.py gerava um wrapper <adjustment> inválido — resolvido em 2026-09-22
fcpxml/writer/adjustment.py gerava um wrapper <adjustment> inválidoClipDeAjuste embrulhava filtros num <clip><adjustment>...</adjustment></clip>,
que não existe no DTD real da Apple. Corrigido para anexar
filter-video/filter-audio direto como filhos do <clip> (na ordem que o
DTD exige: vídeo antes de áudio). Teste de regressão em
tests/test_writer_adjustment.py. Segue sem uso em server_tools/admin/api
— só deixou de estar pronto pra alguém reusar do jeito errado.
→ 05_EXPERIENCIAS.md #34.
2.7 test_refine_voice_timeline_tool.py quebrado: voice_timeline.extract_pitch ausente
TestRefineVoiceTimelineHandler::test_max_zooms_caps_the_list tenta
monkeypatch.setattr(vt, "extract_pitch", ...) mas fcpxml/voice_timeline.py
não tem mais (ou nunca teve, nesta branch) essa função. Pertence ao trabalho
de análise de voz já em andamento nesta branch (voice_timeline.py
modificado, não commitado) — não investigado a fundo, só registrado aqui
para não se perder.
→ fcpxml/voice_timeline.py, tests/test_refine_voice_timeline_tool.py.
2.8 Submódulo WHISPERX com conteúdo modificado e não commitado — resolvido em 2026-09-22
WHISPERX com conteúdo modificado e não commitadoNão era um submódulo git registrado (sem .gitmodules) — era uma pasta
.git solta de 2,6 GB dentro de code/, com cópias/backups congelados do
próprio projeto (WHISPERX_backup_88476/, uma cópia inteira e antiga de
fcp-mcp-server-main). Só 3 referências no código ativo, todas em
comentários (fcpxml/diarize.py, tests/test_diarize.py,
admin/api/shared.py), nenhum import ou caminho dependia dela. Além do
peso morto, ela também inflava qualquer lint rodado com --exclude
explícito (que sobrescreve o exclude do pyproject.toml) — foi assim que
um ruff check . --exclude docs/ chegou a acusar 510 erros, quase todos
dentro dela. Movida para ~/Archives/G-ART-WHISPERX-backup (fora do
workspace git), copiada e verificada (diff -rq) antes de remover o
original. WHISPERX/ também saiu do exclude do ruff em
code/pyproject.toml — não faz mais sentido excluir um caminho que não
existe mais dentro de code/.
3. Onde o código ainda é grande (e onde isso não é problema)
Quatro arquivos foram divididos (writer.py, models.py, models_api.py,
_shared.py): 6.685 linhas concentradas viraram 43 módulos.
O que sobrou grande, e o diagnóstico honesto de cada um:
| Arquivo | Linhas | Vale dividir? |
|---|---|---|
fcpxml/text_layout.py |
901 | Não. É diagramação — um assunto coeso. |
fcpxml/rough_cut.py |
798 | Não. É geração de timeline, um assunto. |
fcpxml/model_manager.py |
748 | Talvez: mistura catálogo, download e config. |
server_tools/voice.py |
754 | Talvez, se crescer mais. |
MacApp/TranscriptionView.swift |
843 | Sim, quando for mexer nela. |
MacApp/WizardView.swift |
808 | Sim: sete etapas num switch só. |
Critério, não número: divida quando o arquivo tiver assuntos que não se falam. Um arquivo grande de um assunto só é mais fácil de ler que seis arquivos pequenos que você precisa abrir juntos. Código picado sem motivo atrapalha tanto quanto arquivo gigante.
4. Checklist antes de dar algo por pronto
cd code && ./Engine/run_after_fix.sh # lint zerado + 1.498 testes
admin/run_app.command # se mexeu no app (padrão de revisão)
admin/run.command # app + atualização incremental da RAG
rag/search_gart.sh "consulta" # busca híbrida no índice RAG (ver rag/README.md)
E, além do script:
- Mexeu na interface? Abriu a tela? Compilar não prova que roda —
VideoPlayercompilava e abortava (05_EXPERIENCIAS.md#22). - Mexeu em XML? Importou no FCP? DTD válido ≠ renderiza certo.
- Dividiu ou moveu módulo? Procure
patch('<módulo>.e imports relativos dentro de funções — é o que quebra em silêncio (#23). - Criou teste fora de
code/tests/? Confirme que a contagem total subiu. Teste fora detestpathsnão roda e dá falsa sensação de rede (#24). - Problema estrutural ou erro recorrente? Registre em
05_EXPERIENCIAS.mdcom o índice atualizado. - Documentação divergiu? Corrija no mesmo commit. Doc velha engana mais que doc ausente.
5. Mapa de sintomas → onde olhar
| Sintoma | Suspeite de | Arquivo |
|---|---|---|
| FCP recusa o arquivo ao importar | id inválido, ordem de filhos, timebase |
writer/validation.py, dtd.py |
| Título importa mas não aparece | Template/uid Motion que não resolve | writer/titles.py |
| Corte no lugar errado | Tempo pós-corte usado como se fosse original | voice_actions.py (shift_after_cuts) |
| Zoom/marker sumindo perto de um corte | Borda encostando exatamente no cut |
§2.1 |
| Legenda sobrepondo | Layout ou conteúdo antigo no arquivo | collision.py, text_layout.py |
| "Ênfase" apontando para palavra à toa | Falta renormalizar após o corte | refine_voice_timeline |
| App diz que falta librosa/pyannote | uv run com cwd errado |
PythonBridge.swift (§3 do doc 08) |
App crasha com ModuleNotFoundError: server_tools |
sys.path de admin/api/ mal calculado |
05_EXPERIENCIAS.md #25 |
| Tela do app fecha o programa | Componente de framework que só falha em runtime | 05_EXPERIENCIAS.md #22 |
| Comando existe no MCP mas não no app | Falta expor na ponte | admin/api/, #20 |
6. Convenções que não são negociáveis
Estão em 01_ARCHITECTURE.md §2 e valem repetir as três que mais custaram:
- Tempo é fração racional. Float para tempo produz drift que só aparece depois de dez operações encadeadas.
- Ação de voz é sempre em tempo da mídia original. Nunca pós-corte.
- Original nunca é sobrescrito. Toda saída ganha sufixo.
Documentos relacionados
- 01 Arquitetura — camadas e onde cada coisa mora
- 02 Módulos — mapa do engine, módulo a módulo
- 03 Server/Tools — as 77 ferramentas MCP
- 04 Testes & Workflow
- 05 Experiências — o que já quebrou e por quê
- 06 Boas Práticas
- 08 App macOS — o app e o Assistente