harden and streamline sm-flow protocol

This commit is contained in:
zhuyongxin
2026-05-25 11:44:20 +08:00
parent 54741dd6c0
commit 1f01e30c4e
20 changed files with 1102 additions and 88 deletions
@@ -0,0 +1,208 @@
# SM Flow 首次执行回顾
**日期**:2026-05-21
**变更**:[ops-message-support](projects/2026-05-21-ops-message-support/) — 站内消息新增 OMC 支持
**目的**:以本次交互为例,逐阶段复盘实际执行与 SM Flow 预期的差距,作为后续执行的改进依据。
---
## Phase 0 — 入口澄清
### 应该做的
- 收集问题、期望结果、目标用户、涉及代码区域、约束条件
- 输出入口摘要、slug、规模分档
### 实际做的
- 用户输入需求后,直接开始读代码和查数据库
- 输出了 slug(`ops-message-support`)和分档(micro)
### 没做到的
- 没有输出入口摘要(清晰的 1-2 句话问题 + 1-2 句话期望结果)
- 没有列已知影响代码或模块清单
### 改进建议
- Phase 0 结束时花 1 分钟写 3-5 行入口摘要到 `brief.md`,而不是等用户问再补
---
## Phase 0.5 — Devflow 上下文收集
### 应该做的
- 初始化 devflow 目录结构
- 读取 glossary、ADR、历史项目
- 形成上下文摘要写入 brief.md
### 实际做的
- 等用户质疑 devflow 无产物时才在 Phase 2.9 补创建
### 没做到的
- ❌ **没有在 Phase 0.5 创建 devflow 项目目录和任何文件**
- 没检查 glossary(当时为空也正常,但应该初始化和告知)
### 改进建议
- 进入 Phase 0.5 就执行 `mkdir devflow/projects/{slug}/` 并创建 `brief.md` 骨架
- Devflow 是"思考记录"不是"文档任务",哪怕只写 3 行也比事后补强
---
## Phase 1 — OpenSpec propose
### 应该做的
- 声明"本阶段调用 openspec-propose skill"
- 如果不可用,降级为 fallback 并说明原因
- 产出 proposal / design / specs / tasks
### 实际做的
- 调用了 `openspec new change` 创建了 change 目录
- openspec CLI 模板不匹配时报错,**没有声明降级**,直接手动创建文件
- 手动创建了 research、proposal、design、specs、tasks
### 没做到的
- ❌ **没有声明"openspec CLI 模板不匹配,降级为 manual fallback"**
- ❌ **没有区分 Draft OpenSpec 和 Committed OpenSpec**(两者在流程中意义不同)
- 产出顺序按了 research-first schema,但未验证 artifacts 间的依赖一致性
### 改进建议
- Skill 不可用时必须说清楚:什么 skill + 什么原因不可用 + 降级方式
- Draft OpenSpec 阶段标记为 draft,和 Committed OpenSpec 区分
---
## Phase 1.5 — PRD / OpenSpec 对齐
### 应该做的
- 检查 proposal 是否覆盖 research 范围
- 检查 design 是否满足 proposal 承诺的能力
- 检查接口影响等级(L1-L4)
### 实际做的
- **直接跳过**,没有做任何 formal 的对齐检查
### 没做到的
- ❌ 对齐检查完全缺失
- 后果:proposal.md 漏了 type 字段,design.md 和 research.md 都已包含但 proposal 没更新,直到用户 review 才发现
### 改进建议
- 即使 micro 模式,至少做一次快速交叉检查:research 范围 ↔ proposal 变更 ↔ design 决策 ↔ specs 场景
---
## Phase 2 — Human-in-the-loop 澄清
### 应该做的
- 声明"本阶段调用 grill-with-docs skill",按结构化方式追问
- 至少覆盖术语、边界、验收三个维度
- evidence-driven 的先查证再汇报
- user-interview 的**一次只问一个问题**,等用户确认后再问下一个
- 用户确认后回写 OpenSpec
- 对模糊的术语(如"运管")通过 grill 确认其准确定义
### 实际做的
- **没有调用 grill-with-docs** ❌
- **一次问了 3 个 user-interview 问题**,违反规则 ❌
- 收集了充分的 evidence(代码和数据库分析到位)✓
- 用户确认后及时回写了 OpenSpec ✓
### 没做到的
- ❌ 没有使用 grill 或任何结构化追问工具,自己随意问了几个问题
- ❌ 一次多问被用户 reject
- 问题数量太少:只用了 3 个问题(编码、子分类、字段范围),远不足以覆盖所有盲区
- 以下该问但没有问的问题:
- OMC 消息从哪里发送?通过什么 identifier/messageCode 触发投递?
- OMC 用户侧的权限体系是怎样的?和 APP 用户在同一张权限表吗?
- OMC 前端需要怎样的响应结构?只要总数还是要子分类列表?
- 现有 APP 端有 hasUnread/readAll 等功能,OMC 端是否也需要?
- OMC 消息的创建时间和保留策略?
- "运管"这个概念从一开始就模棱两可,没有通过 grilling 追根究底,到用户主动纠正为 OMC 时才明确
### 改进建议
- 必须调用 grill-with-docs,不调用就是跳过
- 问题数量下限:至少 5-8 个尝试性提问,覆盖:术语定义、发送来源、权限模型、前端需求、功能对标
- 一次一问,等回复后再继续
- 在 Phase 2 开始时创建 Task 跟踪 grill 进度:"Q1[术语]...→Q2[边界]...→Q3[验收]...",每问一个更新一次
---
## Phase 2.5 — 架构审计
### 应该做的
- 画出输入 → 处理 → 输出的模块链路
- 识别跨模块依赖、数据所有权、生命周期和耦合风险
- 用不超过五句话写出架构风险评估
- 影响实现的结论回写 OpenSpec design/tasks
### 实际做的
- **直接跳过**
- 做了代码分析但未输出正式的架构审计记录
### 没做到的
- ❌ 模块链路图缺失
- ❌ 接口影响分析表是用户追问后才补的
- ❌ listMessageCategory 泄漏 OMC 的问题在架构审计中本应发现,但跳过后留到了用户 review 才发现
### 改进建议
- Phase 2.5 至少画一张文本链路图:`User → Controller → Service → Mapper → DB`
- 然后问自己:新增的 type 字段会影响哪些链路节点?
---
## Phase 2.9 — Commit OpenSpec
### 应该做的
- 检查所有 artifacts 的一致性
- 检查所有 user-interview 都已确认
- 检查接口影响已记录
- 向用户汇报并请求 Phase 3 授权
### 实际做的
- 做了检查,但不够彻底(proposal 漏了 type)
- 接口影响分析是补的
- 汇报了,但用户先发现了 type 字段问题
### 没做到的
- 没能在用户发现问题前自己找出 proposal 遗漏
- 自检清单没有对照执行
### 改进建议
- Phase 2.9 不能光靠头脑检查,要逐行对比 research ↔ proposal ↔ design ↔ specs ↔ tasks 的关键断言
---
## Phase 3 — OpenSpec apply
尚未开始
---
## Phase 4 — 回填 Devflow
### 应该做的
- 验收记录
- 更新 devflow/index.md
- 询问是否归档 OpenSpec change
### 实际做的
- devflow 产物在用户要求下补创建
- index.md 在用户质疑后创建
### 改进建议
- Phase 4 的 devflow 产物应该是最轻松的,因为内容已经在各阶段产出过,只需要汇总
---
## 根因总结
### 约束是否到位?
SM Flow 的 rules 在 SKILL.md 和 reference 中写得很清楚。问题**不是约束不到位**,而是:
1. **高估了小改动的判断** — micro 分档让我误以为"可以跳过检查",实际 micro 只合并产物不跳过阶段
2. **按代码习惯而非按流程执行** — 作为习惯于输出代码的 agent,对流程节点的重视度天然低于代码
3. **缺少执行中的自检机制** — rules 只在加载时读一次,被上下文冲走后就没有对照检查
### 核心教训
- **Devflow 是思考过程,不是文档任务** — 写文档的过程就是做架构审计和一致性检查的过程
- **Micro 不等于跳过** — 产物可以合并,但检查点不能省略
- **声明即约束** — 把"本阶段调用 X / 降级为 Y"说出来,是对自己的提醒也是对用户的透明
- **Devflow 和 OpenSpec 同步更新** — 更新 OpenSpec 时同步更新 devflow,不要把 devflow 留到 Phase 4 一次性补。两者是同一件事的两面,不是先后关系
+115
View File
@@ -412,8 +412,56 @@ Phase 2 的 `grill-with-docs` 不是代理自问自答。`user-interview` 问题
`evidence-driven` 问题可以由代理先查证,但也必须汇报证据、结论和是否需要用户确认。
Phase 2 在开始追问前,还应该先建立一个 question pool。最小问题池至少覆盖:
- 术语
- 范围边界
- 验收口径
如果变更涉及多模块、接口、权限、下游消费者、响应结构或生命周期规则,再把这些维度补进问题池。问题池的作用是先把风险面列全,再继续保持 one-at-a-time 的 `user-interview` 消费节奏,而不是一次把所有问题都抛给用户。
单个 grill 决策确认不等于 Phase 3 apply 授权。用户在 Phase 2 回答“可以”只表示该问题已确认;代理必须先回写 OpenSpec/devflow,停在 Phase 2.9,报告 Committed OpenSpec 检查结果,并等待用户明确要求进入 apply、开始实现、执行修改或继续 Phase 3。
### Phase Checkpoint
v3.1 的另一个收紧点是:关键阶段不再靠“看起来做完了”判断完成,而是靠显式 checkpoint。
关键阶段至少包括:
- Phase 0
- Phase 0.5
- Phase 1
- Phase 2
- Phase 2.5
- Phase 2.9
每个 checkpoint 至少说明:
- 当前阶段
- 调用的 capability 来源
- 产出的关键 artifact
- 已满足的退出条件
- 尚未解决的 blocker
如果没有这些信息,就不应该把阶段视为已完成,更不应该直接进入下一阶段。
### Cross-Artifact Alignment
v3.1 之后,Phase 1.5 和 Phase 2.9 不只是“看看文档差不多”,而是要显式检查一条对齐链:
```text
brief/prd -> proposal -> design -> specs -> tasks
```
检查重点不是格式,而是下游产物有没有把上游已经确定的内容接住,例如:
- `brief/prd` 里的范围和非目标有没有进入 `proposal`
- `proposal` 的关键承诺有没有进入 `design`
- `design` 里的实现约束和接口影响有没有进入 `specs` 或 `tasks`
- `specs` 里的可观察行为有没有被 `tasks` 切成可执行工作
如果字段、术语、约束、行为或切片只停留在上游文档里,就应该视为对齐缺口,先修 OpenSpec,再继续流程。
### 接口影响分级
v3.1 区分“接口影响记录”和“独立接口文档”:
@@ -445,6 +493,21 @@ devflow/compound/
Phase 4 回填项目档案时必须更新 `devflow/index.md`。最小字段为日期、slug、领域、关键词、关联 OpenSpec 和状态。
另外,v3.1 也把一个实践经验写成硬规则:devflow 不是等到 Phase 4 才第一次补写。`brief.md`、`evidence.md`、`decisions.md` 这类过程内档案应该随阶段就近更新,Phase 4 主要负责 consolidation 和归档口径收束。
### Micro 不是 Skip
`micro` 的目标是降低文档重量,不是给代理发放“可以跳 gate”的许可证。
因此即使是 `micro` 变更,也仍然要保留:
- Phase 0.5 最小上下文收集
- Phase 2 最小澄清
- Phase 2.9 commit gate
- Phase 4 轻量回填
如果因为“改动很小”就跳过这些 gate,应该视为协议偏差,而不是合法优化。
### 实现期冲突处理
Phase 3 中,如果用户质疑、用户修改、代码发现、测试失败或运行行为与 Committed OpenSpec 冲突,必须先分类:
@@ -470,6 +533,58 @@ v3.1 将子 skill 从“路径绑定”改为“能力绑定”。例如 `opensp
这样 `sm-flow` 可以在 Claude、Codex 或其他代理环境中迁移,而不会被某个固定目录锁死。
一旦进入 fallback,代理还必须把这次降级本身记录下来。也就是说,fallback 不只是“内部换个做法”,而是一个需要显式声明 capability 缺失、降级原因和风险的协议事件。
## v3.1 后续收口:协议瘦身与 review 修正
在执行硬化规则落地后,又做了一轮非常实际的收口:不是再增加新规则,而是把已经确认的规则放到更稳定、可维护的位置,并修掉瘦身过程中暴露的引用问题。
### 顶层 skill 瘦身
`SKILL.md` 不再同时承担“入口协议”和“大段运行手册”两种职责,而是收敛为:
- 工作流定位
- 真理源分层
- 核心硬规则
- reference 加载入口
- 阶段总览
原来放在顶层但更适合按需读取的内容,被下沉到新的:
```text
references/operating-rules.md
```
这里集中放:
- 接口影响分级
- 启动检查
- 项目标识规则
- devflow 产物分层
- 快速模式细则
- 完成标准
这样做的目标不是减少规则,而是减少“启动时一次读太多”和“顶层协议与 reference 抢职责”的问题。
### Fallback 去重复
`fallbacks.md` 也做了第二轮整理:
- 顶部统一定义 fallback 通用记录要求
- 各 fallback 小节只保留自己的额外记录义务
这样可以避免每个 fallback 都重复写一遍“要声明 fallback、要记录 fallback”,同时不丢失协议要求。
### Review 驱动的自洽性修正
瘦身后又发现了一类很典型的问题:**规则本身没错,但 cross-reference 可能断掉**。因此又补了一轮 review 驱动修正,重点包括:
- `phase-contracts.md` 在首次使用接口分级、分档、快速模式时,显式指向 `operating-rules.md`
- 修正 fallback 锚点,避免 skill 指向不存在的章节名
- 统一 `operating-rules.md` 的语言风格,避免在主协议是中文时夹着一整份英文运行规则
这轮修正说明一件事:协议产品化不只是“把规则写出来”,还要保证**入口、逐阶段契约、fallback 和运行规则之间的导航关系始终自洽**。