Menu

Zero JSON-диагностика: структурированные ошибки компилятора для агентов

Компилятор Zero выдаёт машинно-читаемые JSON-диагностики со стабильными кодами ошибок и структурированными планами починки. Вот формат, зачем он существует и как агент его потребляет.

Главная фича

Самая характерная фича Zero — это не кусок синтаксиса. Это то, как компилятор разговаривает с тем — или с тем самым кем-то, — кто читает его вывод.

Прогоните сломанную программу через zero check --json — и получите поток, который агент может читать напрямую:

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

Это маленький, но нагруженный blob. Распакуем каждое поле и решения за ним.

Анатомия диагностики

Диагностика — это структурированный объект, описывающий одну проблему в исходнике. Каноничные поля:

  • code — стабильный идентификатор (например, NAM003). Всегда означает одно и то же, независимо от версии компилятора.
  • message — человеческое описание. Формулировка может меняться между версиями; смысл закрепляется через code, а не через сообщение.
  • line (и другие поля локации) — где находится проблема.
  • repair — необязательные структурированные метаданные, описывающие починку, которая, по мнению компилятора, исправит диагностику. Форма этого поля сама документирована и стабильна.

Верхнеуровневая форма включает булев ok для всего запуска целиком и массив diagnostics; даже когда запуск удался, массив может содержать предупреждения или замечания.

Стабильные коды ошибок

Контракт по code — то, что, скорее всего, удивит вас сильнее всего. NAM003 сегодня означает «unknown identifier». NAM003 через месяц и через год тоже будет означать «unknown identifier». Агенты (и люди) могут на это полагаться.

Это важно, потому что языковые модели и тулинг склонны кэшировать или запоминать то, что видели. Если бы смысл NAM003 дрейфовал с каждым релизом, каждый закэшированный поиск был бы небезопасен. Закрепление кода даёт:

  • Валидные обучающие данные для агентов между версиями.
  • Документацию, индексируемую по коду.
  • Стабильные пайплайны тулинга.

Человеческое message может меняться по мере того, как команда улучшает формулировки. code — это несущий идентификатор.

Метаданные починки

Поле repair, когда оно есть, говорит потребителю, какой вид починки, по мнению компилятора, подойдёт:

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

declare-missing-symbol здесь — это вид починки, высокоуровневое намерение. Чтобы получить сами правки, вызовите zero fix --plan --json. Это вернёт план, в котором есть путь к файлу, диапазоны байтов для изменения и новый текст:

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

(Точные имена полей и форма могут отличаться в вашей версии тулчейна — принцип «структурированные данные, не проза».)

У агента, читающего план, есть несколько вариантов:

  1. Применить правки как есть.
  2. Применить правки с модификациями.
  3. Отклонить план и потянуться к другой починке.

В любом случае агент оперирует структурированными данными, а не пытается интерпретировать английское предложение. В этом и есть разница между планами починки и подсказками «did you mean ...?» в обычном компиляторе.

Как агент реально это использует

Упрощённый сквозной цикл, который может запустить агент:

  1. Сгенерировать или изменить файл Zero.
  2. Прогнать zero check --json против него.
  3. Если результат { "ok": true, ... }, идти дальше.
  4. Иначе, для каждой диагностики:
    • Поискать code, чтобы понять, что не так (через zero explain или локальную таблицу).
    • Если предложен repair и он выглядит безопасно, вызвать zero fix --plan --json за правками.
    • Применить (или просимулировать) правки.
  5. Вернуться к шагу 2.

Сравните с работой по прозаическому сообщению: агенту приходится разбирать английский, извлекать вероятный номер строки, угадывать вид починки и выводить точный текст вставки или замены. Каждый шаг размыт. JSON-путь заменяет каждый шаг поиском по задокументированной схеме.

За пределами ошибок: Graph и Size

--json нужен не только для диагностик. Другие команды отдают структурированные данные тем же способом:

  • zero graph --json — отдаёт граф зависимостей пакета как структурированные данные. Полезно, чтобы понять, что от чего зависит, и для агентов, которые хотят рассуждать о местах вызова перед тем, как их трогать.
  • zero size --json — отчёт о размере собранных артефактов на диске, в разбивке по целям. Те же данные, что человек видит в zero size, только парсятся.

