Как разложены документы

Один огромный файл в корне плохо обновляется точечно. Слои такие.

На сервере лежит общий договор для всех агентов на машине (AGENTS.md и соседние правила рантайма). В репозитории проекта — свой AGENTS.md и операционный гайд: куда смотреть, какие инварианты нельзя ломать. В docs/ — потоки (FLOWS), известные проблемы и короткие записи «что искать, где лежит, чего не делать». Отдельно скилы: пошаговые сценарии на повторяющиеся действия, не вторая простыня архитектуры.

сервер:  AGENTS.md (+ правила рантайма)
проект:  AGENTS.md, CLAUDE.md
         docs/FLOWS.md
         docs/KNOWN_ISSUES.md  (известные проблемы)
         docs/…                (короткие записи по дырам)
скилы:   skills/*/SKILL.md     (пошаговые сценарии)
сверка:  граф кода → find_doc_drift (markdown ↔ код)

Нюанс нескольких сред запуска: часть агентов подхватывает общий AGENTS.md и объединяет его с проектным, другой формат операционного гайда сама не читает. Устойчивые правки иногда приходится дублировать в оба файла, иначе один агент правило видит, а другой нет.

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

Дыра в сессии → запись сейчас

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

Формулировка: что искать, где лежит, как работает, чего не делать. Две–пять строк. Эссе в чате не пишем. По ходу максимум одна-две строки, если иначе факт потеряется. В конце нетривиальной задачи уборка поднимает инварианты в общие документы. Любая правка текста сверяется с кодом сейчас.

Три случая, где запись закрыла повтор.

В боевом каталоге агент правил код прямо там, где крутится прод: процесс перечитывает файлы с диска без выкладки, у клиентов оказался недоделанный дифф. В документы ушло правило: код только в отдельной рабочей копии от main, боевой каталог без недоделанных правок. На студии вроде arckep.ru это особенно чувствительно: недоделанный дифф сразу бьёт по регистрации и входу.

На фронте в запросе на слияние добавили маршруты API, а сгенерированный TypeScript-файл типов не обновили. Сборка поймала устаревшие типы, в документах ещё путали имя файла. Правило: любое изменение API или схем — локально перегенерировать типы и закоммитить файл, не тянуть боевой OpenAPI ради быстрой проверки. Когда в продукте десятки моделей и внешних API, и новые подключаются регулярно, без такого правила агент снова оставляет фронт с устаревшими типами.

С HEIC в одном продукте конвертация уже была, в другом белый список jpeg/png/webp без конвертации. Искали регрессию не там. После исправления в файле с известными проблемами зафиксировано, где конвертят на сервере, где в браузере, и что проекты нельзя путать.

Как устроено автообновление

Три независимых контура. Они не ждут, пока я вспомню поправить markdown.

1. Закрылась сессия → через ~30 минут уроки в LEARNED.md

Сессию по таймеру не обрываю. «Около получаса» — не лимит длины чата.

Закрытая сессия сама LEARNED.md не пишет. Агент уже вышел.

Цепочка такая:

  1. Сессия заканчивается. Транскрипт остаётся на диске.

  2. Хук SessionEnd только ставит session_id в очередь (enqueue). Текст уроков он не пишет.

  3. Systemd-таймер agent-learn-distill раз в ~30 минут будит distill.py.

  4. Скрипт берёт сессию из очереди или простаивающую. Если с последнего обновления ещё нет примерно 25 минут простоя и сессия не в очереди — ждёт. Нужно минимум два хода пользователя, иначе пропуск и повтор позже. Строит выдержку из chat_history: до 12 ходов пользователя и до 4 коротких хвостов ассистента (лимит около 24k символов), не весь сырой транскрипт.

  5. Дальше вызывает Grok без интерактива, с готовым промптом и JSON-схемой. В промпт уже вложены текущий LEARNED.md, заголовок сессии и выдержка; модели нельзя звать инструменты и перечитывать файлы. На выход: либо skip, либо новый полный LEARNED.md (замена целиком, до ~80 строк и ~8k символов: живое оставить, устаревшее и дубли выкинуть; дата сверху, русский, без дампов кода) плюс список уроков с метками learned / gotcha / decision. Тот же текст зеркалится в секцию Auto-learned файла MEMORY.md проекта.

  6. Уроки с меткой learned уже в теле LEARNED.md; gotcha и decision уходят в inbox на воскресный подъём в общие инструкции. В живой сессии тот же прогон можно форсировать командой /learn.

Итого автор файла: таймер, distill.py и отдельный вызов модели по сохранённому транскрипту. Не «сессия сама дописала» и не чистые эвристики без модели. На выходе сырой конспект, не операционный гайд. В CLAUDE.md и AGENTS.md руками на каждом шаге не копирую.

Пример. В буфере: «черновик в живой папке до влития ломал вход; код — только копия от main». В общие инструкции это попадёт позже, на воскресенье или по явной просьбе, уже как инвариант.

2. Коммит → граф кода догоняет сам

Перед широким поиском или правкой чувствительных путей агент спрашивает граф: символы, кто вызывает, влияние, план изменения (find_symbol, callers_of, endpoint_impact, plan_change).

Индекс не обновляю вручную «когда вспомню»:

  1. post-commit помечает проект грязным.

  2. Примерно через минуту паузы идёт частичная переиндексация (AST, web, embeddings).

  3. После слияния веток и сторожевой таймер раз в несколько часов (у меня раз в шесть часов) — более полный проход.

  4. MCP графа поднимается на сессию по stdio; это не вечный демон в systemctl.

Как граф понимает расхождения (find_doc_drift)

Это не модель «перечитай документы». Модуль codegraph, детерминированный пайплайн:

  1. Собирает markdown по маскам (docs/**/*.md, CLAUDE.md, AGENTS.md, README.md и т.п.).

  2. Парсер вытаскивает упоминания в backticks и похожие ссылки: маршруты (/api/…), функции и символы, таблицы и схемы, иногда числовые утверждения. Отсекает блоки кода, TODO, зачёркнутое, явные «удалён / не использовать».

  3. Верификатор сверяет каждую ссылку с индексами проекта:

    • маршрут → api-map web-индексера (route_not_found, если пути нет);

    • символ → AST sqlite (symbol_not_found);

    • таблица или колонка → кэш схемы БД (table_not_found).

  4. Делит результат на уверенные срабатывания (например чистый route_not_found) и сомнительные (бэктикнутое слово могло быть прозой; спорные числовые claims вроде stale_count). В tool оба бакета есть; на практике и в воскресном прогоне оставляем уверенные (include_uncertain=false / пост-фильтр), иначе тысячи ложных. Weekly дополнительно чистит FP и на правки только в markdown может подключить Grok.

