AI 编码 Agent 总是越界改不该动的代码?ANMA 边界合同让 Claude Code 和 Cursor 乖乖遵循架构设计
场景痛点:当 AI Agent 觉得你的模块边界可有可无
先讲一个真实场景。
你在一个大型 Python 单体仓库里工作了几周——src/domains/billing/ 是支付模块,src/domains/users/ 是用户模块,几个月前重构时定死了它们不应互相直接依赖。一切正常,直到你让 Claude Code 帮忙修一个 billing 的小 bug。三分钟后,AI 不仅在 billing/utils.py 里直接 from users.models import User,还在 billing/payment.py 里调用了 user 模块的内部函数。代码能跑,但架构已经悄悄被突破——下次重构时,没人记得这个依赖原本不应该存在。
这不是你一个人的问题。ANMA 项目在基准测试中做了一个严肃实验:用 Claude Haiku 4.5(一个性价比很高的模型)在没有任何边界约束的仓库中执行代码生成任务,结果 19 次运行里有 13 次突破了声明的模块边界(68% 的违规率)。而当加上 ANMA 的边界合同后——20 次运行,0 次违规(Fisher’s exact p < 0.0001)。
同样的情况也发生在 TypeScript 上:对照组 20 次中 18 次越界,启用 ANMA 后同样归零。
痛点对比表
| 问题 | 传统方案 | ANMA 方案 |
|---|---|---|
| AI Agent 跨模块调用不该调的函数 | 靠 Code Review 人工发现 → 修复成本极高 | anma check 在 pre-commit + CI 中自动拦截 |
| 开发者写的 CLAUDE.md 和实际架构不一致 | 手动维护,半年后完全过时 | anma sync 从 YAML 合同自动生成 CLAUDE.md |
| 便宜模型不遵守架构约束 | 只能用贵模型(Opus 4.5,Gemini 2.5 Pro) | 边界合同让 Haiku 4.5 级模型达到 0 违规 |
| 大规模 monorepo 的架构治理 | CODEOWNERS + 文档各自维护,不同步 | 一份 YAML 合同 → CLAUDE.md + CI + CODEOWNERS 统一生成 |
快速上手:从零到拦截违规编辑,60 秒
ANMA 的核心流程极其简单——四步走:
pip install anma[tach] anma init anma sync anma check
anma init 会在当前目录创建一个 src/domains/ 示例结构,内含 accounts 和 billing 两个模块及其完整的 anma.yaml 合同文件。执行 anma sync 后,你会看到类似下面的文件结构被自动创建:
CLAUDE.md # 架构总图(ANMA 标记之间自动维护) .claude/rules/boundaries.md # 始终加载的边界约束指令 .claude/hooks/anma_pretooluse.py # 拦截越界编辑的 PreToolUse hook tach.toml # tach 引擎配置 .github/workflows/anma.yml # CI: drift check + boundary check
核心功能
1. YAML 合同即架构声明
这是 ANMA 的基石。你在每个模块目录下放一个 anma.yaml,声明它允许依赖什么、暴露什么公开接口:
name: billing summary: Invoices and payments. public: - billing.service.create_invoice depends_on: - accounts owners: - @billing-team invariants: - Never store raw card numbers.
这份文件同时扮演了架构文档和规则引擎输入两个角色——改动它即同时更新了文档和约束规则。
2. 自动生成 CLAUDE.md 和 Hook 拦截
运行 anma sync 后,ANMA 会把 YAML 合同编译成两类产物:
- 引导层(Guidance):在每个模块目录生成
CLAUDE.md,Codex 或 Claude Code 打开该目录时自动加载此文件作为上下文。文件里写着「你是 billing 模块,你的公开接口是billing.service.create_invoice。你可以依赖 accounts 模块,不能依赖其他模块」。基准测试证明,光是这一层就把违规率从 68% 降到了 0%。
- 强制层(Enforcement):
.claude/hooks/anma_pretooluse.py是一个 PreToolUse hook——在 AI 执行编辑之前,hook 会检查本次编辑涉及的文件导入是否违反了模块依赖规则。如果发现违规,hook 返回 exit 2,直接阻止写入。这个 hook 对任何模型都有效——不管人类还是 AI 写的 diff,一视同仁。
3. CI 漂移检测
架构最怕「改了代码忘了更新文档」。ANMA 的解决方案很优雅:
anma sync --check # 在 CI 中运行,如果生成产物和合同不一致就失败
这条命令会检查 CLAUDE.md、hook、tach.toml 等生成文件是否与当前 YAML 合同一致。如果团队有人只改了 anma.yaml 却忘了跑 anma sync,CI 直接红。反过来,如果有人偷偷改了 CLAUDE.md 但没改合同,也会被捕获。
4. 三种语言支持 + 渐进式采用
| 语言 | 功能 | 引擎 |
|---|---|---|
| Python | 模块边界 + 公开接口检查 | tach(推荐,可选) |
| TypeScript | 模块间依赖检查 | dependency-cruiser(可选) |
| Go | 模块间依赖检查 | go-arch-lint(可选) |
ANMA 支持在同一个 monorepo 的不同子项目中使用不同语言。
对于已有大量历史遗留依赖的大型项目,ANMA 提供了 --warn 模式:
anma check --warn # 报告违规但不阻止提交
配合 deprecated_deps 字段,可以逐步清理旧依赖而不需要在第一天就通过全部检查。
横向对比:ANMA vs 替代方案
| 特性 | ANMA | 手动 CLAUDE.md | 静态分析工具 | 人工 Code Review |
|---|---|---|---|---|
| 对 AI Agent 生效 | ✅ 引导 + 强制双保险 | ✅ 弱指导(写时有效,改后过期) | ❌ 只有 CI 阶段 | ❌ 事后发现 |
| 覆盖便宜模型 | ✅ 68%→0% 已验证 | ❌ 模型不会自动读 | ❌ 只能阻止提交 | ❌ 审查者看不到 Agent 意图 |
| CI 集成 | ✅ drift check + boundary check | ❌ 依赖人工 | ✅ 需单独配置 | ❌ |
| 多语言 | ✅ Python, Go, TypeScript | ✅ 不限语言 | ❌ 通常限一种 | ✅ |
| 增量采用 | ✅ --warn + deprecated_deps | ✅ 直接改文件 | ✅ 逐步扩规则 | ✅ |
| 学习成本 | ~800 行代码,一个依赖 | 零 | 中等 | 无 |
注意事项
- 价值取决于你使用的模型:如果团队只用 Opus 4.8 级别的模型,ANMA 的基准测试诚实地说——边界其实不会被突破。它的价值在于用便宜模型时的保底。Opus 自己就能守好架构,但 Opus 的价格是 Haiku 的 10 倍以上。
- Python 的接口级检查暂时独有:Go 和 TypeScript 目前只能检查模块间的「是否允许依赖」,还不能像 Python 那样检查具体公开接口是否被外部使用。
- Stars 很低(2 星):ANMA 是一个 2026 年 5 月才发布的新项目,社区还在早期。但它的文档质量、基准测试方法论和架构设计都远超这个星数应有的水平。
- 无需 run time:ANMA 只在同步和检查时运行,不在生产环境执行——零运行时开销。
总结
ANMA 解决了一个真实且正在恶化的痛点:AI 编码 Agent 越改越快,架构约束越改越乱。它用 YAML 合同作为单一真实来源,自动生成引导层(CLAUDE.md)和强制层(PreToolUse hook + CI check),在基准测试中证明可以将便宜模型的越界违规从 68% 降至 0%。
如果你在用 Claude Code、Cursor、Codex 或 OpenCode 开发大型代码库,尤其是 monorepo,ANMA 值得一试——它可能就是你下一份架构文档不变成废纸的原因。
- GitHub: https://github.com/anma-labs/anma
- PyPI:
pip install anma[tach] - 文档: https://github.com/anma-labs/anma/blob/main/docs/QUICKSTART.md
- 许可证: Apache-2.0