# 10 - Mapa de Reestruturacao de Funcionalidades > Escopo: roteiro pratico para reorganizar o codigo sem quebrar o produto. > Baseado na varredura de 2026-08-24 sobre engine Python, ponte do app, > ferramentas MCP e app SwiftUI. ## 1. Diagnostico rapido O projeto ja tem uma arquitetura-alvo correta: `fcpxml/` como engine puro, `server.py` + `server_tools/` como camada MCP, `admin/` como ponte JSON-lines do app e `MacApp/` como interface. A melhoria agora nao e "reinventar" a arquitetura, e reduzir os pontos onde as responsabilidades ainda se misturam. ### Pontos fortes - Engine Python bem testado e com regra clara: logica de timeline fica em `fcpxml/`. - `writer/` ja foi quebrado em mixins por assunto, preservando API publica. - `server.py` funciona como composition root e usa dispatch por dicionario. - Documentacao interna registra decisoes, armadilhas e padroes do projeto. - Fluxos criticos tem testes extensos em `code/tests/`. ### Dores atuais - Alguns arquivos voltaram a virar centros de gravidade: - `server_tools/voice.py` (~999 linhas) - `server_tools/subtitles.py` (~760 linhas) - `MacApp/Sources/WizardView.swift` (~979 linhas) - `MacApp/Sources/TranscriptionView.swift` (~843 linhas) - `fcpxml/model_manager.py` (~748 linhas) - `admin/` e `server_tools/` expõem fluxos parecidos por caminhos diferentes, o que aumenta risco de uma funcionalidade existir no MCP e faltar no app. - ~~`admin/` ainda fica fora do lint principal~~ — resolvido na Fase 0 (2026-09-22): `admin/` entrou no gate de `run_after_fix.sh`. - ~~`WHISPERX` e backups aparecem junto da base ativa~~ — resolvido na Fase 0 (2026-09-22): movido para fora do workspace git. - O app SwiftUI quase nao tem rede automatizada; compilar nao garante que uma tela abre. ## 2. Mapa de dominios desejado ```text Produto MacApp/ Interface e experiencia do usuario admin/ Ponte JSON-lines do app server.py + server_tools/ Entrada MCP Engine fcpxml/models/ Dados e contratos fcpxml/parser.py FCPXML -> objetos fcpxml/writer/ Escrita e edicao de XML fcpxml/voice_* Analise e decisoes por voz fcpxml/text_layout.py Layout de legendas fcpxml/model_manager.py Catalogo, configs e modelos Suporte tests/ Rede automatizada Engine/docs/ Decisoes e operacao examples/ Fixtures de uso Legado / referencia WHISPERX/ Deve sair do caminho ativo ou virar referencia clara ``` Regra de organizacao: uma funcionalidade nasce no engine, depois ganha duas portas finas se necessario: uma tool MCP em `server_tools/` e um comando do app em `admin/api/`. ## 3. Reestruturacao por fases ### Fase 0 - Higiene antes de mexer — `concluída em 2026-09-22` Objetivo: reduzir ruido e proteger a base antes de mover codigo. - ~~Decidir o destino de `code/WHISPERX`~~ — não era submodule (sem `.gitmodules`), era 2,6 GB de backups órfãos do próprio projeto sem nenhuma referência ativa. Movido para `~/Archives/G-ART-WHISPERX-backup` (fora do workspace git), copiado com `rsync` e conferido com `diff -rq` antes de remover o original. Detalhe: essa pasta também inflava qualquer `ruff check --exclude docs/` manual (a flag sobrescrevia o `exclude` do `pyproject.toml`, que já ignorava `WHISPERX/`) — ver `05_EXPERIENCIAS.md` #34. - ~~Incluir `admin/` em uma checagem de lint separada antes de colocar no gate obrigatório~~ — checado com a config real do projeto (não o default do ruff): só 6 erros, todos `E402` por `sys.path.insert` antes de import local. Resolvido com `# noqa: E402` (convenção já usada no projeto) e `admin/` entrou direto no gate obrigatório (`run_after_fix.sh`, passo 2/3), sem precisar de etapa intermediária "separada". - Corrigido de quebra: `fcpxml/writer/adjustment.py` gerava um `` inválido no DTD — não estava no escopo original da Fase 0, mas surgiu na investigação e era pequeno o bastante para resolver junto (ver `05_EXPERIENCIAS.md` #34). - Atualizados: `02_MODULES.md` (versão, linhas de `writer/`, módulos novos `builders.py`/`adjustment.py`/`analise.py`/`transcription/`), `09_MANUTENCAO.md` (contagem de testes/lint, itens §2.3/§2.6/§2.8 resolvidos, novo item §2.7 registrando `test_refine_voice_timeline_tool`). - **Pendente, não fechado nesta rodada:** "documentar oficialmente quais pastas são produto ativo, legado e backup" como um documento à parte — o que existia de fato como "legado" (`WHISPERX`) já foi resolvido, não sobrou candidato claro para justificar um novo documento agora. Entrega obtida: lint de `admin/` no gate, `code/writer/adjustment.py` correto e testado, ~2,6 GB fora do caminho ativo, docs sincronizados com o código atual. ### Fase 1 - Contratos entre camadas Objetivo: impedir que MCP, app e engine driftam entre si. - Criar um registro unico de capacidades, por exemplo: - nome interno da funcionalidade; - funcao pura do engine; - handler MCP, se existir; - comando `admin`, se existir; - tela Swift, se existir; - testes associados. - Adicionar teste que detecta comandos importantes presentes no MCP mas ausentes na ponte do app, quando fizer sentido. - Padronizar o retorno dos comandos `admin/api`: `ok`, `path`, `message`, `error`, `unchanged`, `artifacts`. Entrega esperada: mapa vivo de funcionalidades e menos "funciona no Claude, nao aparece no app". ### Fase 2 - Dividir `server_tools/voice.py` Objetivo: separar o fluxo de voz por etapas reais do produto. Divisao sugerida: ```text server_tools/voice/ __init__.py Reexporta TOOLS e HANDLERS analysis.py analyze_voice_features, build_voice_timeline speakers.py diarize_media, remove_speakers refinement.py refine_voice_timeline, remove_speech_gaps actions.py apply_voice_actions local_ai.py generate_voice_script config.py get/save_voice_analysis_config ``` Cuidados: - Manter os nomes publicos reexportados para nao quebrar testes/imports. - Mover em uma etapa por arquivo, rodando testes de voz a cada passo. - Nao mover regra de negocio para `server_tools/voice/`; se aparecer regra nova, ela deve descer para `fcpxml/voice_*`. Testes minimos: `test_voice_actions.py`, `test_voice_actions_tool.py`, `test_voice_timeline.py`, `test_voice_timeline_tool.py`, `test_diarize.py`, `test_voice_features.py`. ### Fase 3 - Separar `fcpxml/model_manager.py` Objetivo: reduzir mistura entre catalogo, download, configuracao e estado. Divisao sugerida: ```text fcpxml/model_manager/ __init__.py API publica atual catalog.py models.json, recomendados, metadata storage.py diretorios, instalados, migracao download.py download/cancel/progresso transcription_config.py modelo selecionado, idioma voice_config.py analise de voz, silencio, legendas ``` Cuidados: - Preservar imports atuais via `__init__.py`. - Separar funcoes puras de funcoes com I/O para facilitar teste. - Nao acoplar config do app a nomes de tela Swift. Testes minimos: `test_models.py`, `test_models_api.py` se existir, `test_voice_analysis_config.py`, `test_project_config.py`. ### Fase 4 - Reorganizar o Assistente SwiftUI Objetivo: tornar o fluxo de 7 etapas legivel e testavel por partes. Divisao sugerida: ```text MacApp/Sources/Wizard/ WizardView.swift Casca, navegacao e estado global WizardState.swift Estado do fluxo e canAdvance ProjectStepView.swift TranscribeStepView.swift VoiceAnalysisStepView.swift AIScriptStepView.swift ReviewStepHost.swift ProcessStepView.swift DoneStepView.swift ``` Boas praticas para essa fase: - Extrair primeiro views pequenas, sem alterar comportamento. - Depois extrair calculos puros de `canAdvance`, nomes de arquivos e selecao de artefatos para tipos testaveis. - Usar harness manual documentado em `08_APP_MACOS.md` para abrir as telas tocadas. Entrega esperada: cada etapa do wizard vira um arquivo com responsabilidade unica. ### Fase 5 - Unificar validacao e saida da ponte `admin/` Objetivo: deixar os comandos do app tao disciplinados quanto os handlers MCP. - Criar helpers de path/output equivalentes aos de `server_tools/_shared`, ou mover helpers comuns para uma camada compartilhada que nao saiba de MCP. - Trocar chamadas diretas a `server.generate_output_path` por helper de dominio que nao puxe `server.py` quando a ponte so precisa de path. - Adicionar lint de `admin/` ao fluxo de manutencao depois de corrigir erros existentes. Entrega esperada: ponte mais fina, menos import acidental de transporte MCP. ### Fase 6 - Tests e gates de seguranca Objetivo: fazer a reorganizacao ser barata de continuar. - Criar testes de "arquitetura": - `fcpxml/` nao importa `server`, `server_tools` nem `admin`; - handlers MCP sempre retornam via `_text_result`; - comandos `admin` retornam JSON no formato padrao. - Criar teste de import publico para garantir que reexports antigos continuam. - Para SwiftUI, manter harnesses por tela critica ate existir um build mais estruturado. Entrega esperada: mover arquivos deixa de ser aposta. ## 4. Prioridade recomendada 1. Fase 0: limpar mapa ativo vs legado. 2. Fase 1: criar registro de capacidades. 3. Fase 2: dividir voz em `server_tools`. 4. Fase 5: fortalecer `admin/`. 5. Fase 4: quebrar `WizardView`. 6. Fase 3: dividir `model_manager.py`. 7. Fase 6: ampliar gates conforme as fases estabilizam. Motivo: primeiro se reduz incerteza, depois se separa o arquivo que mais muda no fluxo novo de voz, e so entao se mexe nas telas maiores. ## 5. Checklist para cada refatoracao - Mover sem mudar comportamento na primeira passada. - Preservar API publica com reexports. - Rodar testes focados depois de cada movimento. - Rodar `cd code && ./Engine/run_after_fix.sh` antes de concluir. - Se mexeu em `MacApp/`, compilar e abrir a tela afetada. - Atualizar docs no mesmo commit. - Registrar aprendizado em `05_EXPERIENCIAS.md` quando houver bug real. ## 6. Principios de boas praticas para este projeto - Engine puro: sem MCP, sem Swift, sem JSON de tela. - Camadas de entrada finas: validam, chamam engine, formatam resposta. - Tempo de timeline sempre racional (`TimeValue`), exceto metricas de audio e UI onde segundos float sao apenas apresentacao/analise. - Original nunca e sobrescrito. - XML sempre entra por `safe_xml.py`. - Dependencias opcionais continuam lazy. - Arquivo grande so e problema quando contem varios assuntos. - Toda funcionalidade importante deve ter dono, porta MCP/app documentada e teste correspondente.