Menu

Diagnósticos JSON en Zero: errores estructurados para agentes

El compilador de Zero emite diagnósticos JSON legibles por máquinas con códigos de error estables y planes de reparación estructurados. Aquí tienes el formato, por qué existe y cómo lo consume un agente.

La funcionalidad estrella

La característica más distintiva de Zero no es una pieza de sintaxis. Es la manera en que el compilador le habla a quien — o lo que — lee su salida.

Pasa un programa con errores por zero check --json y obtienes una fuente que un agente puede leer directamente:

{
    "ok": false,
    "diagnostics": [
        {
            "code": "NAM003",
            "message": "unknown identifier",
            "line": 3,
            "repair": { "id": "declare-missing-symbol" }
        }
    ]
}

Ese blob pequeño está cargado. Desmontemos cada campo y las decisiones de diseño detrás de ellos.

La anatomía de un diagnóstico

Un diagnóstico es un objeto estructurado que describe un problema en el código. Los campos canónicos:

  • code — un identificador estable (p. ej. NAM003). Siempre significa lo mismo, sin importar la versión del compilador.
  • message — una descripción legible. La redacción puede cambiar entre versiones; el significado lo fija el code, no el mensaje.
  • line (y otros campos de ubicación) — dónde está el problema.
  • repair — metadatos estructurados opcionales que describen un arreglo que el compilador cree resolvería el diagnóstico. La forma de este campo también está documentada y es estable.

La forma de nivel superior incluye un booleano ok para la ejecución en conjunto y un array diagnostics; incluso cuando la ejecución tiene éxito, el array puede contener advertencias o notas.

Códigos de error estables

El contrato sobre code es la parte que probablemente más te sorprenda. NAM003 hoy significa "identificador desconocido". NAM003 el mes que viene y el año que viene también significará "identificador desconocido". Agentes (y humanos) pueden confiar en eso.

Esto importa porque los modelos de lenguaje y las herramientas tienden a cachear o memorizar lo que han visto. Si el significado de NAM003 cambiara con cada release, cada búsqueda cacheada sería insegura. Fijar el código mantiene:

  • Datos de entrenamiento de agentes válidos entre versiones.
  • Documentación indexable por código.
  • Pipelines de herramientas estables.

El message legible es libre de cambiar según el equipo mejore la redacción. El code es el identificador que carga el peso.

Metadatos de reparación

El campo repair, cuando está presente, dice al consumidor qué tipo de arreglo cree el compilador que funcionaría:

{
    "code": "NAM003",
    "message": "unknown identifier",
    "line": 3,
    "repair": { "id": "declare-missing-symbol" }
}

declare-missing-symbol aquí es el tipo de reparación — la intención de alto nivel. Para obtener las ediciones reales, llama a zero fix --plan --json. Eso devuelve un plan que incluye la ruta del archivo, los rangos de bytes a modificar y el texto nuevo:

{
    "diagnostic": { "code": "NAM003", "line": 3 },
    "plan": {
        "id": "declare-missing-symbol",
        "edits": [
            { "kind": "insert", "line": 1, "text": "fun answer() -> i32 { return 42 }\n" }
        ]
    }
}

(Los nombres exactos de los campos y la forma pueden diferir en tu versión del toolchain — el principio es "datos estructurados, no prosa".)

Un agente que lea el plan tiene algunas opciones:

  1. Aplicar las ediciones tal cual.
  2. Aplicar las ediciones con modificaciones.
  3. Rechazar el plan y recurrir a otro arreglo.

En cada caso, el agente opera sobre datos estructurados en lugar de intentar interpretar una sugerencia en inglés. Esa es la diferencia entre planes de reparación y las pistas tipo "¿quisiste decir...?" de un compilador típico.

Cómo lo usa de verdad un agente

Un bucle de extremo a extremo simplificado que un agente podría ejecutar:

  1. Generar o modificar un archivo de Zero.
  2. Ejecutar zero check --json contra él.
  3. Si el resultado es { "ok": true, ... }, seguir adelante.
  4. Si no, para cada diagnóstico:
    • Buscar el code para entender qué falla (con zero explain o una tabla local).
    • Si se ofrece un repair y parece seguro, llamar a zero fix --plan --json para las ediciones.
    • Aplicar (o simular) las ediciones.
  5. Volver al paso 2.

Compáralo con trabajar a partir de un mensaje en prosa: el agente tiene que parsear inglés, extraer un número de línea probable, adivinar el tipo de arreglo e inferir el texto exacto de inserción o reemplazo. Cada paso es difuso. La ruta JSON reemplaza cada paso por una búsqueda sobre un esquema documentado.

Más allá de errores: graph y size

--json no es solo para diagnósticos. Otros comandos exponen datos estructurados de la misma forma:

  • zero graph --json — emite el grafo de dependencias de un paquete como datos estructurados. Útil para entender qué depende de qué y para agentes que quieren razonar sobre sitios de llamada antes de tocarlos.
  • zero size --json — reporta el tamaño en disco de los artefactos compilados, desglosado por destino. Los datos son los mismos que ven los humanos en zero size, solo que parseables.

