在庞大单体应用中防止AI Agent触碰错误代码的目录整理法
如果在数十万行的单一代码仓库中接入 Claude Code 或 Aider,它们往往会从错误的文件开始读取。模型的上下文窗口是有限的,当它们把不相关的文件也抓取进来时,就会填满 Token 限制并修改错误的代码。
这个问题无法通过写更长的提示词来解决。我们必须缩小 Agent 探索代码的物理半径,并在本地植入机械化验证的规则。
1. 隔离引发循环引用的目录
在单体仓库中,Agent 陷入无限探索的点通常有三个:汇聚了各种杂项辅助函数的公共工具文件夹(src/utils/)、业务逻辑错综复杂的服务层(src/services/)以及全局模型目录(src/models/)。当这三个文件夹开始相互引用时,Agent 为了修改一行代码就会读取数十个文件。
按技术层级划分的文件夹如果能以领域为单位进行隔离,探索范围就会缩小。
| 区分 |
依赖层级中心化结构 |
领域分离结构 |
Agent 动作变化 |
| 文件夹标准 |
技术层级分离(/controllers, /services) |
领域分离(/domains/order) |
仅在单个文件夹内探索所需文件 |
| 依赖连接 |
直接导入全局实体 |
通过领域接口边界进行通信 |
阻断连锁加载不相关文件的现象 |
| 公共逻辑 |
函数混杂在单个 src/utils/ 中 |
分离为领域专属工具和公共包 |
防止不必要的全局上下文污染 |
为确保正在运行的服务不中断,迁移目录的顺序如下:
- 确认 Agent 过度调用的依赖关系,确定要分离的领域。
- 为了切断领域间的直接引用,创建服务边界接口。
- 将相关的业务逻辑移至
src/domains/{领域名}/ 文件夹,并更新 tsconfig.json 的路径别名。
- 在分离出的子目录中放入该领域专属的配置文件(
CLAUDE.md)。
2. 将模糊的自然语言规则变更为数值约束
以自然语言长篇大论编写的编码规范很容易被 Agent 忽略。我们必须在配置文件顶部明确放置数值和禁止事项,才能准确遵循指令。
`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. 通过本地钩子自动验证 Agent 修改的代码
Agent 生成的代码中的语法错误或回归漏洞必须在提交时自动捕获。使用以 Go 单一二进制文件运行的 Lefthook,可以比基于 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 秒内检查暂存(staged)文件,而整体类型检查和单元测试则移交给推送阶段的 pre-push。
为了防止 Agent 使用 --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);
`
如果钩子失败,控制台错误输出将进入下一个提示词,促使 Agent 自行修改代码。
4. 通过限制探索范围防止 Token 浪费
当 Agent 开始读取构建产物或锁文件时,Token 会迅速耗尽。只有关闭文件探索范围,才能防止产生意外的费用。
在项目根目录创建 .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)先确认变更事项,编写会失败的单元测试后再编写能通过的代码,这样就能安全地保持 Agent 的工作半径。