Организация директорий, чтобы ИИ-агент не трогал лишний код в разросшемся монолите
Если подключить Claude Code или Aider к монолитному репозиторию сотен тысяч строк кода, агент начинает читать не те файлы. Контекстное окно модели ограничено, и когда она собирает кучу несвязанных файлов, то забивает лимит токенов и начинает исправлять совсем не тот код.
Эту проблему не решить длинными промптами. Нужно сократить физический радиус поиска кода для агента и внедрить локальные правила с механической проверкой.
1. Разделение директорий, вызывающих циклические зависимости
В монолитных репозиториях агент обычно застревает в бесконечном поиске в трех местах: папка общих утилит со всякими хелперами (src/utils/), сервисный слой с переплетенной бизнес-логикой (src/services/) и директория глобальных моделей (src/models/). Когда эти три папки начинают ссылаться друг на друга, агент читает десятки файлов ради исправления одной строчки кода.
Изоляция папок, разделенных по техническим слоям, в структуры на основе доменов помогает сузить область поиска.
| Различие |
Архитектура на основе слоев |
Разделение по доменам |
Изменение поведения агента |
| Критерий папок |
Разделение по тех. слоям (/controllers, /services) |
Разделение по доменам (/domains/order) |
Поиск только нужных файлов внутри одной папки |
| Связи зависимостей |
Прямой импорт глобальных сущностей |
Взаимодействие через границы доменных интерфейсов |
Блокировка каскадной загрузки несвязанных файлов |
| Общая логика |
Функции перемешаны в единой src/utils/ |
Утилиты конкретного домена и общие пакеты |
Предотвращение засорения ненужного глобального контекста |
Порядок перемещения директорий без остановки работающего сервиса выглядит так:
- Определите домен для выделения, проверив зависимости, которые агент вызывает слишком часто.
- Создайте интерфейсы границ сервиса, чтобы разорвать прямые ссылки между доменами.
- Перенесите связанную бизнес-логику в папку
src/domains/{название_домена}/ и обновите псевдонимы путей (path aliases) в tsconfig.json.
- Поместите специальный файл конфигурации (
CLAUDE.md) для этого домена внутрь созданной поддиректории.
2. Замена расплывчатых правил на естественном языке числовыми ограничениями
Агент легко пропускает длинные описания правил кодирования на естественном языке. Чтобы инструкции соблюдались точно, в верхней части файла конфигурации нужно разместить четкие цифры и запреты.
`markdown
Ограничения проекта (размещаются вверху CLAUDE.md)
- Безопасность и обработка исключений
- NEVER allow raw SQL string concatenation. ALWAYS use parameterized queries with ORM.
- NEVER throw generic Exception or Error. ALWAYS throw domain-specific exceptions inheriting from BaseDomainException.
- ALWAYS enforce tenant_id filtering in all database queries under src/domains/.
- Числовые ограничения структуры кода
- Functions MUST NOT exceed 40 lines of code.
- Cyclomatic complexity MUST be kept under 8 per function.
- ALWAYS return Result<T, E> pattern for business layer operations instead of null.
`
Если файл конфигурации превышает 200 строк, последующие инструкции начинают часто пропускаться.
- В корневом файле
CLAUDE.md оставляйте только команды сборки и глобальные правила коммитов общим объемом до 200 строк.
- Правила для подпапок вроде
src/domains/order/ распределяйте по специальным файлам правил внутри соответствующих директорий.
- Личные настройки разработчика пишите в
CLAUDE.local.md и добавляйте его в .gitignore, чтобы избежать конфликтов.
3. Автоматическая проверка измененного агентом кода с помощью локальных хуков
Ошибки синтаксиса или регрессионные баги в коде, написанном агентом, должны автоматически отсекаться в момент коммита. Использование Lefthook, работающего как единый бинарник Go, позволяет запускать параллельные проверки быстрее, чем инструменты на базе Node.js.
Разместите lefthook.yml в корне проекта, разделив легкие статические проверки и тяжелые тесты.
`yaml
pre-commit:
parallel: true
commands:
linter:
glob: ".{ts,tsx}"
run: npx eslint --fix {staged_files}
stage_fixed: true
formatter:
glob: ".{ts,tsx,json,md}"
run: npx prettier --write {staged_files}
stage_fixed: true
security-scan:
run: gitleaks git --staged --no-banner
pre-push:
parallel: false
commands:
typecheck:
run: npx tsc --noEmit
unit-tests:
run: npm run test:unit -- --passWithNoTests
`
Хук pre-commit проверяет только проиндексированные файлы менее чем за 10 секунд, а полная проверка типов и модульные тесты переносятся на этап pre-push.
Чтобы агент не мог обойти хуки с помощью опции --no-verify, зарегистрируйте перехватчик в .claude/hooks/block-no-verify.mjs.
`javascript
import fs from 'fs';
const input = fs.readFileSync(0, 'utf8');
const parsed = JSON.parse(input);
if (parsed.tool_input?.command?.includes('--no-verify')) {
console.error("Policy Violation: --no-verify flag is strictly prohibited.");
process.exit(1);
}
process.exit(0);
`
Если хук падает, вывод ошибки консоли передается в следующий промпт, и агент исправляет код самостоятельно.
4. Ограничение области поиска для предотвращения перерасхода токенов
Когда агент начинает читать результаты сборки или файл блокировок (lock-file), токены тратятся очень быстро. Чтобы избежать непредвиденных затрат, диапазон поиска файлов необходимо ограничить.
Создайте .ignore или .aiderignore в корне проекта и добавьте туда крупные артефакты.
`text
node_modules/
dist/
build/
coverage/
*.min.js
*.svg
*.lock
package-lock.json
public/assets/
db/migrations/
`
При запуске из терминала также явно указывайте рабочую директорию, чтобы заблокировать глобальное сканирование.
bash aider "Refactor Order validation logic" --path=src/domains/order/ --exclude=src/domains/order/__tests__/
Если перед изменением кода переключаться в режим планирования (plan mode) для проверки изменений, сначала писать падающие модульные тесты, а затем заставлять агента писать только тот код, который их проходит, рабочий радиус агента будет оставаться безопасным.