Esas formas son parte del diseño: siempre que el compilador tenga datos útiles, están disponibles como JSON para que las herramientas los consuman sin scraping de pantalla.

Cómo es el esquema

Los nombres de campo y las formas exactas están documentados en el repositorio de Zero y evolucionarán mientras el proyecto sea pre-1.0. Las categorías que puedes esperar:

  • Metadatos de ejecuciónok, version, tiempos.
  • Diagnósticoscode, message, ubicación (archivo/línea/columna/rangos de bytes), severidad (error/warning/note), repair opcional.
  • Planes de reparación — cuando los pides, la lista de ediciones estructurada.

Si estás construyendo herramientas contra esta superficie, el patrón seguro es leer los campos que conoces, ignorar campos desconocidos con elegancia y basar las decisiones de comportamiento en code.

Un recorrido rápido de extremo a extremo

Supón que tu código usa un identificador que no está declarado:

pub fun main(world: World) -> Void raises {
    check world.out.write(answer())   // 'answer' no está definido en ningún sitio
}

Ejecutar zero check --json produce algo así:

{
    "ok": false,
    "diagnostics": [
        {
            "code": "NAM003",
            "message": "unknown identifier 'answer'",
            "line": 2,
            "column": 27,
            "repair": { "id": "declare-missing-symbol" }
        }
    ]
}

zero fix --plan --json devuelve la edición:

{
    "diagnostic": { "code": "NAM003", "line": 2 },
    "plan": {
        "id": "declare-missing-symbol",
        "edits": [
            { "kind": "insert", "line": 1, "text": "fun answer() -> i32 { return 42 }\n" }
        ]
    }
}

zero fix (sin --plan) aplica la edición in situ, tras lo cual zero check devuelve ok: true. Cada paso es una transacción discreta e inspeccionable.

Por qué esto importa más allá de los agentes

Las mismas propiedades — salida estructurada, códigos estables, planes de reparación — también facilitan la vida a:

  • Editores e IDEs. Subrayados ondulados y bombillas que actúan sobre IDs de repair en lugar de texto parseado.
  • Pipelines de CI. Fallos que se loguean con code para grepping y dashboards fáciles.
  • Herramientas de codemod. Arreglos masivos que apuntan a un código, no a una regex sobre mensajes.

El sistema se diseñó pensando en agentes, pero las herramientas para humanos reciben los mismos beneficios.

Lo siguiente: diseño agent-first

El sistema de diagnósticos es el ejemplo más concreto de la filosofía agent-first de Zero. La próxima página, diseño agent-first, retrocede para mirar los principios subyacentes — superficie pequeña, tooling determinista, efectos explícitos — y cómo cada uno se gana su sitio.

Preguntas frecuentes

¿Qué son los diagnósticos JSON en Zero?

Cuando ejecutas zero check --json (u otros comandos con --json), el compilador emite sus hallazgos como JSON estructurado en lugar de prosa formateada para humanos. Cada diagnóstico lleva un código de error estable como NAM003, la ubicación en el código, un mensaje legible y, cuando corresponde, un campo repair estructurado que describe cómo arreglarlo.

¿Por qué Zero emite JSON en lugar de texto plano?

Los agentes necesitan parsear la salida del compilador. Los diagnósticos en texto plano están escritos para humanos y obligan a aplicar regex sobre inglés para sacar un número de línea o adivinar un arreglo. JSON es inequívoco: un agente lee el campo code, busca el significado documentado y actúa sobre el plan repair estructurado sin parsear prosa.

¿Qué es un código de error estable en Zero?

Cada diagnóstico que el compilador puede emitir tiene un identificador corto y estable como NAM003 (identificador desconocido). El contrato es que el código mantiene su significado entre versiones del compilador, aunque la redacción del mensaje humano cambie. Agentes y herramientas pueden hacer pattern matching sobre el código sin preocuparse por la deriva del mensaje.

¿Qué es un plan de reparación?

Cuando el compilador cree que sabe cómo arreglar un diagnóstico, adjunta un campo repair estructurado que nombra el tipo de arreglo que propondría. Llamar a zero fix --plan --json devuelve el plan completo: las operaciones de edición a aplicar, los archivos afectados y los rangos. Un agente puede aplicar, modificar o rechazar el plan de forma programática.

¿Cómo se relaciona zero explain con los diagnósticos JSON?

zero explain <código> devuelve la explicación legible de un código de diagnóstico: qué significa el error, por qué el compilador lo lanza y arreglos típicos. Es la cara en prosa del diagnóstico. El código es estable, así que las explicaciones cacheadas siguen siendo válidas; los agentes las buscan cuando un código queda fuera de sus datos de entrenamiento.

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR