Harden dev-flow: pre-authorization marker, alternatives log, check script

- Record rejected answers in decision.md at the moment they are rejected

- Allow explicit pre-authorized Build via a pre-authorized marker line

- Land scripts/check-dev-flow.sh and derive devflow/index.md from archives

- Add dev-flow process artifacts (decisions, prd) for open changes
This commit is contained in:
zhuyongxin
2026-09-18 18:23:18 +08:00
parent d607861c6a
commit 24a71e78f1
14 changed files with 528 additions and 31 deletions
@@ -24,7 +24,8 @@
| 节 | 写下时机 | 原因 |
|---|---|---|
| `## Problem` | **Think** | 动机在需求刚澄清时最准确 |
| `## Alternatives considered` | **Think** | 备选是在方案讨论中被否决的,当时记最真实;事后补写会变成回忆录 |
| `## Alternatives considered` | **Think**,grill 问答当场 | 备选是在方案讨论中被否决的,当时记最真实;事后补写会变成回忆录 |
| `<!-- pre-authorized: ... -->` | **Think 退出时**(仅预授权场景) | 授权状态的文件载体,恢复会话时以它为准 |
| `## Decision` | Think 记意图,**Close 校准为事实** | 见下 |
| `## Consequences` | **Close** | 代价要等实现完才知道 |
| `## Verification` | **Close** | 验证要跑过才能写成可重跑的命令 |
@@ -65,6 +66,19 @@
**要求**:每个**真实存在过**的备选一段,加粗开头,说明它**为什么输了**。
**首选形态是压缩 Q&A——一行一条**。grill 问答中被否决的答案,就是备选;当场一行记下,转写成本接近零:
```markdown
## Alternatives considered
- Q: 上完整 BM25 schema? A: 不——先 sparse-lite + RRF,schema 重建是后续变更。
- Q: 默认用 hybrid? A: 不——dense 默认,hybrid 显式 opt-in。
```
(SuperBizAgent 实测:180 个档案文件里,段落式备选记录率为 0;唯一自然发生的高质量备选记录就是这个 Q&A 形态。)
**值得写深时**(难以逆转的架构决策)才展开成段落,并要求写出推理链:
```markdown
**新增 year 字段到条目数据。** 冗余且需要同步维护——`date` 已是唯一来源,
派生成本为零,多一个字段就多一处会不一致的地方。
@@ -78,6 +92,7 @@
| 只列备选,不说为什么输 | 等于没写——读者无法判断它现在是否仍然输 |
| 把"什么都不做"当默认备选 | 除非当时真的认真考虑过维持现状,否则它只是修辞 |
| 备选写成一堆标签 | 没有推理链,未来无法复用 |
| **段落式凑字数** | Q&A 一行能说清的,不要为了"看起来正式"展开成三段 |
**"什么都不做"什么时候是真的备选**:当维持现状确实是一个被权衡过的选项时(例如"暂不修复这个边界,先观察")。
@@ -146,7 +161,7 @@
| 方案 | 被拒原因 |
|------|---------|
| YAML 全优先 | 字段名不一致(date vs created) |
| YAML 全优先 | 字段名不一致(date vs created) |
| 目录名全优先 | 标题中的语义信息在下划线转空格后丢失 |
```
@@ -154,6 +169,20 @@
**注意它的形式**:两条备选,每条一句被拒理由,没有废话。**短不等于差。**
### 值得写深的备选(真实)
SuperBizAgent 的 `phase1-infrastructure/decisions.md` ADR-001(Flyway):
```markdown
### 后果
- 表结构修改必须通过 SQL 迁移脚本
- 开发环境首次启动需要执行 Flyway 迁移
- 生产环境部署自动执行未执行的迁移脚本
```
难以逆转的基础设施决策,后果写得具体到"改表必须走迁移脚本"——三个月后最需要读的就是这几行。
**这是 Q&A 一行记不住的那种备选,值得整段。**
### 应当补录备选(真实)
`openspec/changes/add-year-filter/` 那次变更,实际发生过两条备选,但一条都没记:
+13 -4
View File
@@ -16,7 +16,7 @@
> **relentless 是对问题质量的,不是对数量的。**
> 只问**答案会改变** `proposal.md` / `specs/` / `tasks.md` 的问题;不会改变产物的疑问,自己判断即可。
**先自己查证,再问用户。** 查证时格外看两处——它们专门用来避免重复劳动:
**先自己查证,再问用户。** 查证时格外看四处——前两处专门用来避免重复劳动:
1. 搜 `devflow/rejected/` —— 这个方案是不是已经被否决过?
2. 搜已归档的 `decision.md` —— 相关决策的历史理由是什么?
@@ -44,10 +44,12 @@ openspec/specs/ ← 相关的既有能力规格
- 关键假设(没有验证、但方案依赖它的部分)
- 主要风险
- **放弃的备选**(1–2 条,连同为什么)
- 请求实现授权
- 请求实现授权(或记录 `<!-- pre-authorized: 日期 + 范围/原因 -->`)
**不要**复述 proposal、不要列产物清单、不要贴对齐表格。用户要的是判断依据,不是工作汇报。
**pre-authorized 是显式旁路,不是默认。** 它适合用户已在对话中明确说"直接做"的快节奏场景。写它 = 承认确认点被有意识地跳过;不写而直接进 Build = 违规。授权状态的唯一载体是这行标记——恢复会话时以它为准。
---
## Build — 做出来
@@ -58,6 +60,12 @@ openspec/specs/ ← 相关的既有能力规格
第一个切片完成后,对照 `specs/` 检查一次:验收场景是否真的成立。**规格写得含糊会在这里第一次暴露。**
### 参考实现先读,再动手
`tasks.md` / `design.md` 点名"参考 XXX 实现"的,**实现前完整读它**。路径不明确时按类名/模式 Grep 定位。
设计文档点名参考而实现时没看,是返工最常见的来源(SuperBizAgent 复盘:山东商客接口因此返工 4-5 次)。
第一次在某区域写代码、或要用项目现有基础设施(MQ/统一请求结构/工具类)时,同此处理。
### 冲突三分法的判断细则
先分类,再动手。分类的错误比不分类更糟。
@@ -123,8 +131,9 @@ Think 阶段已经写下了 `## Problem` 和 `## Alternatives considered`。Clos
|---|---|
| 没有 `openspec/changes/<slug>/` | Think 之前 |
| 有 `proposal.md`,但 `decision.md` 缺 `## Problem` | Think 进行中 |
| 有 `proposal.md` 和 `decision.md`,但没有实现授权 | **确认点 1** |
| 有实现,但 `decision.md` 缺 `## Decision` / `## Consequences` / `## Verification` | Close 进行中 |
| 有 `proposal.md` 和 `decision.md`,但没有 `<!-- pre-authorized` 也没有对话中的明确授权 | **确认点 1** |
| 有 `<!-- pre-authorized: ... -->` 或已获授权,实现未完成 | Build 进行中 |
| 实现完成,`decision.md` 缺 `## Decision` / `## Consequences` / `## Verification` | Close 进行中 |
| `decision.md` 五节齐全 | 收尾检查 + 确认点 2 |
**恢复时不重新提问已经解决的问题。** 先读 `decision.md` 和 `proposal.md`——已经确认过的内容就在里面。