# Dev Flow:背景与技术演进 **状态**:设计中 **日期**:2026-07-05 **范围**:说明 `dev-flow` skill 为什么存在、从哪来、为什么是现在这个形态 --- ## 1. 这份文档解决什么 `dev-flow` 的核心只有一条规则:**每个非平凡变更必须留下 `decision.md`**。 这个规则看起来很轻,但它是从五次设计迭代、一次完整协议重写、以及和三个外部实现的对比里收敛出来的。**如果只看结论,很容易觉得它"太简单了,不够"**——所以这份文档把推理链完整留下来。 配套文档: - `.agents/skills/dev-flow/SKILL.md` — 运行协议 - `.agents/skills/dev-flow/references/decision-note.md` — 格式规范与校准案例 --- ## 2. 背景:为什么需要一层"决策档案" ### 2.1 原始动机(2026-05-18 前后) 第一次完整跑通一个 AI 驱动的开发流程后,暴露的问题是**产物散落**: ```text CONTEXT.md ← 根目录 docs/adr/ ← 架构决策 docs/agents/ ← PRD openspec/changes/ ← 提案与规格 knowledge/entries/ ← 知识条目 ``` 三个月后想回溯"这个项目到底做了什么决策",需要同时翻 4 个目录。**产物按"工具来源"组织,而不是按"项目"组织。** 这是 `devflow/` 聚合层的直接起因,设计上借鉴了 CodeStable 的**单一聚合根**。 ### 2.2 当时确立的两层分工 | | `openspec/changes/` | `devflow/projects/` | |---|---|---| | 角色 | 工具工作区(WAL) | **人类可读档案层(Tables)** | | 谁读 | 机器 | **人** | | 生命周期 | 活跃变更期 | 永久保留 | | 组织方式 | 按变更名 | 按日期 + 项目 | **"给人看"是明确的设计目标**,不是副产品。这一点在后来的讨论中被反复确认,也是最终形态的关键约束。 ### 2.3 但有一个前提,后来被证伪 原始设计文档里写着: > `openspec/changes/` 是工具工作区(WAL),**archive 后清空**;`devflow/projects/` 永久保留。 **在真实仓库里这个前提不成立。** 实测: ```text openspec/archive/2026-05-19-add-clear-filters/ openspec/archive/2026-05-21-sm-flow-v3-1-upgrade/ openspec/archive/2026-07-05-validate-sm-flow-explicit-trigger/ openspec/changes/archive/2026-05-25-knowledge-index-sort/ ``` 归档内容**没有被清空**,而且历史上出现过两个归档位置(`openspec/archive/` 与 `openspec/changes/archive/`)。 后来设计文档自己把真正丢失的东西说清楚了: > 旧:`openspec archive` 只归档需求,项目的**术语、业务规则、架构决策**散落在对话中,下次新对话全丢 关键点:**丢的不是变更产物,是 `why`。** 术语有 `devflow/glossary/CONTEXT.md` 承载;而"架构决策"就是决策档案本身。 **结论:"需要一层新目录"这个判断,建立在错误的前提上。** --- ## 3. 技术演进 ### 3.1 v1 — `dev-flow` 骨架 `.claude/skills/dev-flow/` 的最早形态:Phase 1-4 流水线(手动 PRD → openspec propose → to-prd → grill → apply),外加一个 `devflow/` 目录约定。 ### 3.2 v2.0.0 — 产物聚合层(现存 213 行) 现行 `.claude/skills/dev-flow/SKILL.md` 的版本。核心贡献: ```text devflow/ ├── projects/YYYY-MM-DD-{slug}/ │ ├── {slug}-prd.md {slug}-research.md │ ├── {slug}-design.md {slug}-tasks.md │ ├── {slug}-acceptance.md │ └── adr/ ├── glossary/CONTEXT.md ├── compound/ └── reference/ ``` 确立了两层架构与"Phase 4 从 OpenSpec 提取到 devflow"的回填模式。 **它已经埋下了后来的两个问题**: 1. **数量不封顶**——一个项目 5 个文件起,`adr/` 与 `compound/` 还可再长 2. **提取 = 有损转换**——`{slug}-tasks.md` 是从 openspec `tasks.md` **提炼**出来的,同一事实两个权威 ### 3.3 sm-flow v2 — 产品化 `dev-flow` 被重构为 `.agents/skills/sm-flow/`,把设计说明书拆成代理可执行的 skill 结构(`SKILL.md` + `references/`)。 ### 3.4 sm-flow v3 / v3.1 — 真理源分层与产物瘦身 v3 解决的问题:**devflow 产物越来越完整,agent 开始直接拿 devflow 写代码,OpenSpec 被架空。** 确立分层: ```text devflow = 上下文真理源 OpenSpec = 执行真理源 代码 = 结果 ``` v3.1 进一步明确 **devflow 不复制 OpenSpec**,只保存它不擅长表达的人类上下文、证据、决策和验收归档。默认产物收敛为 `brief` / `evidence` / `decisions` / `acceptance`。 **这一步方向是对的,但执行没有一致性保障**——见第 5 节的实测。 ### 3.5 sm-flow v4.0 — 协议层 harness 重设计 一次设计评审后做了一次**结构性重写**(不是加规则): | 改动 | 性质 | |---|---| | 19 条规则 → 6 条硬约束 | 删减 | | `SKILL.md` ~85 行 → ~50 行 | 删减 | | **grill 提到 specify 之前** | 消除"细化 → 澄清 → 回写"的必然返工 | | devflow 延迟写入:过程只维护 `decisions.md` | 消除双重记录 | | 阶段改英文动词命名,4 个用户命令 | 接口收窄 | 设计文档自己写下了这次重写最重要的判断: > **这不是 agent 执行问题,是流程顺序决定了返工必然存在。** **v4.0 是这条演进线上唯一一次"减法生效"的版本。** ### 3.6 sm-flow v4.1 / v4.2 — 两次应激加码 | 版本 | 触发原因 | 成本 | |---|---|---| | v4.1 | 山东商客意向单同步接口返工 4-5 次 | +55 行,门控 4→6 | | v4.2 | `lookup-knowledge-integration` 跳过 7 个阶段 | +80 行,门控 6→8,新增 `.committed` / `.archive-ready` | v4.2 的核心主张是**把软性约束变成硬性检查**——但形式上仍然是提示词里的检查清单。 两个值得记录的问题: 1. **v4.0 的验证复盘已经观察到同类跳过行为,并明确决定"暂不改协议"**(原文:"问题 1 和 2 暂不改协议,如果多次验证中反复出现再考虑加约束")。**v4.1/v4.2 违反了自己定下的门槛。** 2. **v4.2 的动机案例按 v4.3 的触发规则根本不算 sm-flow 运行**——优化建议文档自己标注"执行模式:手动跳阶段(用户直接要求修复问题)"。 ### 3.7 sm-flow v4.3 — 回到减法 | 改动 | 性质 | |---|---| | **只显式触发**(不再按需求类型自动触发) | 砍掉常驻税与假阳性违规 | | `.agents/skills/sm-flow/references/scales.md` 成为分档**唯一**来源 | 消除重复定义 | | 新增 `.agents/skills/sm-flow/references/glossary.md` | 统一术语 | | **拒绝**引入 `.sm-flow-state` 状态文件 | 主动不做 | | 删掉固定投入指标 | 去掉会腐化的经验值 | **v4.3 是自 v4.0 以来第一个走简化方向的版本。** 它证明这条演进线是活的。 ### 3.8 现状实测(截至本文) `sm-flow` skill 本体: | 指标 | 实测 | |---|---| | 文件数 / 体积 | 8 个 / 58,597 B | | 总行数 | **1,253 行** | | "必须 \| 不得" | **52 处** | | 列表项 | **454 个** | | 首次加载(SKILL.md + phase-contracts) | ≈ 8.5k tokens(**占全量一半**) | | 单次 standard 变更产物 | OpenSpec 7 文件 14.8 KB + devflow 5 文件 20.3 KB = **35 KB** | 设计文档自己给出的成本表: | 规模 | 代码工作量 | 流程开销 | 占比 | 自评 | |---|---|---|---|---| | micro | 30 min | 40–60 min | **~60%** | **太重** | | standard | 2 h | 1–1.5 h | ~40% | 还行 | | complex | 1–2 d | 2–3 h | ~20% | 值得 | --- ## 4. 对照外部实现 为了让判断不建立在自我推演上,对三个外部实现做了一手对照。 ### 4.1 三个外部实现的做法 | | 状态持有者 | 强制力在哪 | 约束对象 | |---|---|---|---| | **OpenSpec**(v1.13) | 产物依赖图,**CLI 计算** readiness | `status --json` 与 schema | 一次变更的产物 | | **Trellis**(0.7) | `task.json.status` + **hook 每轮注入** | 平台 hook | 一轮该做什么 | | **DSH Agent Notes** | **文件路径** | **CI 脚本 + PR 原子性** | 一个决策必须留下理由 | | *sm-flow* | *agent 的 checkpoint 陈述* | *提示词自查* | *阶段顺序* | **三家都把强制力移出了提示词,sm-flow 是唯一没移的。** ### 4.2 关键发现一:DSH 并不强制"必须写" DSH 有 19 个 CI workflow、110+ 个 `verify-*` 脚本,其中与 Agent Notes 相关的只有三个: | 脚本 | 管什么 | |---|---| | `verify-agent-note-classification.ts` | 路径是否在关闭集内 | | `verify-agent-note-format.ts` | 三行头 + 骨架 + **`## Alternatives considered` 必须存在** | | `verify-archived-agent-notes.ts` | 冻结三元组 + 哈希 manifest | 检索确认:**没有任何脚本强制"改了代码就必须有笔记"。** 那条规则靠约定与人工 review。 **一个 1,026 篇笔记、110 个校验脚本的项目,把所有机器能查的东西都做成了脚本,却单独把这一条留给了判断。** 原因是"非平凡"本身是判断,机器强制会产生假阳性——正是 pre-commit hook 拦琐碎提交的那个问题。 **结论:任何"三条时机不变量 + hook"的方案都比业界最成熟的实现更重。这个方向的复杂度应当被否决。** ### 4.3 关键发现二:devflow 层的前提被证伪 见第 2.3 节。归档不丢数据,丢的是 `why`。 ### 4.4 收敛出的三条原则 **① 不新增检查点,把义务挂在已有的动作上。** - DSH:写新笔记 → 顺手检查旧笔记是否被取代 - DSH:改代码 → 同一次变更里更新笔记的事实 - `triage`:决定拒绝 → 同时写 `.out-of-scope/` - *反面*:sm-flow 现在新增 4 个 checkpoint + 8 个门控文件 + 各类自检清单 **② 检查只有一个,放在收尾边界。** - OpenSpec:archive 时检查完整性 - Trellis:finish 时拒绝在不一致状态下完成 两家独立收敛——不是"全过程多条不变量",而是"收尾时一次检查"。 **③ "是否该写"是判断,不强行机器强制。** 见 4.2。 --- ## 5. devflow 现状实测:问题不是"文件太多" `devflow/` 现状: | 指标 | 实测 | |---|---| | 文件数 / 体积 | **37 个 / 85.0 KB** | | 项目数 | 9 | | 每项目文件数 | **2 – 7,无规律** | | 命名约定 | **4 套并存** | | **含"替代方案"的文件** | **1 / 37** | ### 5.1 四套命名约定并存 | 世代 | 形态 | |---|---| | 早期 | `{slug}-{prd,design,research,tasks,acceptance}.md` | | 早期 | 自由式(`dev-flow-skill-evaluation.md` + `todo.md`) | | 早期 | `adr/` 子目录 | | v3.1 后 | `{brief,evidence,decisions,acceptance}.md` | **没有任何机制阻止格式漂移**,因为格式从未被校验。 ### 5.2 真正的病:同一个"5 个文件",两种质量 | 项目 | 文件数 | 与 OpenSpec 的关系 | |---|---|---| | `add-year-filter` | 5 | **严重重复**——`-design.md` 与 `design.md` 同一件事写两遍;`-tasks.md` 与 `tasks.md` 任务核对两遍 | | `sm-flow-execution-hardening` | 5 | **做对了**——`brief.md` 写的是"OpenSpec 对齐:已覆盖",用引用代替复制 | **两种质量共存,而文件名看不出区别。** 只能靠打开和回忆。 ### 5.3 最稀缺的内容几乎为零 在整个 `devflow/` 里检索 `备选|替代方案|放弃了|代价|alternatives|trade-off|权衡|否决`: ```text Found 1 match devflow/projects/2026-05-18-knowledge-index-panel/adr/0001-directory-name-as-truth-source.md Line 21: ## 替代方案 ``` **37 个文件、85 KB,只有一篇文章记录了"我们放弃了什么"。** 而它的骨架恰好就是决策档案的骨架: ```markdown ## 背景 ← Problem ## 决策 ← Decision ## 替代方案 ← Alternatives considered ## 后果 ← Consequences(正面 / 负面分开) ``` **正确答案在 2026-05-18 就被写出过一次,此后 9 个项目再没出现第二次——因为没有机制要求它。** --- ## 6. 决策:三个方案 | | A:devflow 分层 + 同步机械 | B:devflow 只给 agent 读 | **C:取消 devflow 层** | |---|---|---|---| | 决策笔记落点 | `devflow/decisions///` | 同 A,但格式机器优先 | **`openspec/changes//decision.md`** | | 受众 | 人 + agent | 只 agent | **人 + agent** | | 同步问题 | 有,需 3 条不变量 + hook 解 | 有,且对 agent 更严重 | **不存在** | | 新增机械 | ~200 行 + hook | ~60 行 | **~0 行** | | 写入时机 | 需要保证 | 需要保证 | **天然正确**(写变更产物的同一时刻) | | 人的可读性 | 是 | 否 | **是** | ### 为什么否决 A A 要新增三条时机不变量 + pre-commit hook。**4.2 的发现表明这比 DSH 更重**,而 DSH 是靠约定解决的。 更根本的是:A 是在**解决同步问题**;而 4.3 表明这个同步问题**本来不需要存在**。 ### 为什么否决 B B 的直觉是"只给 agent 读就不用管可读性和索引,复杂度就降了"。但: - 省掉的只是 `index.md` 和文笔(**便宜**) - 省不掉时机同步(**昂贵**),而且对 agent 阅读**更关键**——agent 会照着过时的记忆干活 而且 A/B 是超集关系:一份写好的人类可读决策档案**同时**是 agent 能读的;反过来不成立。 **唯一支持 B 的论证是"没人读的档案会腐烂"——而这一点已被 5.3 实测证明:覆盖率 1/37,无人校对。** ### 为什么选 C 1. **它消除问题而不是解决问题**——同步复杂度归零 2. **它纠正了事实错误**:devflow 层的主要理由(archive 后清空)不成立 3. **它符合设计原则 ①**:写入义务挂在"写变更产物"这个已有动作上 4. **它满足原始设计目标**:`decision.md` 是给人看的,而且和它描述的那次变更放在一起,人类读起来上下文最完整 保留下来的是三样最有价值的东西: - **强制 `## Alternatives considered`**(ADR-001 就是范例) - **`glossary/CONTEXT.md`**(真正的跨项目知识) - **`rejected/`**(未实施提案的归宿,DSH 与 `triage` 独立收敛的机制) 放弃的是:devflow 作为独立"人类档案层"的存在感,以及 A 的那套同步机械。 --- ## 7. 新 dev-flow 的设计 ### 7.1 定位:替代 sm-flow **dev-flow 是一套轻量开发流程,并且替代 sm-flow。** 这不是"两套正交工具",而是一次替换: | | sm-flow | dev-flow | |---|---|---| | 身份 | 协议层 harness,编排 9 阶段 | **轻量开发流程,3 阶段** | | 人类确认点 | 4 | **2** | | 分档 | micro / standard / complex | **无** | | 协议行数 | 1,253 | **~150** | | 单次变更产物 | OpenSpec 7 文件 + devflow 5 文件 = 35 KB | **OpenSpec 4 件 + `decision.md`** | | 强制内容 | "按顺序做 9 件事并逐项自查" | **"放弃了什么"** | | 强制力 | 提示词 + 8 个自查清单 | **1 个收尾检查** | **sm-flow 的归档由用户手动执行**,在 dev-flow 实现完成之后。 ### 7.2 三阶段流程 ```text Think 想清楚 → Build 做出来 → Close 收好尾 ⏸ 确认点 1 ⏸ 确认点 2 授权进入实现 是否归档 ``` | 阶段 | 做什么 | 用 OpenSpec 的 | |---|---|---| | **Think** | 澄清 → 读上下文 → 写 proposal/design/specs/tasks → **写下 `decision.md` 的 Problem 与 Alternatives** | `openspec-propose` | | **Build** | 按 tasks 分步实现 + 验证;冲突三分法 | `openspec-apply-change` | | **Close** | 补齐 Decision / Consequences / Verification → 收尾检查 → 归档确认 | `openspec-archive-change` | **为什么是 3 个而不是 9 个**:sm-flow 的 9 阶段里有一半是"为了防止 agent 偷懒"而设的编排层。当强制力改由文件与收尾检查承担之后,这些中间阶段失去了存在理由。**Trellis 用 Plan / Execute / Finish 三段跑通,是同一判断的独立佐证。** **为什么不分档**:sm-flow 的分档设计者自己评分 micro 开销约 60%、"太重"。**流程本身就轻的时候,分档是多余的**——它只是在给一个重流程寻找减负的借口。 ### 7.3 产物布局 ```text openspec/changes// ├── proposal.md ├── design.md ← 实现设计(执行向) ├── specs/ ├── tasks.md └── decision.md ← why + 备选 + 代价 + 验证(人向) devflow/ ├── glossary/CONTEXT.md ← 跨项目术语 ├── rejected// ← 未实施的提案 └── index.md ← 脚本扫描归档生成,不手写 ``` ### 7.4 保留了 sm-flow 的什么 dev-flow 不是全盘重写。三样东西被完整继承: - **Draft / Committed 思想** → 变成**确认点 1**("未获授权不得进入 Build")。这是三家外部实现独立收敛到同一处的设计。 - **冲突三分法** → 完整保留,是四家对比里唯一没找到对应物的原创资产。 - **显式触发** → 保留,v4.3 唯一一次生效的减法。 放弃的是:9 阶段编排、micro / standard / complex 分档、8 个自查清单、`.committed` / `.archive-ready` 门控文件、每阶段声明 capability 来源的仪式、以及 devflow 的 4–5 件套档案。 ### 7.5 三条设计原则 见 `SKILL.md`。**① 义务挂在已有动作上 ② 确认点只有两个 ③ "是否该写"是判断。** ### 7.6 能力来源:编排,而不是重写 dev-flow 和 sm-flow 一样是**元技能**——由多个子 skill 实现。但组合的务实程度不同: | | sm-flow | dev-flow | |---|---|---| | 组合的子 skill | 8 个(3 个 OpenSpec + grill / to-prd / zoom-out / diagnose / tdd) | **5 个**(3 个 OpenSpec + grill-with-docs + diagnose / tdd) | | 能力声明 | 每个阶段显式声明 capability 来源 | **一张表,不逐阶段声明** | | 不可用时 | `references/fallbacks.md`,8 个内置协议(49 行) | **一行规则**:按能力绑定;不可用时读本地 `SKILL.md`;仍不可用时按最小等价协议直接产出文件并注明 | | 不使用 | — | `to-prd`(发布到 issue tracker,且与 `proposal.md` + `specs/` 重复) | | 不设阶段 | — | `audit`。`zoom-out` 降为按需能力,不再是关卡 | **设计期间发生的三次修正,值得记录:** 1. **澄清环节一度被重写。** 初版 `phases.md` 把"一次一问、能查代码的自己查、术语沉淀进 `CONTEXT.md`"又写了一遍——而这三条 `grill-with-docs` 已经实现了。 这正是 sm-flow v2 自己修过的错(元技能复述子技能逻辑)。现已改为**引用 + 只保留 dev-flow 特有的部分**。 2. **`grill-with-docs` 的取向与本流程有张力。** 它要求 "interview me **relentlessly** … until we reach a shared understanding",而 dev-flow 要轻。 解法是分层:**relentless 是对问题质量的,不是对数量的**——方法借用,范围收窄。 3. **ADR 与 `decision.md` 原本会重复。** `grill-with-docs` 会提议创建 ADR(需同时满足难以逆转 / 缺少上下文会困惑 / 源自真实权衡),而 dev-flow 要求每个变更写 `decision.md`,两者形态几乎相同。 处置:**`decision.md` 吸收 ADR**,不再另建 `adr/` 目录。ADR 三条件从"要不要写"降级为"值不值得写深"。 (DSH Agent Notes 用 `architecture` class 承担 ADR 角色,是同一思路。) 4. **冲突面比预想的宽。** 逐一实测后,`grill-with-docs` 有**三处**默认与本仓库不符: | 它的默认 | 本仓库实际 | |---|---| | ADR 写入 `docs/adr/` | `docs/adr/` **不存在**;实际在 `devflow/projects/*/adr/`(3 个目录) | | 用 `ADR-FORMAT.md` | dev-flow 用 `decision-note.md` | | 假设根目录 `CONTEXT.md` | 用 `devflow/glossary/CONTEXT.md`(根目录是 235 B 重定向 stub) | #### 裁决:都不内置 理由是结构性的,不是偏好: > **内置只在被组合 skill "消失"时才消除冲突。** 只要它还装在目录里(用户可以直接调用), > 内置就只是让 dev-flow 多出一份**会漂移的私有副本**——重复实现加上版本漂移,两个问题。 改成一条**可判定的归属规则**,它能覆盖未来还没组合的 skill: > **子 skill 管"这一步怎么做";dev-flow 管"做多少、结果放哪"。冲突时,流程赢。** > 归属规则解决不了的 → **不组合它**(`to-prd` 就是这么处理的)。 | 内容 | 归属 | |---|---| | 一次一问、先查代码、场景压测 | `grill-with-docs`(方法,引用不内联) | | 问多少、何时停、要不要写 ADR | **dev-flow** | | `CONTEXT.md` 在哪、ADR 落哪、用什么格式 | **dev-flow** | #### 为什么 `openspec-*` 尤其不能内置 它们由 `openspec update` 生成,同时存在于 `.claude/skills/` 和 `.codex/skills/`,是**外部管理的多副本产物**。只能按能力名引用。 **顺带发现**:`.agents/skills/` 下**没有** `openspec-*`,所以在本环境里"优先用平台原生 skill"会失败,必须降级到"读本地 `SKILL.md`"(`.claude/` 或 `.codex/` 下有)。这正好验证了"能力绑定而非路径绑定"这条规则在**兜住一个真实的不一致**——而不是一条装饰性的设计原则。 --- ## 8. 验证记录 ### 8.1 `openspec validate` 是否容忍 change 目录内的 `decision.md` —— ✅ 容忍 这是方案 C 的硬前提。**已实测确认。** | 步骤 | 结果 | |---|---| | 基线:`validate knowledge-index-panel` | `is valid` / exit=0 | | **探针:加入 `decision.md`** | `is valid` / **exit=0** ✅ | | **反向对照:抽掉 `proposal.md`** | **exit=1** ✅ 证明探针可信 | | 恢复后复验 | exit=0 | | 工作区洁净度 | 干净,无残留 | **反向对照是必须的。** 第一次探测只跑出 exit=0 就下结论,那是假阳性——CLI 当时根本没执行。 ### 8.2 环境约束:受限沙箱下无法捕获外部程序输出 本次踩到的坑,记录下来避免重复: ```powershell $x = & openspec validate foo # ❌ 捕获 -> 命令静默不执行,仍返回 0 & openspec validate foo | Select-Object -First 5 # ❌ 管道 -> 同样失效 & openspec validate foo # ✅ 直连控制台 -> 正常 ``` **后果**:所有 CLI 验证必须让输出直连控制台。否则会得到"永远通过"的假象——**而且比没有验证更危险**,因为它会让人相信一个不存在的结论。 ### 8.3 顺带发现:`add-year-filter` 通不过校验——根因是 UTF-8 BOM ```text Change 'add-year-filter' has issues ✗ [ERROR] knowledge-filtering/spec.md: No delta sections found. ✗ [ERROR] file: Change must have at least one delta. ``` **这个报错会误导。** `specs/knowledge-filtering/spec.md` 第 1 行**就是** `## ADDED Requirements`,完全按要求写的。 真正的原因是文件带 **UTF-8 BOM**——解析器把行首标题读成了 `\ufeff## ADDED Requirements`,匹配不上。 字节级实测,相关性完美: | change | 首 4 字节 | BOM | validate | |---|---|---|---| | `add-year-filter`(4 个文件全部) | `EF BB BF 23` | **有** | ❌ 失败 | | `knowledge-index-panel` | `23 23 20 57`(`## W`) | 无 | ✅ 通过 | | `sm-flow-execution-hardening` | `23 23 20 57` | 无 | ✅ 通过 | **这个结论差点写错。** 第一版是从报错**推断**出"它的 spec 用的是普通 `##` 小节",而没有实际读那个文件—— 读进去才发现推断是错的。**报错信息描述的是解析器看到的东西,不是文件里实际写的东西。** 本地 CLI 版本 **1.3.1**(官网最新 1.13.0),偏旧,但 BOM 不兼容与版本关系不大——这是一个**可机械修复**的问题(去掉 BOM 即可)。 ### 8.4 dev-flow 首次验证(retrofit) 用 `add-year-filter` 做了一次 **retrofit** 验证:Think 与 Build 在历史上已发生,所以本次验证的是 **Close 阶段与产物格式**。 产物:`openspec/changes/add-year-filter/decision.md`(4,198 B) | 验证项 | 结果 | |---|---| | 五节骨架齐备 | ✅ | | 新文件无 BOM | ✅ | | **收尾检查 3 项** | ✅ **全部机械通过** | | 加入 `decision.md` 后 validate 报错集合未变 | ✅ 未引入新问题 | | **补出被丢弃的备选** | ✅ 第 3 条「只改 HTML 不改生成脚本」原本藏在 `design.md` 的"架构风险"里 | **未被验证的部分**(本次覆盖不到):Think 的澄清、确认点 1、Build 的冲突三分法,以及**冲突裁决**——retrofit 没有调用 `grill-with-docs`,所以三项覆盖一次都没触发。 **本次暴露的一个格式缺口**:`## Verification` 要求"可重跑的命令",但**最有说服力的那条验证会修改文件**(重建 `knowledge-index.html`),导致收尾时不敢跑,只好把它拆成"已实测"和"需执行"两段。 → 应补充约定:**区分只读命令与有副作用的命令**。这是格式需要补的第一处。 --- ## 9. 尚未解决 | # | 问题 | 处置 | |---|---|---| | 1 | 旧的 `.claude/skills/dev-flow/`(2.0.0,213 行)同名但设计相反 | **已删除**(2026-09-18) | | 2 | `sm-flow` 归档 | **改造完成后归档**。完成定义:`scripts/check-dev-flow.sh` 落盘 ✅ + 一次从 Think 开始的全路径真实运行 + 一条旧档案迁移规则(单样本) | | 3 | 现有 3 个活跃 change(`knowledge-index-panel` / `add-year-filter` / `sm-flow-execution-hardening`) | **本次忽略** | | 4 | 现有 9 个项目 37 个 devflow 文件的迁移 | 未定;先做单样本再定规则。SuperBizAgent 实测(46 项目/180 文件)给出处置口径:压缩 Q&A 与 ADR 段落并入对应归档的 decision.md,骨架文件删除 | | 5 | `rejected/` 是否照搬 DSH 的 6 类关闭集 | 沿用,未验证 | | 6 | "计划写在 `decision.md` 却从未更新为事实"会不会出现 | 观察到再引入 DSH 的两套骨架 | | 7 | `scripts/check-dev-flow.sh` 与 `devflow/index.md` | **已落盘**(2026-09-18):`` / `--all` / `--index` 三种模式,三项收尾检查 + index 派生均已实测 | ### 9.1 SuperBizAgent 实证带来的协议修订(2026-09-18) SuperBizAgent-java 是 sm-flow 唯一一次大规模实践(6 周、46 项目、180 档案文件)。实证结论与据此合入的修订: | 实证 | 据此修订 | |---|---| | 备选记录率 **0/180**(段落式太贵,没人写) | Alternatives 首选形态改为**压缩 Q&A 一行**,寄生在 grill 问答当场 | | 后期 `apply pre-authorized` 常态化静默绕过确认点 | 确认点 1 增加显式旁路 ``,兼作授权的文件载体 | | 手写 index 腐化(死链/自指/状态不符) | index 只由 `check-dev-flow.sh --index` 派生,协议明令不手写 | | 4 文件配额在小变更上产出 176B 占位文件 | 不加回分档;触发规则补充"小修不进来,事后可补录" | | "参考 XXX 实现"没读导致返工 4-5 次(v4.1 的真实教训) | Build 契约加一行:点名参考的实现,动手前先完整读 | --- ## 10. 附录:对照结论一览 | 收敛的设计 | 出现处 | |---|---| | 状态必须外化到文件 | 全部四家 | | **强制力不该放在提示词** | OpenSpec(CLI 计算)/ Trellis(hook 注入)/ DSH(CI 脚本) | | 保留被否决的方案以防重新争论 | DSH `rejected/` / `triage` `.out-of-scope/` / OpenSpec archive | | 单一来源,不建中央索引 | DSH(明令禁 INDEX)/ Trellis(hook parser-only,零文案副本) | | 角色/上下文隔离靠进程 | Trellis(research/implement/check 子代理)/ OpenSpec(规划 skill "Never code") | | 按需加载 | OpenSpec(optional skills)/ Trellis(JSONL manifest) | | 不新增检查点,义务挂在已有动作上 | DSH(supersession)/ `triage`(决定即写) | | 检查只在收尾一次 | OpenSpec(archive)/ Trellis(finish) | | 用真实案例校准,不用阈值 | DSH("word count is never the test") |