Как автоматически обновлять AGENTS.md с помощью dox
Файл AGENTS.md быстро устаревает, что заставляет агентов совершать ошибки. Используйте утилиту dox для генерации документации из кода и проверяйте изменения через git diff.
Почему ваш файл AGENTS.md устаревает через три недели
Файл AGENTS.md устаревает, так как он никак не связан с кодом. Вы создаете его вручную в тот день, когда репозиторий имеет определенную структуру. Затем меняется средство запуска тестов, переименовывается пакет или удаляется сервис, а файл продолжает описывать состояние за июнь. Никаких ошибок не возникает, так как ни один этап сборки не считывает этот файл.
Агент считывает его и доверяет содержимому. Именно это обходится вам дороже всего. В репозитории без AGENTS.md агент вынужден изучить окружение перед выполнением действий. В репозитории с неверным AGENTS.md агент перестает искать информацию, так как у него уже есть готовый ответ. Он запускает команду, указанную в вашем файле, оболочка возвращает Missing script: "test", и агент начинает действовать наугад. Часто он редактирует package.json, чтобы добавить скрипт, обещанный в вашей документации. Устаревший файл не просто «тихо» подвел вас. Он спровоцировал правки, которые вам не нужны.
dox — одно из решений этой проблемы. Это набор правил для агента, который делает обновление документации частью процесса завершения работы. В результате файл изменяется в том же коммите, что и код, который сделал его неактуальным.
Что такое dox и чем он не является
dox — это один файл в формате Markdown. Репозиторий находится по адресу agent0ai/dox, он распространяется по лицензии MIT, и по состоянию на 11 августа 2026 года весь проект представляет собой один файл AGENTS.md размером 3906 байт, README, LICENSE и два изображения. Здесь нет пакетов для установки и нет среды выполнения.
Это важно, так как само слово «генератор» наводит на мысль о программе, которая анализирует ваш код. Ничто не анализирует ваш код. dox — это контракт, который читает ваш агент разработки: агент является генератором, а dox — это набор инструкций, который указывает ему, когда читать документацию, когда её переписывать и какую структуру должен иметь каждый документ.
Файл состоит из десяти разделов, два из которых выполняют основную работу. Раздел "Read Before Editing" предписывает агенту пройти от корня репозитория до каждого пути, который он планирует изменить, и прочитать каждый файл AGENTS.md на этом маршруте в текущем сеансе, не полагаясь на память. Раздел "Update After Editing" указывает, что каждое значимое изменение требует прохода DOX, что означает этап обновления документации, который должен быть выполнен до того, как задача будет считаться завершённой. Этот проход обновляет ближайший профильный документ, если изменились назначение, структура, рабочий процесс, права доступа или предпочтения пользователя.
Остальная часть файла определяет структуру. Дочерний файл AGENTS.md имеет стандартный порядок разделов: Purpose (Назначение), Ownership (Владение), Local Contracts (Локальные контракты), Work Guidance (Руководство по работе), Verification (Проверка) и Child DOX Index (Индекс дочерних DOX). Корневой файл содержит правила для всего проекта, а также верхнеуровневый Child DOX Index, с помощью которого агент обнаруживает дочерние документы. "Closeout" — это контрольный список, который агент выполняет в конце задачи: повторная проверка изменённых путей по цепочке, обновление ближайших профильных документов, обновление всех затронутых индексов, удаление противоречий, выполнение существующей проверки и отчёт о том, какие документы он намеренно оставил без изменений.
Закрепление документации на конкретном коммите, а не на main
В репозитории отсутствуют теги и релизы, поэтому закрепиться на номере версии невозможно. Вместо этого зафиксируйте коммит. Текущая версия AGENTS.md соответствует коммиту f34ec7ad1055d3393887e5a2670e8cb7320c9165 от 1 августа 2026 года.
mkdir -p .agent
curl -fsSL -o .agent/dox-f34ec7a.md \
https://raw.githubusercontent.com/agent0ai/dox/f34ec7ad1055d3393887e5a2670e8cb7320c9165/AGENTS.md
wc -c .agent/dox-f34ec7a.mdКоманда wc -c должна вывести 3906. Другое число означает, что вы получили не тот файл, который описывает данное руководство, поэтому ознакомьтесь с ним, прежде чем доверять содержимому. Если вы допустите ошибку в хеше коммита, -f заставит curl завершить работу с curl: (22) The requested URL returned error: 404 и не записывать данные, а wc -c затем выведет 0. Файл с неполным содержимым опаснее, чем его отсутствие, так как агент будет следовать половине контракта, не осознавая этого.
cp .agent/dox-f34ec7a.md AGENTS.md
git add AGENTS.md .agent/dox-f34ec7a.md
git commit -m "Add DOX rules (agent0ai/dox @ f34ec7a)"Эта команда cp предназначена для репозитория, в котором еще нет файла AGENTS.md. Если он у вас уже есть, не перезаписывайте его. Разместите разделы документации над существующим содержимым, сохраните свои правила ниже и один раз прочитайте итоговый файл целиком. Два противоречащих друг другу документа приведут к тому, что агент будет следовать той строке, которую прочитал последней.
Затем, находясь внутри репозитория, запросите у агента выполнение первого прохода. В README указана точная формулировка:
Initialize DOX tree for this project now.Эта команда создает дочерние файлы AGENTS.md и индексы, которые на них указывают. Проверьте результат, прежде чем доверять ему:
git status --short
find . -name AGENTS.md -not -path './.git/*' | sortКаждый файл из вывода find должен быть упомянут в каком-либо индексе дочерней документации выше по дереву. Дочерний документ, не упомянутый ни в одном индексе, может быть пропущен агентом, так как именно через индексы он находит документы, не расположенные непосредственно на пути его обхода.
Что видит dox, а чего он знать не может
Агент, строящий ваше дерево, считывает репозиторий, поэтому всё содержимое репозитория может попасть в инвентарь: структура каталогов, манифесты пакетов и lock-файлы, скрипты в package.json, Makefile или pyproject.toml, файлы рабочих процессов CI, Dockerfiles, точки входа и CODEOWNERS, если он у вас есть. Инвентарь, построенный на основе этих данных, по-настоящему поддерживает себя сам. Когда пакет перемещается, следующий проход обновляет строку, которая его описывает.
Всё, что перечислено ниже, должны указывать вы, так как этой информации нет в репозитории:
- причина существования правила: именно это не дает агенту удалить его как избыточную сложность;
- какой из двух рабочих путей поддерживается, а какой ожидает удаления;
- всё, что находится вне репозитория, например, staging-окружение или причина, по которой зависимость зафиксирована на две версии назад;
- ваши планы на следующую неделю: в этом заключается разница между файлом, который является актуальным, и файлом, который является полезным.
dox знает это о себе. Его собственные правила гласят, что Work Guidance должен отражать текущие стандарты проекта или инструкции пользователя, и если их пока нет, раздел следует оставить пустым. Verification должен отражать существующую проверку, поэтому при отсутствии тестового фреймворка в репозитории этот раздел остается пустым до тех пор, пока он не появится. Сгенерированный файл, который выдумывает стандарт, хуже, чем пустой раздел, так как агент начнет принудительно применять эту выдумку.
Исключите ручные пояснения из сгенерированного инвентаря
Это именно та проблема, из-за которой пользователи отказываются от автоматизированной документации. Вы пишете абзац с пояснением, что очередь задач должна обслуживаться одним потребителем. Через три недели скрипт перезаписывает файл, ваш абзац исчезает внутри diff-файла на сорок строк, где в основном переименованы файлы, и никто этого не замечает.
Вам потребуются два механизма, и использовать нужно оба.
Во-первых, вынесите долгосрочные проектные решения в отдельный файл. Обоснование архитектурных решений должно находиться в файле DESIGN.md, предназначенном для агента, а заметки для людей — там, где вы отделили HUMAN.md от AGENTS.md. В AGENTS.md тогда останется только инвентарь и локальные контракты — именно та часть, которая должна меняться при изменении кода.
Во-вторых, ограничьте пояснения, которые должны оставаться внутри AGENTS.md. Оберните их в маркеры и считайте этот блок зоной ответственности человека:
## User Preferences
<!-- dox:keep start -->
The jobs queue stays single consumer. Ordering is the reason this service exists.
Deploys ship on Tuesday. A Friday deploy is a human decision, not an agent decision.
<!-- dox:keep end -->Комментарии Markdown не отображаются на странице, но агент продолжает их считывать. Теперь сделайте проверку сохранности этого блока, чтобы скрипт, который его удаляет, выдавал ошибку. Запускайте это в CI (continuous integration) при каждом pull request:
git fetch -q origin main
sed -n '/dox:keep start/,/dox:keep end/p' AGENTS.md > /tmp/keep.head
git show origin/main:AGENTS.md | sed -n '/dox:keep start/,/dox:keep end/p' > /tmp/keep.base
diff -u /tmp/keep.base /tmp/keep.headdiff ничего не выводит и завершается с кодом 0, если блок не был изменен. Любой вывод означает, что скрипт перезаписал текст, принадлежащий человеку, поэтому его должен либо одобрить ответственный сотрудник, либо изменения должны быть отменены. Проверка работает автоматически, и о ней не нужно помнить.
Обновление при создании pull request, а не по расписанию
Лучший момент для обновления документа — момент коммита, который делает его неактуальным. Включайте проход DOX в тот же pull request, что и структурные изменения: тогда diff останется достаточно компактным, чтобы его можно было прочитать.
Блокирующая проверка, которая это обеспечивает:
#!/usr/bin/env bash
set -euo pipefail
git fetch -q origin main
base=$(git merge-base origin/main HEAD)
changed=$(git diff --name-only "$base" HEAD)
if grep -qE '^(src|apps|packages)/' <<<"$changed" && ! grep -q 'AGENTS\.md$' <<<"$changed"; then
echo "Code changed but no AGENTS.md was touched. Run a DOX pass, or say why not."
exit 1
fiНастройте пути в соответствии с вашим репозиторием. Ценность такого подхода в том, что проверка падает на ветке, где исправление стоит дешево, и указывает на причину, с которой может работать ревьюер.
Расписание — это резервный механизм, а не основной. Еженедельное задание обнаруживает то, что никто не заметил в ветке: файлы, перемещенные при rebase, пакет, удаленный при merge, или документ, ссылающийся на несуществующий каталог. Запускайте его на небольшой машине — той же, которую вы могли бы использовать, чтобы запустить агента для написания кода на VPS, — и настройте создание pull request вместо отправки изменений напрямую в main.
#!/usr/bin/env bash
set -euo pipefail
cd /srv/src/myapp
git fetch -q origin
git switch -c "dox/refresh-$(date +%Y%m%d)" origin/main
# Your agent CLI goes on the next line, in whatever non-interactive mode it offers.
# Prompt: "Run a DOX pass over this repository. Change AGENTS.md files only."
git add '*AGENTS.md'
git commit -m "dox: refresh AGENTS.md tree" || { echo "nothing to refresh"; exit 0; }
git push -q -u origin HEAD
gh pr create --fillЭтот комментарий намеренно оставлен как заполнитель. У каждого агента свой CLI (интерфейс командной строки) и свой флаг для неинтерактивного режима. Команда, скопированная со страницы в интернете и не соответствующая вашей версии, завершится ошибкой внутри cron, где никто не увидит проблему. Заполните параметры и запустите скрипт вручную один раз, прежде чем добавлять его в планировщик. Параметр || exit 0 также важен: git commit завершается с ненулевым кодом nothing to commit, working tree clean, если дерево уже актуально, и при set -e это будет интерпретировано как сбой успешного запуска.
Каждый проход расходует токены, так как принцип "прочитать перед редактированием" заставляет агента считывать всю цепочку при каждой задаче. Это неизбежный компромисс, и за ним стоит следить, если вы уже считаете стоимость работы вашего агента.
Монорепозитории: множество контрактов, один индекс
Наличие одного корневого файла AGENTS.md в репозитории с сорока пакетами приводит к созданию diff-файла при перегенерации, который никто не читает, и к документу, который по большей части не относится к текущим задачам агента. Решением в dox является дочерний индекс DOX: корень содержит правила для всего репозитория и ссылки на дочерние элементы, а каждая устойчивая граница владеет собственным файлом. О том, как выстроить такое дерево и какие инструменты вообще поддерживают чтение вложенных файлов, рассказано в вложенных файлах AGENTS.md для монорепозиториев.
То, что меняет dox — это область проверки. Pull request, затрагивающий packages/api, должен приводить к diff-файлу документации внутри packages/api и нигде больше:
git diff --stat -- '*AGENTS.md'Если эта команда выводит шесть файлов при изменении одного пакета, значит, дерево построено неверно. Либо границы слишком широкие, либо правило, которое должно находиться в корне, было скопировано в каждый дочерний элемент. dox прямо указывает на исправление: общие правила размещаются в родительских документах, конкретные детали — в дочерних. Дублирование правил — это то, что заставляет при обычном проходе переписывать всё подряд. Если одни и те же правила действительно применимы к разным репозиториям, это другая проблема, и для неё лучше подходит общий доступ к навыкам агентов между репозиториями.
Проверка diff как программного кода
Сгенерированный diff документации легко одобрить, не читая, что приводит к выпуску некорректных файлов. Читайте его с той же подозрительностью, что и сгенерированный код, и обращайте внимание на четыре аспекта:
- команда, указанная в файле: выполните её самостоятельно перед слиянием. Выдуманные инструкции по сборке — самая частая причина сбоев.
- удалённая строка, содержавшая важный смысл. Добавления стоят дёшево. Потеря информации происходит именно при удалениях.
- абсолютный путь, имя хоста, внутренний URL или любой фрагмент, похожий на учётные данные.
- запись в инвентаре для объекта, который больше не существует, что
lsисправляет за секунду.
Затем проверьте размер с помощью wc -l AGENTS.md. Если корневой файл превышает 200 строк, это сигнал к его разделению, так как вся ценность цепочки заключается в том, что агент считывает небольшую релевантную часть, а не всё содержимое целиком.
При возникновении ошибок
Проход удалил ваш блок намерений. Проверка diff выше выводит удаленные строки. Восстановите файл из точки ветвления с помощью git restore --source=origin/main AGENTS.md, затем повторно запустите проход с более узкой инструкцией, указав разделы, которые он может затрагивать.
Обе ветки были пересозданы. Вы получаете CONFLICT (content): Merge conflict in AGENTS.md и маркеры конфликтов <<<<<<< HEAD внутри файла. Не редактируйте маркеры вручную. Файл является сгенерированным, поэтому правильное решение — это новый проход по объединенному дереву.
Агент полностью игнорирует файл. Проверьте, какой именно файл считывает ваш инструмент. Если он считывает другой файл, укажите на тот же контент с помощью ln -s AGENTS.md CLAUDE.md и закоммитьте символическую ссылку. Так вы сохраните единый источник вместо двух документов, которые со временем разойдутся.
В дереве появились дочерние элементы, которые никто не проиндексировал. Сравните вывод find . -name AGENTS.md с записями индекса в родительских документах. Дочерний элемент, не упомянутый ни в одном индексе, — это элемент, который агент может пропустить при обходе.
Когда генератор избыточен
Один пакет, одна команда тестирования, два человека, знающих репозиторий: напишите двадцать строк вручную. Файл AGENTS.md из двадцати строк не устаревает настолько быстро, чтобы оправдать создание дерева, индекса, проверки в CI и еженедельной задачи. Перечитывайте его при изменении сборки. Это все затраты на поддержку, и они меньше, чем стоимость инфраструктуры вокруг него.
dox стоит использовать, когда репозиторий имеет границы, которые никто не может удержать в голове: несколько пакетов с разными правилами или участники, которые приходят без подготовки. Ценность заключается не в сгенерированном тексте. Ценность в том, что документация становится объектом, из-за которого может быть отклонен pull request, что является единственной причиной, по которой любой файл в репозитории остается актуальным.
FAQ
Нужно ли что-то устанавливать для использования dox?
Нет. dox — это один файл Markdown, распространяемый по лицензии MIT. По состоянию на 11 августа 2026 года репозиторий не содержит пакетов и не выпускает релизы. Вы копируете содержимое файла в AGENTS.md вашего проекта, и ваш агент программирования следует указанным там правилам. Зафиксируйте коммит, который вы скопировали (на момент написания это f34ec7ad1055d3393887e5a2670e8cb7320c9165), и укажите его в сообщении к коммиту. Это позволит в будущем определить, какая версия правил использовалась при сборке вашего дерева.
Как предотвратить удаление моих правил при перегенерации?
Разделяйте намерения и инвентарь. Постоянные обоснования храните в отдельном документе, а всё, что должно оставаться внутри AGENTS.md, помещайте в маркированный блок. Затем проверяйте этот блок в CI: извлекайте его из ветки и из origin/main с помощью sed, сравнивайте их через diff и прерывайте сборку при любом расхождении. В таком случае изменения будет одобрять или отклонять человек, а не пропускать их незамеченными внутри большого diff.
Как часто нужно перегенерировать AGENTS.md?
В момент создания pull request, который делает текущую версию неактуальной. Структурные изменения и их документация должны находиться в одном diff, так как только в этот момент у автора есть контекст для проверки обоих аспектов. Еженедельный автоматический запуск служит резервным методом для устранения отклонений, которые могли просочиться в ветку; такой запуск должен открывать pull request, а не вносить коммиты напрямую в main.
Где должны находиться команды сборки: в корневом AGENTS.md или в дочернем?
В ближайшем документе, к которому они относятся. Общие правила репозитория и индекс дочерних элементов находятся в корне. Команда, применимая к одному пакету, должна находиться в AGENTS.md этого пакета. dox разрешает конфликты по принципу близости: ближайший документ управляет локальными деталями, и ни один дочерний документ не может ослабить правило родительского. Копирование одной и той же команды в каждый дочерний файл приводит к тому, что при плановой перегенерации перезаписывается всё дерево.
Стоит ли использовать dox для небольшого репозитория?
Обычно нет. Один пакет с одной командой тестирования и AGENTS.md на двадцать строк деградирует медленно, и вы можете исправить его за минуту после обнаружения проблемы. dox окупает себя, когда в репозитории есть несколько границ с разными правилами или когда у участников нет достаточного контекста. В таких случаях цепочка документов выполняет работу, которую не делает ни один человек в отдельности.