fix(short): el primer plano gastaba el gancho en la fecha
El gancho de un Short es lo que se DIBUJA, no solo lo que se dice. El prompt llevaba la mitad hablada desde 4b («the first line is the whole hook») y no tenía nada sobre la mitad vista. De los diecisiete short_en generados, once abren mal: diez ponen la fecha en el titular —el texto más grande del vídeo— mientras el subline de debajo ya lleva el sitio, y el output 131 abre con document_quote. Medido sobre el renderizador a 5,5 s de plano: las cinco plantillas con `headline` lo ponen a tinta plena en 0,33-0,40 s, y shortsmith lo garantiza a cualquier duración desde db1ac7e. Las tres que no lo tienen dejan la banda superior del fotograma al nivel del fondo TODO el plano —su texto se escribe a máquina más abajo y no está entero hasta 2,6-2,8 s—. Con 6,9 s de visionado medio, abrir con una de esas regala el tercio de la ventana en el que se decide todo. La costura es `headline`, preguntada al esquema y no a una lista de nombres: una plantilla nueva de shortsmith con titular podrá abrir sin tocar este repo, y una sin él no podrá. El mismo pacto que el resto del contrato. Y `_closer_to_target` ordenaba SOLO por segundos, lo que hacía decorativo el aviso nuevo: una reescritura que arreglaba el titular pero se pasaba un segundo perdía contra el intento que abría con una fecha. Ahora el gancho va delante — los segundos son un gradiente, el gancho es binario. Comprobado contra los 17 specs reales de producción: avisa de once y de ninguno más. Los que pasan son los titulares que se quieren (62 CHILDREN, 23 HELICOPTERS, RELEASE 05). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -105,6 +105,17 @@ def test_prompt_states_the_editorial_constraints():
|
||||
assert "material" in prompt
|
||||
|
||||
|
||||
def test_the_prompt_states_what_the_opening_shot_has_to_do():
|
||||
"""Las dos mitades del gancho visual. Sin la primera el modelo abre con una
|
||||
plantilla que aún se está escribiendo; sin la segunda gasta el texto más
|
||||
grande del vídeo en la fecha, que es lo que hizo en cinco de once casos."""
|
||||
w, _ = writer("{}")
|
||||
prompt = w.build_prompt("Caso X", "material", None, "X.TEST")
|
||||
|
||||
assert "`headline`" in prompt and "0.4 seconds" in prompt
|
||||
assert "never the date" in prompt and "subline" in prompt
|
||||
|
||||
|
||||
def test_prompt_includes_the_worked_example_in_full():
|
||||
w, _ = writer("{}")
|
||||
prompt = w.build_prompt("Caso X", "material", None, "X.TEST")
|
||||
@@ -394,6 +405,27 @@ async def test_a_rewrite_that_makes_it_worse_is_discarded():
|
||||
assert result.attempts == 2, "se pagaron dos generaciones aunque valga la primera"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_a_fixed_hook_beats_a_closer_duration():
|
||||
"""El desempate entre intentos válidos ordenaba SÓLO por segundos, y eso
|
||||
hacía inútil el aviso de apertura: el modelo obedecía la nota, se pasaba un
|
||||
poco de largo al reescribir, y se elegía igualmente el intento que abría con
|
||||
una fecha. Los segundos son un gradiente; el gancho es binario y cuesta más.
|
||||
"""
|
||||
fecha = json.loads(json.dumps(GOOD))
|
||||
fecha["shots"][0]["props"]["headline"] = "8 JAN 1981" # 30 s: en objetivo
|
||||
arreglado = json.loads(json.dumps(GOOD))
|
||||
arreglado["shots"][0]["props"]["headline"] = "62 CHILDREN"
|
||||
for shot in arreglado["shots"]:
|
||||
shot["duration"] = 24.0 # 48 s: se pasa
|
||||
w, _ = writer(json.dumps(fecha), json.dumps(arreglado))
|
||||
|
||||
result = await w.write("Caso X", "material")
|
||||
|
||||
assert result.spec["shots"][0]["props"]["headline"] == "62 CHILDREN"
|
||||
assert result.notes and "objetivo" in result.notes[0]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_a_note_does_not_eat_the_attempt_the_contract_needs():
|
||||
"""Si la reescritura sale malformada, aún queda un intento para arreglarla."""
|
||||
|
||||
Reference in New Issue
Block a user