Эти формы — часть дизайна: всегда, когда у компилятора есть полезные данные, они доступны в JSON для инструментов, без скрейпинга экрана.

Как выглядит схема

Имена полей и точные формы задокументированы в репозитории Zero и будут эволюционировать, пока проект pre-1.0. Категории, которые можно ожидать:

  • Метаданные запускаok, version, тайминги.
  • Диагностикиcode, message, локация (файл/строка/колонка/диапазоны байтов), severity (error/warning/note), необязательный repair.
  • Планы починки — структурированный список правок при загрузке.

Если вы строите тулинг против этой поверхности, безопасный паттерн — читать известные вам поля, мягко игнорировать неизвестные и ключевать поведение по code.

Быстрый сквозной разбор

Допустим, ваш исходник использует идентификатор, который нигде не объявлен:

pub fun main(world: World) -> Void raises {
    check world.out.write(answer())   // 'answer' нигде не определён
}

Запуск zero check --json производит что-то вроде:

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

zero fix --plan --json возвращает правку:

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

zero fix (без --plan) применяет правку на месте, после чего zero check возвращает ok: true. Каждый шаг — отдельная инспектируемая транзакция.

Почему это важно за пределами агентов

Те же свойства — структурированный вывод, стабильные коды, планы починки — также упрощают жизнь:

  • Редакторам и IDE. Squigglies и лампочки, которые действуют по repair-ID, а не по разобранному тексту.
  • CI-пайплайнам. Падения логируются с code для удобного grep и дашбордов.
  • Codemod-инструментам. Массовые починки, нацеленные на код, а не на регулярки над сообщениями.

Систему проектировали под агентов, но человеческий тулинг получает те же выгоды.

Дальше: Agent-First дизайн

Система диагностики — самый конкретный пример agent-first философии Zero. Следующая статья, agent-first дизайн, отдаляется к лежащим в основе принципам — маленькая поверхность, детерминированный тулинг, явные эффекты — и тому, как каждый из них зарабатывает своё место.

Часто задаваемые вопросы

Что такое JSON-диагностика в Zero?

Когда вы запускаете zero check --json (или другие команды с --json), компилятор выдаёт свои находки как структурированный JSON, а не как человеческую прозу. Каждая диагностика несёт стабильный код ошибки вроде NAM003, локацию в исходнике, человеческое сообщение и — где применимо — структурированное поле repair, описывающее, как это починить.

Почему Zero выдаёт JSON, а не обычный текст?

Агентам нужно разбирать вывод компилятора. Текстовые диагностики написаны для людей и требуют регулярок над английским, чтобы извлечь номер строки или угадать починку. JSON однозначен: агент читает поле code, ищет задокументированное значение и действует по структурированному плану repair, никогда не разбирая прозу.

Что такое стабильный код ошибки в Zero?

У каждой диагностики, которую может выдать компилятор, есть короткий стабильный идентификатор вроде NAM003 (unknown identifier). Контракт в том, что код сохраняет своё значение между версиями компилятора, даже если меняется формулировка человеческого сообщения. Агенты и тулинг могут паттерн-матчить по коду, не беспокоясь о дрейфе сообщений.

Что такое план починки?

Когда компилятор думает, что знает, как исправить диагностику, он прикладывает структурированное поле repair, называющее вид починки, который он предложил бы. Вызов zero fix --plan --json возвращает полный план — операции редактирования для применения, затронутые файлы и диапазоны. Агент может применить, изменить или отклонить план программно.

Как zero explain связана с JSON-диагностикой?

zero explain <code> возвращает человеческое объяснение кода диагностики — что означает ошибка, почему компилятор её выдаёт и каковы типичные починки. Это проза-сторона диагностики. Код стабилен, поэтому закэшированные объяснения остаются валидными; агенты подгружают их, когда код выпадает за пределы их обучающих данных.

Coddy programming languages illustration

Учитесь программировать с Coddy

НАЧАТЬ