SSD Nodes Learn Hosting plans →
Руководства Matt ConnorАвтор: Matt Connor

Как автоматически обновлять 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, и по состоянию на 13 октября 2026 года весь проект состоит из одного файла размером 3965 байт AGENTS.md, файла README, лицензии и двух изображений. Здесь нет пакетов для установки и нет среды выполнения.

Это важно, так как само слово «генератор» наводит на мысль о программе, которая анализирует ваш код. Ничто не анализирует ваш код. dox — это контракт, который читает ваш агент разработки: ваш агент и есть генератор, а dox — это набор инструкций, который указывает ему, когда читать документацию, когда её переписывать и какой вид должен иметь каждый документ.

Файл состоит из девяти разделов, два из которых выполняют основную работу. Раздел «Read Before Editing» (Читать перед редактированием) предписывает агенту пройти путь от корня репозитория до каждого файла, который он планирует изменить, и прочитать каждый файл AGENTS.md на этом пути в рамках текущей сессии, не полагаясь на память. Раздел «Update After Editing» (Обновлять после редактирования) указывает, что каждое значимое изменение требует выполнения процедуры DOX, то есть этап обновления документации должен быть завершён до того, как задача будет считаться выполненной. Эта процедура обновляет ближайший профильный документ при изменении назначения, структуры, рабочего процесса, прав доступа или пользовательских настроек.

Остальное определяет структуру. Дочерний файл AGENTS.md имеет стандартный порядок разделов: «Purpose» (Назначение), «Ownership» (Владение), «Local Contracts» (Локальные контракты), «Work Guidance» (Руководство по работе), «Verification» (Верификация) и «Child DOX Index» (Индекс дочерних DOX). Корневой файл содержит общепроектные правила и индекс дочерних DOX верхнего уровня, с помощью которого агент обнаруживает дочерние документы. «Closeout» (Завершение) — это контрольный список, который агент выполняет в конце задачи: повторная проверка изменённых путей по цепочке, обновление ближайших профильных документов, обновление всех затронутых индексов, удаление противоречий, выполнение существующей верификации и отчёт о том, какие документы он намеренно оставил без изменений.

Закрепление dox на конкретном коммите, а не на ветке main

В репозитории отсутствуют теги и релизы, поэтому закрепиться на номере версии невозможно. Вместо этого закрепитесь на коммите. Текущий файл AGENTS.md соответствует коммиту 765ae4ac02cc884eefcd41a3d0f71941721adb89 от 1 сентября 2026 года.

mkdir -p .agent
curl -fsSL -o .agent/dox-765ae4a.md \
  https://raw.githubusercontent.com/agent0ai/dox/765ae4ac02cc884eefcd41a3d0f71941721adb89/AGENTS.md
wc -c .agent/dox-765ae4a.md

Команда wc -c должна вывести 3965. Другое значение означает, что вы получили не тот файл, который описывается в данном руководстве, поэтому ознакомьтесь с ним, прежде чем доверять содержимому. Если вы допустите ошибку в хеше коммита, -f заставит curl завершить работу с кодом curl: (22) The requested URL returned error: 404 и не записывать данные, а wc -c затем выведет 0. Усеченный файл хуже, чем отсутствие файла вообще, так как агент будет следовать половине контракта, не осознавая этого.

Если вы закрепились на более раннем коммите, f34ec7a от 1 августа 2026 года, проверьте его Child DOX Index. В той версии раздел описывает собственный репозиторий dox: там указано, что дочерние файлы AGENTS.md не требуются, и перечислены README.md, LICENSE и два изображения как файлы, принадлежащие root. Будучи скопированным в ваш проект, этот индекс описывает неверный репозиторий. В редакции от 1 сентября этот раздел был заменен на заглушку, которая сообщает, что проект еще не проиндексирован, и предписывает агенту просканировать репозиторий и построить дерево перед продолжением работы. Замените старый раздел на ваш реальный индекс или на новую заглушку.

cp .agent/dox-765ae4a.md AGENTS.md
git add AGENTS.md .agent/dox-765ae4a.md
git commit -m "Add DOX rules (agent0ai/dox @ 765ae4a)"

Этот cp предназначен для репозитория, в котором еще нет файла AGENTS.md. Если он у вас уже есть, не перезаписывайте его. Разместите разделы dox над вашим существующим содержимым, сохраните свои правила ниже и один раз прочитайте итоговый результат сверху вниз. Два противоречащих друг другу документа заставят агента следовать той строке, которую он прочитал последней.

Затем попросите вашего агента, находясь внутри репозитория, выполнить первый проход. В README приведена точная формулировка:

Initialize DOX tree for this project now.

Это создаст дочерние файлы AGENTS.md и индексы, указывающие на них. Явный запрос все равно полезен, даже если индекс-заглушка предписывает агенту сделать это перед любой другой работой: вы получите всё дерево в одном проверяемом коммите, а не как побочный эффект несвязанной задачи. Проверьте результат, прежде чем доверять ему:

git status --short
find . -name AGENTS.md -not -path './.git/*' | sort

Каждый файл в выводе find должен быть упомянут в каком-либо Child DOX Index выше по иерархии. Дочерний документ, который не упоминается ни в одном индексе, может быть пропущен агентом, так как именно через индекс он находит документы, не расположенные непосредственно на пути его обхода.

Что видит dox, а чего он знать не может

