Хватит писать CLAUDE.md с нуля: шесть файлов харнесса для агентов
Каждый agentic-проект стартует с пустого CLAUDE.md и наполняет его галлюцинациями. Шесть детерминированных файлов харнесса, brownfield-safe.
Месяц назад я писал про spec drift — что происходит, когда агент читает устаревший project.intent.md и принимает неверные факты за истину. Решение: реверсивный диф. Вывести из кода, что должна говорить спека, сравнить с тем, что она говорит, и классифицировать дрейф по секциям.
Тот пост отвечает на вопрос: спека есть и протухла — что делать?
Вопрос, который меня преследовал после: а что с проектами, где спеки ещё нет?
Откройте любой свежий репо, в котором за последние полгода работал Claude Code, — и увидите один и тот же артефакт: CLAUDE.md (или AGENTS.md, или .cursor/rules, или .github/copilot-instructions.md) на три строки, похожие на заглушку. «Это Python-проект. Используй type hints. Запускай pytest». Агент послушно его читает, добивает пробелы предположениями и шипит фичу, опираясь на то, как обычно выглядит Python-проект, а не на то, что есть в этом конкретном.
Это не дрейф. Это отсутствие. И именно оно формирует первые 50 коммитов агента.
Почему одного файла мало
Когда у тебя только CLAUDE.md, в нём оседают все вопросы агента. Какая архитектура? Что может сломаться? Какой бар на мердж? Кто чем владеет? Файл превращается либо в kitchen-sink на 4000 слов, который никто не обновляет, либо в заглушку на 200 слов, которая не отвечает ни на один из них.
Я наблюдал этот паттерн в пяти своих проектах. CLAUDE.md гласил «архитектура event-driven» — и агент уверенно проектировал новую фичу вокруг event bus. Никакого event bus там не было. Эта фраза была скопирована из шаблона полгода назад.
Глубже проблема такая: агентам нужны типизированные входы. Ревьюер-агент, спрашивающий «безопасно ли это мерджить?», нуждается в другом контексте, чем контрактор-агент со своим «что в скоупе?». Запихивая оба в один файл, мы получаем половинчатый ответ для каждого. Остальное агент добивает из priors из обучающих данных.
Шесть файлов харнесса
/signum init --harness генерирует шесть харнесс-документов, и каждый отвечает на один конкретный вопрос, который задаст агент:
| Файл | На какой вопрос отвечает |
|---|---|
AGENTS.md | Что читать первым? Какие правила переопределяют дефолты? |
ARCHITECTURE.md | Как реально устроен этот код? |
docs/PLANS.md | Что сейчас в работе? |
docs/RELIABILITY.md | Что должно продолжать работать? Как я узнаю, что сломалось? |
docs/SECURITY.md | Какая модель угроз? Что трогать нельзя? |
docs/QUALITY_SCORE.md | Какой бар «готово»? |
Шесть файлов, у каждого — одинаковый frontmatter (status: draft, owner: TODO, last_reviewed: <дата>, review_cadence: quarterly), фиксированный набор секций, и каждая секция мапится на реальное решение агента.
last_reviewed важнее last_edited. Когда агент через два квартала после создания читает RELIABILITY.md и видит last_reviewed: 2026-01-15, он знает: документ за пределами cadence, и его надо проверять, а не доверять слепо. Тот же инсайт, что в посте про spec drift — дата верификации сильнее даты редактирования, — применённый на старте.
Что значит «детерминированно»
Скаффолд генерирует bash-скрипт (lib/init-harness-scaffold.sh), читая закоммиченные шаблоны (lib/templates/init-harness/*.tmpl). Не модель. Тот же project root, та же дата, тот же вывод. Никакой LLM-креативности на стадии скаффолда.
Это сознательное разделение. Структура (секции, frontmatter, заголовки таблиц) — детерминированна и шаблонна. Содержимое (что в каждой секции) — заполняется отдельным шагом с LLM или руками. Так сам скаффолд никогда не дрейфует: у каждого проекта одинаковые заголовки, одинаковый порядок секций, одинаковый паттерн. Дифы между проектами становятся сравнимыми.
В версии 4.21 шаблоны вынесены из inline-heredocs в отдельные .tmpl-файлы. Скучное изменение, но из-за него шаблоны теперь — отдельная code-review поверхность с golden-тестами на побайтовое равенство.
Brownfield-safe по умолчанию
Главный страх любой команды init — что она затопчет реальную работу. init --harness не топчет:
- Если есть
project.intent.md— сохраняем. - Если есть
project.glossary.json— сохраняем. - Если уже есть любой из шести харнесс-файлов — сохраняем.
- Скаффолдим только реально отсутствующие.
- Только
--forceобходит проверки.
Поведение brownfield-first. Запустив init --harness на четырёхлетнем кодбейзе, в котором уже есть половина доков, ты получишь черновики только для недостающей половины. Существующее остаётся нетронутым, даже если оно протухло или неверно. Дрейф — это работа init --actualize, а не init --harness.
Что даёт скаффолд (и что не даёт)
Скаффолженный RELIABILITY.md выглядит так:
---
status: draft
owner: TODO
last_reviewed: 2026-04-27
review_cadence: quarterly
---
# myproject — Reliability
## Critical User Journeys
- TODO: List the flows that must keep working for the product to be viable.
- TODO: Link tests, smoke checks, or dashboards that cover each flow.
## Service Levels
- TODO: Define availability / latency / throughput goals if they exist.
- TODO: Record error budgets or acceptable degradation rules.
## Failure Modes and Recovery
- TODO: Top known failure modes.
- TODO: Detection signal for each failure mode.
- TODO: Recovery / rollback procedure for each failure mode.
Это не готовая документация. Это типизированный промпт для человека (или follow-up-агента), который его заполнит. TODO — точечные: не «опиши reliability», а «перечисли потоки, которые должны продолжать работать». Каждый промпт заставляет вписать факт, а не абзац настроения.
Структура ещё и подсвечивает дыры. Если скаффолден RELIABILITY.md, а через три месяца секция «Failure Modes and Recovery» всё ещё одни TODO — это сигнал. У команды нет задокументированных failure modes, и агент, шипящий изменения в эту поверхность, делает это без контекста.
Почему шесть, а не три или двенадцать
Шесть — минимум, при котором не схлопываются два разных агентских вопроса в один файл. Я пробовал меньше. Объединение RELIABILITY.md и SECURITY.md в общий OPS.md сделало файл слишком большим: агент уже не мог найти конкретный failure mode, не сканируя файл целиком. Слияние PLANS.md в AGENTS.md — последний начинал гнить еженедельно.
Пробовал больше. Дробление ARCHITECTURE.md на DATAFLOW.md + MODULES.md + BOUNDARIES.md дало три полупустых файла. У большинства проектов не хватает архитектуры на три дока, но хватает на один.
Сплит, который выжил: один файл — один агентский вопрос, а не один файл — одна тема. Это контракт дизайна.
Что не заменяет
init --harness не генерирует project.intent.md. Этот файл — контрактная поверхность пайплайна Signum, его читает контрактор-агент для деривации scope и acceptance criteria, и у него свой путь bootstrap (signum init без флагов), который использует не харнесс-шаблоны, а код-сканер.
Харнесс-доки — поверхность для человека и ревьюера: они задают, как ревьюер-агент думает про merge gates, как контрактор формулирует non-goals, как инженер-агент решает, пересекает ли изменение reliability-границу. Они не контракт сами по себе.
Эти две вещи стыкуются. project.intent.md говорит «что делает этот проект». Харнесс — «как этот проект ведётся».
Попробовать
claude plugin install signum@emporium
cd your-project/
claude "/signum init --harness"
Получишь шесть черновиков. Пробежишь, заполнишь TODO, закоммитишь. Если один из них уже есть — он сохранён, скаффолдятся только недостающие.
Если существующий харнесс уже подрейфовал — это работа init --actualize из предыдущего поста. Другая поверхность, та же логика под капотом: вывести из кода, что должен говорить док, классифицировать гэп, записать только то, что ты принял.
Большинство agentic-проектов проваливают первый месяц не потому, что агент пишет плохой код, а потому, что у агента изначально не было типизированного контекста. Харнесс — шесть файлов, потому что это минимум типизированных вопросов, которые агент задаст ещё до второго коммита. Пропусти — получишь галлюцинированную архитектуру. Затычка одним файлом — половинчатые ответы на все шесть.
Source: github.com/heurema/signum (v4.21.0)
Попробуйте
Signum
Contract-first AI dev pipeline. Write specs, not prompts — get verified code.
5k+ читателей в месяц
Короткие заметки, промежуточные идеи и обсуждение новых постов — в @ctxtdev.
Если статья была полезна, можно поддержать блог. Если тебе нужен разбор похожей задачи в реальном проекте — пиши по рабочему запросу.