Кто запускает: воскресный weekly.py, либо вручную CLI или MCP find_doc_drift. Поиск расхождений без LLM. Править документ — weekly, я или агент по отчёту.

При частой смене провайдеров и автодобавлении моделей без этой сверки markdown начинает описывать маршруты и таблицы, которых в индексе уже нет.

3. Воскресенье утром → сверка и подъём в общие инструкции

Раз в неделю (воскресенье 09:00 по локальному времени) таймер agent-learn-weekly будит скрипт weekly.py. Он делает то, что вручную на каждой задаче не тянется:

  1. вызывает find_doc_drift по горячим проектам и собирает уверенные расхождения;

  2. смотрит inbox уроков из LEARNED.md и поднимает устойчивое в ветку, AGENTS.md, CLAUDE.md и файлы с известными проблемами;

  3. шлёт короткий отчёт в мессенджер.

Именно здесь буфер сессий превращается в правило для всех агентов. Не весь LEARNED.md оптом, а то, что должно пережить смену среды запуска. Проверка расхождений находит кандидатов; подъём в общие инструкции — отдельный шаг weekly, плюс мой явный ок, если правка спорная.

Кто что делает одной таблицей:

Когда

Что срабатывает

Куда пишет

Кто инициирует

По ходу сессии

правило «дыра → запись»

живой документ / известные проблемы

агент или я

SessionEnd

хук enqueue

очередь distill

автоматически

каждые ~30 мин

distill.py + вызов Grok

LEARNED.md (+ inbox gotcha/decision)

systemd

после коммита

пометка dirty + пауза ~1 мин

индекс графа

git-hook

раз в ~6 ч / после слияния

полная переиндексация

индекс графа

таймер / hook

вс 09:00

weekly.pyfind_doc_drift + подъём

правки документов + отчёт

systemd

вручную / в сессии

CLI/MCP find_doc_drift

отчёт о расхождениях

я или агент

Хуки и скилы

Подсказка в промпте «не делай X» — это совет. Хук перед действием — это механизм.

Предохранитель на shell режет опасные команды на нескольких средах. Напоминание про граф перед чувствительными правками удерживает шаг, который иначе выпадает к середине длинного контекста. Отдельный предохранитель про дату обучения модели (не отвечать «из головы» про новые продукты и цены) не про сверку markdown с кодом. Расхождения в документах закрывают find_doc_drift и воскресенье.

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

Поддержка разных API и моделей плюс автоматическое добавление новых ИИ требуют жёсткой дисциплины действий агентов: сначала схема, тип и инвариант в документах, потом правка кода. Иначе агент угадывает провайдера из головы. На arckep.ru это повседневный режим работы студии.

Минимум для повторения

Развести роли файлов. Писать в живой документ при дыре в сессии. Поставить выжимку закрытых сессий в буфер. Обновлять граф с коммитами и раз в неделю сверять markdown с индексом, поднимая устойчивое из буфера в общие инструкции. Вынести в хуки опасный shell и «сначала граф» перед чувствительными правками.

Комментарии (0)