docs: varredura geral, documentação por função e regra de atualização

A documentação descrevia um sistema que não existe mais: 62/73 ferramentas
(são 74), writer.py e models.py como arquivos (viraram pacotes), 1032 testes
(são 1454), models_api.py descrito como "API FastAPI" (é ponte JSON) e o app
SwiftUI ausente por completo — 5.500 linhas que o usuário opera todo dia sem
uma linha de documentação.

Cada arquivo passa a ter uma função específica, com cabeçalho de escopo
dizendo o que cobre e o que NÃO cobre (com a seta para quem cobre). O objetivo
é ler só o necessário: doc fora do assunto custa tempo e processamento sem
entregar nada.

    01 arquitetura   camadas, duas portas de entrada, regras transversais
    02 módulos       mapa do engine, incluindo o pipeline de voz
    03 server/tools  as 74 tools, helpers e como criar uma nova
    08 app macOS     NOVO — build por swiftc, telas, ponte, etapa 5
    09 manutenção    NOVO — por onde começar, o que está aberto, sintoma→arquivo

CLAUDE.md ganha a seção "Documentação (MANDATORY)": tabela de roteamento
(qual arquivo abrir para cada tarefa) e a regra de que toda alteração de
código atualiza a doc no mesmo commit, com o mapa de o-que-mexeu → o-que-
atualizar. Doc velha engana mais que doc ausente.

O índice do 05_EXPERIENCIAS subiu para o topo: consultar "isso já quebrou
antes?" custava carregar 1.281 linhas antes de chegar na tabela.

Dívidas levantadas na varredura e registradas em 09 §2: etapa 6 ainda ignora
o phrase_review.json, offset de ~400ms do Whisper, MacApp sem teste, admin/
fora do lint, confirmações visuais pendentes no FCP, submódulo WHISPERX sujo.

