Introduce dev-flow: lightweight 3-phase flow with decision archive
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
---
|
||||
name: dev-flow
|
||||
description: 轻量开发流程:想清楚 → 做出来 → 收好尾。编排 OpenSpec 的 propose / apply / archive 三个能力,并为每个非平凡变更留下 decision.md——记录为什么这么做、否决了哪些备选、代价是什么。在用户显式调用 /dev-flow,或明确要求走开发流程时使用。
|
||||
---
|
||||
|
||||
# Dev Flow
|
||||
|
||||
三个阶段,两个确认点,不分档。
|
||||
|
||||
```text
|
||||
Think 想清楚 → Build 做出来 → Close 收好尾
|
||||
⏸ 确认点 1 ⏸ 确认点 2
|
||||
授权进入实现 是否归档
|
||||
```
|
||||
|
||||
**每个非平凡变更留下一份 `decision.md`**——记录代码和规格承载不了的东西:**为什么这么做,以及放弃了什么。**
|
||||
|
||||
## 能力来源
|
||||
|
||||
dev-flow 编排已有能力,**不重复实现它们**:
|
||||
|
||||
| 阶段 | 能力 | 用途 |
|
||||
|---|---|---|
|
||||
| Think | `grill-with-docs` | 澄清:一次一问、能查代码的自己查、术语沉淀进 `CONTEXT.md` |
|
||||
| Think | `openspec-propose` | 生成 `proposal.md` / `design.md` / `specs/` / `tasks.md` |
|
||||
| Build | `openspec-apply-change` | 按规格实现 |
|
||||
| Build | `diagnose` / `tdd` | 按需:bug 排查 / 测试驱动 |
|
||||
| Close | `openspec-archive-change` | 归档 |
|
||||
|
||||
**按能力绑定,不按路径绑定**:优先用平台原生 skill;不可用时读本地 `SKILL.md` 并按其协议执行;仍不可用时按最小等价协议直接产出文件。**不可用时在 `decision.md` 里注明。**
|
||||
|
||||
**不使用 `to-prd`**:它把 PRD 发布到 issue tracker(本仓库没有),且内容与 `proposal.md` + `specs/` 重复。
|
||||
**不设 `audit` 阶段**:`zoom-out` 保留为按需能力(不熟悉代码区域时拉高视角),但它不是一个必须走的关卡。
|
||||
|
||||
### 冲突裁决
|
||||
|
||||
被组合的子 skill 与本流程会冲突——这是组合的固有代价。**靠规则裁决,不靠内置。**
|
||||
|
||||
> **子 skill 管"这一步怎么做";dev-flow 管"做多少、结果放哪"。**
|
||||
> **冲突时,流程赢。**
|
||||
|
||||
当前组合里,由 dev-flow 覆盖子 skill 默认的有三处:
|
||||
|
||||
| 子 skill 的默认 | dev-flow 的覆盖 |
|
||||
|---|---|
|
||||
| `grill-with-docs` 要求 relentlessly 追问 | **范围收窄**:只问答案会改变产物的问题 |
|
||||
| ADR 写入 `docs/adr/`,用 `ADR-FORMAT.md` | **落点改为 `decision.md`**,格式用 `decision-note.md`,**不创建 `docs/adr/`** |
|
||||
| 假设根目录 `CONTEXT.md` | 用 **`devflow/glossary/CONTEXT.md`** |
|
||||
|
||||
**归属规则解决不了的冲突,不要靠内置解决,而是不组合它。**
|
||||
|
||||
> 理由:内置只在被组合 skill **消失**时才消除冲突。只要它还装在目录里(用户可以直接调用),
|
||||
> 内置就只是让 dev-flow 多出一份**会漂移的私有副本**——重复实现加上版本漂移,两个问题。
|
||||
> `to-prd` 就是这么处理的:直接排除,而不是改造成 dev-flow 的版本。
|
||||
|
||||
## Think — 想清楚
|
||||
|
||||
**进入**:用户给出需求——粗略想法、issue、草稿、已有 PRD 都算。
|
||||
|
||||
**动作**:
|
||||
|
||||
1. **澄清** —— 用 `grill-with-docs` 的方法,但按上面的 **「冲突裁决」** 覆盖它的默认:
|
||||
范围收窄(只问答案会改变产物的问题)、ADR 落点为 `decision.md`、`CONTEXT.md` 用 `devflow/glossary/` 下那份。
|
||||
2. **读上下文**:`devflow/glossary/CONTEXT.md`,并搜索 `devflow/rejected/` 与已归档的 `decision.md`——
|
||||
**避免重新提出已经被否决过的方案。**
|
||||
3. 写 `openspec/changes/<slug>/proposal.md`,并用 OpenSpec 补全 `design.md` / `specs/` / `tasks.md`。
|
||||
4. **写下 `decision.md` 的 `## Problem` 和 `## Alternatives considered`。**
|
||||
理由在这一刻最新鲜;留到事后补写会变成回忆录。
|
||||
|
||||
**退出**:proposal 能说清做什么、范围、非目标;`decision.md` 有 `## Problem` 和至少一条备选(或用 `<!-- alternatives-not-recorded -->` 显式声明没有)。
|
||||
|
||||
**⏸ 确认点 1** —— 向用户汇报方案方向、关键假设、主要风险,然后**等待明确的实现授权**。
|
||||
|
||||
> 未获授权不得进入 Build。
|
||||
> **方案讨论中的任何一次确认,都不等于实现授权。**
|
||||
|
||||
## Build — 做出来
|
||||
|
||||
**进入**:确认点 1 已过。
|
||||
|
||||
**动作**:
|
||||
|
||||
- 按 `tasks.md` 的纵向切片实现,按 `specs/` 验收。
|
||||
- **分步验证**:每完成一层再继续,不要一次写完再验。
|
||||
- **冲突先分类再处理**:
|
||||
|
||||
| 分类 | 处理 |
|
||||
|---|---|
|
||||
| 规格不准(遗漏、边界未覆盖、验收口径缺失) | 暂停,修正 OpenSpec,再继续 |
|
||||
| 代码偏离(实现没按规格做) | 修正代码,不改 OpenSpec |
|
||||
| 不确定、或涉及设计方向 | **暂停,问用户** |
|
||||
|
||||
- 遇到 bug 或行为不明 → 用 `diagnose`;需要测试驱动 → 用 `tdd`。两者都不强制。
|
||||
|
||||
**退出**:tasks 完成或剩余已明确记录;已运行验证,或记录了未验证的原因;已知限制已列出。
|
||||
|
||||
Build 结束**自动进入 Close**,中间不设确认点。
|
||||
|
||||
## Close — 收好尾
|
||||
|
||||
**进入**:实现达到可交接状态。
|
||||
|
||||
**动作**:
|
||||
|
||||
1. **补齐 `decision.md`**——把 `## Decision` 校准为**实际发布的做法**(现在时),补 `## Consequences` 和 `## Verification`。
|
||||
2. **执行收尾检查**(见下)。
|
||||
3. 有新术语 → 更新 `devflow/glossary/CONTEXT.md`。
|
||||
4. 有被否决的提案 → 写入 `devflow/rejected/<class>/`。
|
||||
5. **⏸ 确认点 2** —— 汇报产物、验证情况、剩余风险,询问是否归档。
|
||||
|
||||
**退出**:`decision.md` 五节齐全;收尾检查通过;用户已被询问是否归档。
|
||||
|
||||
## 核心规则
|
||||
|
||||
| 规则 | 说明 |
|
||||
|---|---|
|
||||
| **必须写 `decision.md`** | 每个非平凡变更 |
|
||||
| **`## Alternatives considered` 强制** | 没有记录"打败了什么"的决策会招来重新争论 |
|
||||
| **备选是记录的,不是编造的** | 当时没记录就写 `<!-- alternatives-not-recorded -->` |
|
||||
| **实现前必须有授权** | 确认点 1 |
|
||||
| **冲突先分类再处理** | 三分法 |
|
||||
| **一个事实只有一个权威** | 见下表 |
|
||||
|
||||
**"非平凡"的判据**:改变行为、架构、跨文件或跨包的契约、流程或工具、测试策略、磁盘/线缆/配置格式,或其他维护者可能重新考察的决策。
|
||||
**豁免**:纯机械或局部编辑。
|
||||
|
||||
### 事实的唯一权威
|
||||
|
||||
| 内容 | 权威 |
|
||||
|---|---|
|
||||
| 为什么这么做、放弃了什么、代价 | `decision.md` |
|
||||
| 实现设计、接口影响 | `design.md` |
|
||||
| 可观察行为、验收场景 | `specs/` |
|
||||
| 执行切片与完成状态 | `tasks.md` |
|
||||
| 跨项目术语 | `devflow/glossary/CONTEXT.md` |
|
||||
| 未实施的提案 | `devflow/rejected/` |
|
||||
|
||||
**任何一句话只能在一个地方是权威。出现第二处,就是错**——两边会各自腐化,而且没人知道以哪边为准。
|
||||
|
||||
## 为什么这么轻
|
||||
|
||||
这三条是有意为之。**不要"补全"它们。**
|
||||
|
||||
1. **义务挂在已有动作上。** 写规划产物的时刻,就是写 `decision.md` 的时刻。不设独立的归档阶段,不做事后提取。
|
||||
2. **确认点只有两个。** 进入实现、是否归档。不新增。
|
||||
3. **"是否该写"是判断。** 规则 + 收尾看一眼。机器只校验**已经写下**的东西是否合规,不用脚本强制这件事本身。
|
||||
|
||||
## 收尾检查
|
||||
|
||||
1. `openspec/changes/<slug>/decision.md` 存在
|
||||
2. 含 `## Alternatives considered`,或显式的 `<!-- alternatives-not-recorded -->`
|
||||
3. `## Verification` 里没有"已确认 X 存在"这类**不可重跑的结论**
|
||||
|
||||
纯机械改动可以豁免。**豁免必须显式,但可以廉价**——目的是让"跳过"变成有意识的选择,而不是静默遗忘。
|
||||
|
||||
> **计划中的自动化**:`scripts/check-dev-flow.sh`,遵循仓库现有脚本约定(`scripts/*.sh`)。
|
||||
> 在它落盘之前,上面三步手动执行。
|
||||
|
||||
## 目录
|
||||
|
||||
```text
|
||||
openspec/changes/<slug>/
|
||||
├── proposal.md design.md specs/ tasks.md
|
||||
└── decision.md ← 人向:为什么、放弃了什么、代价
|
||||
↓ 随归档一起冻存
|
||||
|
||||
devflow/
|
||||
├── glossary/CONTEXT.md ← 跨项目术语
|
||||
├── rejected/<class>/ ← 未实施的提案
|
||||
└── index.md ← 由脚本扫描归档生成,不手写
|
||||
```
|
||||
|
||||
`rejected/` 的保留条件:它**仍能防止一个诱人的、有意义的错误**。否则整体删除。
|
||||
|
||||
## 触发规则
|
||||
|
||||
- 用户输入 `/dev-flow`。
|
||||
- 用户明确要求走开发流程。
|
||||
|
||||
不要因为任务涉及 OpenSpec、跨模块、架构决策或 devflow 目录就自动触发。
|
||||
未被这样要求之前,按普通工程任务处理。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- `references/phases.md` — 三阶段契约与判断细则
|
||||
- `references/decision-note.md` — `decision.md` 格式规范、校准案例、反模式
|
||||
- `skill-workbench/docs/dev-flow/background-and-evolution.md` — 背景、技术演进、设计取舍
|
||||
@@ -0,0 +1,230 @@
|
||||
# 决策档案格式
|
||||
|
||||
本文件定义 `decision.md` 的格式、每节的要求、校准案例和反模式。
|
||||
|
||||
## 骨架
|
||||
|
||||
```markdown
|
||||
# Decision: <一句话标题>
|
||||
|
||||
## Problem
|
||||
## Decision
|
||||
## Alternatives considered
|
||||
## Consequences
|
||||
## Verification
|
||||
```
|
||||
|
||||
小节顺序固定。固定顺序不是为了机器,是为了**人能跳转**——任何时候你想知道"代价是什么",往下翻到 `## Consequences` 就行。
|
||||
|
||||
节名是规范名,不要用近义词替代(`## 背景` / `## 方案` / `## 风险`)。
|
||||
需要额外内容时,在 `## Decision` 和 `## Alternatives considered` 之间插入自定义小节。
|
||||
|
||||
### 各节在哪个阶段写下
|
||||
|
||||
| 节 | 写下时机 | 原因 |
|
||||
|---|---|---|
|
||||
| `## Problem` | **Think** | 动机在需求刚澄清时最准确 |
|
||||
| `## Alternatives considered` | **Think** | 备选是在方案讨论中被否决的,当时记最真实;事后补写会变成回忆录 |
|
||||
| `## Decision` | Think 记意图,**Close 校准为事实** | 见下 |
|
||||
| `## Consequences` | **Close** | 代价要等实现完才知道 |
|
||||
| `## Verification` | **Close** | 验证要跑过才能写成可重跑的命令 |
|
||||
|
||||
**`## Decision` 的两段式**:Think 时写"打算怎么做",Close 时校准为"实际做了什么"。
|
||||
|
||||
**如果两者不一致,不要静默改写。** 把差异写进正文——计划与现实的偏差,本身往往是最有价值的一条决策信息。
|
||||
|
||||
---
|
||||
|
||||
## 逐节要求
|
||||
|
||||
### `## Problem` —— 动机
|
||||
|
||||
**要求**:必须能**脱离方案独立成立**。读者只读这一节,就该明白为什么值得做。
|
||||
|
||||
**反模式**:
|
||||
|
||||
| 反模式 | 为什么不行 |
|
||||
|---|---|
|
||||
| 在 Problem 里提到方案名或实现手段 | 循环论证——说明动机没想清,只是把方案重述了一遍 |
|
||||
| 写成"当前代码的缺陷清单" | 那是 bug 报告,不是动机 |
|
||||
| 一句话带过 | 读者无法判断这个决策是否还成立 |
|
||||
|
||||
**自检**:把 `## Decision` 整节删掉,`## Problem` 还读得通吗?读不通就重写。
|
||||
|
||||
### `## Decision` —— 做法
|
||||
|
||||
**要求**:现在时,描述**已经采用的做法**。如果变更还在进行中,写"将要采用的做法"并保持它随后更新为事实。
|
||||
|
||||
**反模式**:
|
||||
|
||||
- 写成任务清单(那是 `tasks.md`)
|
||||
- 复述 `design.md` 的实现细节(那是 `design.md`)
|
||||
- 用"我们计划"而不说"我们决定"
|
||||
|
||||
### `## Alternatives considered` —— 备选(强制)
|
||||
|
||||
**要求**:每个**真实存在过**的备选一段,加粗开头,说明它**为什么输了**。
|
||||
|
||||
```markdown
|
||||
**新增 year 字段到条目数据。** 冗余且需要同步维护——`date` 已是唯一来源,
|
||||
派生成本为零,多一个字段就多一处会不一致的地方。
|
||||
```
|
||||
|
||||
**反模式**:
|
||||
|
||||
| 反模式 | 为什么不行 |
|
||||
|---|---|
|
||||
| **稻草人备选** | 编一个明显更差的选项来凑数。这会让真实读者对整个文档失去信任 |
|
||||
| 只列备选,不说为什么输 | 等于没写——读者无法判断它现在是否仍然输 |
|
||||
| 把"什么都不做"当默认备选 | 除非当时真的认真考虑过维持现状,否则它只是修辞 |
|
||||
| 备选写成一堆标签 | 没有推理链,未来无法复用 |
|
||||
|
||||
**"什么都不做"什么时候是真的备选**:当维持现状确实是一个被权衡过的选项时(例如"暂不修复这个边界,先观察")。
|
||||
|
||||
**没有可记录的备选时**,写这一行注释而不是编造:
|
||||
|
||||
```markdown
|
||||
<!-- alternatives-not-recorded -->
|
||||
```
|
||||
|
||||
宁可承认"当时没记录",也不许发明一个假备选。**读者读到一条备选时,必须能相信它真的发生过。**
|
||||
|
||||
### `## Consequences` —— 代价
|
||||
|
||||
**要求**:同时写清**买到了什么**和**付出了什么**。包含已知限制。
|
||||
|
||||
**反模式**:
|
||||
|
||||
- 只写收获(那是营销文案,不是档案)
|
||||
- 不写已知限制("目前不支持 X")
|
||||
- 不写被放弃的能力
|
||||
|
||||
**这是全文第二有价值的一节。** 未来维护者最常需要判断的正是"这个代价现在还能接受吗"。
|
||||
|
||||
### `## Verification` —— 验证
|
||||
|
||||
**要求**:写**可重跑的命令**,或**明确的人工步骤**。并且**标明哪些是只读的、哪些有副作用**。
|
||||
|
||||
```markdown
|
||||
**只读(可直接跑)**
|
||||
- `grep -c 'id="year-filter"' knowledge-index.html` → 1
|
||||
- `bash -n scripts/update-knowledge-index.sh` → exit=0
|
||||
|
||||
**有副作用(会重写文件,收尾时不必跑)**
|
||||
- `bash scripts/update-knowledge-index.sh`,然后复跑上面两条
|
||||
|
||||
**人工**
|
||||
- 选择 2026,只显示 date 以 2026 开头的条目
|
||||
```
|
||||
|
||||
**为什么必须分**:收尾检查发生在变更即将落地的时候,**那时最不愿意再改文件**。如果把最有说服力的验证写成有副作用的命令,执行者只有两个选择——跑(有风险)或者跳(失去验证)。
|
||||
分开之后,只读的那部分**每次都能跑**。
|
||||
|
||||
**反模式**:
|
||||
|
||||
| 反模式 | 为什么不行 |
|
||||
|---|---|
|
||||
| `已确认年份筛选控件存在` | **结论不可重跑**。三个月后没人知道当时确认了什么 |
|
||||
| `手动测试一下` | 不是步骤,是托付 |
|
||||
| 只写"测试通过" | 哪个测试?覆盖率多少? |
|
||||
| 只读命令与有副作用命令混在一起 | 执行者要么全跑(有风险),要么全不跑(失去验证) |
|
||||
|
||||
**判据**:换一个人拿着这一节,能不能在 5 分钟内重跑一遍——**而且不必担心它改坏什么?**
|
||||
|
||||
---
|
||||
|
||||
## 校准案例
|
||||
|
||||
校准判断用真实案例,**不用字数阈值**。字数从来不是标准。
|
||||
|
||||
### 值得写的备选(真实)
|
||||
|
||||
来自 `devflow/projects/2026-05-18-knowledge-index-panel/adr/0001-directory-name-as-truth-source.md`:
|
||||
|
||||
```markdown
|
||||
## 替代方案
|
||||
|
||||
| 方案 | 被拒原因 |
|
||||
|------|---------|
|
||||
| YAML 全优先 | 字段名不一致(date vs created) |
|
||||
| 目录名全优先 | 标题中的语义信息在下划线转空格后丢失 |
|
||||
```
|
||||
|
||||
只有 39 行,但它是本仓库 37 篇档案里**唯一**记录了备选的一篇——也是唯一读完之后还记得住内容的一篇。
|
||||
|
||||
**注意它的形式**:两条备选,每条一句被拒理由,没有废话。**短不等于差。**
|
||||
|
||||
### 应当补录备选(真实)
|
||||
|
||||
`openspec/changes/add-year-filter/` 那次变更,实际发生过两条备选,但一条都没记:
|
||||
|
||||
```markdown
|
||||
## Alternatives considered
|
||||
|
||||
**引入第三方筛选组件(Select2 等)。** 为 4 行原生 `<select>` 代码引入依赖,
|
||||
与仓库"单文件静态 HTML"的约束冲突。
|
||||
|
||||
**只改 knowledge-index.html,不改生成脚本。** 更快,但重建即丢功能——
|
||||
生成脚本才是真理源,这条诱惑在本次实现中差点导致返工。
|
||||
```
|
||||
|
||||
第二条特别值得记:**它在现有的 `design.md` 里其实被写成了"架构审计:主要风险是……"**。
|
||||
风险的痕迹在,但它没有被记成一条可查、可复用的决策。**这就是备选被浪费的典型形态。**
|
||||
|
||||
### 备选的粒度
|
||||
|
||||
一条备选**值得记录**当且仅当:**它现在仍然可能被重新提出。**
|
||||
|
||||
- "用 X 库"—— 如果 X 库还在、还流行,值得记
|
||||
- "用某个已下线的内部服务"—— 除非它是诱人的错误,否则不必记
|
||||
|
||||
---
|
||||
|
||||
## 与 ADR 的关系:`decision.md` 就是它
|
||||
|
||||
**本仓库不另建 `adr/` 目录。`decision.md` 承担 ADR 的角色**——它的骨架(Problem / Decision / Alternatives considered / Consequences)本来就是 ADR 的形态。
|
||||
|
||||
`grill-with-docs` 会在同时满足三个条件时提议创建 ADR:
|
||||
|
||||
1. **难以逆转** —— 以后改主意的代价可观
|
||||
2. **缺少上下文会令人困惑** —— 未来读者会想"他们为什么这么做?"
|
||||
3. **源自真实权衡** —— 确实存在备选,并且有具体理由选了其中一个
|
||||
|
||||
**在本流程里,这个提议的落点是 `decision.md`,不是 `docs/adr/` 或 `devflow/*/adr/`。**
|
||||
|
||||
> **不要同时产出两份。** 同一决策只有一个权威——两份文档必然各自腐化,而且没人知道以哪边为准。
|
||||
|
||||
当一个变更**只**满足部分条件(很日常、并不难逆转),仍然要写 `decision.md`——它是每个非平凡变更的义务。
|
||||
**ADR 三条件在这里的作用,是判断这篇笔记值不值得写深,而不是判断要不要写。**
|
||||
|
||||
---
|
||||
|
||||
## 与 DSH Agent Notes 的差异
|
||||
|
||||
本格式参考了 DeepSeek Harness 的 `.agents/notes/` 范式,但有三处**简化**,原因是本仓库的约束不同:
|
||||
|
||||
| | DSH Agent Notes | 本协议 | 为什么 |
|
||||
|---|---|---|---|
|
||||
| 生命周期 | 路径含 `{lifecycle}/{class}/`,需手动移动 | **路径由 OpenSpec 表达**(在 `changes/` = 进行中,在 `archive/` = 已完成) | 文件随 change 一起走,不需要自己维护生命周期 |
|
||||
| 词汇表 | `proposed/` 与 `implemented/` 有**两套不同的合法小节名**,由 gate 强制 | **单一骨架** | 两套骨架需要一次"翻转"动作,而翻转要靠记得;单骨架零维护 |
|
||||
| 多语言 | en + zh + `i18n.yaml` 三元组 + 哈希 | **单语** | 那是公开仓库的需求;本仓库少两个文件 |
|
||||
| `Status:` 行 | 强制,且与目录交叉校验 | **不需要** | 路径已经表达了状态,不引入需要同步的冗余字段 |
|
||||
|
||||
**保留自 DSH 的**:强制备选、反稻草人规则("recorded, never invented")、以真实案例校准而非阈值、冻结归档不当作当前权威。
|
||||
|
||||
**可选的升级路径**:如果将来发现"计划写在 `decision.md` 里但从未更新为事实"这个问题反复出现,
|
||||
可以引入 DSH 的两套骨架(`## Proposal` → `## Decision`),代价是需要一个收尾步骤负责翻转。
|
||||
在观察到这个问题之前不引入。
|
||||
|
||||
---
|
||||
|
||||
## 交付前自检
|
||||
|
||||
写完 `decision.md` 后,逐条对照:
|
||||
|
||||
- [ ] 删掉 `## Decision`,`## Problem` 还读得通吗?
|
||||
- [ ] `## Alternatives considered` 里的每一条,**当时真的被考虑过**吗?
|
||||
- [ ] 每条备选都写了**为什么输**吗?
|
||||
- [ ] `## Consequences` 同时写了收获和代价吗?
|
||||
- [ ] `## Verification` 里的每一项,换个人能在 5 分钟内重跑吗?
|
||||
- [ ] 有没有一句话在两个地方都是权威?(有就是错)
|
||||
@@ -0,0 +1,130 @@
|
||||
# 三阶段契约
|
||||
|
||||
本文件是三阶段的判断细则。**它只规定"怎么判断",不新增检查点**——检查只有收尾那一次。
|
||||
|
||||
---
|
||||
|
||||
## Think — 想清楚
|
||||
|
||||
### 澄清:借用 grill-with-docs,但收窄范围
|
||||
|
||||
**方法来自 `grill-with-docs`** —— 一次只问一个问题并等待回答、能通过探索代码回答的自己去探索、术语确认后立即写入 `CONTEXT.md`。这些不在这里重复。
|
||||
|
||||
**范围由本流程收窄**:
|
||||
|
||||
> `grill-with-docs` 自身的取向是 "interview me **relentlessly** … until we reach a shared understanding"。
|
||||
> **relentless 是对问题质量的,不是对数量的。**
|
||||
> 只问**答案会改变** `proposal.md` / `specs/` / `tasks.md` 的问题;不会改变产物的疑问,自己判断即可。
|
||||
|
||||
**先自己查证,再问用户。** 查证时格外看两处——它们专门用来避免重复劳动:
|
||||
|
||||
1. 搜 `devflow/rejected/` —— 这个方案是不是已经被否决过?
|
||||
2. 搜已归档的 `decision.md` —— 相关决策的历史理由是什么?
|
||||
3. 读相关代码 / 配置 / 测试;看 `openspec/specs/` 有没有既有规格
|
||||
4. **能复现的问题先复现**——一次成功的复现比一轮追问更有信息量
|
||||
|
||||
**什么时候算够**:你能写出一份 proposal,别人读了知道要做什么、不做什么。**没有"至少 N 个问题"的要求**——问题数不是质量指标。
|
||||
|
||||
### 上下文读取顺序
|
||||
|
||||
```text
|
||||
devflow/glossary/CONTEXT.md ← 术语,先对齐语言
|
||||
devflow/rejected/ ← 有没有被否决过的相似方案
|
||||
已归档的 decision.md ← 有没有相关的历史决策
|
||||
openspec/specs/ ← 相关的既有能力规格
|
||||
```
|
||||
|
||||
**第二步和第三步最重要。** 一个已经被否决过的方案,如果你不知道,就会重新提出一遍、重新争论一遍——这正是决策档案存在的理由。
|
||||
|
||||
### 确认点 1 的汇报格式
|
||||
|
||||
**向用户汇报时不超过 10 行:**
|
||||
|
||||
- 方案方向(1–2 句)
|
||||
- 关键假设(没有验证、但方案依赖它的部分)
|
||||
- 主要风险
|
||||
- **放弃的备选**(1–2 条,连同为什么)
|
||||
- 请求实现授权
|
||||
|
||||
**不要**复述 proposal、不要列产物清单、不要贴对齐表格。用户要的是判断依据,不是工作汇报。
|
||||
|
||||
---
|
||||
|
||||
## Build — 做出来
|
||||
|
||||
### 分步实现与验证
|
||||
|
||||
按 `tasks.md` 的纵向切片推进。**每完成一层先验证,再进下一层**——一次写完再验,出了问题无法定位是哪一层。
|
||||
|
||||
第一个切片完成后,对照 `specs/` 检查一次:验收场景是否真的成立。**规格写得含糊会在这里第一次暴露。**
|
||||
|
||||
### 冲突三分法的判断细则
|
||||
|
||||
先分类,再动手。分类的错误比不分类更糟。
|
||||
|
||||
**怎么区分"规格不准"和"代码偏离"**:问一句——**"如果完全按规格做出来,行为对不对?"**
|
||||
|
||||
| 回答 | 分类 | 处理 |
|
||||
|---|---|---|
|
||||
| 对,但我没按规格做 | **代码偏离** | 改代码,不动 OpenSpec |
|
||||
| 不对,规格本身就写错了 | **规格不准** | 暂停,改 OpenSpec,再继续 |
|
||||
| 说不清 / 涉及设计方向 | **不确定** | 暂停,问用户 |
|
||||
|
||||
**"不确定"这一类必须真的停下来问。** 判断设计方向是用户的权力,不是 agent 可以代劳的——
|
||||
把设计问题当成实现问题自行消化,是返工最常见的来源。
|
||||
|
||||
冲突的分类、证据和处置结果写进 `decision.md` 的正文。
|
||||
|
||||
---
|
||||
|
||||
## Close — 收好尾
|
||||
|
||||
### 补齐 decision.md
|
||||
|
||||
Think 阶段已经写下了 `## Problem` 和 `## Alternatives considered`。Close 要补的是后三节:
|
||||
|
||||
**`## Decision`** —— 校准为**实际发布的做法**(现在时)。
|
||||
|
||||
> Think 时写的是"打算怎么做",Close 要把它改成"实际做了什么"。
|
||||
> **如果两者不一致,不要偷偷改成后者**——把差异写出来,它本身就是有价值的决策记录。
|
||||
|
||||
**`## Consequences`** —— 必须同时写**收获**和**代价**,包括已知限制。
|
||||
|
||||
只写收获的是营销文案,不是档案。未来维护者最需要判断的,恰恰是"这个代价现在还接受得了吗"。
|
||||
|
||||
**`## Verification`** —— 写成**可重跑的命令**或**明确的人工步骤**。
|
||||
|
||||
| 不写 | 写 |
|
||||
|---|---|
|
||||
| 已确认年份筛选控件存在 | `grep -c 'year-filter' knowledge-index.html` → ≥1 |
|
||||
| 手动测试一下 | 选择 2026,只显示 date 以 2026 开头的条目 |
|
||||
|
||||
判据:换一个人拿着这一节,能不能在 5 分钟内重跑一遍?
|
||||
|
||||
格式细则与校准案例见 `decision-note.md`。
|
||||
|
||||
### 收尾检查
|
||||
|
||||
三步,一次做完:
|
||||
|
||||
1. `decision.md` 存在
|
||||
2. 含 `## Alternatives considered`,或显式的 `<!-- alternatives-not-recorded -->`
|
||||
3. `## Verification` 里没有不可重跑的结论
|
||||
|
||||
**豁免**:纯机械或局部编辑(不改变行为、契约、结构、流程或理由)。豁免要**显式**——在 `decision.md` 或提交信息里写出来,让"跳过"是有意识的选择。
|
||||
|
||||
---
|
||||
|
||||
## 中断与恢复
|
||||
|
||||
**流程状态全部在文件里,不依赖对话记忆。** 换会话、隔天继续时,按下面的顺序读一下就知道停在哪:
|
||||
|
||||
| 观察到 | 当前在 |
|
||||
|---|---|
|
||||
| 没有 `openspec/changes/<slug>/` | Think 之前 |
|
||||
| 有 `proposal.md`,但 `decision.md` 缺 `## Problem` | Think 进行中 |
|
||||
| 有 `proposal.md` 和 `decision.md`,但没有实现授权 | **确认点 1** |
|
||||
| 有实现,但 `decision.md` 缺 `## Decision` / `## Consequences` / `## Verification` | Close 进行中 |
|
||||
| `decision.md` 五节齐全 | 收尾检查 + 确认点 2 |
|
||||
|
||||
**恢复时不重新提问已经解决的问题。** 先读 `decision.md` 和 `proposal.md`——已经确认过的内容就在里面。
|
||||
Reference in New Issue
Block a user