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>
168 lines
9.3 KiB
Markdown
Executable File
168 lines
9.3 KiB
Markdown
Executable File
# CLAUDE.md — fcp-mcp-server
|
||
|
||
## Idioma (MANDATORY)
|
||
|
||
Responder **sempre em português** ao usuário, sem exceção. Nunca responder em
|
||
inglês nas mensagens de chat/prompt — inclusive resumos, atualizações de
|
||
progresso e confirmações. Comentários e nomes de código continuam em inglês
|
||
normalmente; a regra é sobre a comunicação com o usuário.
|
||
|
||
## What This Is
|
||
|
||
MCP server that reads/writes Final Cut Pro XML (FCPXML) files. 74 tools for timeline analysis, batch editing, QC, generation, multi-track support, media relink, NLE export, transcript-based editing (local Whisper), and LIVE FCP control (push_to_fcp / list_fcp_libraries via Apple events). Reads FCPXML 1.8–1.14 (incl. `.fcpxmld` bundles with sidecar preservation), writes 1.13 by default. Dual-mode (XML + Live) direction: `code/docs/CAPABILITY-AUDIT-2026-06.md`.
|
||
|
||
## Architecture
|
||
|
||
Toda a estrutura do projeto fica em `code/`. A pasta `admin/` fica na raiz (fora de `code/`).
|
||
|
||
Há **duas portas de entrada** para o mesmo engine: o MCP (Claude decide a
|
||
edição) e a ponte JSON (o app macOS opera). Nenhuma das duas tem lógica de
|
||
timeline — as duas delegam a `fcpxml/`.
|
||
|
||
```
|
||
code/server.py — MCP entry point (592 linhas). Só dispatch: TOOL_HANDLERS.
|
||
code/server_tools/ — Os handlers das 74 tools, um módulo por categoria.
|
||
code/server_tools/_shared/ — Helpers compartilhados (paths, project, formatting,
|
||
captions, detection, media).
|
||
|
||
code/fcpxml/parser.py — Reads FCPXML → Python objects (Timeline, Clip, Marker…)
|
||
code/fcpxml/writer/ — PACOTE. Edição/escrita de FCPXML. FCPXMLModifier é
|
||
montado por mixins, um por assunto (markers, trim,
|
||
speed, titles, cut, silence…). Ver writer/modifier.py.
|
||
code/fcpxml/models/ — PACOTE. Data classes por família: timing, timeline,
|
||
enums, subtitles, qc, planning.
|
||
code/fcpxml/rough_cut.py — Generates new timelines (rough cuts, montages, A/B rolls).
|
||
code/fcpxml/diff.py — Timeline comparison engine.
|
||
code/fcpxml/export.py — DaVinci Resolve v1.9 + FCP7 XMEML v5 export.
|
||
code/fcpxml/media_intel.py — Silence detection + beat detection.
|
||
code/fcpxml/dtd.py — Validates output against Apple's official DTDs.
|
||
code/fcpxml/voice_*.py — Pipeline de voz: features → emphasis → voice_timeline
|
||
→ voice_actions → phrase_review. Ver Engine/docs/02.
|
||
|
||
admin/models_api.py — Ponte JSON com o app: docstring de comandos + dispatch.
|
||
admin/api/ — Os 37 comandos, um módulo por assunto.
|
||
code/MacApp/Sources/ — App SwiftUI. Compilado por swiftc (sem Xcode/SPM).
|
||
```
|
||
|
||
Os dois `__init__.py` de pacote (`writer/`, `models/`) reexportam tudo, então
|
||
`from .writer import FCPXMLModifier` e `from .models import TimeValue` seguem
|
||
valendo em todo o projeto.
|
||
|
||
## Documentação (MANDATORY)
|
||
|
||
A documentação viva fica em `code/Engine/docs/`. Cada arquivo tem **uma função
|
||
específica** — leia só o que a tarefa exige, não o conjunto. Carregar
|
||
documentação que não é do assunto custa tempo e processamento sem entregar nada.
|
||
|
||
### Qual arquivo abrir
|
||
|
||
| Sua tarefa | Abra | Não precisa de |
|
||
|-----------|------|----------------|
|
||
| Entender como o sistema é dividido | `01_ARCHITECTURE.md` | o resto |
|
||
| Achar onde mora uma função do engine | `02_MODULES.md` | 01, 03 |
|
||
| Criar/alterar uma ferramenta MCP | `03_SERVER_TOOLS.md` | 08 |
|
||
| Entender ou rodar os testes | `04_TESTS_AND_WORKFLOW.md` | — |
|
||
| "Isso já quebrou antes?" | `05_EXPERIENCIAS.md` — **só o índice no topo** | as entradas que não são a sua |
|
||
| Checklist antes de fechar | `06_BOAS_PRATICAS.md` | — |
|
||
| Mexer no app / no Assistente | `08_APP_MACOS.md` | 02, 03 |
|
||
| Escolher o que fazer, ver o que está aberto | `09_MANUTENCAO.md` | — |
|
||
|
||
Quando não souber por onde começar: `09_MANUTENCAO.md`. Ele roteia para o resto.
|
||
|
||
### Regra de atualização (obrigatória)
|
||
|
||
**Toda alteração de código atualiza a documentação no mesmo commit.** Doc velha
|
||
engana mais do que doc ausente — quem lê confia nela e erra com confiança.
|
||
|
||
| Você alterou | Atualize |
|
||
|--------------|----------|
|
||
| Estrutura de pastas, camadas ou dependências | `01_ARCHITECTURE.md` |
|
||
| Criou/moveu/dividiu módulo em `fcpxml/` | `02_MODULES.md` (tabela + linhas) |
|
||
| Criou/removeu ferramenta MCP | `03_SERVER_TOOLS.md` + contagem no `CLAUDE.md` |
|
||
| Comando da ponte | docstring de `admin/models_api.py` + `08_APP_MACOS.md` |
|
||
| Tela ou fluxo do app | `08_APP_MACOS.md` |
|
||
| Resolveu ou abriu uma dívida | `09_MANUTENCAO.md` §2 |
|
||
| Bateu num problema estrutural ou erro recorrente | `05_EXPERIENCIAS.md` + **índice no topo** |
|
||
|
||
Se um número (tools, testes, linhas) mudou, corrija onde ele aparece. Se um
|
||
documento divergir do código, **o código está certo** — conserte o documento.
|
||
|
||
### Ao escrever documentação
|
||
|
||
- **Um assunto por arquivo.** Se um doc começar a cobrir dois, divida.
|
||
- **Diga o que não está ali** e para onde ir — economiza a leitura seguinte.
|
||
- **Fatos verificados**, não suposições: rode o comando e use o número real.
|
||
- **Registre o porquê**, não só o quê. O "o quê" está no código; o "por quê"
|
||
se perde, e é o que evita alguém desfazer uma decisão por engano.
|
||
|
||
## Key Patterns
|
||
|
||
- **TimeValue**: All times are rational fractions (numerator/denominator) matching FCPXML's `"600/2400s"` format. Never use floats for time math.
|
||
- **_parse_project()**: Helper that parses FCPXML and returns `(tree, timeline, project)` tuple. Most handlers start with this.
|
||
- **generate_output_path()**: Creates `_modified`, `_chapters`, etc. suffixed output paths so originals aren't overwritten.
|
||
- **Tool handlers**: Each tool has its own `async def handle_<name>(arguments: dict)` function. All return via `_text_result(text)` which wraps strings in the MCP `TextContent` list.
|
||
- **Connected clips**: Clips with `lane` attribute hang off spine clips. Positive lane = above (video), negative = below (audio). Secondary `<storyline>` elements also contain connected clips.
|
||
- **XMEML export**: Converts spine-based model to track-based model. Primary storyline → Track 0, connected clip lanes → higher tracks.
|
||
|
||
## Running
|
||
|
||
```bash
|
||
cd code && uv run server.py # Start MCP server
|
||
cd code && uv run --extra dev pytest tests/ -v # Run tests
|
||
```
|
||
|
||
## Registro de Experiências e Boas Práticas (MANDATORY)
|
||
|
||
Sempre que um problema de estrutura ou um erro recorrente for detectado e
|
||
corrigido, **registre-o** em `code/Engine/docs/05_EXPERIENCIAS.md` (template já
|
||
presente no arquivo). Antes de concluir qualquer alteração/correção, aplique e
|
||
verifique as boas práticas e o checklist final em
|
||
`code/Engine/docs/06_BOAS_PRATICAS.md`.
|
||
|
||
## Pre-Commit (MANDATORY)
|
||
|
||
Padrão do sistema: **sempre após concluir uma correção, o sistema é
|
||
automaticamente executado/validado.** Acione o script único a cada correção:
|
||
|
||
```bash
|
||
cd code && ./Engine/run_after_fix.sh
|
||
```
|
||
|
||
Ele roda o lint (zero erros) e toda a suíte de testes, e falha se qualquer um
|
||
não passar. Equivalente a rodar manualmente os dois comandos abaixo.
|
||
|
||
## Executar o App Localmente (MANDATORY)
|
||
|
||
Sempre que uma alteração for feita no app (MacApp/) durante o período de
|
||
implementação, **compile e rode o programa localmente no computador** para
|
||
validar visualmente a alteração, além de rodar os testes:
|
||
|
||
```bash
|
||
cd code && ./MacApp/build_app.sh --run # compila e abre o app localmente
|
||
```
|
||
|
||
Regra geral: após qualquer alteração, o app deve ser executado localmente
|
||
antes de concluir a tarefa. Se houver erro de compilação, corrija antes de
|
||
seguir.
|
||
|
||
Before committing ANY changes, run both:
|
||
```bash
|
||
cd code && ruff check . --exclude docs/ # Lint — must pass with zero errors
|
||
cd code && pytest tests/ -v # Tests — all must pass
|
||
```
|
||
CI runs both on every push to main. If either fails, the commit gets an X on GitHub. Fix lint errors before committing, not after.
|
||
|
||
## Testing
|
||
|
||
1454 tests across 42 files, all under `code/tests/`. Um teste fora dessa pasta não roda (`testpaths = ["tests"]`) — se você criar um em outro lugar, confirme que a contagem total subiu. Cobertura por área: `test_models.py` (TimeValue/Timecode/Clip/Timeline), `test_writer.py` (insert/marker/trim/delete/split/speed), `test_server.py` (handlers e dispatch), `test_rough_cut.py`, `test_features_v05.py` (connected clips, roles, diff, reformat, silêncio, export), `test_marker_pipeline.py`, `test_refactored_helpers.py`, `test_transcribe.py`, `test_media_intel.py` (pula sem ffmpeg; o CI instala), `test_phrase_review.py` (revisão de frases da etapa 5) e `test_models_api.py` (comandos da ponte). Fixtures: `examples/sample.fcpxml` e XML inline. Os testes criam temporários e limpam depois.
|
||
|
||
## FCPXML Gotchas
|
||
|
||
- FCPXML uses rational time everywhere: `"3600/2400s"` = 1.5 seconds
|
||
- `offset` in clips is the timeline position, `start` is the source media in-point
|
||
- Library clips (`<asset-clip>`) are different from timeline clips (`<clip>`)
|
||
- Markers are children of clips, not siblings
|
||
- The `<spine>` element is the primary storyline — clips go here
|
||
- `.fcpxmld` bundles are DIRECTORIES wrapping `Info.fcpxml` + sidecar data files — sidecars must be copied on save or object-tracking/Cinematic data is destroyed
|
||
- `code/examples/sample.fcpxml` is NOT DTD-conformant (pre-`media-rep` assets, sequence-level chapter markers) — don't use it as a DTD-validity fixture
|