Handbooks
Концепции

Зачем это существует

Сводка по кодовой базе не помогает агенту находить вещи. Помогает маршрутизация. Вот аргумент — и дизайн, который из него следует.

Сбой, который вы уже видели

Вы просите кодинг-агента внести изменение, охватывающее всю систему. Он делает grep по символу, находит правдоподобное место, правит его и сообщает об успехе.

Он пропустил:

  • константу, которая на самом деле управляет поведением, в трёх каталогах отсюда;
  • зеркальную реализацию в batch-ветке;
  • метрику, считающую то самое, что он только что изменил;
  • тест, который проверяет старое поведение.

Агент не путался в том, как написать код. Он путался в том, где этот код находится. И у него не было способа это выяснить, потому что его единственными инструментами были текстовый поиск и контекстное окно, слишком маленькое для целого репозитория.

Почему сводки это не чинят

Очевидный ответ — «сделать сводку по кодовой базе и отдать её агенту». Это не работает по конкретной причине:

Сводка отвечает на вопрос «что это?». Агенту нужно «где это?»

Красиво написанный абзац о подсистеме загрузки не скажет агенту, что бюджет повторов также живёт в worker/queue.py и читается из metrics/emit.py. Хуже того, сводка — это правдоподобная проза: агент охотно будет рассуждать поверх неё и не сможет отличить, какие предложения — несущие факты, а какие — пересказ модели.

Отсюда три режима отказа:

  1. Она не адресуема. Проза называет концепции, а не пути и диапазоны строк.
  2. Она не проверяема. Ничто в ней не отличает разобранный парсером факт от догадки.
  3. Она гниёт. В момент, когда код меняется, сводка становится тихо неверной, и ничто в ней об этом не говорит.

Что Handbooks делает вместо этого

Он строит индекс, а не сводку

Результат отвечает ровно на один вопрос: какие файлы, функции и элементы состояния должно затронуть это изменение?

Каждая запись — это адрес: путь, квалифицированное имя, диапазон строк — выведенный из настоящего разбора. Проза вокруг этих адресов существует, чтобы человеку было удобно читать, и она явно не то, на основании чего агент должен действовать. SKILL-пакет говорит об этом в первой же строке:

Это руководство — индекс местоположений для кодовой базы, а не описание кода. Используйте его, чтобы решить, КАКИЕ файлы, функции и состояние должно затронуть изменение, — а затем читайте настоящие исходники.

Он разделяет факты и прозу — по построению

Откуда берётсяМожет ли быть неверным?
Файлы, функции, диапазоны строк, рёбра вызововtree-sitterНет — это результат разбора
Какие вызовы не удалось разрешитьtree-sitterНет — они помещены в карантин, а не угаданы
Какие файлы не удалось разобратьtree-sitterНет — они раскрыты, а не выброшены
Структура этаповLLM, затем механическая валидацияСтруктурно — нет; в части суждений — да
Назначение, разборы, обзорыLLMДа — и это помечено как проза

Разделение обеспечивается границей пакетов, а не соглашением: анализатор, рендерер, упаковщик skill и патчер вообще не зависят от LLM-пакета.

Он падает видимо

Каждое проектное решение здесь следует одному правилу: когда что-то не работает — скажи об этом.

  • Файл, для которого не удалась генерация карточки, всё равно появляется — с пустым описанием. Он перечислен в _coverage.json. Он никогда не выбрасывается и никогда не выдумывается.
  • Вызов, который анализатор не смог разрешить, попадает в dropped-calls.json со своей категорией и исходным текстом. Он никогда не превращается угадыванием в правдоподобное ребро.
  • Файл, который анализатор не смог прочитать или разобрал лишь частично, попадает в scan-coverage.json с указанием причины. Он никогда не засчитывается как покрытый: файл, который никто не открывал, — это не «файл без функций».
  • Язык, проанализированный движком на основе конфигурации, назван в обзоре, чтобы «отношения вызовов по мере возможностей» нельзя было прочитать как «точные».
  • Запуск планировщика, который сдался, завершается ненулевым кодом, чтобы никакой скрипт не принял его извинение за план.
  • Якорь патча, совпавший ноль раз или дважды, вызывает отказ. Он никогда не выбирает один из вариантов.

Он остаётся актуальным по пропорциональной цене

Документация гниёт потому, что её обновление стоит столько же, сколько написание. resync сравнивает старый граф вызовов с новым и перегенерирует только то, что изменилось: карточки для затронутых файлов, назначение для новых, прозу для затронутых этапов. Тронули три файла — платите за три файла.

Остальное делает кеш по хешу содержимого: этап, чьи входные данные не изменились, вообще не повествуется заново.

Экономика

Генерация — дорогой шаг, и он происходит один раз. Всё после неё — рендеринг в markdown, в HTML-сайт, в агентский индекс, в llms.txt, упаковка в SKILL, валидация этого пакета — детерминировано и бесплатно. Это можно запускать на каждом коммите.

Именно из-за этого разделения render и skill — отдельные команды, а не флаги у generate, и живут они в пакетах, которые не могут дотянуться до LLM даже случайно.

Чем это не является

  • Не инструмент поиска по коду. Он не заменяет grep или ваш LSP. Он говорит агенту, куда их направить.
  • Не автономный кодинг-агент. Планировщик по построению работает только на чтение; у него нет инструмента записи. apply — механический исполнитель без модели в контуре. Между ними решает человек.
  • Не замена вашей собственной документации. Архитектурные решения, продуктовый замысел и командные соглашения не выводимы из графа вызовов, и Handbooks не делает вид, что это не так.

Дальше

На этой странице