Também corrigidos dois links quebrados no Engine/README que apontavam um
nível acima do certo.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
João Henrique
2026-08-19 22:51:33 -04:00
co-authored by Claude Opus 5
parent ffaebb3f72
commit dcdd73edb5
10 changed files with 881 additions and 261 deletions
+55 -21
View File
@@ -1,26 +1,49 @@
# 03 — Camada MCP (`server.py`) — 73 ferramentas
# 03 — Camada MCP (`server.py` + `server_tools/`) — 74 ferramentas
`server.py` (3824 linhas) é a camada de transporte. Não tem lógica de timeline —
mapeia nome → handler e delega ao Engine. O dispatch é um dicionário
`TOOL_HANDLERS` (padrão de despacho, sem cadeias gigantes de if/elif).
> **Escopo:** As 74 ferramentas MCP: helpers, categorias e como criar uma nova.
> **Não cobre:** Lógica de edição, que mora no engine (→ 02) · comandos do app (→ 08)
`server.py` (592 linhas) é só o transporte: dispatch por dicionário
`TOOL_HANDLERS`, sem cadeia de if/elif e **sem lógica de timeline**. Os handlers
moram em `server_tools/`, um módulo por categoria, e os helpers que todos usam
em `server_tools/_shared/`.
```
server_tools/
editing.py (649) qc.py (696) voice.py (754) timeline.py (400)
subtitles.py markers_import generation.py transcript.py
export.py roles.py live.py
_shared/ ← helpers compartilhados, ver abaixo
```
## Helpers centrais (use-os, não reinvente)
| Helper | Linha | Função |
|--------|------:|--------|
| `_check_json_depth()` | 83 | Rejeita payloads além de 50 níveis |
| `_validate_filepath()` | 103 | Sandbox de entrada |
| `_validate_output_path()` | 149 | Sandbox de saída |
| `_format_clip_table()` | 245 | Renderização de tabela |
| `_markdown_table()` | 259 | Renderização de tabela markdown |
| `_parse_project()` | 319 | Parseia FCPXML → `(tree, timeline, project)`; quase todos os handlers começam aqui |
| `_resolve_io_paths()` | 357 | Validação de caminho de entrada/saída |
| `_setup_modifier()` | 390 | Prepara modifier com validação |
| `_setup_generator()` | 414 | Prepara generator com validação |
| `_parse_timestamp_parts()` | 433 | Parse de timestamps (min:seg, H:MM:SS, SMPTE) |
| `_detect_flash_frames/gaps/duplicate_groups()` | 1667+ | Detectores de QC |
Todos reexportados por `server_tools/_shared`, então `from ._shared import X`
continua funcionando. A coluna diz o módulo real, para quando você precisar
**editar** o helper — ou apontar um `monkeypatch` para ele.
## As 73 ferramentas por categoria
| Helper | Mora em | Função |
|--------|---------|--------|
| `_validate_filepath()` | `_shared/paths.py` | Sandbox de entrada |
| `_validate_output_path()` | `_shared/paths.py` | Sandbox de saída |
| `_check_json_depth()` | `_shared/paths.py` | Rejeita payloads além de 50 níveis |
| `generate_output_path()` | `_shared/paths.py` | Nome derivado, sem tocar no original |
| `_resolve_io_paths()` | `_shared/paths.py` | Entrada + saída de uma vez |
| `_parse_project()` | `_shared/project.py` | FCPXML → `(tree, timeline, project)`; quase todo handler começa aqui |
| `_setup_modifier()` | `_shared/project.py` | Prepara modifier já validado |
| `_setup_generator()` | `_shared/project.py` | Prepara generator já validado |
| `_text_result()` | `_shared/project.py` | Envolve o texto em `TextContent` MCP |
| `_markdown_table()` | `_shared/formatting.py` | Tabela markdown |
| `_format_clip_table()` | `_shared/formatting.py` | Tabela de clipes |
| `_format_batch_result()` | `_shared/formatting.py` | Relatório de operação em lote |
| `_parse_timestamp_parts()` | `_shared/captions.py` | min:seg, H:MM:SS, SMPTE |
| `parse_srt()` / `parse_vtt()` | `_shared/captions.py` | Legendas coladas |
| `_detect_flash_frames/gaps/duplicate_groups()` | `_shared/detection.py` | Detectores de QC |
| `_load_or_transcribe()` | `_shared/media.py` | Transcrição com cache em disco |
| `_cut_transcript_spans()` | `_shared/media.py` | Corte por trecho falado |
| `_apply_placed_action()` | `_shared/media.py` | Aplica zoom/text/marker já posicionado |
## As 74 ferramentas por categoria
### Timeline & análise (Projeto)
`list_projects`, `analyze_timeline`, `list_clips`, `list_markers`, `list_connected_clips`,
@@ -144,7 +167,18 @@ Regras:
- Sempre retornam via `_text_result(text)` (envolve o texto em `TextContent` MCP).
## Para adicionar uma ferramenta nova
1. Escrever a função no módulo do Engine (`fcpxml/…`) + testes.
2. Criar `handle_<nome>` em `server.py` seguindo o padrão acima.
3. Registrar no dicionário `TOOL_HANDLERS`.
1. **Escrever a função no Engine** (`fcpxml/…`) com testes. É aqui que mora o
trabalho de verdade; o resto é encanamento.
2. **Criar `handle_<nome>`** em `server_tools/<categoria>.py`, seguindo o padrão
acima. Escolha a categoria pelo assunto, não pelo tamanho do arquivo.
3. **Declarar o schema** (`Tool(...)`) no mesmo módulo.
4. **Registrar** no `TOOL_HANDLERS` de `server.py`.
5. Rodar `./Engine/run_after_fix.sh`.
Se a ferramenta também deve aparecer no app, exponha um comando equivalente em
`admin/api/<assunto>.py` e registre na tabela de `admin/models_api.py` — ver
`08_APP_MACOS.md`. Uma capacidade que só existe como tool MCP **não existe para
quem usa o app** (foi exatamente o que aconteceu com `apply_voice_actions`,
`05_EXPERIENCIAS.md` #20).
4. Rodar `./Engine/run_after_fix.sh`.