SP-05 · Vibe Coding 护栏手册:五文档体系,让 AI 不再乱飘
引言:Agent 越强,飘得越厉害
用 Cursor、Claude Code、Copilot 写过大项目的人都踩过同一个坑:
你让 AI 实现一个功能,它实现了。但顺手改了三个不相关的文件,引入了两个你没让它装的依赖,重构了一个你觉得没问题的函数,然后告诉你"顺便优化了一下"。
这不是 AI 变笨了,而是它没有边界。
大模型的核心驱动是"完成目标",没有约束时它会把"顺手"的事情都做掉。越强的 model,飘得越远、越自信。
五文档体系是一套在开跑前花 10 分钟设置护栏的轻量工作流。核心原则只有一句话:
让 AI 可以跑,但不能自由发挥;每一轮都要有边界、有记录、有验收。
五文档体系全景
项目根目录/
├── CLAUDE.md # 1. 总规则 — AI 的宪法
├── ARCHITECTURE.md # 2. 架构图 — AI 的地图
├── TASKS.md # 3. 任务拆分 — AI 的工单
├── STEPS.md # 4. 执行记录 — AI 的日志
└── ACCEPTANCE.md # 5. 验收清单 — AI 的考卷
五个文件,每个有独立职责,缺一不可。下面逐个拆解。
Step 1:CLAUDE.md — AI 的宪法
痛点解析:AI 不知道这个项目的边界在哪。没有约束时,它会做"合理推断"——而合理推断经常是错的。CLAUDE.md 是你给 AI 的第一份上下文,告诉它"这是什么项目、能做什么、不能碰什么"。
模板:
## 项目目标
[一句话说清楚这个项目要解决什么问题]
## 技术栈
- 语言:Python 3.11+
- 框架:FastAPI
- 数据库:SQLite(开发) / PostgreSQL(生产)
- 部署:Docker + Nginx
## 硬边界(禁止项)
- 不允许修改 `auth/` 目录下的任何文件(已上线,不在本次范围内)
- 不允许引入新的第三方依赖,除非我明确授权
- 不允许重构已有函数的签名
- 不允许改动数据库 Schema
## 验收标准
- 所有改动必须通过 `pytest tests/` 才算完成
- 改动后运行 `python -m mypy src/` 无新增错误
- 每次改动必须有对应的 STEPS.md 记录
## 本次任务范围
[每次开工前填写,明确这一轮要做什么]
核心要素:禁止项 > 验收标准 > 任务范围。这三项缺任何一项,AI 都会在边界外行动。
Step 2:ARCHITECTURE.md — AI 的地图
痛点解析:AI 看到的是你粘贴进去的文件片段,不是系统全貌。没有架构图,它不知道模块之间的依赖关系,不知道改这里会影响那里,不知道数据从哪里来、流向哪里。
模板:
# ARCHITECTURE.md
## 系统主流程
用户请求 → Nginx → FastAPI Router → Service Layer → Repository → DB
↓
Auth Middleware(每个请求都经过)
## 模块关系
src/
├── api/ # 路由层,只做参数校验和响应格式化,不含业务逻辑
├── services/ # 业务逻辑层,唯一允许跨模块调用的层
├── repositories/ # 数据访问层,只和数据库交互
├── models/ # Pydantic 模型,不含逻辑
└── auth/ # 认证模块,独立,不允许其他模块直接修改
## 数据流
POST /api/orders
→ OrderRouter.create() [api/orders.py]
→ OrderService.create_order() [services/order.py]
→ OrderRepository.save() [repositories/order.py]
→ orders 表
## 失败条件
- DB 连接失败 → 返回 503,不抛异常到用户层
- 认证失败 → 返回 401,记录到 audit_log
- 业务校验失败 → 返回 422,包含字段级错误信息
## 禁止的依赖方向
api → services → repositories(✅ 单向)
repositories → services(❌ 禁止反向依赖)
关键点:画出禁止的依赖方向。这是让 AI 不乱引用的核心约束。
Step 3:TASKS.md — AI 的工单
痛点解析:你说"帮我做一个用户管理功能",AI 会做一个完整的用户管理系统,包括你没想到要的 RBAC 权限控制和头像上传。任务越模糊,AI 发挥越多。TASKS.md 把大需求切成小工单,每个工单有输入、输出、完成标准,不给 AI 自由发挥的空间。
模板:
# TASKS.md
## 当前任务列表
### TASK-01:用户注册接口
- **状态**: 进行中
- **输入**: POST /api/users/register,body: {email, password}
- **输出**: 201 Created,body: {user_id, email, created_at}
- **完成标准**:
- [ ] email 格式校验(无效格式返回 422)
- [ ] 重复 email 返回 409,错误信息为 "Email already registered"
- [ ] 密码 bcrypt hash 后存储,明文不落库
- [ ] 通过 tests/test_register.py 所有用例
- **不在范围内**: 邮件验证、短信验证、第三方 OAuth
### TASK-02:用户登录接口
- **状态**: 待开始
- **依赖**: TASK-01 完成后才能开始
- **输入**: POST /api/users/login,body: {email, password}
- **输出**: 200 OK,body: {access_token, token_type: "bearer"}
- **完成标准**:
- [ ] 密码错误返回 401,不透露是邮箱不存在还是密码错误
- [ ] token 有效期 24 小时
- [ ] 通过 tests/test_login.py 所有用例
- **不在范围内**: refresh token、多设备登录、登录日志
核心技巧:每个任务都写"不在范围内"。这一行比"完成标准"更重要,它明确告诉 AI 什么不要做。
Step 4:STEPS.md — AI 的日志
痛点解析:AI 改了什么,你不一定看得过来。三轮之后,你已经不记得第一轮改了什么、为什么改、有没有留下隐患。STEPS.md 是强制的执行日志,每一轮结束必须更新,让你随时能回溯。
模板:
# STEPS.md
## 执行记录
### 第 1 轮(2026-05-02)
**任务**: TASK-01 用户注册接口
**AI 做了什么**:
- 新增 `src/api/users.py`,实现 POST /api/users/register
- 新增 `src/services/user_service.py`,实现 create_user() 业务逻辑
- 新增 `src/repositories/user_repository.py`,实现 save_user()
- 新增 `tests/test_register.py`,覆盖正常注册、重复邮箱、格式错误三个场景
**手动修改了什么**:
- 将 bcrypt rounds 从 10 改为 12(AI 用了默认值,安全性不够)
- 删除了 AI 自动加的 `/api/users/me` 接口(不在本次范围)
**遗留问题**:
- password_hash 字段长度设为 60,bcrypt hash 实际是 60 字符,刚好够,但建议后续改为 72
**验收结果**:
- `pytest tests/test_register.py` ✅ 4/4 passed
- `python -m mypy src/` ✅ 无新增错误
---
### 第 2 轮(2026-05-03)
**任务**: [下一轮开始前填写]
核心习惯:每一轮结束,在提交代码之前,先更新这个文件。5 分钟,换来完整的回溯能力。
Step 5:ACCEPTANCE.md — AI 的考卷
痛点解析:AI 说"完成了",不代表真的完成了。你需要一份验收清单,列出怎么证明功能真的跑通,包括测试命令、日志检查、diff 审查、回滚方式。有了这份清单,“完成"才有客观标准。
模板:
# ACCEPTANCE.md
## 验收清单
### 功能验收
- [ ] 运行 `pytest tests/ -v`,所有用例通过
- [ ] 运行 `python -m mypy src/`,无新增 type error
- [ ] 手动测试主流程(见下方 curl 命令)
### 手动验收命令
```bash
# 注册新用户
curl -X POST http://localhost:8000/api/users/register \
-H "Content-Type: application/json" \
-d '{"email": "[email protected]", "password": "Test1234!"}'
# 期望: 201 {"user_id": "...", "email": "[email protected]"}
# 重复注册(应返回 409)
curl -X POST http://localhost:8000/api/users/register \
-H "Content-Type: application/json" \
-d '{"email": "[email protected]", "password": "Test1234!"}'
# 期望: 409 {"detail": "Email already registered"}
代码审查检查点
-
diff HEAD~1中没有修改auth/目录 - 没有引入新的
requirements.txt条目(除非已授权) - 没有修改任何已有函数的签名
- 日志中没有明文密码
回滚方式
# 回滚到上一个 commit
git revert HEAD
# 或直接重置(危险,确认后再用)
git reset --hard HEAD~1
发布结论
- 以上所有项通过
- STEPS.md 已更新本轮记录
- 代码已提交,commit message 符合规范
---
## 极客实战:完整五文档模板包
把以下内容存为 `init_guardrails.sh`,一键初始化五文档护栏:
```bash
#!/bin/bash
# init_guardrails.sh — 一键初始化五文档护栏体系
# 用法:bash init_guardrails.sh
set -e
PROJECT_NAME="${1:-my-project}"
DATE=$(date +%Y-%m-%d)
echo "🛡️ 初始化五文档护栏:$PROJECT_NAME"
# 1. CLAUDE.md
cat > CLAUDE.md << 'EOF'
# CLAUDE.md — AI 协作总规则
## 项目目标
[一句话描述这个项目要解决什么问题]
## 技术栈
- 语言:
- 框架:
- 数据库:
## 硬边界(禁止项)
- [ ] 不允许修改 [填写受保护目录]
- [ ] 不允许引入未经授权的新依赖
- [ ] 不允许重构已有函数签名
## 验收标准
- 通过 [填写测试命令]
- 类型检查无新增错误
## 本次任务范围
[每次开工前在此填写]
EOF
# 2. ARCHITECTURE.md
cat > ARCHITECTURE.md << 'EOF'
# ARCHITECTURE.md — 系统架构
## 主流程
[描述请求的完整路径]
## 模块关系
[描述各模块的职责边界]
## 数据流
[描述数据从哪来、流向哪里]
## 失败条件
[描述各类错误的处理方式]
## 禁止的依赖方向
[明确哪些模块不允许互相引用]
EOF
# 3. TASKS.md
cat > TASKS.md << 'EOF'
# TASKS.md — 任务工单
## 当前任务
### TASK-01:[任务名称]
- **状态**: 待开始
- **输入**: [接口 / 函数 / 触发条件]
- **输出**: [期望的返回值 / 行为]
- **完成标准**:
- [ ] [具体可验证的条件]
- **不在范围内**: [明确排除项]
EOF
# 4. STEPS.md
cat > STEPS.md << "EOF"
# STEPS.md — 执行记录
## 执行记录
### 第 1 轮($DATE)
**任务**:
**AI 做了什么**:
**手动修改了什么**:
**遗留问题**:
**验收结果**:
EOF
# 5. ACCEPTANCE.md
cat > ACCEPTANCE.md << 'EOF'
# ACCEPTANCE.md — 验收清单
## 功能验收
- [ ] 自动化测试全部通过
- [ ] 手动验收命令执行正常
## 手动验收命令
```bash
# 在此填写验证命令和期望输出
代码审查检查点
- diff 中无超出范围的文件改动
- 无新增未授权依赖
- 无函数签名变更
回滚方式
git revert HEAD
发布结论
- 以上所有项通过
- STEPS.md 已更新
- commit message 符合规范 EOF
echo "” echo “✅ 五文档护栏初始化完成:” echo " 📋 CLAUDE.md — AI 总规则" echo " 🗺️ ARCHITECTURE.md — 系统架构" echo " 📝 TASKS.md — 任务工单" echo " 📒 STEPS.md — 执行记录" echo " ✅ ACCEPTANCE.md — 验收清单" echo "" echo “下一步:打开 CLAUDE.md,填写项目目标和硬边界,然后开始第一个任务。”
---
## 架构师结语
Vibe Coding 的本质不是"让 AI 随便写",而是"在有约束的空间里让 AI 全速跑"。
赛车不是没有边界才快——是因为有赛道、有护栏、有规则,车手才敢把油门踩到底。
五文档体系就是你给 AI 建的赛道。10 分钟的前期投入,换来的是每一轮都可回溯、可验收、可回滚的工程确定性。
> 没有护栏的 Vibe Coding,是在赌运气。
> 有了护栏的 Vibe Coding,才是工程能力。