Genera
el plan o el diff
Un modelo produce el plan o el diff que se va a mergear.
Evidencia versionada para la revisión adversarial de código con IA
Lo que pasó en esa revisión termina como un archivo JSON en tu repo, al lado del código que juzga. Ni un badge verde ni un puntaje de cobertura: qué hallazgos se verificaron, cuáles se refutaron, qué no se pudo ejecutar y qué sigue descansando sobre el juicio de alguien. disensor es el CLI y la GitHub Action que lo revisan contra el esquema, sus reglas y el cambio que el pull request realmente hace.
¿Primera vez acá? Mirá una ronda de punta a punta, sin instalar nada
Instalación
pip install disensordisensor guide.disensor round ejecuta el revisor que tengas instalado. En los dos casos hace falta un árbitro humano; sin él el artefacto no valida.init --no-workflow escribe todo menos el workflow, y el gate corre igual en tu máquina. Si nunca lo viste, cómo funciona, explicado despacio.§ 01
Ese archivo se llama declaración de residuo. El residuo es lo que la revisión deja anotado para que una persona sepa dónde mirar: los hallazgos que quedaron sin decidir, los que el generador refutó, incluso con pruebas, lo que no se pudo comprobar ejecutando y los límites del propio revisor. La declaración lista eso en lugar de cobertura, y la página del método explica por qué no se parece en nada a un badge verde.
Guía de revisión adversarial de código Qué es el desacuerdo controlado
§ 02
Dentro de un evento el ciclo es lineal: el revisor ataca una vez. disensor se queda afuera de ese ciclo. Define el artefacto con el que termina, y lo revisa.
el plan o el diff
Un modelo produce el plan o el diff que se va a mergear.
uno o más revisores (R4)
Un modelo de otra familia lo revisa con una consigna adversarial. Dos modelos del mismo linaje fallan en los mismos lugares, y por eso la familia tiene que cambiar.
contra el repositorio o la ejecución
El generador contrasta cada hallazgo contra el repositorio o la ejecución y lo lleva a un estado terminal: incorporado, deuda registrada, decisión del dueño, refutado o escalado.
cierra el ciclo, no el problema
El ciclo cierra cuando todo hallazgo llegó a un estado terminal. Lo que no cerró queda escrito y viaja versionado con el commit. Ese archivo lo escribe tu asistente, no vos.
escalated_open, refuted_interpretive
Requerido en todo evento. Sin él la declaración no cumple el protocolo.
§ 03
Un JSON versionado en el repositorio, junto al código que juzga. Registra los actores, su familia y cuán independiente fue realmente el revisor, cada hallazgo con su estado terminal y las métricas del evento. Una ronda que no pudo llegar a otra familia de modelo queda registrada como el modo degradado que es, y arrastra su propio ítem de residuo.
El bloque para leer es residue. En este evento real, los 3 hallazgos llegaron todos a un estado terminal, y aun así dejaron 3 ítems de residuo, de tres clases distintas. Una refutación con pruebas cierra su hallazgo y entra igual al residuo, para que el árbitro pueda no darla por buena.
El gate no corre ningún modelo ni pide claves de API: valida un archivo que ya está versionado. Correr la revisión es un paso aparte, y ese sí le entrega tu diff a un modelo de otra familia; desde la 0.9 lo orquesta disensor round con el revisor que tengas instalado.
| total_findings | 3 |
|---|---|
| incorporated | 1 |
| debt_recorded | 0 |
| owner_decision | 0 |
| refuted_verifiable | 1 |
| refuted_interpretive | 0 |
| escalated_open | 1 |
| residue.items | 3 |
"residue": {
"items": [
{
"id": "r1",
"class": "escalation_without_decision",
"finding_ref": "h2",
"requires_human_attention": true,
"description": "El limite de filas de la exportacion quedo escalado a producto y sin resolver al cierre del ciclo."
},
{
"id": "r2",
"class": "principal_refutation",
"finding_ref": "h3",
"refutation_type": "verifiable",
"requires_human_attention": false,
"description": "Refutacion con enlace al objeto de consulta compartido, para que el revisor humano pueda no darla por buena.",
"evidence": {
"text": "La validacion vive en el objeto de consulta compartido reutilizado por la exportacion.",
"link": "src/consultas/RangoFechas.cs#L41-L58"
}
},
{
"id": "r3",
"class": "execution_gap",
"requires_human_attention": true,
"gap_reason": "environment_not_reproducible",
"description": "El comportamiento bajo concurrencia real no se probo porque el entorno de desarrollo no la reproduce."
}
]
}§ 04
Una GitHub Action que valida las declaraciones que el PR agrega, aplica la política de alcance del repositorio y publica el resultado como comentario. Cuando da verde escribe además un informe HTML de todas las declaraciones del repositorio, con lo que quedó abierto primero y sin red: el documento es lo último del evento.
§ 05
El validador detecta el campo vacío y el marcador genérico. No detecta la declaración falsa, y ninguna herramienta puede. Alguien tiene que abrir PR ya mergeados al azar y leerlos.
Tampoco protege contra un workflow modificado, salteado o sustituido. Esa parte la resuelve la plataforma: required checks estrictos, CODEOWNERS y el pin de la Action por SHA.
Qué exige el artefacto y qué todavía no puede verificar cambia con cada versión del esquema. Los límites conocidos se declaran en la referencia.
El gate corre igual en tu máquina y dice exactamente lo mismo que diría en CI. Recién cuando quieras que haga cumplir, se escribe el workflow.
pip install disensor && disensor init --no-workflow