📚 docs(codestable): 添加 CodeStable 项目知识库
添加 codestable/ 目录,包含项目架构文档、需求文档、 功能设计、问题追踪、参考文档、路线图及工具配置 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
286
codestable/reference/shared-conventions.md
Normal file
286
codestable/reference/shared-conventions.md
Normal file
@@ -0,0 +1,286 @@
|
||||
# CodeStable 共享口径
|
||||
|
||||
本文件由 `cs-onboard` 复制到项目的 `codestable/reference/shared-conventions.md`。所有 CodeStable 子技能在运行时用**项目相对路径** `codestable/reference/shared-conventions.md` 引用本文件——这是跨子技能共享但不适合堆在单个技能里的规范的唯一权威版本。
|
||||
|
||||
skill 本身不共享文件系统(每个 skill 是独立安装单元),所以共享口径不能放在某个 skill 内部被别的 skill 引用。放在"工作项目"里,对所有 skill 都可达。
|
||||
|
||||
---
|
||||
|
||||
## 0. 目录结构与路径命名
|
||||
|
||||
onboarding 完成后,项目里应当存在如下骨架(`cs-onboard` 负责搭建):
|
||||
|
||||
```
|
||||
codestable/
|
||||
├── requirements/ 需求中心目录("为什么要有这个能力",只记现状)
|
||||
│ └── {slug}.md 一个能力一份,扁平(由 cs-req 产出)
|
||||
├── architecture/ 架构中心目录("用什么结构实现",只记现状)
|
||||
│ ├── ARCHITECTURE.md 架构总入口(索引 + 关键架构决定)
|
||||
│ └── {slug}.md 子系统 / 模块架构 doc(由 cs-arch 产出)
|
||||
├── roadmap/ 规划层目录("接下来打算怎么做这块大需求 + 模块怎么切 + 接口怎么定",独立于现状档案)
|
||||
│ └── {slug}/ 一个大需求一个子目录(由 cs-roadmap 产出)
|
||||
│ ├── {slug}-roadmap.md 主文档:背景 / 范围 / 模块拆分(概设)/
|
||||
│ │ 接口契约(架构层详设)/ 子 feature 清单 / 排期思路
|
||||
│ ├── {slug}-items.yaml 机器可读的子 feature 清单,acceptance 回写状态
|
||||
│ └── drafts/ 可选,草稿 / 调研 / 讨论
|
||||
├── features/ feature spec 聚合根
|
||||
│ └── YYYY-MM-DD-{slug}/ 每个 feature 一个目录
|
||||
│ ├── {slug}-brainstorm.md (可选,由 cs-brainstorm 判为 case 2 时产出)
|
||||
│ ├── {slug}-design.md
|
||||
│ ├── {slug}-checklist.yaml
|
||||
│ └── {slug}-acceptance.md
|
||||
├── issues/ issue spec 聚合根
|
||||
│ └── YYYY-MM-DD-{slug}/ 每个 issue 一个目录
|
||||
│ ├── {slug}-report.md
|
||||
│ ├── {slug}-analysis.md (根因不显然时才有)
|
||||
│ └── {slug}-fix-note.md
|
||||
├── refactors/ refactor spec 聚合根
|
||||
│ └── YYYY-MM-DD-{slug}/ 每次 refactor 一个目录
|
||||
│ ├── {slug}-scan.md
|
||||
│ ├── {slug}-refactor-design.md
|
||||
│ ├── {slug}-checklist.yaml
|
||||
│ └── {slug}-apply-notes.md
|
||||
├── compound/ 沉淀类文档统一目录
|
||||
│ └── YYYY-MM-DD-{doc_type}-{slug}.md
|
||||
│ doc_type ∈ {learning, trick, decision, explore}
|
||||
├── tools/ 跨工作流共享脚本(由 onboarding 从技能包释放)
|
||||
└── reference/ 共享参考文档(由 onboarding 从技能包释放,即本文件所在目录)
|
||||
```
|
||||
|
||||
### 命名规则
|
||||
|
||||
- 需求文档:`codestable/requirements/{slug}.md`(长效能力清单,不带日期前缀,扁平不分组)
|
||||
- roadmap 目录:`codestable/roadmap/{slug}/`(一个大需求一个子目录,不带日期前缀,平铺不嵌套)
|
||||
- feature 目录:`codestable/features/YYYY-MM-DD-{slug}/`,日期用创建当天
|
||||
- issue 目录:`codestable/issues/YYYY-MM-DD-{slug}/`,日期用报告当天
|
||||
- refactor 目录:`codestable/refactors/YYYY-MM-DD-{slug}/`,日期用首次扫描当天
|
||||
- 沉淀类文档:`codestable/compound/YYYY-MM-DD-{doc_type}-{slug}.md`,日期用**归档当天**(不是问题发生当天)
|
||||
- 架构文档:`codestable/architecture/{type}-{slug}.md`(长效地图,不带日期前缀);总入口始终叫 `ARCHITECTURE.md`
|
||||
- `AGENTS.md` 在项目根目录,**不在 `codestable/` 里**
|
||||
|
||||
### 架构 doc 的分组规则(同类聚合)
|
||||
|
||||
`codestable/architecture/` 下的 doc 用文件名**第一段**(首个连字符之前)作为类型标记:`ui-chat.md` 和 `ui-events.md` 同属 `ui` 类,`api-routing.md` 自成 `api` 类。所以**所有架构 doc 命名必须遵循 `{type}-{slug}.md`**——只有一份且预计长期独占的,也要带个合理的 type 段(如 `cli-entry.md` 而非 `entry.md`),否则未来同类出现时统计不到、聚合不了。
|
||||
|
||||
**触发条件**:某个 type 在 `codestable/architecture/` 根目录下达到或超过 **6 份**文档时(即新加第 6 份的那一次操作),把这一类全部收进同名子目录。
|
||||
|
||||
**收入子目录后的命名**:去掉 type 前缀。`ui-chat.md` → `ui/chat.md`、`ui-open-files-tree.md` → `ui/open-files-tree.md`。子目录里不再带 `ui-` 前缀。
|
||||
|
||||
**只升不降**:文档因删除回到 ≤5 份也不折回平铺,避免反复改一堆引用。
|
||||
|
||||
**触发时谁负责**:`cs-arch` 的 `backfill` / `update` 模式在 Phase 6 落盘前主动检查;命中阈值时这次操作要把"本次新加 / 改的这份 + 已有同类全部"一起搬迁,并同步改 `ARCHITECTURE.md` 里所有相关链接(搬迁本身要在 Phase 5 一并给用户 review,不偷偷做)。`check` 模式不主动搬迁,但读 `architecture/` 时若发现某 type 已 ≥6 仍平铺,在报告末尾列为观察项交给用户。
|
||||
|
||||
### 要改目录结构
|
||||
|
||||
改 `cs-onboard/reference/shared-conventions.md` 这个模板,新项目 onboarding 时会带上新版本。已有项目需要手动同步 `codestable/reference/shared-conventions.md`。
|
||||
|
||||
---
|
||||
|
||||
## 1. 共享元数据口径
|
||||
|
||||
### feature spec
|
||||
|
||||
- `{slug}-brainstorm.md` / `{slug}-design.md` / `{slug}-acceptance.md` 共用 `doc_type`、`feature`、`status`、`summary`、`tags` 这组核心字段
|
||||
- 子技能只补充本阶段特有字段,不重复改写这组字段的含义
|
||||
- `status` 取值各阶段不同:brainstorm = `confirmed`(落盘即确认,无 draft);design = `draft` / `approved`;acceptance 见对应技能
|
||||
|
||||
### issue spec
|
||||
|
||||
- `{slug}-report.md` / `{slug}-analysis.md` / `{slug}-fix-note.md` 共用 `doc_type`、`issue`、`status`、`tags` 这组核心字段
|
||||
- `severity`、`root_cause_type`、`path` 等属于阶段特有字段,由对应阶段按需补充
|
||||
|
||||
### 归档类文档
|
||||
|
||||
- `learning` / `trick` / `decision` / `explore` 四个子技能的产物**统一写入 `codestable/compound/` 目录**
|
||||
- 每个文档必须在 frontmatter 顶部带 `doc_type` 字段(`learning` / `trick` / `decision` / `explore`),作为跨子技能的归属判定
|
||||
- 文件名统一用 `YYYY-MM-DD-{doc_type}-{slug}.md`——日期打头、`doc_type` 段在中间,`ls` 按名字排序就按归档日期排好;要按类型筛就 grep 中间那段
|
||||
- 各子技能在 `doc_type` 之外保留自己的专属 frontmatter(learning 的 `track`、trick 的 `type`、decision 的 `category`、explore 的 `type`)
|
||||
- 各子技能只认自己的 `doc_type` 和文件名里的类型段(`YYYY-MM-DD-{doc_type}-...` 中间那段),不读不写别的子技能的文档
|
||||
- `status` 一类通用字段的语义必须和本文件保持一致,不另起一套口径
|
||||
- 子技能里如果需要解释状态,只保留该工作流特有的状态流,不重新定义通用语义
|
||||
|
||||
### 面向外部读者的文档
|
||||
|
||||
- `guidedoc` / `libdoc` 的 frontmatter 由各自子技能定义
|
||||
- 如无特殊说明:`draft` = 待 review,`current` = 当前有效,`outdated` = 代码已变更待同步
|
||||
|
||||
### 写作约束
|
||||
|
||||
- 子技能提到字段时,优先写"本技能额外字段"或"本阶段状态变化"
|
||||
- 不要把整套通用字段定义在多个技能里重复展开
|
||||
|
||||
---
|
||||
|
||||
## 2. {slug}-checklist.yaml 生命周期
|
||||
|
||||
- `{slug}-checklist.yaml` 是 feature 工作流的唯一执行清单
|
||||
- 由 `cs-feat-design` 在 `{slug}-design.md` 确认通过后一次生成
|
||||
- `cs-feat-ff` **不生成** checklist(也不写 design doc / acceptance),它是跳过 spec 流程、直接让 AI 写代码的超轻量通道,只做动手前的知识检索引导
|
||||
|
||||
### design 的职责
|
||||
|
||||
- 只负责从方案里提取 `steps` 和 `checks`
|
||||
- 不预先把任何条目标成完成
|
||||
|
||||
### implement 的职责
|
||||
|
||||
- 只更新 `steps[].status`
|
||||
- 状态流:`pending` → `done`
|
||||
- 不改写 `checks` 的所有权和来源
|
||||
|
||||
### acceptance 的职责
|
||||
|
||||
- 只更新 `checks[].status`
|
||||
- 状态流:`pending` → `passed` / `failed`
|
||||
- 不回头重写 `steps`
|
||||
|
||||
### 写作约束
|
||||
|
||||
- 子技能描述 `{slug}-checklist.yaml` 时,只补充本阶段具体要读/写哪一部分
|
||||
- 不重新定义整份文件的生命周期
|
||||
|
||||
---
|
||||
|
||||
## 2.5 roadmap ↔ feature 衔接协议
|
||||
|
||||
`codestable/roadmap/{slug}/{slug}-items.yaml` 是"规划层"和"feature 执行层"之间的唯一接口。三个技能共同读写它——**不算跨 skill 耦合**,是 skill 都读写项目共享产物,和都读写 `codestable/features/` 同理。
|
||||
|
||||
### items.yaml 的状态机
|
||||
|
||||
```
|
||||
planned → in-progress (cs-feat-design 启动 feature 时改)
|
||||
in-progress → done (cs-feat-accept 验收完成时改)
|
||||
planned → dropped (cs-roadmap update 模式,用户决定不做时改)
|
||||
```
|
||||
|
||||
`done` 和 `dropped` 是终态。需要回退重做的要新加一条 slug 略改的条目,不要改终态。
|
||||
|
||||
### cs-roadmap 的职责
|
||||
|
||||
- 生成和维护 `{slug}-roadmap.md` 主文档和 `{slug}-items.yaml` 的结构
|
||||
- 把 `planned` 条目改 `dropped`(用户决定放弃时)
|
||||
- 不改 `in-progress` / `done` 状态——那两类跃迁由 feature 技能负责
|
||||
|
||||
### cs-feat-design 的职责
|
||||
|
||||
从 roadmap 条目起头 feature 时:
|
||||
|
||||
1. 在 `{slug}-design.md` frontmatter 加两个字段:`roadmap: {roadmap-slug}` + `roadmap_item: {子 feature slug}`
|
||||
2. 打开 `codestable/roadmap/{roadmap-slug}/{roadmap-slug}-items.yaml`,把对应条目 `status` 改为 `in-progress`、`feature` 填为 feature 目录名(`YYYY-MM-DD-{slug}`)
|
||||
3. 校验 yaml 语法
|
||||
|
||||
直接起 feature(不从 roadmap 来)时两个字段留空或省略,不触发任何 roadmap 写操作。
|
||||
|
||||
### cs-feat-accept 的职责
|
||||
|
||||
验收流程走到收尾时:
|
||||
|
||||
1. 读 `{slug}-design.md` frontmatter 的 `roadmap` / `roadmap_item` 字段
|
||||
2. 字段为空 → 跳过 roadmap 回写
|
||||
3. 字段有值 → 打开 `codestable/roadmap/{roadmap}/{roadmap}-items.yaml`,把 `roadmap_item` 对应条目 `status` 改为 `done`
|
||||
4. 同步主文档 `{roadmap}-roadmap.md` 子 feature 清单里对应行的显示状态(保持两份一致)
|
||||
5. 校验 yaml 语法
|
||||
|
||||
回写是**实际写文件的动作**,不是自评"应该不需要改"。验收报告里要明确记录回写结果。
|
||||
|
||||
### 最小闭环标记
|
||||
|
||||
items.yaml 每份里只有一条 `minimal_loop: true`,标记"这条做完后系统能端到端跑通最窄路径"。feature-design 启动 `minimal_loop: true` 条目时优先级最高——它是整个大需求能不能落地的早期信号。
|
||||
|
||||
---
|
||||
|
||||
## 3. 阶段收尾推荐
|
||||
|
||||
### feature-acceptance
|
||||
|
||||
收尾时按顺序判断是否要推荐:
|
||||
|
||||
1. `cs-learn`:沉淀经验
|
||||
2. `cs-decide`:记录长期约束/选型
|
||||
3. `cs-guide`:更新开发者/用户指南
|
||||
4. `cs-libdoc`:更新公开 API 参考
|
||||
5. `scoped-commit`
|
||||
|
||||
### issue-fix
|
||||
|
||||
收尾时按顺序判断是否要推荐:
|
||||
|
||||
1. `cs-learn`:记录坑点
|
||||
2. `cs-decide`:如修复暴露出长期约束
|
||||
3. `scoped-commit`
|
||||
|
||||
### 推荐动作的统一规则
|
||||
|
||||
- 一律一句话提示
|
||||
- 用户说"不用"立刻跳过
|
||||
- 推荐不是强制,不得把用户拖入新的工作流
|
||||
- 上游技能负责主动提示,下游技能负责承接执行
|
||||
- 不要出现下游说"应该由上游推荐"、上游却没有动作的漂移
|
||||
|
||||
---
|
||||
|
||||
## 4. 收尾提交(scoped-commit)
|
||||
|
||||
feature-acceptance 和 issue-fix 走完后要把本次产物提交为一个 commit。规则:
|
||||
|
||||
- **提交范围**:本次工作改到的代码 + 相关 spec 文档 + 本次实际更新过的架构 doc + 本次实际更新过的 roadmap items.yaml / 主文档
|
||||
- **不该进这个 commit**:和本次工作无关的顺手修改;属于"下次另起一个 feature / issue"的扩大范围
|
||||
- **提交前确认**:用户没明确同意就不要 `git commit`
|
||||
- **commit message**:一句话说清楚"这次做了什么",不要把 spec 目录路径贴进 message
|
||||
|
||||
子技能只描述本阶段的特有提交范围(比如 acceptance 要带架构 doc),通用规则看这里。
|
||||
|
||||
---
|
||||
|
||||
## 5. 归档检索规则
|
||||
|
||||
feature-design / issue-analyze / issue-fix 在动手前要到 `codestable/compound/` 里搜已有的沉淀:
|
||||
|
||||
- 总是先搜 `architecture/` 和 `compound/` 两个目录
|
||||
- 在 `compound/` 里用 `doc_type` 字段按需过滤(learning / trick / decision / explore)
|
||||
- 搜到的结果只作为参考输入,不盲目套用——可能已过期(`status=outdated`)或不适合当前上下文
|
||||
- 搜到和当前方向冲突的 decision → 必须在方案 / 分析里正面回应"为什么仍然要这么做"或调整方向
|
||||
|
||||
子技能只补充本阶段的具体查询命令。完整搜索语法看 `codestable/reference/tools.md`。
|
||||
|
||||
---
|
||||
|
||||
## 6. 归档类子技能共享守护规则
|
||||
|
||||
`cs-learn` / `cs-trick` / `cs-decide` / `cs-explore` 四个子技能共享下面这组规则。各子技能的正文只写本技能特有反模式,通用规则看这里:
|
||||
|
||||
1. **只增不删**——已归档的文档除非被明确取代(`status=superseded`),否则不删除;理由丢失的成本极高
|
||||
2. **宁缺毋滥**——用户说不出理由的节直接省略,不要 AI 编造听起来合理的内容
|
||||
3. **不替用户写实质内容**——AI 负责起草结构和串联语言,实质结论必须来自用户或可追溯的代码证据
|
||||
4. **可发现性检查**——写完后检查 `AGENTS.md` / `CLAUDE.md` 里有没有指引 AI 查阅 `codestable/compound/`,没有就**提示**用户(不替用户改)
|
||||
5. **起草前先查重叠,而不是归档后**——动手写之前就用 `search-yaml.py --query` 查语义相近的旧文档。有命中就把候选列给用户,让用户在三条路径里选一条:
|
||||
- **更新已有条目**(默认优先):沿用原文件名和原创建日期,**不新建文件**;修改正文相关节,在 frontmatter 补 `updated: YYYY-MM-DD`(归档当天);变更超出小修的话在文末加一段"YYYY-MM-DD 更新"简述改了什么
|
||||
- **supersede 已有条目**:旧文档保留原文,把 `status` 改成 `superseded`,加 `superseded-by: {新文档文件名}`,正文顶部加一行 `**[已取代]** 见 {新文档 slug}`;然后新建文档,frontmatter 带 `supersedes: {旧文档文件名}`
|
||||
- **确实是不同主题**:直接新建,在新文档末尾 `相关文档` 节列出已有那条,说明区别
|
||||
6. **识别用户意图是"改已有"还是"记新的"**——用户说"改 / 更新 / 修订 / 补充 {某条}"、明确指向某条旧文档、或话题高度重合时,默认走"更新已有条目"路径,不要闷头新建。分不清就问一句,不要猜。
|
||||
|
||||
各子技能只认自己的 `doc_type`,不读写别家产物。
|
||||
|
||||
---
|
||||
|
||||
## 7. 写代码时的反射检查
|
||||
|
||||
`cs-feat-impl` 和 `cs-issue-fix` 共用的一组代码质量反射检查。AI 默认会往"大函数 / 大文件 / god class / 处处特殊分支"这些方向漂,这一节的目的是把漂移截在发生的那一刻。
|
||||
|
||||
**不是阈值,是触发器**。不是"超过 N 行必须拆"——硬数字会诱发为拆而拆,把自然聚合的代码切碎。这里每一条都是"遇到 X 情况就停下来问自己"的反射动作。
|
||||
|
||||
| 触发场景 | 停下来问自己 |
|
||||
|---|---|
|
||||
| 要往一个已经很长的文件里追加代码时 | 这文件现在承担了几件事?新加的东西是已有职责的延伸,还是第 N+1 件事?是第 N+1 件就默认新建文件 |
|
||||
| 要给一个已经很多方法的类加方法时 | 新方法是这个类核心职责的自然扩展,还是把这个类推向"什么都能干"? |
|
||||
| 写的函数已经超过一屏时 | 这函数在做几件事?几件事就拆 |
|
||||
| 要加一个 `if (特殊情况) { 特殊处理 }` 分支时 | 是不是抽象维度选错了?正确的做法可能是把特殊路径和通用路径分成不同的函数 / 策略 / 类,而不是往现有代码里打补丁 |
|
||||
| 要 copy-paste 一段代码时 | 这段代码能抽成共用的,还是只是碰巧字面相似?能抽就抽 |
|
||||
| 要给一个函数加第 4+ 个参数时 | 这个函数在做的事情是不是太多了?参数列表是 API 恶化的早期信号 |
|
||||
| 要新写一个"万能工具类 / helper"时 | 这个东西真的没有归属吗?还是只是因为一时想不起来放哪儿,就先堆在 util 里? |
|
||||
|
||||
### 停下来之后
|
||||
|
||||
反射检查**只负责把问题提出来**,结论用户定。如果停下来想清楚后的动作(拆文件 / 新建文件 / 重命名 / 抽共用层)会让这次改动超出 `{slug}-checklist.yaml` 里现有步骤的范围,跟用户对齐再决定——要么纳入当前 feature / fix 的推进计划,要么记成顺手发现留到后续。
|
||||
|
||||
不许偷偷拆完继续写,也不许忽略信号硬冲。默认动作是停、问、再继续。
|
||||
Reference in New Issue
Block a user