SKILL.md
readonly只读
name
documentation-and-adrs
description
记录决策和文档。在进行架构决策、更改公共API、发布功能或需要记录未来工程师和代理理解代码库所需的上下文时使用。
文档和架构决策记录
概述
记录决策,而不仅仅是代码。最有价值的文档记录的是为什么——导致决策的上下文、约束和权衡。代码展示做了什么;文档解释为什么这样构建以及考虑了哪些替代方案。这个上下文对于未来在代码库中工作的人类和代理至关重要。
何时使用
- 做出重要的架构决策
- 在竞争方案之间做出选择
- 添加或更改公共API
- 发布改变用户行为的功能
- 新团队成员(或代理)加入项目时
- 当你发现自己反复解释同一件事时
何时不使用: 不要记录显而易见的代码。不要添加重复代码含义的注释。不要为一次性原型编写文档。
架构决策记录(ADR)
ADR 记录了重要技术决策背后的理由。这是你能写的最有价值的文档。
何时编写 ADR
- 选择框架、库或主要依赖
- 设计数据模型或数据库模式
- 选择认证策略
- 决定 API 架构(REST vs. GraphQL vs. tRPC)
- 在构建工具、托管平台或基础设施之间选择
- 任何撤销成本高昂的决策
ADR 模板
将 ADR 存储在 docs/decisions/ 中,使用顺序编号:
# ADR-001: 使用 PostgreSQL 作为主数据库
## 状态
已接受 | 被 ADR-XXX 取代 | 已弃用
## 日期
2025-01-15
## 上下文
我们需要一个任务管理应用的主数据库。关键需求:
- 关系型数据模型(用户、任务、团队及其关系)
- 任务状态变更的 ACID 事务
- 支持任务内容的全文搜索
- 提供托管服务(小团队,运维能力有限)
## 决策
使用 PostgreSQL 和 Prisma ORM。
## 考虑的替代方案
### MongoDB
- 优点:灵活的模式,易于上手
- 缺点:我们的数据本质上是关系型的;需要手动管理关系
- 拒绝原因:在文档数据库中存储关系型数据会导致复杂的连接或数据重复
### SQLite
- 优点:零配置,嵌入式,读取速度快
- 缺点:并发写入支持有限,生产环境无托管服务
- 拒绝原因:不适合生产环境中的多用户 Web 应用
### MySQL
- 优点:成熟,广泛支持
- 缺点:PostgreSQL 在 JSON 支持、全文搜索和生态系统工具方面更优
- 拒绝原因:PostgreSQL 更符合我们的功能需求
## 后果
- Prisma 提供类型安全的数据库访问和迁移管理
- 我们可以使用 PostgreSQL 的全文搜索,无需添加 Elasticsearch
- 团队需要 PostgreSQL 知识(标准技能,风险低)
- 托管在托管服务上(Supabase、Neon 或 RDS)
ADR 生命周期
提议 → 已接受 → (被取代或已弃用)
- 不要删除旧的 ADR。 它们记录了历史上下文。
- 当决策发生变化时,编写一个新的 ADR,引用并取代旧的 ADR。
内联文档
何时添加注释
注释为什么,而不是做什么:
// 不好:重复代码含义
// 计数器加1
counter += 1;
// 好:解释非显而易见的意图
// 速率限制使用滑动窗口——在窗口边界重置计数器,
// 而不是固定时间,以防止窗口边缘的突发攻击
if (now - windowStart > WINDOW_SIZE_MS) {
counter = 0;
windowStart = now;
}
何时不添加注释
// 不要注释自解释的代码
function calculateTotal(items: CartItem[]): number {
return items.reduce((sum, item) => sum + item.price * item.quantity, 0);
}
// 不要留下 TODO 注释,应该现在就做
// TODO: 添加错误处理 ← 直接添加
// 不要留下注释掉的代码
// const oldImplementation = () => { ... } ← 删除它,git 有历史记录
记录已知陷阱
/**
* 重要:此函数必须在首次渲染之前调用。
* 如果在水合后调用,会导致无样式内容闪烁,
* 因为 SSR 期间主题上下文不可用。
*
* 完整设计理由见 ADR-003。
*/
export function initializeTheme(theme: Theme): void {
// ...
}
API 文档
对于公共 API(REST、GraphQL、库接口):
类型内联(TypeScript 首选)
/**
* 创建一个新任务。
*
* @param input - 任务创建数据(标题必填,描述可选)
* @returns 创建的任务,包含服务器生成的 ID 和时间戳
* @throws {ValidationError} 如果标题为空或超过 200 个字符
* @throws {AuthenticationError} 如果用户未认证
*
* @example
* const task = await createTask({ title: '买杂货' });
* console.log(task.id); // "task_abc123"
*/
export async function createTask(input: CreateTaskInput): Promise<Task> {
// ...
}
REST API 的 OpenAPI / Swagger
paths:
/api/tasks:
post:
summary: 创建任务
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateTaskInput'
responses:
'201':
description: 任务已创建
content:
application/json:
schema:
$ref: '#/components/schemas/Task'
'422':
description: 验证错误
README 结构
每个项目都应有一个 README,涵盖以下内容:
# 项目名称
一段描述该项目功能的段落。
## 快速开始
1. 克隆仓库
2. 安装依赖:`npm install`
3. 设置环境变量:`cp .env.example .env`
4. 启动开发服务器:`npm run dev`
## 命令
| 命令 | 描述 |
|---------|-------------|
| `npm run dev` | 启动开发服务器 |
| `npm test` | 运行测试 |
| `npm run build` | 生产构建 |
| `npm run lint` | 运行 linter |
## 架构
项目结构和关键设计决策的简要概述。
详情请参阅 ADR。
## 贡献
如何贡献、编码标准、PR 流程。
变更日志维护
对于已发布的功能:
# 变更日志
## [1.2.0] - 2025-01-20
### 新增
- 任务共享:用户可以与团队成员共享任务 (#123)
- 任务分配的电子邮件通知 (#124)
### 修复
- 快速点击创建按钮时出现重复任务 (#125)
### 变更
- 任务列表现在每页加载 50 项(之前是 20 项)以改善用户体验 (#126)
面向代理的文档
对 AI 代理上下文的特别考虑:
- CLAUDE.md / 规则文件 — 记录项目约定,以便代理遵循
- 规范文件 — 保持规范更新,以便代理构建正确的内容
- ADR — 帮助代理理解过去决策的原因(防止重新决策)
- 内联陷阱 — 防止代理陷入已知陷阱
常见借口
| 借口 | 现实 |
|---|---|
| “代码自文档化” | 代码展示做了什么。它不展示为什么、拒绝了哪些替代方案或存在哪些约束。 |
| “等 API 稳定后再写文档” | 当你编写文档时,API 会更稳定。文档是设计的第一个测试。 |
| “没人读文档” | 代理会读。未来的工程师会读。三个月后的你自己也会读。 |
| “ADR 是额外负担” | 一个 10 分钟的 ADR 可以防止六个月后关于同一决策的两小时争论。 |
| “注释会过时” | 关于为什么的注释是稳定的。关于做什么的注释会过时——这就是为什么你只写前者。 |
红旗
- 没有书面理由的架构决策
- 没有文档或类型的公共 API
- 不解释如何运行项目的 README
- 注释掉的代码而不是删除
- 存在数周的 TODO 注释
- 有重要架构选择的项目却没有 ADR
- 重复代码含义而不是解释意图的文档
验证
文档编写后:
- [ ] 所有重要的架构决策都有对应的 ADR
- [ ] README 涵盖快速开始、命令和架构概述
- [ ] API 函数有参数和返回类型的文档
- [ ] 已知陷阱在相关位置内联记录
- [ ] 没有残留的注释掉的代码
- [ ] 规则文件(CLAUDE.md 等)是最新且准确的