Агент, строящий ваше дерево, считывает репозиторий, поэтому всё содержимое репозитория может попасть в инвентарь: структура каталогов, манифесты пакетов и lock-файлы, скрипты в package.json, Makefile или pyproject.toml, файлы рабочих процессов CI, Dockerfiles, точки входа и CODEOWNERS, если они у вас есть. Инвентарь, построенный на этих данных, по-настоящему поддерживает себя сам. Когда пакет перемещается, при следующем проходе строка, описывающая его, также перемещается.

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

  • почему существует то или иное правило (это не дает агенту удалить его как избыточную сложность);
  • какой из двух рабочих путей поддерживается, а какой ожидает удаления;
  • всё, что находится вне репозитория, например, staging-окружение или причина, по которой зависимость зафиксирована на две версии назад;
  • ваши планы на следующую неделю (это разница между файлом, который является актуальным, и файлом, который является полезным).

dox знает это о себе. Его собственные правила гласят, что руководство по работе (Work Guidance) должно отражать текущие стандарты проекта или инструкции пользователя, и если их пока нет, этот раздел следует оставить пустым. Верификация должна отражать существующую проверку, поэтому при отсутствии в репозитории фреймворка для верификации этот раздел остается пустым до тех пор, пока он не появится. Сгенерированный файл, который выдумывает стандарт, хуже, чем пустой раздел, так как агент начнет принудительно внедрять эту выдумку.

Исключите ручные пояснения из сгенерированного инвентаря

Это именно та проблема, из-за которой пользователи отказываются от автоматической документации. Вы пишете абзац о том, что очередь задач должна обслуживаться одним потребителем. Через три недели скрипт перезаписывает файл, и ваш абзац исчезает внутри 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.head

diff ничего не выводит и завершается с кодом 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 является индекс дочерних документов (Child DOX Index): в корне хранятся правила для всего репозитория со ссылками на дочерние элементы, а каждая устойчивая граница владеет собственным файлом. О том, как спроектировать такую структуру и какие инструменты поддерживают чтение вложенных файлов, рассказано в вложенные файлы AGENTS.md для монорепозиториев.

То, что меняет dox — это область проверки (review surface). Pull request, затрагивающий packages/api, должен приводить к изменению документации только внутри packages/api и больше нигде:

git diff --stat -- '*AGENTS.md'

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

Проверка diff как программного кода

Сгенерированный diff документации легко одобрить, не читая, что приводит к выпуску некорректных файлов. Изучайте его с тем же подозрением, что и сгенерированный код, и обращайте внимание на четыре аспекта:

  • команда, которую теперь содержит файл; выполните её самостоятельно перед слиянием. Выдуманные инструкции по сборке — самая частая причина сбоев.
  • удалённая строка, которая содержала важный смысл. Добавления стоят дёшево. Потери происходят именно при удалениях.
  • абсолютный путь, имя хоста, внутренний URL или любой объект, похожий на учётные данные.
  • запись в инвентаре для объекта, который больше не существует, что ls исправляет за секунду.

Затем проверьте размер с помощью wc -l AGENTS.md. Файл root объёмом более 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. По состоянию на 13 октября 2026 года в репозитории нет пакетов и релизов. Вы копируете содержимое файла в AGENTS.md вашего проекта, и ваш агент программирования следует указанным там правилам. Зафиксируйте коммит, который вы скопировали (на момент написания это 765ae4ac02cc884eefcd41a3d0f71941721adb89), и укажите его в сообщении к коммиту. Это позволит в будущем определить, какая версия правил использовалась при создании вашего дерева исходного кода.

Как предотвратить удаление моих собственных правил при перегенерации?

Разделяйте намерения и инвентаризацию. Долгосрочные обоснования храните в отдельном документе, а всё, что должно оставаться внутри AGENTS.md, помещайте в специальный маркированный блок. Затем проверяйте этот блок в CI: извлекайте его из текущей ветки и из origin/main с помощью sed, сравнивайте их через diff и прерывайте сборку при обнаружении любых различий. В таком случае человек сможет одобрить или отклонить изменения, вместо того чтобы они прошли незамеченными в составе большого diff.

Как часто нужно перегенерировать AGENTS.md?

В момент создания pull request, который делает текущую версию неактуальной. Структурные изменения и их документация должны находиться в одном diff, так как только в этот момент у автора есть контекст для проверки обоих аспектов. Еженедельный автоматический запуск служит резервным вариантом для устранения расхождений, которые могли просочиться в ветку; такой запуск должен открывать pull request, а не коммитить изменения напрямую в main.

Где должны находиться команды сборки: в корневом AGENTS.md или в дочернем?

В ближайшем документе, к которому они относятся. Общие правила репозитория и индекс дочерних элементов находятся в корне. Команда, применимая к одному пакету, должна находиться в AGENTS.md этого пакета. При возникновении конфликтов между документами dox позволяет более близкому документу управлять деталями локальной работы. Единственное, что не может ослабить ни один дочерний документ — это сам контракт DOX. Общие правила размещаются в родительских документах, а конкретные детали — в дочерних. Копирование одной и той же команды в каждый дочерний файл приводит к тому, что плановая перегенерация переписывает всё дерево.

Стоит ли использовать dox для небольшого репозитория?

Обычно нет. Один пакет с одной командой тестирования и AGENTS.md на двадцать строк деградирует медленно, и вы сможете исправить его за минуту после обнаружения проблемы. dox окупает себя, когда в репозитории есть несколько границ с разными правилами или когда у участников проекта недостаточно контекста. В таких случаях цепочка документов выполняет работу, которую не делает ни один человек в отдельности.

Была ли эта статья полезной?