当结构足够好,你不需要 CLAUDE.md

一次内部复盘引发的思考:为什么 OpenSpec 驱动的工程不需要那 70 行行为约束?

起因

最近网上流行一份叫 CLAUDE.md 的文件,大约 65-70 行,专门用来"驯服"AI 编程助手。内容大致是这类规则:

# CLAUDE.md — Behavioral guidelines to reduce common AI coding mistakes

- Do NOT delete or rewrite existing code unless explicitly asked
- Do NOT add dependencies without asking
- Do NOT modify files outside the scope of the current task
- Always run tests after making changes
- Keep changes minimal — do one thing per commit
- Preserve existing code style and patterns
- Do NOT refactor code that isn't related to the task
- When unsure, ask — don't guess
- Always check if a function/class already exists before creating a new one
- Do NOT change public API signatures without discussion
...

这些规则解决的是一个真实痛点:AI 在大型工程中容易"乱改一通"——删掉不该删的代码、引入不需要的依赖、偏离既有风格、一次改太多文件导致难以 review。

我在 H项目 中用 AI 协作开发了几个月,突然意识到:我的工程从来没出过这些问题。 是 OpenSpec 帮我解决了吗?我专门去查了一下——OpenSpec 里并没有任何类似 CLAUDE.md 的"行为约束"条款。

那问题到底是怎么被解决的?

CLAUDE.md 在解决什么

把那 65 行规则归类,本质上在防三件事:

问题类别 典型症状 CLAUDE.md 的应对
作用域失控 AI 改了不该改的文件,重构了不相关的代码 "Do NOT modify files outside scope"
风格漂移 新代码和老代码风格不一致,命名混乱 "Preserve existing code style"
破坏性变更 删除已有功能、改变公共接口、引入未经审批的依赖 "Do NOT delete code unless asked"

这三类问题的共同根源是:AI 缺乏对工程边界的认知。 它不知道哪些能动、哪些不能动、动了之后影响范围有多大。

CLAUDE.md 的策略是用自然语言告诉 AI "别乱来"。有效,但本质上是补丁式的行为约束——你得预判 AI 可能犯的每一种错,然后逐条写规则去堵。

OpenSpec 为什么不需要这些规则

H项目 使用的 OpenSpec 是一套 spec-driven 的工程管理体系。它的目录结构如下:

openspec/
├── specs/                    # 主规格文档(真理源)
│   ├── arch/                 # 架构约束(按端点)
│   │   ├── global/spec.md    # 全局:错误处理、日志、命名、安全、幂等
│   │   ├── iosapp/spec.md    # iOS:Swift 5.9+, Clean Arch, singleton
│   │   ├── watchapp/spec.md  # Watch:资源限制, ExtendedRuntime
│   │   ├── vault/spec.md     # Vault:Python, filesystem-first
│   │   ├── router/spec.md    # Router:FastAPI, DDD
│   │   └── worker/spec.md    # Worker:处理流水线
│   ├── local/                # 单端功能规格(按端点/层级/能力)
│   │   ├── iosapp/
│   │   │   ├── ui_conversation/spec.md
│   │   │   ├── app_task-queue/spec.md
│   │   │   └── inf_local-first/spec.md
│   │   ├── vault/
│   │   │   ├── inf_storage/spec.md
│   │   │   └── app_ingest/spec.md
│   │   └── ...
│   └── domain/               # 跨端协作规格
│       ├── transcription/
│       ├── auth/
│       └── sync/
├── changes/                  # 增量变更(每个 change 是一个完整的迭代单元)
│   ├── mcp-data-catalog/
│   │   ├── proposal.md       # 为什么做
│   │   ├── design.md         # 怎么做(含决策记录)
│   │   ├── tasks.md          # 拆解的任务清单
│   │   └── specs/            # Delta Spec(变更的规格增量)
│   ├── recall-full-coverage/
│   ├── graph-recall-pipeline/
│   └── ... (45+ changes)
└── config.yaml               # 目录结构规则定义

关键在于,这个结构天然解决了 CLAUDE.md 试图用规则堵住的三个问题:

1. 作用域失控 → Spec 天然划定边界

每个 change 目录就是一次迭代的完整边界。以 mcp-data-catalog 为例:

AI 读到这些信息后,它知道这次改动只涉及 vault 的 MCP 工具层,不会去碰 iOS 端的 UI 代码或 Worker 的转写流水线。不是因为有人告诉它"别改别的文件",而是它根本没有理由去改别的文件——spec 没有要求。

