feat: criado monitoramento contínuo de trilhas com varredura recur

- criado monitoramento contínuo de trilhas com varredura recursiva e baixa prioridade
- gerado e validado plano editorial revisável do depoimento da Erika sem aplicação na timeline
- adicionada leitura e comparação estrutural da timeline após aplicar planos de edição
- limitadas as classificações de trilhas às duas maiores probabilidades de cada categoria
- limpo o catálogo musical para reiniciar as análises sem remover dados de vídeo

Resumo:
- 34 arquivos alterados
- 6 novos
- 28 modificados
- 0 removidos

 28 files changed, 833 insertions(+), 75 deletions(-)

Arquivos:
  - .jhonny/analises.db
  - code/cep-plugin/index.html
  - code/cep-plugin/main.js
  - code/engine/analisar_trilhas.py
  - code/engine/aplicar_plano_de_edicao.py
  - code/engine/consultar_detalhes_de_trilha.py
  - code/engine/editor/__init__.py
  - code/engine/editor/aplicador_de_plano_de_edicao.py
  - code/engine/editor/backup_de_sequencia.py
  - code/engine/editor/escrita/escrita_no_editor.py
  - code/engine/editor/modelos.py
  - code/engine/editor/validacao_semantica.py
  - code/engine/integracoes/audio/classificador_de_musica_essentia.py
  - code/engine/integracoes/audio/modelos_de_analise_musical.py
  - code/engine/integracoes/audio/provider_de_analise_musical_essentia.py
  - code/engine/persistencia/esquema.py
  - code/engine/persistencia/repositorio_de_trilhas.py
  - code/engine/testes/duplos_de_premiere.py
  - code/engine/testes/test_aplicador_de_plano_de_edicao.py
  - code/engine/testes/test_aplicar_plano_de_edicao.py
  - code/engine/testes/test_escrita_no_editor.py
  - code/engine/testes/test_leitor_de_plano_de_edicao.py
  - code/engine/testes/test_validador_semantico_de_plano.py
  - code/plugins/premiere-pro/skills/editar-por-voz/SKILL.md
  - code/plugins/premiere-pro/skills/editar-por-voz/criterios/08-formato-de-saida.md
  - code/plugins/premiere-pro/skills/editar-por-voz/criterios/10-revisao-humana.md
  - code/src/tools/timeline.ts
  - code/tests/tools/tool-modules.test.ts
  - .jhonny/planos/
  - code/.jhonny/analises.db-shm
  - code/.jhonny/analises.db-wal
  - code/engine/editor/verificador_da_aplicacao.py
  - code/engine/testes/test_verificador_da_aplicacao.py
  - code/plugins/premiere-pro/skills/editar-por-voz/criterios/11-gancho.md
