Un agente audita la pieza y devuelve una checklist booleana con evidencia y correcciones. Un validador sin LLM decide si esa auditoría está completa. Si no, el error vuelve al agente y se regenera. El usuario recibe un informe de correcciones sellado: qué cumple, qué no y qué cambiar. El candado no depende de que el orquestador se acuerde: está en el código, en el harness y en la firma.
El requisito era que fuera imposible saltarse el gate desde el flujo normal. Una sola capa no lo garantiza: el código puede tener otra ruta, el orquestador puede olvidarse, un consumidor posterior puede recibir un archivo editado. Por eso son tres.
pipeline/run.py tiene seis etapas fijas: hechos, brief, generar, gate, bucle, entrega. informe.json solo se escribe cuando validar() devuelve ok. No existe un flag que lo saltee ni una segunda entrada.
Invocar la SuperSkill arma la sesión (PreToolUse sobre Skill). El hook de Stop bloquea el fin del turno hasta que exista <sesión>.passed o .exhausted. Tope de 5 bloqueos: después libera con un incidente visible y sin contenido.
Cada resultado aprobado lleva sha256 del contenido y un HMAC con clave local. Un publicador, un bot de Slack o YouTube puede correr content-audit verify sin repetir nada. Si alguien edita el análisis después, el sello deja de verificar.
Un solo comando. Todo lo que sigue ocurre adentro, sin intervención del orquestador.
Derivada sección por sección de La rueda que ya gira. Cada campo tiene la pregunta que responde, el motivo que se devuelve cuando está en false y la sección de la que sale. El perfil decide cuáles son obligatorios: un post no tiene miniatura ni huecos visuales.
| id | grupo | pregunta | requerido | fuente |
|---|
Tres booleanos tienen una medición numérica asociada. Si el generador los marca en true y la medición viola el umbral, el gate devuelve inconsistencia. Las mediciones las hace el pipeline, no el generador.
| medición | campo | regla | por qué |
|---|---|---|---|
| hueco_visual_max_s | sin_huecos_visuales_largos | <= 90 s | el tramo más largo sin novedad visual supera el ritmo del resto de la pieza (una novedad cada 75 segundos) |
| segundo_del_gancho | tiene_gancho_5s | <= 5 s | el gancho llega después del quinto segundo |
| segundo_de_credencial | credencial_en_primer_minuto | <= 60 s | la credencial llega después del primer minuto |
El generador devuelve siempre esta forma. El gate no lee el análisis: exige que exista, que tenga 200 caracteres o más, y valida el resto por presencia, tipo y valor. Tiene dos políticas: auditoria_completa para el modo auditar, donde un false con corrección es un hallazgo, y todo_true para el modo producir, donde la pieza tiene que cumplir todo.
{
"schema_version": "1.0",
"pieza": {"id": "ai4m-ep2", "tipo": "video_largo", "titulo": "...", "contenido": "solo en modo producir"},
"analisis": "texto libre: el gate no lo interpreta",
"checklist": {
"tiene_gancho_5s": {"valor": true, "evidencia": "0:00 Hay un número de la historia de Frank que todavía cuesta creer"},
"cierre_con_gancho": {"valor": false, "evidencia": "termina en 11:07 y corta", "correccion": "grabar el cierre con el gancho a Frank"}
},
"mediciones": {"hueco_visual_max_s": 74.1}
}
$.schema_version distinta de la soportada: fallo.pieza.tipo que no es un perfil conocido: fallo sin evaluar nada, porque no se sabe qué es obligatorio.ausente.valor que no es un booleano JSON (ni "true" como texto ni 1): esquema.true sin evidencia: esquema. La evidencia es lo único que le permite a un humano verificar un true.campo_desconocido. El generador no inventa checks.false en un campo requerido: con política todo_true es falso, con el motivo del esquema, el detalle del generador y su corrección propuesta; con política auditoria_completa pasa si trae corrección concreta y es esquema si no la trae.inconsistencia.{
"status": "failed",
"iteracion": 1,
"failed_checks": [
{"campo": "tiene_gancho_5s", "tipo": "falso",
"motivo": "No se encontró un gancho claro en los primeros 5 segundos.", "correccion": "..."},
{"campo": "coherencia_entre_guion_y_visuales", "tipo": "falso",
"motivo": "La narrativa verbal no coincide con los keyframes principales: hay visuales anclados al guion y no a lo que se dice."}
]
}
El orden de failed_checks es siempre el mismo: errores estructurales primero, después los campos en el orden del esquema. Dos entradas iguales producen dos salidas iguales.
El brief original completo, el JSON que produjo, la lista de failed_checks con motivo y corrección, y la instrucción literal: REGENERÁ el análisis y el checklist corrigiendo específicamente los puntos fallidos. Conservá con su evidencia lo que ya estaba en true. Devolvé el JSON completo.
auditar: la pieza es fija y el entregable es la lista de correcciones; el gate exige que cada false diga qué cambiar. producir: la pieza se reescribe en pieza.contenido hasta cumplir todo. El modo elige la política del gate y la instrucción del brief, nada más.
--max-iter, default 4. En modo auditar una auditoría bien hecha pasa en la primera iteración; las siguientes solo completan lo que el gate marcó. Al agotarse no se entrega contenido, solo el objeto de fallo con la historia de cada iteración. Códigos de salida: 0 la pieza cumple todo, 1 informe con correcciones, 2 agotado.
Antes de validar, el pipeline pisa mediciones con lo que midió: duración por ffprobe, huecos visuales por intervalos verificados o por detección de escenas. Un generador no puede declarar que no hay huecos cuando la medición dice que sí.
trace.jsonl. El objeto de error se escribe en iter-N.error.json además de volver al generador. Un humano o un agente que observe la corrida ve exactamente lo mismo que ve el generador.Dos hooks en ~/.claude/settings.json. Ninguno decide sobre el contenido; solo saben si el pipeline terminó.
Si el skill invocado es content-audit-gate, escribe <sesión>.armed con un nonce y limpia marcas viejas. Nunca bloquea.
Si la sesión está armada y no existe una marca passed, exhausted o aborted posterior al armado, devuelve {"decision":"block"} con el motivo. Al quinto bloqueo consecutivo libera con systemMessage de INCIDENTE y deja <sesión>.incident.
exhausted, libera el turno, el usuario recibe el objeto de fallo. Es la salida normal de una pieza que no cumple.content-audit disarm --motivo "..." escribe aborted con motivo y hora en hooks.log. El SKILL.md lo prohíbe al orquestador.# cómo se ve desde la sesión
content-audit status
{"sesion": "…", "marcas": {"armed": false, "passed": true, "exhausted": false, "aborted": false, "incident": false}}
Generador claude-sonnet-5 headless, sin herramientas, con structured output. Los números salen de los archivos de cada corrida; este documento los lee al generarse.
| campo | qué falla | corrección |
|---|---|---|
| titulo_solucion | El título no responde la tercera pregunta del scroll: describe a un tercero y no promete nada a quien mira. El título es puramente descriptivo del caso de Frank en tercera persona ('Pagó... y no llegaron'); no dice nada que conecte con la vida, los deseos o el miedo del espectador que mira. | Reformular para incluir al espectador, por ejemplo: «Pagó 7 ingenieros 8 meses y no llegó ni al 5%: así es como tu equipo puede estar cometiendo el mismo error». |
| titulo_con_giro | El título es reconocible pero no tiene giro: le falta el pero, el sin embargo o la pregunta directa que rompe el patrón. El título usa 'y' para unir el setup con el resultado inesperado, sin 'pero', 'sin embargo' ni pregunta directa. El propio guion sí usa el giro explícito en 0:31: 'Pero según Frank, después de esos ocho meses, no habían llegado ni al 5%'. | Cambiar 'y no llegaron' por 'pero no llegaron', alineando el título con la ruptura que ya está en el habla a 0:31. |
| titulo_y_miniatura_complementarios | Título y miniatura repiten el mismo mensaje en vez de complementarse. Según el contexto, la miniatura del episodio 2 todavía no está definida. | Definir la miniatura antes de publicar. Como el título ya lleva la cifra (5%) y el caso, la miniatura debería llevar la promesa complementaria para el espectador (p. ej. la cara de Frank más una frase corta de beneficio), no repetir la cifra. |
| packaging_con_promesa | El packaging no contiene ninguna promesa para el espectador. Título, primera línea (0:00 'Hay un número de la historia de Frank que todavía cuesta creer') y miniatura (sin definir) generan intriga sobre el caso de Frank, pero ninguno formula una promesa de valor para quien mira. | Agregar una frase de promesa en el packaging, por ejemplo cerrar la primera línea con algo como '...y te va a servir para revisar si tu equipo tiene el mismo problema'. |
| promesa_para_el_que_mira | La promesa del packaging está formulada para el autor y no para quien mira. Todo el packaging (título y primera línea) está formulado en tercera persona sobre Frank; no hay una reformulación 'esto te puede pasar a vos / a tu empresa'. | Sumar una línea que traslade el caso de Frank al espectador, por ejemplo en el título o en la miniatura: 'esto le puede estar pasando a tu equipo ahora mismo'. |
| identidad_al_consumir | No está claro qué dice de alguien consumir esta pieza. No hay ninguna línea que le diga al espectador qué dice de él estar viendo esto (tipo 'si llegaste hasta acá es porque...'). | Agregar una línea cerca del cierre que valide la identidad de quien mira, por ejemplo: 'si seguiste hasta acá es porque ya sospechabas que el problema no era de talento sino de proceso'. |
| identidad_al_compartir | No está claro qué identidad refuerza compartir esta pieza. No hay ningún llamado o frase orientada a compartir la pieza ni una identidad asociada a hacerlo (con el jefe, con el equipo). | Cerrar con una invitación específica, por ejemplo: 'si tu equipo técnico también está reconstruyendo el mismo contexto una y otra vez, compartile esto'. |
| oferta_en_nivel_3 | La oferta se queda en el nivel 1 o 2 (qué es, qué hace) y no dice qué significa para quien la consume. La pieza no menciona en ningún momento la oferta (Arquitectura Ejecutable, diagnóstico, trimestre) ni la landing; termina en 11:07 sin puente comercial. | Agregar, tras el cierre actual, un bloque de oferta en nivel 3 tomando la frase de la landing v3: 'en 7 días tu sistema deja de estar en tu cabeza y empieza a funcionar', antes de explicar el mecanismo del diagnóstico. |
| nivel_3_antes_del_mecanismo | El mecanismo va antes que el significado: el orden es primero qué cambia para la persona, después cómo. No hay oferta en la pieza, por lo tanto no existe ningún orden significado-mecanismo para evaluar. | Al construir el bloque de oferta faltante, ordenar primero el significado ('tu sistema deja de estar en tu cabeza') y recién después el mecanismo (diagnóstico de 500, trimestre de 3.000). |
| frase_de_oferta_sin_nudo | La frase de oferta tiene un nudo de redacción (concordancia o antecedente ambiguo) que se va a repetir cien veces. La oferta no aparece en la pieza. El pitch heredado de la v1 citado en el contexto ('Convierto el sistema que tenés en la cabeza en un plano técnico de agentes que se puede ejecutar, y te dejo operándola') tiene un nudo: el pronombre 'la' en 'operándola' no tiene antecedente femenino claro ('sistema' y 'plano técnico' son masculinos). | Si se incorpora el pitch a la pieza, corregir a 'y te dejo operándolo' (refiriendo a 'el sistema') o reformular sin el pronombre ambiguo. |
| pitch_hablado_alineado_con_escrito | La oferta hablada y la escrita no dicen lo mismo. El pitch hablado no aparece en la pieza actual. Además, el pitch heredado de la v1 citado en el contexto pone el foco en el proceso ('plano técnico de agentes') mientras que la landing v3 pone el foco en el resultado ('en 7 días tu sistema deja de estar en tu cabeza y empieza a funcionar'); no dicen lo mismo. | Incluir en el cierre de la pieza un pitch hablado que use literalmente la frase de la landing v3 ('en 7 días tu sistema deja de estar en tu cabeza y empieza a funcionar') en vez del pitch heredado de la v1. |
| sin_ideas_repetidas | Hay frases que repiten una idea ya dicha y no se cortaron. 1:12 'Más reuniones, más documentos, más requerimientos, más explicaciones' y 2:58-3:00 'Y entonces aparece otra reunión. Otra explicación, otro documento, otro ajuste' repiten casi textualmente la misma idea (el ciclo de comunicación que no cierra la brecha) con apenas dos minutos de diferencia. | Eliminar o reformular una de las dos menciones; conservar la de 1:12 como planteo inicial y en 2:58 avanzar directamente a la consecuencia ('el equipo puede estar trabajando muchísimo...') sin repetir la lista de reunión/documento/ajuste. |
| cierre_con_gancho | La pieza termina sin gancho al siguiente capítulo: no arrastra a la siguiente pieza. El guion termina en 11:03-11:07 con 'Estamos reduciendo la distancia entre conocer profundamente un problema y poder convertir ese conocimiento en algo que realmente funciona' y corta ahí. El contexto confirma que el gancho al episodio 3 todavía no está grabado. | Grabar y montar el cierre con gancho al episodio 3 ya guionado, sin pedir nada (ni suscripción ni comentario), antes de publicar. |
| pieza_distinta_a_las_publicadas | La pieza repite el contenido de algo ya publicado en el canal: canibaliza en vez de acumular. El canal ya publicó 'Documentación vs. Realidad IA' y '8 meses con 7 personas' (mismo archivo, 6:54) el 27 de agosto, con un título casi idéntico al eje de ep2 ('8 meses' + equipo). No se dispone del transcript de esa pieza para confirmar si ep2 aporta ángulos nuevos más allá de la duración (11:09 vs 6:54). | Comparar el guion de ep2 contra el transcript de 'Documentación vs. Realidad IA' antes de publicar; si el núcleo narrativo del caso de Frank se superpone, recortar ep2 a lo que es nuevo (cita de Chamath, historia propia de Roberto 7:31-8:19, segmento de audiencia 9:00-9:52) y dejarlo explícito como continuación, no como repetición. |
| campo | evidencia del generador |
|---|---|
| tiene_gancho_5s | 0:00 'Hay un número de la historia de Frank que todavía cuesta creer.' ocupa los primeros 5 segundos completos y plantea curiosidad inmediata. |
| credencial_en_primer_minuto | Rótulo en 0:11 con nombre de Roberto, qué construyó y 'Partner Registered de Anthropic' (según contexto de la pieza), dentro del primer minuto. |
| sin_huecos_visuales_largos | El hueco visual más largo medido por el pipeline es de 74.1s (8:19 a 9:33), por debajo del umbral de 90s. |
| da_antes_de_pedir | Los 11:09 de la pieza son íntegramente historia y marco conceptual (el caso de Frank, la charla de Chamath, la propia experiencia de Roberto); no hay ningún pedido, CTA ni mención de precio en ningún punto del guion. |
| no_regala_el_producto | 8:19-8:33 explica qué es y por qué existe el substrato ('La aplicación es lo que se ve. El substrato es lo que hace que el trabajo de hoy le sirva a la semana que viene') sin dar pasos técnicos de construcción ni configuración de agentes. |
| titulo_familiaridad | Título «Pagó 7 ingenieros durante 8 meses y no llegaron ni al 5%» sigue el patrón familiar de 'inversión de tiempo/dinero + resultado fallido en cifra', un formato de gancho ya probado en contenido de negocios/tech. |
| audiencia_definida | 9:33-9:52 delimita explícitamente a quién sirve y a quién no: 'Sirve especialmente cuando el cuello de botella está en la distancia entre quien decide y quien ejecuta... Si tu principal problema está en máquinas, logística física... los agentes no van a [aparecer esa limitación]'. |
mediciones en el documento validado: {"hueco_visual_max_s": 74.1, "segundo_del_gancho": 0, "segundo_de_credencial": 11}
| campo | evidencia del generador |
|---|---|
| tiene_gancho_5s | Primera línea: 'Frank pagó siete personas durante ocho meses para construir el sistema de su empresa. Terminaron sin llegar ni al cinco por ciento.' |
| credencial_en_primer_minuto | Segundo párrafo: 'Sé de qué hablo: construí el sistema que hoy opera La Punta del Iceberg, soy Partner Registered de Anthropic.' |
| da_antes_de_pedir | Todo el post entrega el diagnóstico del error antes de mencionar el episodio; el cierre solo informa la fecha, no pide nada. |
| no_regala_el_producto | El cierre dice 'cuento cómo pasó esto con Frank... qué falló y qué cambió después' sin explicar el mecanismo del plano de agentes. |
| titulo_familiaridad | El título sigue la estructura ya probada de post de fracaso con cifra ('Pagó 7 ingenieros 8 meses y no llegó al 5%'), un formato reconocible en LinkedIn. |
| audiencia_definida | Párrafo 4: 'cualquier fundador o gerente de TI que sabe exactamente qué hay que construir, pero no tiene tiempo de construirlo'. |
Un frame del episodio (0:31) hizo de miniatura de prueba. El generador la miró con la herramienta Read, la única que se le habilita cuando hay imágenes, y evaluó únicamente los 8 puntos del packaging. El informe sale marcado y sellado como parcial.
| campo | qué falla | corrección |
|---|---|---|
| titulo_solucion | El título no responde la tercera pregunta del scroll: describe a un tercero y no promete nada a quien mira. El título narra el caso de Frank en tercera persona ("Pagó 7 ingenieros...") y no contiene ninguna frase que lo conecte con la vida, el problema o el deseo de quien mira; tampoco la primera línea hablada (0:00, "Hay un número de la historia de Frank que todavía cuesta creer") lo hace, sigue hablando de Frank. | Agregar al final del título o como texto en pantalla en los primeros segundos una frase dirigida al espectador, por ejemplo: "...y seguramente a tu equipo le está pasando lo mismo" o "así evitás pagar 8 meses por un problema que no era técnico". |
| titulo_y_miniatura_complementarios | Título y miniatura repiten el mismo mensaje en vez de complementarse. La miniatura muestra el texto "OCHO MESES" en una tarjeta superior y "7 personas" con un ícono de puntos abajo a la izquierda, junto a un gráfico de línea (expectativa punteada vs. resultado verde plano) con eje "mes 1". Repite exactamente las dos cifras que ya están en el título (7 y 8) en vez de aportar la promesa o el rostro; el fondo muestra a una persona desenfocada sin rostro visible. | Quitar "OCHO MESES" y "7 personas" de la miniatura (ya están en el título) y reemplazarlos por el rostro de Frank o de Roberto en primer plano junto con la promesa ("el error no fue técnico") o el resultado "5%" en grande, que no aparece en la miniatura actual. |
| packaging_con_promesa | El packaging no contiene ninguna promesa para el espectador. Ni el título, ni la miniatura (cifras "OCHO MESES" y "7 personas" más un gráfico), ni la primera línea ("Hay un número de la historia de Frank que todavía cuesta creer") formulan un beneficio o resultado para quien mira; las tres piezas del packaging describen el caso de Frank, no una promesa. | Sumar en la miniatura o en el texto en pantalla de los primeros 5 segundos una frase de beneficio explícito, por ejemplo "por qué esto no era un problema de ingenieros" o "lo que cambia si lo ves antes". |
| promesa_para_el_que_mira | La promesa del packaging está formulada para el autor y no para quien mira. Al no existir promesa en el packaging (ver packaging_con_promesa), tampoco existe una formulada para el espectador; el sujeto de todas las frases del título y la primera línea es Frank, nunca "vos" o "tu equipo". | Redirigir explícitamente al espectador en el título, la miniatura o la primera línea, por ejemplo cerrando con "y probablemente a vos te está pasando lo mismo" o agregando un rótulo en video "esto no es solo el caso de Frank". |
| campo | evidencia del generador |
|---|---|
| titulo_familiaridad | Título: "Pagó 7 ingenieros 8 meses pero no llegó al 5%." Usa la estructura ya probada en contenido de negocios/tech de "invertí X en Y y el resultado fue bajo", un formato de gancho ampliamente reconocido por el espectador de este tipo de contenido. |
Detección de escenas sobre el ep2 v17: 90 eventos a umbral 0,25 y hueco máximo de 32,9 s, porque el podcast de HeyGen alterna planos entre los dos avatares cada pocos segundos. Ese proxy sirve para una cámara fija y no para este formato. Con los 13 intervalos verificados con frames, el hueco máximo es 74,1 s: el mismo 1:14 del análisis manual, ahora calculado por código.
Validador (reglas, orden, sello, CLI), pipeline (convergencia en dos iteraciones, agotamiento sin contenido, respuesta sin JSON, corte por repetición, mediciones que pisan al generador, generador caído, contrato HTTP con un servidor local) y hooks (armado, bloqueo, liberación por passed, exhausted y aborted, incidente, y el pipeline real liberando el candado).
# una vez por pieza: registrar lo estático content-audit registrar ai4m-ep2 --alias episodio-2 --tipo video_largo --titulo "…" \ --material ~/shots-tmp/ep2-seg.json --video ~/playgrounds/ai4m-ep2-v17.mp4 \ --novedades ~/shots-tmp/ep2-novedades.json --contexto ~/shots-tmp/ep2-contexto.md ~/shots-tmp/ep2-packaging-contexto.md # después, cada auditoría son dos o tres palabras content-audit episodio-2 # la pieza completa, 35 puntos content-audit episodio-2 miniatura ~/Descargas/mini-v2.png # solo la miniatura, con la imagen content-audit episodio-2 titulo "Nuevo título a probar" # solo el título, con el texto nuevo content-audit episodio-2 cierre ~/shots-tmp/cierre-seg.json # el cierre grabado content-audit episodio-2 cierre --dry-run # qué va a auditar y con qué, sin gastar content-audit historial episodio-2 # cuántas correcciones quedan, corrida a corrida # la forma larga sigue existiendo, con todos los flags content-audit run --pieza-id … --tipo … --titulo "…" --material … --grupo A --campos … # producir una pieza que tenga que cumplir la checklist content-audit run --pieza-id post-ep2 --tipo post --titulo "…" --material brief.md --modo producir # re-evaluar un documento guardado sin LLM, y verificar un informe ya entregado content-audit informe ~/.claude/state/content-audit/runs/ai4m-ep2-…/iter-1.json --modo auditar --print md content-audit verify ~/.claude/state/content-audit/runs/ai4m-ep2-…/informe.json # otro agente como generador (Nova, un webhook, un servicio propio) content-audit run … --generator http --endpoint https://…/audit # token en CONTENT_AUDIT_HTTP_TOKEN
Los aspectos con nombre viven en el esquema: todo, titulo, miniatura, packaging, primer-minuto, gancho, autoridad, identidad, oferta, cierre, edicion, integridad y canal. Cada uno sabe qué campos cubre y qué material espera; miniatura exige una imagen. Desde la sesión de Claude Code, decir "validá esta miniatura" con la imagen adjunta se convierte en ese comando. El SKILL.md fija que lo único entregable es el informe que produjo el pipeline (o el objeto de fallo).
Nova es un generador más. Basta exponer en apps/api un endpoint que reciba {prompt, iteracion, pieza_id, modo, perfil} y devuelva {"output": "…JSON…"}, y correr el pipeline con --generator http. Si además se quiere el gate dentro de AgentSquad, como middleware del run, para que aplique a lo que Nova entrega por el compose o por voz, es una tarea de ese repo y va por el protocolo Cerebro/Manos. El contrato a respetar es el de este skill: validar(doc, schema) devuelve ok o failed, y ninguna respuesta sale sin ok.
La spec de la SuperSkill sigue el formato que Nova exige a su ecosistema: nombre, propósito, cuándo usarla y cuándo no, inputs, proceso paso a paso, agentes y recursos, criterios de calidad, métricas y feedback, notas de versión. Está en ~/.claude/skills/content-audit-gate/SKILL.md.