2. 风格漂移 → Arch Spec 定义了每个端点的技术契约

spec.arch.vault 明确规定了:

spec.arch.iosapp 明确规定了:

spec.arch.global 统一了跨端约定:

这些不是"建议",是用 MUST/SHALL/MUST NOT 写的强约束,每条都带 Scenario 验证场景。AI 写出来的代码如果不符合这些约束,在 review 阶段就会被 spec 打回。

CLAUDE.md 说"preserve existing code style"是一句模糊的祈使句。Arch Spec 说的是"你的 ViewModel MUST 使用 ObservableObject + @Published,MUST 放在 Presentation/ViewModels/ 目录"——这是可验证的规格。

3. 破坏性变更 → 分层 Spec + Delta Spec 机制

OpenSpec 的三层 spec 结构(Arch / Local / Domain)形成了一个天然的变更影响分析框架:

每次迭代通过 change 目录提交 Delta Spec——不是直接改主 spec,而是先写增量,review 通过后再 sync 到主 spec。这个机制天然防止了"AI 偷偷改了公共接口"的问题,因为:

  1. 如果 AI 要改一个接口,它必须在 Delta Spec 里声明这个变更
  2. Delta Spec 的路径规则严格执行(config.yaml 定义了合法路径模式,禁止了离散目录)
  3. 变更的 Impact 在 proposal.md 里必须列出

CLAUDE.md 说"don't change public API signatures"。OpenSpec 的做法是:你要改可以,但你得先写 proposal 说明为什么改、影响哪些端点、有没有 breaking change,然后在 Delta Spec 里精确描述变更内容。

本质区别:规则约束 vs 结构约束

维度 CLAUDE.md(规则约束) OpenSpec(结构约束)
约束方式 自然语言禁令 目录结构 + 规格文档
作用域控制 "别改别的文件" change 目录天然划定边界
风格一致性 "保持现有风格" Arch Spec 用 MUST/SHALL 定义技术契约
变更安全 "别删代码、别改接口" Delta Spec 机制要求声明变更
可验证性 不可验证(靠 AI 自觉) 每条约束带 Scenario,可机器检查
可扩展性 逐条添加规则,容易遗漏 新端点/新能力自动继承 Arch 约束
适用阶段 项目任何阶段都能加 需要前期投入建立 spec 体系

CLAUDE.md 是防御性的——它假设 AI 会犯错,然后用规则去拦截。
OpenSpec 是建设性的——它通过结构让 AI 天然知道该做什么、怎么做、做到什么程度。

打个比方:CLAUDE.md 像是在高速公路上竖警告牌("限速 120"、"禁止变道"),OpenSpec 像是把路本身修好了——有护栏、有车道线、有匝道,你自然就按规矩开了。

那 CLAUDE.md 没用吗?

不是。CLAUDE.md 在新工程的冷启动阶段非常有价值。

Jun在会议里说得很清楚:

"如果一个新工程它的那几行 cloud 点 md 是可以帮助它避免这些问题的,所以这中间就是说在做这个新工程一定是要么就结构好了,要么就是你准备很好的很多一线的这种实践的一些工程的 prompt。"

一个新工程在 spec 体系建立之前,AI 确实需要一些基本的行为约束来避免低级错误。CLAUDE.md 的 65 行规则就是这个阶段的"脚手架"。

但随着工程结构逐渐成熟——Arch Spec 定义了技术栈和代码组织,Local Spec 覆盖了各个功能模块,change 机制规范了迭代流程——这些行为约束就自然被结构吸收了。你不再需要告诉 AI "别乱改",因为 spec 已经告诉它"该改什么"。

结论

工程阶段 推荐策略
冷启动期(0-1 个月) CLAUDE.md 行为约束 + 基础 Arch Spec
结构形成期(1-3 个月) Arch Spec + Local Spec 逐步覆盖,CLAUDE.md 中的规则被 spec 吸收
稳定迭代期(3 个月+) 完整的 OpenSpec 体系(Arch/Local/Domain + change 机制),CLAUDE.md 可以退役

与其花精力维护一份越来越长的行为禁令清单,不如把精力投入到工程结构本身。 当你的 spec 体系足够完善,AI 不是因为被告知"不能做什么"而表现良好,而是因为它清楚地知道"应该做什么"。

这可能是 AI 协作开发中一个被低估的认知:约束 AI 最好的方式不是写更多规则,而是建更好的结构。


*本文基于 2026-04-23 H项目 团队内部技术复盘会议整理,结合 OpenSpec 实际工程实践撰写。*

原文

源链接