feat: criado repositório jhonny-editor no Gitea

criado repositório jhonny-editor no Gitea
adicionado script admin/deploy.command com commit automático
atualizado admin/DEV-NOTES.md com template limpo

Resumo:
- 4 arquivos alterados
- 0 novos
- 4 modificados
- 0 removidos

 4 files changed, 101 insertions(+), 4 deletions(-)

Arquivos:
  - code/engine/editor/aplicador_de_plano_de_edicao.py
  - code/engine/editor/escrita/escrita_no_editor.py
  - code/engine/testes/duplos_de_premiere.py
  - code/engine/testes/test_aplicador_de_plano_de_edicao.py
This commit is contained in:
João Henrique
2026-09-10 18:07:16 -04:00
parent 4170b32340
commit e73b094187
4 changed files with 101 additions and 4 deletions
+26 -2
View File
@@ -49,6 +49,7 @@ class ClienteMCPFalso(ClienteMCP):
sem_origem_no_audio: bool = False,
clipe_unico: bool = False,
desvio_do_split: float = 0.0,
simular_falha_razor: bool = False,
) -> None:
"""``sem_origem_no_audio`` reproduz o bug real do bridge: relatar clipes de
áudio sem ``inPoint``/``outPoint`` na resposta de ``get_active_sequence``.
@@ -59,9 +60,14 @@ class ClienteMCPFalso(ClienteMCP):
``desvio_do_split`` reproduz o drift real do ``split_clip``: em vez
de cortar exatamente no instante pedido, corta em
``instante + desvio_do_split``."""
``instante + desvio_do_split``.
``simular_falha_razor`` reproduz o bug QE do Premiere 26.x: o
``razor_all_tracks`` reporta clipes elegíveis mas não corta nenhum
(``razored=0, eligibleTracks=N``)."""
self.sem_origem_no_audio = sem_origem_no_audio
self.desvio_do_split = desvio_do_split
self.simular_falha_razor = simular_falha_razor
self.chamadas: list[tuple[str, dict[str, Any]]] = []
self._proximo_id = 0
self._historico: list[dict[str, list[_ClipeFalso]]] = []
@@ -230,9 +236,27 @@ class ClienteMCPFalso(ClienteMCP):
Reproduz o ``razor_all_tracks`` do bridge real: corta todas as faixas
de vídeo e/ou áudio no mesmo ponto de tempo, garantindo
sincronização entre elas.
Quando ``simular_falha_razor`` está ativo, reporta clipes elegíveis
mas não corta nenhum, reproduzindo o bug QE do Premiere 26.x.
"""
instante_pedido = float(argumentos["time_seconds"])
track_type = argumentos.get("track_type", "both")
elegiveis = 0
for identificador_da_faixa, faixa in self._faixas.items():
if track_type == "video" and not identificador_da_faixa.startswith("video_"):
continue
if track_type == "audio" and not identificador_da_faixa.startswith("audio_"):
continue
for clipe in faixa:
if clipe.inicio_na_timeline < instante_pedido < clipe.fim_na_timeline:
elegiveis += 1
break
if self.simular_falha_razor:
return {"razored": 0, "eligibleTracks": elegiveis, "verified": False}
cortados = 0
self._salvar_estado()
for identificador_da_faixa, faixa in self._faixas.items():
@@ -262,7 +286,7 @@ class ClienteMCPFalso(ClienteMCP):
faixa[posicao:posicao + 1] = [parte_esquerda, parte_direita]
cortados += 1
break
return {"razored": cortados, "verified": True}
return {"razored": cortados, "eligibleTracks": elegiveis, "verified": True}
def _simular_ripple_delete(self, argumentos: dict[str, Any]) -> dict[str, Any]:
"""Remove o clipe pedido e fecha o espaço deixado na mesma faixa."""
@@ -317,6 +317,54 @@ class TesteAplicadorDePlanoDeEdicao(unittest.TestCase):
self.assertLess(nomes.index("remove_linked_from_timeline"), nomes.index("duplicate_linked_range_to_start"))
self.assertLess(nomes.index("duplicate_linked_range_to_start"), nomes.index("set_clip_properties"))
def test_corte_falha_limpo_quando_razor_nao_corta_nenhuma_faixa(self):
"""Quando o razor_all_tracks falha (QE no-op do Premiere 26.x),
o corte deve falhar sem corromper a timeline para operações
subsequentes — nenhuma remoção é tentada e marcadores/zooms
continuam funcionando."""
cliente = ClienteMCPFalso(simular_falha_razor=True)
aplicador = AplicadorDePlanoDeEdicao(
acesso_ao_editor=AcessoAoEditor(AcessoATimeline(cliente)),
conversor_de_timeline=ConversorDeTimeline(),
escrita=EscritaNoEditor(cliente),
mapeador=MapeadorDeTempoDeOrigemParaTimeline(),
)
plano = PlanoDeEdicao("0E6A8290.mp4", (
AcaoDeEdicao(TipoDeAcao.CORTE, inicio=0.0, fim=40.6, motivo="bastidor"),
AcaoDeEdicao(TipoDeAcao.MARCADOR, inicio=90.0, fim=90.5, motivo="ok", parametros={"content": "X"}),
))
resultado = aplicador.aplicar(plano)
self.assertFalse(resultado.todas_bem_sucedidas)
self.assertEqual(len(resultado.falhas), 1)
self.assertIn("razor", resultado.falhas[0].detalhe.lower())
self.assertTrue(any(c[0] == "add_marker" for c in cliente.chamadas))
self.assertEqual(cliente.chamadas_de_remocao, [])
def test_gancho_falha_limpo_quando_razor_nao_corta_nenhuma_faixa(self):
"""Quando o razor_all_tracks falha ao isolar o trecho do gancho,
a operação deve falhar sem duplicar nada na timeline."""
cliente = ClienteMCPFalso(clipe_unico=True, simular_falha_razor=True)
aplicador = AplicadorDePlanoDeEdicao(
acesso_ao_editor=AcessoAoEditor(AcessoATimeline(cliente)),
conversor_de_timeline=ConversorDeTimeline(),
escrita=EscritaNoEditor(cliente),
mapeador=MapeadorDeTempoDeOrigemParaTimeline(),
)
plano = PlanoDeEdicao("0E6A8290.mp4", (
AcaoDeEdicao(
TipoDeAcao.GANCHO,
inicio=80.0,
fim=90.0,
motivo="gancho de abertura",
parametros={"target": 0, "keep_original": True},
),
))
resultado = aplicador.aplicar(plano)
self.assertFalse(resultado.todas_bem_sucedidas)
self.assertEqual(len(resultado.falhas), 1)
duplicacoes = [c for c in cliente.chamadas if c[0] == "duplicate_linked_range_to_start"]
self.assertEqual(len(duplicacoes), 0)
if __name__ == "__main__":
unittest.main()