This commit is contained in:
João Henrique
2026-09-10 15:09:27 -04:00
parent da400de7d3
commit 2c9bdf2ff0
34 changed files with 1179 additions and 75 deletions
+36 -4
View File
@@ -37,8 +37,10 @@ from engine.editor import (
LeitorDePlanoDeEdicao,
MapeadorDeTempoDeOrigemParaTimeline,
PlanoDeEdicao,
ResultadoDaVerificacao,
TipoDeAcao,
ValidadorSemanticoDePlano,
VerificadorDaAplicacao,
)
from engine.integracoes.premiere.cliente_mcp import ClienteMCPPorStdio
from engine.integracoes.premiere.cliente_mcp_com_pausa import ClienteMCPComPausa
@@ -52,6 +54,14 @@ CAMINHO_DO_SERVIDOR_MCP = CAMINHO_DO_CODIGO / "dist" / "index.js"
CAMINHO_DO_BANCO = CAMINHO_DO_CODIGO.parent / ".jhonny" / "analises.db"
def _garantir_backup_para_ganchos(plano: PlanoDeEdicao, backup_criado: bool) -> None:
"""Bloqueia ganchos quando não há uma cópia recuperável da sequência."""
if plano.acoes_do_tipo(TipoDeAcao.GANCHO) and not backup_criado:
raise ErroDePlanoInvalido(
"A ação hook não foi aplicada porque o Premiere não confirmou o backup da sequência."
)
def _validar_integridade_semantica(
plano: PlanoDeEdicao,
plano_id: int | None,
@@ -59,7 +69,10 @@ def _validar_integridade_semantica(
exigir_validacao: bool = False,
) -> None:
"""Valida palavras, frases e respiros antes de iniciar a sessão do Premiere."""
if not plano.acoes_do_tipo(TipoDeAcao.CORTE):
if not (
plano.acoes_do_tipo(TipoDeAcao.CORTE)
or plano.acoes_do_tipo(TipoDeAcao.GANCHO)
):
return
if plano_id is None:
if exigir_validacao:
@@ -119,6 +132,7 @@ def _registrar_no_banco(
sequencia: str,
plano_id: int | None = None,
caminho_do_banco: Path = CAMINHO_DO_BANCO,
verificacao: ResultadoDaVerificacao | None = None,
) -> None:
"""Guarda no banco de análises o plano aplicado e o resultado da aplicação.
@@ -145,11 +159,14 @@ def _registrar_no_banco(
if plano_id is None:
plano_id = repositorio.registrar_plano(plano_de_dict(dados))
aplicadas = sum(1 for item in resultado.resultados if item.sucesso)
verificacao_aprovada = verificacao is None or verificacao.aprovada
mensagem = verificacao.mensagem if verificacao is not None else None
repositorio.registrar_aplicacao(
plano_id,
sucesso=resultado.todas_bem_sucedidas,
sucesso=resultado.todas_bem_sucedidas and verificacao_aprovada,
acoes_aplicadas=aplicadas,
sequencia=sequencia,
mensagem=mensagem,
)
except (OSError, ValueError, sqlite3.Error) as erro:
print(f"Plano aplicado, mas não foi possível registrá-lo no banco: {erro}",
@@ -186,9 +203,11 @@ def executar(
# A engine é a única responsável pelo backup. A validação semântica já
# aconteceu antes da conexão, portanto um plano bloqueado não duplica
# a sequência. Uma falha no backup fica registrada em stderr.
# a sequência. Gancho é recusado sem backup porque combina mais de
# uma mutação estrutural; as demais ações preservam o fluxo legado.
sequencia_ativa = conversor_de_timeline.converter(acesso_ao_editor.obter_timeline_ativa())
backup_ok = BackupDaSequencia(cliente).criar_backup(sequencia_ativa.identificador)
_garantir_backup_para_ganchos(plano, backup_ok)
print(
"Backup da sequência criado." if backup_ok else "Não foi possível criar o backup automático; aplicando mesmo assim.",
file=sys.stderr,
@@ -201,15 +220,28 @@ def executar(
mapeador=MapeadorDeTempoDeOrigemParaTimeline(),
)
resultado = aplicador.aplicar(plano)
timeline_depois = conversor_de_timeline.converter(
acesso_ao_editor.obter_timeline_ativa()
)
verificacao = VerificadorDaAplicacao().verificar(
sequencia_ativa, timeline_depois, plano
)
_registrar_no_banco(
caminho_do_plano, resultado, sequencia_ativa.nome,
plano_id=plano_id, caminho_do_banco=caminho_do_banco,
verificacao=verificacao,
)
return {
"arquivo_de_origem": plano.arquivo_de_origem,
"todas_bem_sucedidas": resultado.todas_bem_sucedidas,
"todas_bem_sucedidas": resultado.todas_bem_sucedidas and verificacao.aprovada,
"verificacao": {
"aprovada": verificacao.aprovada,
"mensagem": verificacao.mensagem,
"divergencias": list(verificacao.divergencias),
"avisos": list(verificacao.avisos),
},
"acoes": [
{
"tipo": item.acao.tipo.value,