8 Commits
Author SHA1 Message Date
zhuyongxin fddefab0c9 Add value-scan and value-dig skills for reverse-engineering value points
- value-scan: read-only breadth inventory of mechanisms in delivered code,

  stopping at the human selection gate

- value-dig: depth write-up of chosen points (feature list, design review,

  refactor plan) with templates and mechanical checkers

- Add skill-workbench design doc for the pair
2026-09-18 18:23:23 +08:00
zhuyongxin 24a71e78f1 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
2026-09-18 18:23:18 +08:00
zhuyongxin d607861c6a Introduce dev-flow: lightweight 3-phase flow with decision archive 2026-09-16 20:06:09 +08:00
osiman ca6ae1ee0f Merge pull request 'Refine sm-flow trigger and scale rules' (#2) from emdash/tasty-fans-dress-9sc8f into master
Reviewed-on: #2
2026-07-06 10:00:37 +08:00
aruo e4f6e013a5 Refine sm-flow trigger and scale rules 2026-07-05 14:30:15 +08:00
osiman 433f7a93a4 Merge pull request 'emdash/cuddly-rockets-rhyme-d5jo4' (#1) from emdash/cuddly-rockets-rhyme-d5jo4 into master
Reviewed-on: #1
2026-07-05 03:16:12 +08:00
zhuyongxin c9a6777340 sm-flow v4.2: add verifiable checkpoints and gate file mechanism
Based on real execution review (lookup-knowledge-integration), discovered
that constraints are "soft" - rules are clear but lack enforcement mechanism.

Core problem: Agent can skip stages despite explicit rules saying "must not skip"

Changes:
1. Commit phase: add verifiable checkpoint
   - File completeness check: proposal ≥50 words, design ≥1 data structure, specs ≥3 requirements, tasks ≥5 items
   - Consistency check: proposal concepts → design mapping, design decisions → tasks implementation
   - Gate file: create .committed after passing all checks

2. Apply phase: add pre-gate check
   - Hard constraint: check .committed file existence
   - If missing: report, list gaps, ask user to fix or explicitly skip
   - Block implementation based on incomplete OpenSpec

3. Archive phase: add mandatory execution order
   - 5-step checklist: devflow files → index → .archive-ready → report → archive
   - Self-check: verify Step 1-3 before Step 4
   - Prevent "handoff first, devflow forgotten" issue

New gate files:
- .committed: created by commit phase, checked by apply phase
- .archive-ready: created by archive Step 3

Expected impact:
- Commit skip rate: -100% (explicit checklist prevents fuzzy pass)
- Apply on incomplete OpenSpec: -100% (gate blocks)
- Archive devflow omission: -100% (mandatory order)

Design principles:
- Verifiability: "executable state" → "≥50 words + ≥1 structure + ≥3 requirements"
- Gate files: soft judgment → file existence check
- Mandatory order: advisory "should do" → 5-step checklist "must do"

Complexity: +80 lines (phase-contracts.md +40, archive-rules.md +40)
Approach: turn soft constraints into hard checks, no new stages

Relation to v4.1:
- v4.1: solve "insufficient research causes rework" (quality issue)
- v4.2: solve "lack of enforcement causes stage skipping" (process issue)

Docs:
- phase-contracts.md: enhanced commit + apply phases
- archive-rules.md: added mandatory execution order at top
- workflow.md: added v4.2 evolution chapter
- phase-contracts-v4.2-changelog.md: detailed change log
- sm-flow-optimization-suggestions.md: source review
2026-06-24 14:51:45 +08:00
zhuyongxin b94ee31cb1 sm-flow v4.1: add pre-apply research checkpoint to reduce rework
Based on real execution review (shandong-intent-sync), apply phase
suffered from 4-5 rework cycles due to insufficient upfront research.

Changes:
- grill: add technical implementation dimension to question pool
- apply: add mandatory pre-apply checkpoint (15-20min research)
  - read reference implementations thoroughly
  - grep key tech stack patterns
  - form tech stack checklist in decisions.md
- apply: add incremental implementation guidance
- apply: add first-module alignment check
- apply: add fast-fail rule (≥2 rework → pause)

Expected impact:
- Rework: 4-5 cycles → 0-1 cycle (-80%)
- Core feature empty impl: 100% → 0%
- ROI: 200% (invest 20min, save 60min)

Complexity: +55 lines to phase-contracts.md (+20%)
Approach: simplified version (plan B) to balance value vs overhead

Docs:
- phase-contracts.md: updated grill + apply phases
- workflow.md: added v4.1 evolution chapter
- phase-contracts-v4.1-changelog.md: detailed change log
- sm-flow-execution-review-shandong-intent-sync.md: source review
2026-06-23 11:27:32 +08:00
55 changed files with 5998 additions and 83 deletions
+192
View File
@@ -0,0 +1,192 @@
---
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/` 下那份。
**被否决的答案当场记进 `decision.md` 的 `## Alternatives considered`**(一行一条:问过什么、为什么输)——这是 Q&A 形态,见 `references/decision-note.md`)。
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。
> **方案讨论中的任何一次确认,都不等于实现授权。**
> 快节奏交付下可以预授权,但必须显式:Think 退出时在 `decision.md` 写下
> `<!-- pre-authorized: 日期 + 范围/原因 -->`。静默跳过不允许——旁路是有意识的选择,不是遗忘。
> 授权状态以这行标记为准,恢复会话时读它,不靠对话记忆。
## Build — 做出来
**进入**:确认点 1 已过。
**动作**:
- 按 `tasks.md` 的纵向切片实现,按 `specs/` 验收。
- **分步验证**:每完成一层再继续,不要一次写完再验。
- **tasks/design 里提到"参考 XXX 实现"的,实现前先完整读它**——设计文档点名参考而实现时没看,是返工最常见的来源。
- **冲突先分类再处理**:
| 分类 | 处理 |
|---|---|
| 规格不准(遗漏、边界未覆盖、验收口径缺失) | 暂停,修正 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>/`(这里只兜底检查)。
**退出**:`decision.md` 五节齐全;收尾检查通过;用户已被询问是否归档。
## 核心规则
| 规则 | 说明 |
|---|---|
| **必须写 `decision.md`** | 每个非平凡变更 |
| **`## Alternatives considered` 强制** | 没有记录"打败了什么"的决策会招来重新争论 |
| **备选是记录的,不是编造的** | 当时没记录就写 `<!-- alternatives-not-recorded -->` |
| **实现前必须有授权** | 确认点 1 |
| **冲突先分类再处理** | 三分法 |
| **一个事实只有一个权威** | 见下表 |
**"非平凡"的判据**:改变行为、架构、跨文件或跨包的契约、流程或工具、测试策略、磁盘/线缆/配置格式,或其他维护者可能重新考察的决策。
**豁免**:纯机械或局部编辑。**小修不值得触发本流程**——dev-flow 是显式触发的 opt-in 流程,轻的第一道防线是不进来;后来发现重要时,允许事后补录 `decision.md`(retrofit 已验证)。
### 事实的唯一权威
| 内容 | 权威 |
|---|---|
| 为什么这么做、放弃了什么、代价 | `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 <slug>` 执行上述三项检查;`--index` 扫描归档派生 `devflow/index.md`(不手写);`--all` 检查全部活跃 change。
## 目录
```text
openspec/changes/<slug>/
├── proposal.md design.md specs/ tasks.md
└── decision.md ← 人向:为什么、放弃了什么、代价
↓ 随归档一起冻存
devflow/
├── glossary/CONTEXT.md ← 跨项目术语
├── rejected/<class>/ ← 未实施的提案(否决发生时写入,不是 Close 时)
└── index.md ← scripts/check-dev-flow.sh --index 派生,不手写
```
`rejected/` 的保留条件:它**仍能防止一个诱人的、有意义的错误**。否则整体删除。
**边界**:`decision.md` 的 Alternatives 记"变更内"的方案备选;`rejected/` 收"整个提案被否决"的方向。提案在确认点 1 被整个否决时,当场写入 `rejected/`——那时流程已终止,Close 不会执行。
## 触发规则
- 用户输入 `/dev-flow`。
- 用户明确要求走开发流程。
不要因为任务涉及 OpenSpec、跨模块、架构决策或 devflow 目录就自动触发。
未被这样要求之前,按普通工程任务处理。
**`decision.md` 义务只覆盖经本流程的非平凡变更**——不经 dev-flow 的普通工程任务没有这个义务。
## 相关文档
- `references/phases.md` — 三阶段契约与判断细则
- `references/decision-note.md` — `decision.md` 格式规范、校准案例、反模式
- `skill-workbench/docs/dev-flow/background-and-evolution.md` — 背景、技术演进、设计取舍
@@ -0,0 +1,259 @@
# 决策档案格式
本文件定义 `decision.md` 的格式、每节的要求、校准案例和反模式。
## 骨架
```markdown
# Decision: <一句话标题>
## Problem
## Decision
## Alternatives considered
## Consequences
## Verification
```
小节顺序固定。固定顺序不是为了机器,是为了**人能跳转**——任何时候你想知道"代价是什么",往下翻到 `## Consequences` 就行。
节名是规范名,不要用近义词替代(`## 背景` / `## 方案` / `## 风险`)。
需要额外内容时,在 `## Decision` 和 `## Alternatives considered` 之间插入自定义小节。
### 各节在哪个阶段写下
| 节 | 写下时机 | 原因 |
|---|---|---|
| `## Problem` | **Think** | 动机在需求刚澄清时最准确 |
| `## Alternatives considered` | **Think**,grill 问答当场 | 备选是在方案讨论中被否决的,当时记最真实;事后补写会变成回忆录 |
| `<!-- pre-authorized: ... -->` | **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` —— 备选(强制)
**要求**:每个**真实存在过**的备选一段,加粗开头,说明它**为什么输了**。
**首选形态是压缩 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` 已是唯一来源,
派生成本为零,多一个字段就多一处会不一致的地方。
```
**反模式**:
| 反模式 | 为什么不行 |
|---|---|
| **稻草人备选** | 编一个明显更差的选项来凑数。这会让真实读者对整个文档失去信任 |
| 只列备选,不说为什么输 | 等于没写——读者无法判断它现在是否仍然输 |
| 把"什么都不做"当默认备选 | 除非当时真的认真考虑过维持现状,否则它只是修辞 |
| 备选写成一堆标签 | 没有推理链,未来无法复用 |
| **段落式凑字数** | Q&A 一行能说清的,不要为了"看起来正式"展开成三段 |
**"什么都不做"什么时候是真的备选**:当维持现状确实是一个被权衡过的选项时(例如"暂不修复这个边界,先观察")。
**没有可记录的备选时**,写这一行注释而不是编造:
```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 篇档案里**唯一**记录了备选的一篇——也是唯一读完之后还记得住内容的一篇。
**注意它的形式**:两条备选,每条一句被拒理由,没有废话。**短不等于差。**
### 值得写深的备选(真实)
SuperBizAgent 的 `phase1-infrastructure/decisions.md` ADR-001(Flyway):
```markdown
### 后果
- 表结构修改必须通过 SQL 迁移脚本
- 开发环境首次启动需要执行 Flyway 迁移
- 生产环境部署自动执行未执行的迁移脚本
```
难以逆转的基础设施决策,后果写得具体到"改表必须走迁移脚本"——三个月后最需要读的就是这几行。
**这是 Q&A 一行记不住的那种备选,值得整段。**
### 应当补录备选(真实)
`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,139 @@
# 三阶段契约
本文件是三阶段的判断细则。**它只规定"怎么判断",不新增检查点**——检查只有收尾那一次。
---
## 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 条,连同为什么)
- 请求实现授权(或记录 `<!-- pre-authorized: 日期 + 范围/原因 -->`)
**不要**复述 proposal、不要列产物清单、不要贴对齐表格。用户要的是判断依据,不是工作汇报。
**pre-authorized 是显式旁路,不是默认。** 它适合用户已在对话中明确说"直接做"的快节奏场景。写它 = 承认确认点被有意识地跳过;不写而直接进 Build = 违规。授权状态的唯一载体是这行标记——恢复会话时以它为准。
---
## Build — 做出来
### 分步实现与验证
按 `tasks.md` 的纵向切片推进。**每完成一层先验证,再进下一层**——一次写完再验,出了问题无法定位是哪一层。
第一个切片完成后,对照 `specs/` 检查一次:验收场景是否真的成立。**规格写得含糊会在这里第一次暴露。**
### 参考实现先读,再动手
`tasks.md` / `design.md` 点名"参考 XXX 实现"的,**实现前完整读它**。路径不明确时按类名/模式 Grep 定位。
设计文档点名参考而实现时没看,是返工最常见的来源(SuperBizAgent 复盘:山东商客接口因此返工 4-5 次)。
第一次在某区域写代码、或要用项目现有基础设施(MQ/统一请求结构/工具类)时,同此处理。
### 冲突三分法的判断细则
先分类,再动手。分类的错误比不分类更糟。
**怎么区分"规格不准"和"代码偏离"**:问一句——**"如果完全按规格做出来,行为对不对?"**
| 回答 | 分类 | 处理 |
|---|---|---|
| 对,但我没按规格做 | **代码偏离** | 改代码,不动 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`,但没有 `<!-- pre-authorized` 也没有对话中的明确授权 | **确认点 1** |
| 有 `<!-- pre-authorized: ... -->` 或已获授权,实现未完成 | Build 进行中 |
| 实现完成,`decision.md` 缺 `## Decision` / `## Consequences` / `## Verification` | Close 进行中 |
| `decision.md` 五节齐全 | 收尾检查 + 确认点 2 |
**恢复时不重新提问已经解决的问题。** 先读 `decision.md` 和 `proposal.md`——已经确认过的内容就在里面。
+28 -4
View File
@@ -1,6 +1,6 @@
--- ---
name: sm-flow name: sm-flow
description: OpenSpec-first 的结构化工程开发协议层 harness。编排 OpenSpec 的完整生命周期,通过阶段、门控、人类对齐和长期记忆,约束 agent 以正确的顺序、条件和标准使用 OpenSpec。用户想把粗略想法、issue、PRD 或已有 research 推进为准确 OpenSpec change,并通过 OpenSpec apply 实现、验证、归档时使用。 description: OpenSpec-first 工程流程 harness。仅在用户显式调用 /sm-flow、/sm-flow explore、/sm-flow apply、/sm-flow archive,或明确要求使用 sm-flow 流程时使用;不要根据需求类型自动触发。
--- ---
# SM Flow # SM Flow
@@ -9,6 +9,15 @@ SM Flow 是一个**协议层 harness**——编排 OpenSpec 的完整生命周
sm-flow 会自动维护 `devflow/` 目录作为项目长期记忆。用户不需要手动管理它,sm-flow 会在流程中自动读取和回填。 sm-flow 会自动维护 `devflow/` 目录作为项目长期记忆。用户不需要手动管理它,sm-flow 会在流程中自动读取和回填。
## 触发规则
只在用户显式调用时使用 sm-flow:
- 用户输入 `/sm-flow`、`/sm-flow explore`、`/sm-flow apply`、`/sm-flow archive`。
- 用户用自然语言明确要求"使用 sm-flow"、"走 sm-flow 流程"或等价表达。
不要根据需求类型自动触发 sm-flow。即使任务涉及 OpenSpec、跨模块、接口契约、需求澄清或 devflow 归档,只要用户没有显式要求 sm-flow,就按普通工程任务处理。
## 四层架构 ## 四层架构
``` ```
@@ -30,10 +39,10 @@ sm-flow → 编排层(harness):阶段、门控、产物约束、人
1. **OpenSpec 是唯一执行真理源**。apply 阶段必须读取 Committed OpenSpec 文件作为执行依据;对话中的描述不等于产物。Draft OpenSpec 是讨论对象,不是执行许可。 1. **OpenSpec 是唯一执行真理源**。apply 阶段必须读取 Committed OpenSpec 文件作为执行依据;对话中的描述不等于产物。Draft OpenSpec 是讨论对象,不是执行许可。
2. **不得跳过 context**。生成 OpenSpec 前,必须先读取相关 devflow 上下文(glossary、ADR、历史项目)。 2. **不得跳过 context**。生成 OpenSpec 前,必须先读取相关 devflow 上下文(glossary、ADR、历史项目)。
3. **不得跳过 grill**。即使需求看起来很清楚,至少解决三个高价值澄清或验证问题。 3. **不得跳过 grill**。必须按 `references/scales.md` 的当前分档要求完成澄清或验证。
4. **不得跳过 commit**。进入 apply 前,Draft OpenSpec 必须通过 commit 检查成为 Committed OpenSpec。 4. **不得跳过 commit**。进入 apply 前,Draft OpenSpec 必须通过 commit 检查成为 Committed OpenSpec。
5. **冲突必须先分类再处理**。OpenSpec 不准(规格遗漏)→ 修正 OpenSpec;代码偏离(实现偏差)→ 修正代码;不确定或涉及设计方向 → 暂停并等待用户确认。 5. **冲突必须先分类再处理**。OpenSpec 不准(规格遗漏)→ 修正 OpenSpec;代码偏离(实现偏差)→ 修正代码;不确定或涉及设计方向 → 暂停并等待用户确认。
6. **子 skill 必须显式调用**。每个阶段指定的子 skill 必须显式调用;如果子 skill 不存在,流程失败,不得静默跳过或降级执行。 6. **能力来源必须显式声明**。每个阶段先声明使用外部子 skill / OpenSpec CLI / sm-flow 内置协议;外部能力不可用时可使用 `references/fallbacks.md` 的内置协议,但必须标注为 fallback。若外部能力和内置协议都不可用,流程失败。
每个阶段的过程约束(question pool、one-at-a-time、cross-artifact 对齐、冲突回写等)和质量约束(可观测产出要求)见 `references/phase-contracts.md` 中对应阶段的退出条件和 checkpoint。 每个阶段的过程约束(question pool、one-at-a-time、cross-artifact 对齐、冲突回写等)和质量约束(可观测产出要求)见 `references/phase-contracts.md` 中对应阶段的退出条件和 checkpoint。
@@ -48,11 +57,26 @@ sm-flow → 编排层(harness):阶段、门控、产物约束、人
用户也可以用自然语言指定从某个阶段继续,例如"ops-message-support 的 grill 已经做完了,继续"。harness 识别意图后,自动补做最小前置检查,然后从指定阶段继续。 用户也可以用自然语言指定从某个阶段继续,例如"ops-message-support 的 grill 已经做完了,继续"。harness 识别意图后,自动补做最小前置检查,然后从指定阶段继续。
## 可见 Checkpoint
内部阶段不是用户 API。对用户汇报进度时,默认只暴露 4 个 checkpoint:
| Checkpoint | 覆盖内部阶段 | 用户可见含义 |
|---|---|---|
| Discover | clarify + context + propose + grill | 澄清目标、读取 devflow、形成轻量 proposal、解决关键问题 |
| Commit | specify + audit + commit | 补全 OpenSpec、做架构/产物对齐、生成 Committed OpenSpec |
| Apply | apply | 基于 Committed OpenSpec 实现和验证 |
| Archive | archive | 回填 devflow、汇报验收、询问是否归档 OpenSpec |
除非用户要求看细节,进度汇报、暂停点和恢复提示应使用 checkpoint 名称,而不是逐个暴露 9 个内部阶段。内部阶段仍按顺序执行,并以 `references/phase-contracts.md` 为准。
## 首次加载 ## 首次加载
执行前只读取当前任务需要的 reference 文件: 执行前只读取当前任务需要的 reference 文件:
- 需要执行阶段时,先读取 `references/phase-contracts.md`;如果当前阶段涉及接口影响分级、分档、启动规则、快速模式或完成标准,再补读 `references/operating-rules.md`。 - 需要执行阶段时,先读取 `references/phase-contracts.md`;如果当前阶段涉及接口影响分级、分档、启动规则、快速模式或完成标准,再补读 `references/operating-rules.md`;如果外部 OpenSpec 能力或子 skill 不可用,再补读 `references/fallbacks.md`。
- 判断或执行 `micro / standard / complex` 分档时,读取 `references/scales.md`;其它文件不得重复定义分档细节。
- 当 checkpoint / gate / fallback / Draft / Committed 等术语含义不清,或需要统一对用户说明时,读取 `references/glossary.md`。
- 创建或更新 PRD、ADR、验收报告、词汇表、复合知识文档时,读取 `references/templates.md`。 - 创建或更新 PRD、ADR、验收报告、词汇表、复合知识文档时,读取 `references/templates.md`。
- archive 阶段或需要从 OpenSpec 提取产物时,读取 `references/archive-rules.md`。 - archive 阶段或需要从 OpenSpec 提取产物时,读取 `references/archive-rules.md`。
@@ -2,6 +2,49 @@
archive 阶段的目标是把 OpenSpec 产物、实现结果和过程日志转化为持久、可读、可复用的项目记忆。sm-flow 在 clarify → apply 期间只维护 `decisions.md` 作为过程日志,archive 阶段从中提取完整 devflow 档案。 archive 阶段的目标是把 OpenSpec 产物、实现结果和过程日志转化为持久、可读、可复用的项目记忆。sm-flow 在 clarify → apply 期间只维护 `decisions.md` 作为过程日志,archive 阶段从中提取完整 devflow 档案。
## Archive 强制执行顺序
Archive 阶段必须按以下顺序执行,不得跳过或重排:
### Step 1: 创建 devflow 档案(必需)
- [ ] 创建 `devflow/projects/YYYY-MM-DD-{slug}/brief.md`
(从 proposal.md 提取:背景、目标、范围、非目标)
- [ ] 按 `references/scales.md` 的当前分档决定是否创建 `devflow/projects/YYYY-MM-DD-{slug}/evidence.md`
(创建时从 decisions.md 提取 evidence-driven 记录)
- [ ] 创建 `devflow/projects/YYYY-MM-DD-{slug}/decisions.md`
(整理为最终版:关键决策、权衡、风险)
- [ ] 创建 `devflow/projects/YYYY-MM-DD-{slug}/acceptance.md`
(记录:静态验证、脚本验证、浏览器/人工验证、未验证)
### Step 2: 更新索引(必需)
- [ ] 在 `devflow/index.md` 末尾追加或更新一行:
`| YYYY-MM-DD | slug | 领域 | 关键词 | openspec/changes/xxx | {status} |`
### Step 3: 标记 OpenSpec(必需)
- [ ] 创建 `openspec/changes/{slug}/.archive-ready` 文件
### Step 4: 向用户汇报(必需)
- [ ] 列出创建的 devflow 档案文件路径(验证文件实际存在于磁盘)
- [ ] 汇报验证情况(按静态验证、脚本验证、浏览器/人工验证、未验证分类)
- [ ] 列出剩余风险或后续事项
- [ ] 询问:**是否现在归档 OpenSpec?**
### Step 5: 用户确认后执行 OpenSpec Archive(可选)
- [ ] 调用 `openspec-archive-change`
- [ ] 记录 archive 结果
**自检**:在执行 Step 4 前,检查 Step 1-3 是否都完成。
---
## 目录规则 ## 目录规则
项目档案路径: 项目档案路径:
@@ -10,10 +53,10 @@ archive 阶段的目标是把 OpenSpec 产物、实现结果和过程日志转
devflow/projects/YYYY-MM-DD-{slug}/ devflow/projects/YYYY-MM-DD-{slug}/
``` ```
archive 阶段创建以下文件: archive 阶段按 `references/scales.md` 的当前分档创建以下文件:
- `brief.md`:从 proposal.md 提取背景、目标、范围、非目标。 - `brief.md`:从 proposal.md 提取背景、目标、范围、非目标。
- `evidence.md`:从 decisions.md 中的 evidence-driven 记录提取。 - `evidence.md`:从 decisions.md 中的 evidence-driven 记录提取;是否独立创建按 `references/scales.md` 执行。
- `decisions.md`:保持为最终版,整理格式。 - `decisions.md`:保持为最终版,整理格式。
- `acceptance.md`:从实现结果和验证结果提取。 - `acceptance.md`:从实现结果和验证结果提取。
@@ -34,11 +77,7 @@ archive 阶段创建以下文件:
## 产物分档 ## 产物分档
| 分档 | 适用场景 | 必须文件 | 扩展文件 | 分档的适用场景和必须文件见 `references/scales.md`。本文件只定义 archive 阶段的创建顺序、提取映射和索引规则。
| --- | --- | --- | --- |
| `micro` | 小改动、低风险、需求明确 | `brief.md`、`decisions.md`、`acceptance.md` | 证据少时并入 `brief.md` |
| `standard` | 默认模式 | `brief.md`、`evidence.md`、`decisions.md`、`acceptance.md` | 按需 ADR/compound |
| `complex` | 高风险、跨模块、需求不清、多人协作 | standard 全部文件 | 按需 `prd.md`、`research.md`、`design.md`、`tasks.md`、`alignment.md` |
## 提取映射 ## 提取映射
@@ -0,0 +1,49 @@
# 内置执行协议
本文件只在外部 OpenSpec CLI 或子 skill 不可用时使用。fallback 不是跳过阶段,而是由 sm-flow 用文件方式完成同等最小产物。每次使用 fallback 都必须写入 `decisions.md` 或 `acceptance.md`,说明能力来源、缺失能力、影响和剩余风险。
## 通用规则
- 优先使用外部能力;只有不可用、不可发现或无法在当前环境调用时才使用内置协议。
- 不得因为使用 fallback 跳过 context、grill、commit、apply 授权或 archive 确认。
- fallback 产物仍写入 `openspec/changes/{slug}/` 和 `devflow/projects/YYYY-MM-DD-{slug}/`。
- 如果内置协议也无法满足阶段退出条件,暂停并向用户说明阻塞项。
## grill 内置协议
- 建立 question pool,至少覆盖术语、边界、验收;涉及参考实现或项目基础设施时加入技术实现问题。
- 将问题标记为 `evidence-driven` 或 `user-interview`。
- 先查证 evidence-driven 问题并汇报结论,再逐个询问 user-interview 问题。
- 按 `references/scales.md` 的当前分档满足 grill 要求。
- 将 question pool、证据结论、用户原话和确认状态写入 `decisions.md`;影响实现的结论回写 `proposal.md`。
## openspec 提案内置协议
- 在 `openspec/changes/{slug}/` 创建或更新:
- `proposal.md`:问题、方案、范围、非目标、上下文约束、风险。
- 设计产物:实现设计、接口影响、关键决策、架构风险;形式按 `references/scales.md` 的当前分档要求执行。
- `specs/*/spec.md` 或等价 functional spec:描述用户可观察行为和验收场景。
- `tasks.md`:按可执行切片拆分任务,并给每项写可验证验收标准。
- 运行 cross-artifact 对齐检查:proposal → 设计产物 → specs → tasks。
- 如果发现 gap,先修正 OpenSpec,再进入 commit。
## audit 内置协议
- 用 5 句话以内说明模块链路、数据所有权、跨模块依赖、架构风险和是否需要回写 OpenSpec。
- 如果风险影响实现,修正设计产物或 `tasks.md`。
- 将结论写入 `decisions.md`。
## openspec apply 内置协议
- 只依据 Committed OpenSpec 的 specs/tasks 实现;devflow 只作上下文参考。
- 开始前检查 `.committed` 文件;缺失则返回 commit。
- 如触发 pre-apply checkpoint,先阅读参考实现、grep 项目基础设施模式,并把技术栈清单写入 `decisions.md`。
- 按 tasks 的纵向切片实现、验证并更新任务状态。
- 发现冲突时按三类处理:OpenSpec 不准则修 OpenSpec,代码偏离则修代码,不确定则暂停等用户确认。
## openspec archive 内置协议
- 不删除或移动 OpenSpec change;只标记归档准备状态。
- 完成 devflow 回填、更新 `devflow/index.md`、创建 `.archive-ready`。
- 向用户汇报已创建文件、验证分类、剩余风险,并询问是否需要真实 OpenSpec archive。
- 如果外部 archive 能力仍不可用,在 `acceptance.md` 标记 `accepted-unarchived`。
@@ -0,0 +1,21 @@
# 术语表
本文件统一 sm-flow 协议中的核心词。优先使用这些词,避免同一概念多种说法。
| 术语 | 含义 | 使用边界 |
| --- | --- | --- |
| sm-flow | 协议层 harness | 编排 OpenSpec 生命周期,不替代 OpenSpec |
| OpenSpec | 当前变更的执行真理源 | apply 只能依据 Committed OpenSpec |
| devflow | 长期记忆和上下文层 | 提供术语、历史决策、验收记录,不直接指挥实现 |
| checkpoint | 用户可见检查点 | 默认只暴露 Discover / Commit / Apply / Archive |
| gate | 硬门控 | 不满足就不能进入下一关键动作,如 commit gate |
| Draft OpenSpec | 讨论和审计对象 | propose/specify 期间产生,不能直接 apply |
| Committed OpenSpec | 已通过 commit gate 的 OpenSpec | apply 的唯一执行依据 |
| fallback | 内置执行协议 | 外部 OpenSpec CLI 或子 skill 不可用时使用,必须标注 |
| decisions.md | 过程日志 | clarify 到 apply 期间记录问题、证据、决策、冲突和回写 |
| .committed | commit gate 标记文件 | 存在才可进入合规 apply |
| .archive-ready | archive 准备标记文件 | 表示 devflow 已回填,等待用户确认是否 archive |
| Discover | 用户可见 checkpoint | 覆盖 clarify + context + propose + grill |
| Commit | 用户可见 checkpoint | 覆盖 specify + audit + commit |
| Apply | 用户可见 checkpoint | 覆盖 apply |
| Archive | 用户可见 checkpoint | 覆盖 archive |
@@ -27,13 +27,14 @@
- `/sm-flow apply [change]`:只执行,检查 commit gate → apply。 - `/sm-flow apply [change]`:只执行,检查 commit gate → apply。
- `/sm-flow explore`:带上下文的探索模式,不走标准阶段链。 - `/sm-flow explore`:带上下文的探索模式,不走标准阶段链。
- `/sm-flow archive [change]`:收尾,回填 devflow + 归档确认。 - `/sm-flow archive [change]`:收尾,回填 devflow + 归档确认。
- 明确要求"使用 sm-flow"或"走 sm-flow 流程":按显式调用处理。
- 自然语言指定阶段继续:识别意图后,自动补做最小前置检查,然后从指定阶段继续。 - 自然语言指定阶段继续:识别意图后,自动补做最小前置检查,然后从指定阶段继续。
2. 判断启动模式: 2. 判断启动模式:
- 完整模式:用户提供粗略想法或初始 PRD。 - 完整模式:用户提供粗略想法或初始 PRD。
- Research 模式:用户已有 research,需要转成或修正 OpenSpec。 - Research 模式:用户已有 research,需要转成或修正 OpenSpec。
- PRD 文件模式:用户提供已有 PRD 路径。 - PRD 文件模式:用户提供已有 PRD 路径。
- 恢复模式:用户希望从某个阶段继续(补做最小前置检查)。 - 恢复模式:用户希望从某个阶段继续(补做最小前置检查)。
- 快速模式:小改动,合并 gate(见下文)。 - 快速模式:小改动,合并 gate;具体分档规则见 `references/scales.md`。
3. 如果缺少 `devflow/`,初始化: 3. 如果缺少 `devflow/`,初始化:
- `devflow/projects/` - `devflow/projects/`
- `devflow/glossary/CONTEXT.md` - `devflow/glossary/CONTEXT.md`
@@ -42,7 +43,25 @@
5. 检查 OpenSpec 和子 skill 是否可用: 5. 检查 OpenSpec 和子 skill 是否可用:
- OpenSpec 能力:`openspec-propose`、`openspec-apply-change`、`openspec-archive-change`。 - OpenSpec 能力:`openspec-propose`、`openspec-apply-change`、`openspec-archive-change`。
- 辅助能力:`to-prd`、`grill-with-docs`、`diagnose`、`tdd`、`zoom-out`。 - 辅助能力:`to-prd`、`grill-with-docs`、`diagnose`、`tdd`、`zoom-out`。
6. 如果 OpenSpec 不可用,不要直接绕过;使用内置执行协议(见 `references/fallbacks.md`),并在 apply 前向用户说明。 6. 如果 OpenSpec 或子 skill 不可用,不要静默跳过;使用内置执行协议(见 `references/fallbacks.md`),并在当前 checkpoint 说明 fallback 来源、影响和剩余风险。
## 进度汇报
用户可见进度默认折叠为 4 个 checkpoint:
| Checkpoint | 内部阶段 |
| --- | --- |
| Discover | clarify + context + propose + grill |
| Commit | specify + audit + commit |
| Apply | apply |
| Archive | archive |
汇报规则:
- 面向用户时优先使用 checkpoint 名称,不逐个汇报 9 个内部阶段。
- 内部阶段只在 checkpoint 摘要中作为证据列出,例如"Discover 已完成:读取了 devflow、生成 proposal、解决 2 个问题"。
- 只有发生阻塞、冲突、fallback、用户要求继续某个内部阶段,或需要解释恢复位置时,才暴露内部阶段名。
- 当前分档的汇报压缩规则见 `references/scales.md`;无论分档如何,都不要把内部阶段名当作用户操作入口。
## 项目标识规则 ## 项目标识规则
@@ -63,7 +82,7 @@ Devflow 是 sm-flow 自动维护的项目长期记忆层,不复制 OpenSpec
**最终档案**(archive 阶段从 decisions.md + OpenSpec 产物提取): **最终档案**(archive 阶段从 decisions.md + OpenSpec 产物提取):
- `brief.md`:背景、目标、范围、非目标、分档、关联 OpenSpec change。 - `brief.md`:背景、目标、范围、非目标、分档、关联 OpenSpec change。
- `evidence.md`:代码/文档证据、历史决策、evidence-driven 结论和汇报状态。 - `evidence.md`:代码/文档证据、历史决策、evidence-driven 结论和汇报状态;分档要求见 `references/scales.md` 和 `references/archive-rules.md`。
- `acceptance.md`:实现结果、验证命令、未验证项、归档状态、后续事项。 - `acceptance.md`:实现结果、验证命令、未验证项、归档状态、后续事项。
**按需产物**(archive 阶段按需创建): **按需产物**(archive 阶段按需创建):
@@ -75,28 +94,17 @@ Devflow 是 sm-flow 自动维护的项目长期记忆层,不复制 OpenSpec
- `alignment.md` / `clarifications.md`:仅在 gap 或澄清很多时使用。 - `alignment.md` / `clarifications.md`:仅在 gap 或澄清很多时使用。
- `adr/*.md` 和 `compound/*.md`:仅在满足 ADR / compound knowledge 规则时使用。 - `adr/*.md` 和 `compound/*.md`:仅在满足 ADR / compound knowledge 规则时使用。
**规模分档**: **规模分档**:`micro / standard / complex` 的唯一规则源是 `references/scales.md`。
- `micro`:小且低风险,gate 合并(见快速模式),最终档案同 standard。
- `standard`:默认模式。
- `complex`:高风险、跨模块、需求不清或多人协作时,在 standard 基础上按需增加扩展产物。
## 快速模式 ## 快速模式
快速模式适用于小而低风险的变更。它合并 gate 而不仅仅是压缩产物: 快速模式适用于 `references/scales.md` 定义的 micro 变更。它合并 gate 而不仅仅是压缩产物;具体覆盖规则见 `references/scales.md`。
```
standard 流程:clarify → context → propose checkpoint → grill → specify → audit checkpoint → commit
micro 流程:clarify+context 合并 checkpoint → propose+specify 合并 checkpoint → grill(最少 1 个问题) → commit(简化检查)
```
micro 的定位:**gate 变少但保留最关键的**(grill 最小澄清 + commit gate)。
无论什么模式,以下内容必须保留: 无论什么模式,以下内容必须保留:
- context 最小上下文收集:至少检查 glossary 和相关 ADR。 - context 最小上下文收集:至少检查 glossary 和相关 ADR。
- grill 最小澄清:至少一个术语问题、一个边界问题、一个验收问题;evidence-driven 结论仍需汇报。 - grill 最小澄清:按 `references/scales.md` 当前分档要求执行;evidence-driven 结论仍需汇报。
- commit gate:确认没有未解决用户问题、接口影响已记录、OpenSpec tasks/specs 可执行。 - commit gate:确认没有未解决用户问题、接口影响已记录、OpenSpec tasks/specs 可执行;完整性检查按 `references/scales.md` 当前分档要求执行。
- apply 仍由 OpenSpec tasks/specs 驱动执行。 - apply 仍由 OpenSpec tasks/specs 驱动执行。
- archive 轻量回填:记录验收结果、OpenSpec 链接和归档状态。 - archive 轻量回填:记录验收结果、OpenSpec 链接和归档状态。
@@ -104,8 +112,9 @@ micro 的定位:**gate 变少但保留最关键的**(grill 最小澄清 + co
只有同时满足以下条件,流程才算完成: 只有同时满足以下条件,流程才算完成:
- OpenSpec proposal/design/specs/tasks 已生成或更新到可执行状态。 - 用户可见的 Discover、Commit、Apply、Archive checkpoint 已完成,或未完成项已明确标记为暂停/不适用。
- OpenSpec proposal、设计产物、specs、tasks 已按当前分档生成或更新到可执行状态。
- 实现或规划工作已完成,且执行依据来自 OpenSpec。 - 实现或规划工作已完成,且执行依据来自 OpenSpec。
- 已运行验证,或已记录未运行验证的原因。 - 已运行验证,或已记录未运行验证的原因。
- `devflow/projects/YYYY-MM-DD-{slug}/` 包含 brief.md、evidence.md、decisions.md、acceptance.md。 - `devflow/projects/YYYY-MM-DD-{slug}/` 包含 `references/scales.md` 和 `references/archive-rules.md` 要求的当前分档档案。
- 用户知道剩余风险与下一步,并已被询问是否归档 OpenSpec change。 - 用户知道剩余风险与下一步,并已被询问是否归档 OpenSpec change。
@@ -4,6 +4,18 @@
执行顺序:clarify → context → propose → grill → specify → audit → commit → apply → archive。 执行顺序:clarify → context → propose → grill → specify → audit → commit → apply → archive。
## 目录
- clarify — 入口澄清
- context — 上下文收集
- propose — 轻量 propose
- grill — 人类对齐澄清
- specify — 细化 + 对齐
- audit — 架构审计
- commit — Commit OpenSpec
- apply — OpenSpec 执行
- archive — 回填 + 归档
## clarify — 入口澄清 ## clarify — 入口澄清
**进入条件**:用户提供粗略想法、初始 PRD、已有 research、issue,或要求启动 SM Flow。 **进入条件**:用户提供粗略想法、初始 PRD、已有 research、issue,或要求启动 SM Flow。
@@ -13,7 +25,7 @@
- 如果用户已有 research,先识别它是否已经包含用户价值、技术方案、验收标准和任务拆分。 - 如果用户已有 research,先识别它是否已经包含用户价值、技术方案、验收标准和任务拆分。
- 如果输入过于模糊,最多追加三轮聚焦问题。 - 如果输入过于模糊,最多追加三轮聚焦问题。
- 当答案会改变 OpenSpec proposal/specs/tasks 时,优先一次只问一个问题。 - 当答案会改变 OpenSpec proposal/specs/tasks 时,优先一次只问一个问题。
- 如果需要判断 `micro / standard / complex` 分档,补读 `references/operating-rules.md`。 - 如果需要判断 `micro / standard / complex` 分档,补读 `references/scales.md`。
**退出条件**: **退出条件**:
- 问题可以用 1-2 句话说清楚。 - 问题可以用 1-2 句话说清楚。
@@ -36,7 +48,7 @@
- 读取 `devflow/glossary/CONTEXT.md`,提取相关术语和业务规则。 - 读取 `devflow/glossary/CONTEXT.md`,提取相关术语和业务规则。
- 搜索 `devflow/projects/` 中相关 PRD、design、tasks、acceptance 和 ADR。 - 搜索 `devflow/projects/` 中相关 PRD、design、tasks、acceptance 和 ADR。
- 搜索 `devflow/compound/` 中可复用 learning、trick、decision、explore。 - 搜索 `devflow/compound/` 中可复用 learning、trick、decision、explore。
- 记录哪些上下文会影响 OpenSpec proposal/design/specs/tasks。 - 记录哪些上下文会影响 OpenSpec proposal、设计产物、specs 或 tasks。
- 如果发现旧根目录 `CONTEXT.md` 与 `devflow/glossary/CONTEXT.md` 冲突,暂停并向用户汇报。 - 如果发现旧根目录 `CONTEXT.md` 与 `devflow/glossary/CONTEXT.md` 冲突,暂停并向用户汇报。
**退出条件**: **退出条件**:
@@ -70,18 +82,22 @@
**Human checkpoint**: **Human checkpoint**:
- 向用户简要说明 proposal 范围、关键假设、主要风险、devflow 上下文如何影响方案。 - 向用户简要说明 proposal 范围、关键假设、主要风险、devflow 上下文如何影响方案。
- 询问是否继续进入 grill 澄清阶段;用户明确要求"全自动执行"时可跳过等待。 - 作为 Discover checkpoint 的中间状态汇报;询问是否继续完成 Discover 的人类澄清部分。用户明确要求"全自动执行"时可跳过等待。
## grill — 人类对齐澄清 ## grill — 人类对齐澄清
**进入条件**:propose 已有轻量 proposal.md。 **进入条件**:propose 已有轻量 proposal.md。
**显式子 skill**:`grill-with-docs`。进入本阶段必须调用 `.agents/skills/grill-with-docs/SKILL.md`。 **能力来源**:优先使用 `grill-with-docs`;不可用时使用 `references/fallbacks.md#grill-内置协议`,并在 `decisions.md` 标注 fallback。
**动作**: **动作**:
- 优先使用 `grill-with-docs`。 - 优先使用 `grill-with-docs`。
- 进入 grill 时先建立一个 question pool,并记录到 `decisions.md`: - 进入 grill 时先建立一个 question pool,并记录到 `decisions.md`:
- 默认至少覆盖术语、边界、验收三个维度。 - 默认至少覆盖术语、边界、验收三个维度。
- **技术实现维度**(新增):当 proposal 提到参考实现、或涉及项目现有基础设施时,增加技术澄清问题:
- 参考实现的具体文件路径是什么?
- 项目现有的 [请求结构/MQ/缓存/加密/工具类] 标准是什么?
- 有哪些技术点需要先调研或新建?
- 如果变更涉及多模块、接口、权限、下游消费者、响应结构或生命周期规则,先把这些维度补进问题池。 - 如果变更涉及多模块、接口、权限、下游消费者、响应结构或生命周期规则,先把这些维度补进问题池。
- 逐项标记每个问题的模式: - 逐项标记每个问题的模式:
- `evidence-driven`:问题能通过代码、文档、测试、OpenSpec 或既有 ADR 证明;代理先查证,再向用户汇报证据、结论和是否需要确认。 - `evidence-driven`:问题能通过代码、文档、测试、OpenSpec 或既有 ADR 证明;代理先查证,再向用户汇报证据、结论和是否需要确认。
@@ -97,7 +113,7 @@
**退出条件**: **退出条件**:
- question pool 已建立并覆盖当前 change 所需维度。 - question pool 已建立并覆盖当前 change 所需维度。
- 至少解决三个高价值澄清或验证问题,并记录每个问题属于 `evidence-driven` 还是 `user-interview`。 - 已满足 `references/scales.md` 中当前分档的 grill 要求。每个问题都必须记录属于 `evidence-driven` 还是 `user-interview`。
- 所有 evidence-driven 结论已向用户汇报。 - 所有 evidence-driven 结论已向用户汇报。
- 所有 user-interview 决策已获得用户确认。 - 所有 user-interview 决策已获得用户确认。
- 没有未解决或代理代确认的 user-interview 问题。 - 没有未解决或代理代确认的 user-interview 问题。
@@ -113,20 +129,20 @@
**Human checkpoint**: **Human checkpoint**:
- 汇报已解决和未解决的问题、proposal 变更、术语和 ADR 更新。 - 汇报已解决和未解决的问题、proposal 变更、术语和 ADR 更新。
- 询问是否继续进入 specify 细化阶段。 - 汇报 Discover checkpoint 完成情况,并询问是否继续进入 Commit checkpoint。
## specify — 细化 + 对齐 ## specify — 细化 + 对齐
**进入条件**:grill 已退出,需求已通过澄清稳定下来。 **进入条件**:grill 已退出,需求已通过澄清稳定下来。
**显式子 skill**:`openspec-propose`(基于已稳定的 proposal 补全完整 OpenSpec);`to-prd`(按需生成 PRD)。进入本阶段必须先声明调用方式。 **能力来源**:优先使用 `openspec-propose`(基于已稳定的 proposal 补全完整 OpenSpec);按需使用 `to-prd`。进入本阶段必须先声明调用方式;外部能力不可用时使用 `references/fallbacks.md#openspec-提案-内置协议`,并在 `decisions.md` 标注 fallback。
**动作**: **动作**:
- 基于已稳定的 proposal.md 补全 design.md、specs/、tasks.md: - 基于已稳定的 proposal.md 补全设计产物、specs/、tasks.md:
- 优先调用 `openspec-propose`,输入中明确说明"proposal.md 已存在,本次只需补全 design/specs/tasks"。 - 优先调用 `openspec-propose`,输入中明确说明"proposal.md 已存在,本次只需按当前分档补全设计产物/specs/tasks"。
- 如果不可用,执行 `references/fallbacks.md#openspec-提案-降级`。 - 如果不可用,执行 `references/fallbacks.md#openspec-提案-内置协议`。
- 如果没有结构化 PRD,按需按 `to-prd` 协议生成 `brief.md`;复杂需求、对外协作或用户明确要求时再生成 `prd.md`。 - 如果没有结构化 PRD,按需按 `to-prd` 协议生成 `brief.md`;复杂需求、对外协作或用户明确要求时再生成 `prd.md`。
- `micro` 模式默认不创建独立 PRD,除非用户要求或需求复杂度升级。 - 独立 PRD 是否需要按 `references/scales.md` 的当前分档和用户要求判断。
- 用 grill 阶段的 decisions.md 记录增强 OpenSpec 产物:确保 design/specs/tasks 反映所有已确认的决策。 - 用 grill 阶段的 decisions.md 记录增强 OpenSpec 产物:确保 design/specs/tasks 反映所有已确认的决策。
- **显式 cross-artifact 对齐检查**——在 checkpoint 中输出对齐检查表: - **显式 cross-artifact 对齐检查**——在 checkpoint 中输出对齐检查表:
- `brief/prd` 中的目标、范围、非目标和验收预期 → `proposal` 是否覆盖。 - `brief/prd` 中的目标、范围、非目标和验收预期 → `proposal` 是否覆盖。
@@ -143,14 +159,14 @@
- 如果发现不一致,优先修正 OpenSpec,而不是只修改 devflow 文档。 - 如果发现不一致,优先修正 OpenSpec,而不是只修改 devflow 文档。
**退出条件**: **退出条件**:
- `design.md`、`specs/`、`tasks.md` 存在且与 proposal 对齐。 - OpenSpec 细化产物存在且与 proposal 对齐;产物形态按 `references/scales.md` 的当前分档要求执行。
- `brief.md` 已覆盖背景、目标、范围和非目标;复杂需求存在独立 `prd.md` 或用户明确不需要 PRD。 - `brief.md` 已覆盖背景、目标、范围和非目标;复杂需求存在独立 `prd.md` 或用户明确不需要 PRD。
- cross-artifact 对齐检查表已生成(4 行,每行标记已对齐/存在 gap),没有未处理 gap。 - cross-artifact 对齐检查表已生成(4 行,每行标记已对齐/存在 gap),没有未处理 gap。
- 涉及接口变更时,已记录接口影响等级和产物要求;不确定项已标记。 - 涉及接口变更时,已记录接口影响等级和产物要求;不确定项已标记。
- 所有已知冲突已修正或等待用户决策。 - 所有已知冲突已修正或等待用户决策。
**输出**: **输出**:
- 完整的 Draft OpenSpec:proposal.md + design.md + specs/ + tasks.md。 - Draft OpenSpec:按 `references/scales.md` 的当前分档要求生成 proposal、设计、specs 和 tasks。
- `brief.md`,以及按需创建的 `prd.md`。 - `brief.md`,以及按需创建的 `prd.md`。
- cross-artifact 对齐检查表(写入 checkpoint 或 decisions.md)。 - cross-artifact 对齐检查表(写入 checkpoint 或 decisions.md)。
- 必要的 OpenSpec 修正。 - 必要的 OpenSpec 修正。
@@ -159,7 +175,7 @@
**进入条件**:specify 已退出,完整 OpenSpec 产物已存在。 **进入条件**:specify 已退出,完整 OpenSpec 产物已存在。
**显式子 skill**:`zoom-out`。进入本阶段必须调用 `.agents/skills/zoom-out/SKILL.md`。 **能力来源**:优先使用 `zoom-out`;不可用时使用 `references/fallbacks.md#audit-内置协议`,并在 `decisions.md` 标注 fallback。
**动作**: **动作**:
- 画出输入 → 处理 → 输出的模块链路。 - 画出输入 → 处理 → 输出的模块链路。
@@ -171,20 +187,20 @@
**退出条件**: **退出条件**:
- 架构风险已被接受,或流程返回 grill/specify 修正 OpenSpec。 - 架构风险已被接受,或流程返回 grill/specify 修正 OpenSpec。
- OpenSpec design/tasks 已反映会影响实现的架构审计结论。 - OpenSpec 设计产物/tasks 已反映会影响实现的架构审计结论。
**输出**: **输出**:
- 架构审计记录,写入 `decisions.md`;复杂架构审计可拆出 `design.md`。 - 架构审计记录,写入 `decisions.md`;复杂架构审计可拆出 `design.md`。
- 必要的 OpenSpec design/tasks 修正。 - 必要的 OpenSpec 设计产物/tasks 修正。
**Human checkpoint**: **Human checkpoint**:
- 用不超过五句话向用户说明架构风险、OpenSpec 修正点和实现计划。 - 用不超过五句话向用户说明架构风险、OpenSpec 修正点和实现计划。
- 询问是否进入 commit。 - 作为 Commit checkpoint 的中间状态汇报;询问是否继续完成 commit gate。
## commit — Commit OpenSpec ## commit — Commit OpenSpec
**进入条件**: **进入条件**:
- grill 已解决术语、边界、验收三个维度的高价值问题。 - grill 已满足 `references/scales.md` 中当前分档要求。
- 所有 `user-interview` 问题都已获得用户显式确认。 - 所有 `user-interview` 问题都已获得用户显式确认。
- audit 已经完成,或快速模式下已记录跳过原因;快速模式定义见 `references/operating-rules.md#快速模式`。 - audit 已经完成,或快速模式下已记录跳过原因;快速模式定义见 `references/operating-rules.md#快速模式`。
- Draft OpenSpec 已回写所有会影响实现的澄清、接口影响和架构审计结论。 - Draft OpenSpec 已回写所有会影响实现的澄清、接口影响和架构审计结论。
@@ -194,7 +210,7 @@
- 检查 design 是否记录上下文约束、关键技术决策、架构风险和接口影响。 - 检查 design 是否记录上下文约束、关键技术决策、架构风险和接口影响。
- 检查 specs 是否表达外部可观察行为,并覆盖验收口径。 - 检查 specs 是否表达外部可观察行为,并覆盖验收口径。
- 检查 tasks 是否是可执行的纵向切片,而不是泛泛描述。 - 检查 tasks 是否是可执行的纵向切片,而不是泛泛描述。
- 复核 cross-artifact 对齐:`brief/prd → proposal → design → specs → tasks` 是否闭环,没有把字段、范围项、验收行为或实现切片丢在上游产物里。 - 复核 cross-artifact 对齐:`brief/prd → proposal → 设计产物 → specs → tasks` 是否闭环,没有把字段、范围项、验收行为或实现切片丢在上游产物里。
- 检查 `decisions.md` 中所有影响实现的发现,是否已回写到 proposal、design、specs 或 tasks。 - 检查 `decisions.md` 中所有影响实现的发现,是否已回写到 proposal、design、specs 或 tasks。
- 接口影响分级定义见 `references/operating-rules.md#接口影响分级`。 - 接口影响分级定义见 `references/operating-rules.md#接口影响分级`。
- 检查接口影响是否已按 L1/L4 判级;L3/L4 是否有独立接口文档或等价独立章节。 - 检查接口影响是否已按 L1/L4 判级;L3/L4 是否有独立接口文档或等价独立章节。
@@ -203,7 +219,16 @@
**退出条件**: **退出条件**:
- Draft OpenSpec 已达到可执行状态,并记录为 Committed OpenSpec。 - Draft OpenSpec 已达到可执行状态,并记录为 Committed OpenSpec。
- apply 所需的 proposal、design、specs 和 tasks 均存在且一致;commit checkpoint 必须验证文件实际存在于磁盘,如果任一文件不存在,commit 失败,返回 specify 补写。 - **文件完整性检查**(按 `references/scales.md` 的当前分档要求执行):
- [ ] proposal 存在,且足以说明问题、建议方案、范围和非目标。
- [ ] 设计产物存在,形式符合当前分档要求。
- [ ] specs 存在,且表达用户可观察行为。
- [ ] tasks 存在,且任务可执行、验收标准可验证。
- **一致性检查**(必须通过):
- [ ] proposal 中的核心概念在设计产物中有对应设计
- [ ] 设计产物中的关键决策在 tasks 中有对应实现任务
- [ ] tasks 的验收标准可验证(不是"正确实现""完成功能"这类模糊描述)
- **标记文件**:检查通过后,创建 `openspec/changes/{slug}/.committed` 文件标记为 Committed OpenSpec
- 所有 preflight 风险已消除或明确记录为已接受。 - 所有 preflight 风险已消除或明确记录为已接受。
**输出**: **输出**:
@@ -212,36 +237,83 @@
**Human checkpoint**: **Human checkpoint**:
- 用不超过五句话说明 Committed OpenSpec 的范围、接口影响、剩余风险和执行计划。 - 用不超过五句话说明 Committed OpenSpec 的范围、接口影响、剩余风险和执行计划。
- 询问是否进入 apply;除非用户在启动时明确要求"全自动执行",必须等待用户明确说出进入 apply、开始实现、执行修改或等价授权。 - 汇报 Commit checkpoint 完成情况,并询问是否进入 Apply checkpoint;除非用户在启动时明确要求"全自动执行",必须等待用户明确说出进入 apply、开始实现、执行修改或等价授权。
- 不得把 grill 的单个决策确认当作本 checkpoint 的授权。 - 不得把 grill 的单个决策确认当作本 checkpoint 的授权。
## apply — OpenSpec 执行 ## apply — OpenSpec 执行
**进入条件**: **进入条件**:
- `openspec/changes/{slug}/` 中 proposal/design/specs/tasks 已通过 commit,成为 Committed OpenSpec。 - `openspec/changes/{slug}/` 中 proposal、设计产物、specs、tasks 已通过 commit,成为 Committed OpenSpec。
- **前置门控检查**(硬约束):
- 检查 `openspec/changes/{slug}/.committed` 文件是否存在
- 如不存在,执行以下流程:
1. 汇报:Draft OpenSpec 未通过 commit 检查
2. 列出缺失的 checkpoint 项(文件完整性、一致性检查)
3. 询问用户:是否补做 commit 检查;如用户要求不补做,则中止 apply 或标记为 `emergency-bypass`,且本次流程不得视为合规 sm-flow apply
- commit 后已获得用户明确的 apply 授权,除非用户在启动时要求"全自动执行"。 - commit 后已获得用户明确的 apply 授权,除非用户在启动时要求"全自动执行"。
- devflow 与 OpenSpec 没有未解决冲突。 - devflow 与 OpenSpec 没有未解决冲突。
- 没有未解决的 user-interview 问题、未判级接口影响、未汇报 evidence-driven 结论或未接受架构风险。 - 没有未解决的 user-interview 问题、未判级接口影响、未汇报 evidence-driven 结论或未接受架构风险。
**显式子 skill**:`openspec-apply-change`;遇到 bug/不确定行为时显式调用 `diagnose`;需要测试驱动时显式调用 `tdd`。进入本阶段必须调用指定子 skill,不得静默跳过。 **能力来源**:优先使用 `openspec-apply-change`;不可用时使用 `references/fallbacks.md#openspec-apply-内置协议`,并在 `decisions.md` 标注 fallback。遇到 bug/不确定行为时优先使用 `diagnose`;需要测试驱动时优先使用 `tdd`。不可用时执行对应最小协议并记录原因,不得静默跳过。
**动作**: **动作**:
### Pre-apply Checkpoint
**触发条件**:当 OpenSpec 涉及以下任一情况时必须执行
- design 或 tasks 中提到"参考 XXX 实现"
- 需要调用项目现有基础设施(MQ/统一请求结构/工具类等)
- 技术栈不熟悉或第一次在该项目实现类似功能
**执行步骤**:
1. **阅读所有参考实现**
- 从 OpenSpec design 或 tasks 中定位参考实现文件
- 如果路径不明确,通过 Grep 搜索关键类名或模式
- 理解关键逻辑,提取可复用代码片段和模式
2. **Grep 关键技术栈**
- 请求/响应结构模式(如 `RequestMsg`、`ResponseMsg`、DTO 规范)
- 消息队列模式(如 `@KafkaListener`、`@YkMsg`、发送模板)
- 统一工具类(如 `XxxUtil`、`XxxHelper`、加密/验签工具)
- 异常处理和日志记录标准
3. **形成技术栈清单并写入 decisions.md**
- 项目使用的请求/响应结构标准
- MQ 消息定义和发送标准
- Consumer 标准位置和写法
- 加密/验签/工具类的标准用法
- 识别需要新建的工具类或基础设施
**输出要求**:
- 技术栈清单已写入 `decisions.md` 的 "Pre-apply Research" 章节。
- 已列出所有参考实现的文件路径。
- 已识别需要新建的工具类/基础设施。
**按风险执行**:执行深度按 `references/scales.md` 的当前分档和实现风险决定;退出判断以清单是否足以指导实现为准。
### 实现过程
- 优先调用 `openspec-apply-change`。 - 优先调用 `openspec-apply-change`。
- 执行依据是 OpenSpec specs/tasks;devflow 只能作为上下文参考。 - 执行依据是 OpenSpec specs/tasks;devflow 只能作为上下文参考。
- 按 OpenSpec tasks 的纵向切片实现。 - 按 OpenSpec tasks 的纵向切片实现。
- **分步实现**:建议按 Controller → Service → MQ/异步组件 → Consumer/下游 顺序,每完成一层验证后再继续。
- 进入实现前先汇报本阶段的 capability 来源、当前 task 进度和本轮要推进的切片;否则 apply 不算真正开始。 - 进入实现前先汇报本阶段的 capability 来源、当前 task 进度和本轮要推进的切片;否则 apply 不算真正开始。
- **首模块完成后对齐检查**:完成第一个接口/模块后,对比 OpenSpec design/tasks,标记"已完成/TODO";核心功能(加密/验签/核心业务逻辑)不允许空实现或纯 TODO 注释。
- 当用户质疑、用户要求修改、代码检查、测试失败或运行行为与 OpenSpec 冲突时,做三类判断: - 当用户质疑、用户要求修改、代码检查、测试失败或运行行为与 OpenSpec 冲突时,做三类判断:
- OpenSpec 不准(规格遗漏、边界未覆盖、验收口径缺失)→ 暂停 apply,修正 OpenSpec 后重新提交。 - OpenSpec 不准(规格遗漏、边界未覆盖、验收口径缺失)→ 暂停 apply,修正 OpenSpec 后重新提交。
- 代码偏离(实现没按 OpenSpec 做)→ 修正代码,不改 OpenSpec。 - 代码偏离(实现没按 OpenSpec 做)→ 修正代码,不改 OpenSpec。
- 不确定根因、涉及设计方向、用户改变目标或范围 → 暂停并等待用户确认。 - 不确定根因、涉及设计方向、用户改变目标或范围 → 暂停并等待用户确认。
- 判断结果、证据、用户确认和 OpenSpec 回写状态必须记录到 `decisions.md`。 - 判断结果、证据、用户确认和 OpenSpec 回写状态必须记录到 `decisions.md`。
- **快速失败**:连续返工 ≥ 2 次时,暂停并重新执行 pre-apply checkpoint 或向用户汇报。
- 当用户要求、行为复杂或回归风险高时使用 TDD。 - 当用户要求、行为复杂或回归风险高时使用 TDD。
- 当测试失败、行为意外或原因不确定时使用 diagnose。 - 当测试失败、行为意外或原因不确定时使用 diagnose。
- 如果 diagnose 发现根因是 OpenSpec 不准确,先修正 OpenSpec,再继续 apply。 - 如果 diagnose 发现根因是 OpenSpec 不准确,先修正 OpenSpec,再继续 apply。
- 修改文件前遵守仓库指令,例如 `AGENTS.md`。 - 修改文件前遵守仓库指令,例如 `AGENTS.md`。
**退出条件**: **退出条件**:
- 已完成 pre-apply checkpoint(如触发条件满足),技术栈清单已写入 `decisions.md`。
- OpenSpec tasks 已完成,或剩余 tasks 已明确记录。 - OpenSpec tasks 已完成,或剩余 tasks 已明确记录。
- 核心功能已实现或明确标注"待联调",无纯 TODO 占位。
- 所有实现期冲突已分类并处理;没有未确认的规格遗漏、设计冲突或用户变更。 - 所有实现期冲突已分类并处理;没有未确认的规格遗漏、设计冲突或用户变更。
- 已运行验证,或记录了未验证原因。 - 已运行验证,或记录了未验证原因。
- 已列出已知限制。 - 已列出已知限制。
@@ -255,13 +327,13 @@
**进入条件**:实现或规划工作已经达到可交接状态。 **进入条件**:实现或规划工作已经达到可交接状态。
**显式子 skill**:`openspec-archive-change` 在用户确认 archive 后调用;archive 回填由 `sm-flow` 执行。必须调用子 skill,不得静默跳过。 **能力来源**:`openspec-archive-change` 在用户确认 archive 后优先调用;不可用时使用 `references/fallbacks.md#openspec-archive-内置协议`,并在 `acceptance.md` 标注 fallback。archive 回填由 `sm-flow` 执行。
**动作**: **动作**:
- 遵循 `references/archive-rules.md`。 - 遵循 `references/archive-rules.md`。
- 从 `decisions.md`(过程日志)+ OpenSpec 产物提炼完整 devflow 档案: - 从 `decisions.md`(过程日志)+ OpenSpec 产物提炼完整 devflow 档案:
- `brief.md`:从 proposal.md 提取背景、目标、范围、非目标。 - `brief.md`:从 proposal.md 提取背景、目标、范围、非目标。
- `evidence.md`:从 decisions.md 中的 evidence-driven 记录提取。 - `evidence.md`:按 `references/scales.md` 和 `references/archive-rules.md` 的当前分档要求处理。
- `decisions.md`:保持为最终版,整理格式。 - `decisions.md`:保持为最终版,整理格式。
- `acceptance.md`:从实现结果和验证结果提取。 - `acceptance.md`:从实现结果和验证结果提取。
- 只在复杂场景按需拆出 PRD/research/design/tasks/alignment。 - 只在复杂场景按需拆出 PRD/research/design/tasks/alignment。
@@ -271,7 +343,7 @@
- 询问用户是否要 archive OpenSpec change;不要默认执行归档。 - 询问用户是否要 archive OpenSpec change;不要默认执行归档。
**退出条件**: **退出条件**:
- `devflow/projects/YYYY-MM-DD-{slug}/` 包含 brief.md、evidence.md、decisions.md、acceptance.md;archive checkpoint 必须列出所有已创建的文件路径,验证文件实际存在于磁盘。 - `devflow/projects/YYYY-MM-DD-{slug}/` 包含 `references/scales.md` 和 `references/archive-rules.md` 要求的当前分档档案;archive checkpoint 必须列出所有已创建的文件路径,验证文件实际存在于磁盘。
- `devflow/index.md` 已包含或更新本项目条目。 - `devflow/index.md` 已包含或更新本项目条目。
- 用户已被询问是否 archive OpenSpec change。 - 用户已被询问是否 archive OpenSpec change。
@@ -0,0 +1,42 @@
# 分档规则
本文件是 `micro / standard / complex` 的唯一规则源。其它文件只引用本文件,不重复定义分档细节。
## standard 基准
standard 是默认分档,适用于普通功能、明确但有一定实现范围的变更。
- 用户可见 checkpoint:Discover → Commit → Apply → Archive。
- OpenSpec 产物:`proposal.md`、独立 `design.md`、`specs/`、`tasks.md`。
- grill:解决术语、边界、验收三个维度的高价值问题。
- commit gate:检查 proposal、design、specs、tasks 的完整性和一致性。
- devflow 档案:`brief.md`、`evidence.md`、`decisions.md`、`acceptance.md`。
## micro 覆盖
micro 适用于小改动、低风险、需求明确的变更。micro 是 standard 的减法,不是跳过流程。
- checkpoint 可合并:Discover + Commit 可在无阻塞时合并汇报。
- micro 内部流程压缩为:clarify+context 合并 checkpoint → 轻量 propose → grill → specify+commit 合并 checkpoint。
- context 保留最小收集:至少检查 glossary 和相关 ADR。
- grill 保留最小澄清:至少解决一个高价值问题,并记录术语、边界、验收三类是否明确;不明确项必须补问或标记风险。
- OpenSpec 仍需要 `proposal.md`、`specs/`、`tasks.md`。
- `design.md` 可不独立创建;允许在 `proposal.md` 或 `tasks.md` 中写等价设计小节。
- `specs/` 和 `tasks.md` 可轻量,但必须表达可观察行为和可执行任务。
- commit gate 仍必须通过,并创建 `.committed`。
- devflow 档案至少包含 `brief.md`、`decisions.md`、`acceptance.md`;证据少时可并入 `brief.md` 或 `decisions.md`。
- apply 仍只能依据 Committed OpenSpec。
- archive 仍要轻量回填 devflow,并询问是否归档 OpenSpec。
micro 不适用于接口影响不清、跨团队消费者、迁移/回滚、复杂状态机、长期架构决策或需求边界不清的变更;遇到这些情况应升级为 standard 或 complex。
## complex 增量
complex 适用于高风险、跨模块、需求不清、多人协作或长期架构影响明显的变更。complex 是 standard 的加法。
- 需要更完整的 Discover:增加需求澄清、证据查证、范围确认和风险接受。
- checkpoint 内可补充关键内部阶段结果,但不要把内部阶段名当作用户操作入口。
- 按需创建 `prd.md`、`research.md`、`alignment.md`、接口文档、ADR 或 compound knowledge。
- 接口影响、迁移、灰度、回滚、兼容性和消费者边界必须显式记录。
- audit 需要覆盖模块链路、数据所有权、生命周期、耦合风险和 ADR 冲突。
- archive 在 standard 档案基础上按需提炼长期 design、research、tasks、ADR 和 compound knowledge。
@@ -124,7 +124,7 @@
- 触发来源:用户质疑 / 用户变更 / 代码发现 / 测试失败 / 运行行为 - 触发来源:用户质疑 / 用户变更 / 代码发现 / 测试失败 / 运行行为
- 冲突对象:proposal / design / specs / tasks / ADR / 代码行为 - 冲突对象:proposal / design / specs / tasks / ADR / 代码行为
- 分类:实现偏差 / 规格遗漏 / 设计冲突 / 用户变更 - 分类:OpenSpec 不准 / 代码偏离 / 不确定
## 证据 ## 证据
@@ -136,7 +136,7 @@
- 决策: - 决策:
- 是否需要用户确认:是 / 否 - 是否需要用户确认:是 / 否
- OpenSpec 回写:不需要 / 已回写 / 待回写 - OpenSpec 回写:不需要 / 已回写 / 待回写 / 等待用户确认
- 代码处理: - 代码处理:
- 验证方式: - 验证方式:
``` ```
@@ -353,8 +353,8 @@ specify 阶段的 checkpoint 必须包含此检查表。每项标记"已对齐"
| 上游 → 下游 | 检查内容 | 状态 | | 上游 → 下游 | 检查内容 | 状态 |
|---|---|---| |---|---|---|
| brief/prd → proposal | 目标、范围、非目标、验收预期是否进入 proposal | 已对齐 / 存在 gap | | brief/prd → proposal | 目标、范围、非目标、验收预期是否进入 proposal | 已对齐 / 存在 gap |
| proposal → design | 范围、约束、关键承诺是否进入 design | 已对齐 / 存在 gap | | proposal → 设计产物 | 范围、约束、关键承诺是否进入 design.md 或等价设计小节 | 已对齐 / 存在 gap |
| design → specs/tasks | 影响实现的约束、接口影响、架构结论是否进入 specs 或 tasks | 已对齐 / 存在 gap | | 设计产物 → specs/tasks | 影响实现的约束、接口影响、架构结论是否进入 specs 或 tasks | 已对齐 / 存在 gap |
| specs → tasks | 可观察行为是否被 tasks 覆盖为可执行切片 | 已对齐 / 存在 gap | | specs → tasks | 可观察行为是否被 tasks 覆盖为可执行切片 | 已对齐 / 存在 gap |
### Gap 详情(如有) ### Gap 详情(如有)
+1 -1
View File
@@ -16,7 +16,7 @@
### 真理源 (Source of Truth) ### 真理源 (Source of Truth)
- **日期**和**短标识符 (slug)**:由目录名 `knowledge_YYYYMMDD_Slug/` 提取。 - **日期**和**短标识符 (slug)**:由目录名 `knowledge_YYYYMMDD_Slug/` 提取。
- **显示标题**、**tags**、**author**:由 YAML frontmatter 提取。 - **显示标题**、**tags**、**author**:由 YAML frontmatter 提取。
详见 [ADR-001](./adr/0001-directory-name-as-truth-source.md)。 详见 [decision.md](../../openspec/changes/knowledge-index-panel/decision.md)(原 ADR-001,2026-09-18 迁移)。
### 短标识符 (Slug) ### 短标识符 (Slug)
目录名中 `YYYYMMDD_` 之后的部分。用于脚本定位目录和构建文件路径。不用于显示(显示标题来自 YAML frontmatter 的 `title` 字段)。 目录名中 `YYYYMMDD_` 之后的部分。用于脚本定位目录和构建文件路径。不用于显示(显示标题来自 YAML frontmatter 的 `title` 字段)。
+11 -10
View File
@@ -1,12 +1,13 @@
# Devflow Index # devflow 索引
`devflow/index.md` 是 Phase 0.5 的默认上下文入口。每个 `devflow/projects/YYYY-MM-DD-{slug}/` 默认维护一行,帮助代理先定位相关项目,再读取具体 brief、acceptance、ADR 或 compound knowledge。 > 本文件由 scripts/check-dev-flow.sh --index 派生生成,**不要手写**。
> 存储层是 openspec/archive/ 下的归档目录;此处只是浏览视图。
| 日期 | slug | 领域 | 关键词 | 关联 OpenSpec | 状态 | | 日期 | 标题 | 归档位置 |
| --- | --- | --- | --- | --- | --- | |---|---|---|
| 2026-05-18 | knowledge-index-panel | knowledge-index | knowledge-index, search, tags, static-html | `openspec/changes/knowledge-index-panel/` | active | | 2026-05-25 | knowledge-index-sort Proposal | openspec/changes/archive/2026-05-25-knowledge-index-sort |
| 2026-05-19 | add-clear-filters | knowledge-index | clear-filters, search, tags, year-filter | `openspec/changes/archive/2026-05-19-add-clear-filters/` | archived | | 2026-09-18 | Decision: 建立旧 devflow 档案的迁移规则 | openspec/changes/archive/2026-09-18-migrate-devflow-archives |
| 2026-05-19 | add-year-filter | knowledge-index | year-filter, index-panel, frontmatter | `openspec/changes/add-year-filter/` | active | | 2026-05-19 | 2026-05-19-add-clear-filters | openspec/archive/2026-05-19-add-clear-filters |
| 2026-05-19 | dev-flow-skill-evaluation | sm-flow | dev-flow, sm-flow, skill-evaluation, fallback, phase-contracts | 未关联 | accepted-unarchived | | 2026-05-21 | 2026-05-21-sm-flow-v3-1-upgrade | openspec/archive/2026-05-21-sm-flow-v3-1-upgrade |
| 2026-05-21 | sm-flow-v3-1-upgrade | sm-flow | interface-impact, commit-gate, devflow-index, apply-conflict, skill-compatibility | `openspec/changes/archive/2026-05-21-sm-flow-v3-1-upgrade/` | archived | | 2026-07-05 | Validate SM Flow Explicit Trigger | openspec/archive/2026-07-05-validate-sm-flow-explicit-trigger |
| 2026-05-22 | sm-flow-execution-hardening | sm-flow | execution-hardening, checklist, phase-gate, cross-artifact, question-pool | 未关联 | active | | 2026-07-05 | Validate SM Flow Standard Change | openspec/archive/2026-07-05-validate-sm-flow-standard-change |
@@ -0,0 +1,48 @@
# Validate SM Flow Explicit Trigger Acceptance
## Result
Accepted and archived.
## Static Validation
- Trigger rule verification:
- `SKILL.md` frontmatter says sm-flow is only used for explicit `/sm-flow` commands or explicit natural-language requests.
- `SKILL.md` trigger section says task type alone must not auto-trigger sm-flow.
- `operating-rules.md` startup checks now include explicit natural-language requests.
- Scale source verification:
- Scale definition scan found `standard`, `micro`, and `complex` definition headings and definition phrases only in `references/scales.md`.
- Other files refer to `references/scales.md` instead of redefining the scale rules.
- Obsolete wording verification:
- No matches for minute/hour/second/timebox metrics.
- No matches for old skip semantics or old fixed `proposal.md + design.md` expression.
- No matches for old conflict wording targeted by this validation.
## Script Validation
- Passed: `python C:/Users/兜/.codex/skills/.system/skill-creator/scripts/quick_validate.py .agents/skills/sm-flow`
- Passed: reference integrity scan for `references/*.md`.
## Browser Or Manual Validation
- Not applicable. This change only modifies skill protocol text and validation records.
## Unverified
- Real external OpenSpec CLI integration was not executed because the current tool surface does not expose those child commands.
- Forward-testing with an independent subagent was not run in this pass.
## Fixed During Apply
- Replaced remaining hard-coded `design.md` wording in phase/audit fallback rules where the protocol must respect scale-specific design artifacts.
- Added explicit natural-language sm-flow requests to startup checks.
## OpenSpec Archive
- `.archive-ready` is present.
- User confirmed archive.
- Archived location: `openspec/archive/2026-07-05-validate-sm-flow-explicit-trigger/`.
- Status: `archived`.
- Archive method: local filesystem archive following existing repository convention because external `openspec-archive-change` is not directly callable in the current tool surface.
@@ -0,0 +1,29 @@
# Validate SM Flow Explicit Trigger Brief
## Background
`sm-flow` was simplified so it should only run on explicit user invocation. Related cleanup centralized scale rules, removed time-based metrics, and separated fallback/glossary details into references.
## Goal
Validate the current `sm-flow` design by running a real micro OpenSpec change through Discover, Commit, Apply, and Archive.
## Scope
- Validate `.agents/skills/sm-flow/SKILL.md`.
- Validate `.agents/skills/sm-flow/references/*.md`.
- Fix any protocol inconsistency found during validation.
- Record fallback capability source because external OpenSpec commands are unavailable in the current tool surface.
## Non-Goals
- No business code changes.
- No changes to the four visible checkpoints or nine internal phases.
- No automatic trigger heuristics.
- No historical archive rewrites.
## Scale
- Scale: `micro`.
- Evidence is folded into `decisions.md`.
- Linked OpenSpec change: `openspec/changes/validate-sm-flow-explicit-trigger/`.
@@ -0,0 +1,72 @@
# Validate SM Flow Explicit Trigger Decisions
## Capability Source
- Discover: sm-flow built-in protocol.
- Propose/specify/apply/archive: fallback protocol from `.agents/skills/sm-flow/references/fallbacks.md`.
- Missing external capability: OpenSpec CLI and OpenSpec child skills are not directly callable from the current tool surface.
- Impact: validation is file-based and static; it can verify current protocol text and artifacts but cannot exercise a real external OpenSpec command.
- Remaining risk: future tool availability may require rechecking integration behavior.
## Context
- `devflow/index.md` contains related sm-flow history:
- `dev-flow-skill-evaluation`
- `sm-flow-v3-1-upgrade`
- `sm-flow-execution-hardening`
- `devflow/glossary/CONTEXT.md` is project-level glossary and does not define sm-flow protocol terms.
- Current validation change is new: `validate-sm-flow-explicit-trigger`.
## Scale Decision
- Scale: `micro`.
- Reason: documentation/protocol validation only, no business code, no external interface contract change.
- Interface impact: L1 internal documentation/protocol validation.
- Micro constraints retained: proposal, specs, tasks, commit gate, apply verification, devflow archive, archive confirmation.
## Question Pool
| Question | Mode | Status | Result |
| --- | --- | --- | --- |
| Does top-level trigger text require explicit sm-flow invocation only? | evidence-driven | confirmed | `SKILL.md` frontmatter and trigger section both state explicit invocation only. |
| Are scale definitions centralized in `references/scales.md`? | evidence-driven | confirmed | Scan for scale definition headings and definition phrases only matched `references/scales.md`. |
| Are time/minute metrics absent from skill rules? | evidence-driven | confirmed | Obsolete time metric scan returned no matches. |
| Does fallback usage remain explicit and recorded? | evidence-driven | confirmed | This file records fallback source, impact, and remaining risk. |
| Is user confirmation needed for product scope? | user-interview | not required | User already requested this validation run; no unresolved product preference blocks this micro validation. |
## Cross-Artifact Alignment
| Link | Status | Notes |
| --- | --- | --- |
| brief/prd -> proposal | not applicable | Micro validation has no separate brief/prd before archive. |
| proposal -> design artifact | aligned | Proposal contains inline micro design notes. |
| design artifact -> specs | aligned | Specs cover explicit trigger, scale source, no time metrics, and fallback recording. |
| specs -> tasks | aligned | Tasks include scans, validation, patching if needed, and archive handoff. |
## Commit Gate
- Passed.
- Proposal explains why, what, scope, non-goals, inline design, and risks.
- Specs describe observable validation behavior.
- Tasks are executable and have validation evidence.
- Cross-artifact alignment has no unresolved gap.
- `.committed` created.
## Apply Log
- Validation found one consistency issue: `phase-contracts.md` still hard-coded `design.md` in specify/audit wording even though `scales.md` allows micro changes to use an equivalent inline design section.
- Fix applied: changed those references to "设计产物" where the rule must respect the current scale.
- Fix applied: `fallbacks.md` audit fallback now says to repair the design artifact instead of only `design.md`.
- Fix applied: `operating-rules.md` startup checks now include explicit natural-language requests to use sm-flow.
- Validation commands passed:
- `python C:/Users/兜/.codex/skills/.system/skill-creator/scripts/quick_validate.py .agents/skills/sm-flow`
- reference integrity scan for `references/*.md`
- obsolete wording scan for time metrics, old skip semantics, old conflict wording, and fixed `design.md` expressions.
- scale definition duplication scan.
## Archive Log
- User confirmed OpenSpec archive.
- External `openspec-archive-change` was not directly callable in the current tool surface.
- Archived by moving the OpenSpec change to `openspec/archive/2026-07-05-validate-sm-flow-explicit-trigger/`, matching existing repository archive convention.
- `devflow/index.md` status updated to `archived`.
@@ -0,0 +1,33 @@
# Validate SM Flow Standard Change Acceptance
## Result
Accepted and archived.
## Static Validation
- Scale rule centralization passed.
- Obsolete wording scan passed.
- Standard artifact completeness passed.
- Cross-artifact alignment passed.
## Script Validation
- Passed: skill quick validation.
- Passed: reference integrity scan.
## Browser Or Manual Validation
- Not applicable. This validation covers skill protocol files and OpenSpec/devflow records.
## Unverified
- External OpenSpec CLI integration.
- Independent forward-testing by a separate agent.
## OpenSpec Archive
- User confirmed archive.
- Archived location: `openspec/archive/2026-07-05-validate-sm-flow-standard-change/`.
- Status: `archived`.
- Archive method: local filesystem archive following existing repository convention because external `openspec-archive-change` is not directly callable in the current tool surface.
@@ -0,0 +1,25 @@
# Validate SM Flow Standard Change Brief
## Background
The micro validation confirmed the reduced path. This record validates the normal standard path, where independent design and separate evidence are required.
## Goal
Confirm that the current `sm-flow` skill supports a standard change with complete OpenSpec and devflow artifacts.
## Scope
- Validate standard artifact requirements.
- Validate scale rule centralization.
- Validate skill structure and reference integrity.
## Non-Goals
- No business code changes.
- No archive move without user confirmation.
- No complex migration, rollback, or cross-team interface test.
## Linked OpenSpec
`openspec/changes/validate-sm-flow-standard-change/`
@@ -0,0 +1,52 @@
# Validate SM Flow Standard Change Decisions
## Capability Source
- This is an ordinary engineering validation, not an explicit sm-flow invocation.
- External OpenSpec child commands are not directly callable in the current tool surface.
- Validation uses file-based OpenSpec fixtures and static/script checks.
## Scale Decision
- Scale: `standard`.
- Reason: this validation intentionally exercises the full normal artifact set: proposal, independent design, specs, tasks, and separate evidence.
- Interface impact: L1 internal documentation/protocol validation.
## Question Pool
| Question | Mode | Status | Result |
| --- | --- | --- | --- |
| Does standard require independent `design.md`? | evidence-driven | confirmed | `references/scales.md` defines independent `design.md` for standard. |
| Does standard require separate `evidence.md` in devflow? | evidence-driven | confirmed | `references/scales.md` defines `brief.md`, `evidence.md`, `decisions.md`, `acceptance.md`. |
| Are standard scale definitions duplicated outside `scales.md`? | evidence-driven | confirmed | Scale definition scan matched complete scale definitions only in `references/scales.md`. |
| Is user scope confirmation needed? | user-interview | not required | User asked to validate a regular change; no product scope choice is blocked. |
## Cross-Artifact Alignment
| Link | Status | Notes |
| --- | --- | --- |
| proposal -> design | aligned | Proposal asks for standard artifact validation; design defines standard artifact model. |
| design -> specs | aligned | Specs require full OpenSpec artifacts, evidence archive, and centralized scale definitions. |
| specs -> tasks | aligned | Tasks include fixture creation, validation scans, commit gate, and devflow records. |
## Findings
- Standard OpenSpec artifact completeness passed: `proposal.md`, independent `design.md`, spec file, and `tasks.md` exist.
- Cross-artifact alignment passed: proposal -> design -> specs -> tasks.
- Scale duplication scan passed.
- Obsolete wording scan passed.
- Skill quick validation passed.
- Reference integrity scan passed.
## Commit Gate
- `.committed` created.
- Status: committed standard validation fixture.
## Archive Status
- Devflow standard records created.
- User confirmed OpenSpec archive.
- External `openspec-archive-change` was not directly callable in the current tool surface.
- Archived by moving the OpenSpec change to `openspec/archive/2026-07-05-validate-sm-flow-standard-change/`, matching existing repository archive convention.
- `devflow/index.md` status updated to `archived`.
@@ -0,0 +1,34 @@
# Validate SM Flow Standard Change Evidence
## Static Evidence
- Scale definition scan found complete `standard / micro / complex` definition headings and definition phrases only in `.agents/skills/sm-flow/references/scales.md`.
- Obsolete wording scan returned no matches for:
- minute/hour/second/timebox metrics
- old skip semantics
- old fixed `proposal.md + design.md` expression
- old conflict wording targeted by prior validation
## Script Evidence
- Passed: `python C:/Users/兜/.codex/skills/.system/skill-creator/scripts/quick_validate.py .agents/skills/sm-flow`
- Passed: `references/*.md` integrity scan.
## Artifact Evidence
- OpenSpec standard artifacts exist:
- `openspec/changes/validate-sm-flow-standard-change/proposal.md`
- `openspec/changes/validate-sm-flow-standard-change/design.md`
- `openspec/changes/validate-sm-flow-standard-change/specs/sm-flow-standard-change/spec.md`
- `openspec/changes/validate-sm-flow-standard-change/tasks.md`
- Devflow standard artifacts exist:
- `brief.md`
- `evidence.md`
- `decisions.md`
- `acceptance.md`
## Limits
- This validation is static/file-based.
- It does not run a real external OpenSpec CLI command.
- It does not include independent subagent forward-testing.
@@ -0,0 +1 @@
Devflow archive files are ready for validate-sm-flow-explicit-trigger.
@@ -0,0 +1 @@
Committed OpenSpec for validate-sm-flow-explicit-trigger.
@@ -0,0 +1,44 @@
# Validate SM Flow Explicit Trigger
## Why
Recent edits simplified `sm-flow` so it should only run when the user explicitly invokes it. The same cleanup also centralized scale rules in `references/scales.md`, removed time-based metrics, and split fallback/glossary concepts out of the top-level skill.
This change validates those protocol decisions through a real micro `sm-flow` run instead of another informal review.
## What Changes
- Verify `sm-flow` only triggers on `/sm-flow`, `/sm-flow explore`, `/sm-flow apply`, `/sm-flow archive`, or an explicit natural-language request to use sm-flow.
- Verify task type alone does not trigger `sm-flow`, even when the task mentions OpenSpec, devflow, cross-module work, or clarification.
- Verify `micro / standard / complex` definitions live only in `references/scales.md`.
- Verify the skill has no time/minute-based metrics.
- Verify fallback usage is recorded when external OpenSpec capabilities are unavailable.
## Design Notes
- Scale: `micro`.
- Interface impact: L1 internal documentation/protocol validation only.
- No business code changes.
- Independent `design.md` is intentionally omitted; this section is the micro design artifact.
- OpenSpec CLI and external OpenSpec child skills are not directly callable in the current tool surface, so this run uses `references/fallbacks.md` and records that capability source in devflow.
## Scope
In scope:
- `.agents/skills/sm-flow/SKILL.md`
- `.agents/skills/sm-flow/references/*.md`
- Validation OpenSpec and devflow records for this change
Out of scope:
- Business code
- Rewriting historical OpenSpec archives
- Changing the four visible checkpoints or nine internal phases
- Adding automatic trigger heuristics
## Risks
- A future edit may duplicate scale rules outside `references/scales.md`.
- The frontmatter description may drift from the top-level trigger rule.
- Validation can prove current text consistency, but cannot force future agents to obey it without continued review.
@@ -0,0 +1,53 @@
# sm-flow Explicit Trigger Spec
## ADDED Requirements
### Requirement: Explicit Trigger Only
`sm-flow` SHALL be used only when the user explicitly invokes `/sm-flow`, `/sm-flow explore`, `/sm-flow apply`, `/sm-flow archive`, or clearly asks to use the sm-flow process in natural language.
#### Scenario: Plain engineering request
- **Given** a user asks for an engineering task that mentions OpenSpec, devflow, cross-module work, or clarification
- **When** the user does not explicitly request sm-flow
- **Then** the agent handles the task as ordinary engineering work
- **And** the agent does not auto-trigger sm-flow based on task type
#### Scenario: Explicit sm-flow request
- **Given** a user invokes `/sm-flow` or clearly asks to use sm-flow
- **When** the agent starts the process
- **Then** the agent follows the visible checkpoints Discover, Commit, Apply, and Archive
- **And** the internal phase order remains clarify, context, propose, grill, specify, audit, commit, apply, archive
### Requirement: Scale Rules Have One Source
The `micro / standard / complex` scale definitions SHALL be defined in `references/scales.md`; other files may only reference that file instead of redefining scale details.
#### Scenario: Scale guidance is needed
- **Given** a phase needs to choose or enforce a scale
- **When** the rule is read
- **Then** it points to `references/scales.md`
- **And** no other reference file carries a competing full definition of the three scales
### Requirement: No Time-Based Skill Metrics
The skill SHALL NOT use minute, hour, second, or timebox metrics to define scale, effort, or validation thresholds.
#### Scenario: Protocol text is scanned
- **Given** the sm-flow skill files are scanned
- **When** obsolete time metrics are searched
- **Then** no matching scale or effort rule remains
### Requirement: Fallback Capability Is Explicit
When OpenSpec CLI or child skill capabilities are unavailable, `sm-flow` SHALL use `references/fallbacks.md` only as an explicit fallback and record the capability source in the current devflow process log.
#### Scenario: External capability unavailable
- **Given** OpenSpec child skills are not directly callable
- **When** a change is still executed
- **Then** the decisions log records fallback source, impact, and remaining risk
- **And** the fallback does not skip context, grill, commit, apply, or archive gates
@@ -0,0 +1,26 @@
# Tasks
## 1. Discover
- [x] 1.1 Read current `sm-flow` top-level trigger rule and relevant references.
- [x] 1.2 Read `devflow/index.md` and glossary context for related history.
- [x] 1.3 Classify this validation as `micro` and record capability fallback.
## 2. Commit
- [x] 2.1 Create micro OpenSpec proposal with inline design notes.
- [x] 2.2 Create specs that express the observable validation expectations.
- [x] 2.3 Create executable validation tasks.
- [x] 2.4 Run cross-artifact alignment and create `.committed`.
## 3. Apply
- [x] 3.1 Scan `sm-flow` files for obsolete trigger, scale, time metric, and fallback wording.
- [x] 3.2 Patch any discovered inconsistency in the skill files.
- [x] 3.3 Run skill validation and reference integrity checks.
## 4. Archive
- [x] 4.1 Create micro devflow archive files.
- [x] 4.2 Update `devflow/index.md`.
- [x] 4.3 Create `.archive-ready` and ask whether to archive OpenSpec.
@@ -0,0 +1 @@
Devflow archive files are ready for validate-sm-flow-standard-change.
@@ -0,0 +1 @@
Committed OpenSpec for validate-sm-flow-standard-change.
@@ -0,0 +1,35 @@
# Design
## Scale
Scale: `standard`.
Rationale: this validation has a clear target and no business-code risk, but it intentionally exercises the full normal artifact set rather than the reduced micro path.
## Interface Impact
Interface impact: L1 internal documentation/protocol validation.
No API, DTO, database, event, service, or cross-module runtime contract changes are expected.
## Artifact Model
Standard validation requires:
- OpenSpec: `proposal.md`, independent `design.md`, `specs/`, `tasks.md`.
- Devflow archive: `brief.md`, `evidence.md`, `decisions.md`, `acceptance.md`.
The validation checks that current skill rules point to `references/scales.md` for the exact standard artifact requirements instead of redefining them elsewhere.
## Execution Design
1. Build the standard OpenSpec fixture.
2. Run static scans for standard artifact wording and duplicated scale definitions.
3. Run skill validation and reference integrity checks.
4. Record evidence separately in `devflow/.../evidence.md`.
5. Mark the fixture as committed only if artifact completeness and alignment pass.
## Risks
- The external OpenSpec archive/apply commands are not exposed in the current tool surface; this validation uses file-based checks.
- File presence does not prove independent-agent usability; forward-testing remains a separate optional validation surface.
@@ -0,0 +1,39 @@
# Validate SM Flow Standard Change
## Why
The previous validation covered a micro change. A standard change has stricter expectations: an independent `design.md`, complete OpenSpec artifacts, and a separate `evidence.md` in devflow.
This validation checks whether the current `sm-flow` skill can still describe and validate a normal standard change after the recent simplification work.
## What Changes
- Create a standard-scale validation fixture for `sm-flow`.
- Verify standard OpenSpec artifacts exist and are aligned: `proposal.md`, `design.md`, `specs/`, and `tasks.md`.
- Verify standard devflow archive artifacts exist: `brief.md`, `evidence.md`, `decisions.md`, and `acceptance.md`.
- Verify standard still uses the same four visible checkpoints and nine internal phases without exposing phase names as user commands.
## Scope
In scope:
- Standard-scale validation records.
- Static checks over `.agents/skills/sm-flow`.
- Narrow fixes to the skill if standard validation reveals inconsistency.
Out of scope:
- Business code changes.
- Reworking archived historical changes.
- Changing the current trigger policy.
## Non-Goals
- This change does not test a complex migration, rollback, or cross-team interface change.
- This change does not require independent browser/manual validation.
- This change does not replace the micro validation already archived.
## Risks
- A standard validation fixture can become noise if left unarchived; status must be explicit.
- If standard rules are only validated by file presence, semantic drift may still require future forward-testing.
@@ -0,0 +1,36 @@
# sm-flow Standard Change Spec
## ADDED Requirements
### Requirement: Standard Change Has Full OpenSpec Artifacts
A standard `sm-flow` change SHALL have `proposal.md`, independent `design.md`, `specs/`, and `tasks.md`.
#### Scenario: Standard fixture is committed
- **Given** a change is classified as `standard`
- **When** commit validation runs
- **Then** `proposal.md`, `design.md`, at least one spec file, and `tasks.md` exist
- **And** the artifacts are aligned from proposal to design to specs to tasks
### Requirement: Standard Archive Has Evidence
A standard `sm-flow` archive SHALL include `brief.md`, `evidence.md`, `decisions.md`, and `acceptance.md` in devflow.
#### Scenario: Standard fixture is archived or accepted
- **Given** a standard validation change has completed apply checks
- **When** devflow records are written
- **Then** `evidence.md` exists as a separate file
- **And** it records the static and script validation evidence used for acceptance
### Requirement: Scale Definitions Remain Centralized
Standard-specific artifact requirements SHALL be defined by `references/scales.md`; other files may reference those requirements but not carry a competing full definition.
#### Scenario: Standard wording is scanned
- **Given** sm-flow references mention standard behavior
- **When** scale definition phrases are scanned
- **Then** complete standard definitions appear only in `references/scales.md`
- **And** operational files defer to the current scale rather than hard-coding alternative standard rules
@@ -0,0 +1,29 @@
# Tasks
## 1. Standard OpenSpec Fixture
- [x] 1.1 Create `proposal.md`.
- [x] 1.2 Create independent `design.md`.
- [x] 1.3 Create at least one spec under `specs/`.
- [x] 1.4 Create `tasks.md`.
## 2. Standard Validation
- [x] 2.1 Run scale duplication scan.
- [x] 2.2 Run obsolete wording scan.
- [x] 2.3 Run skill quick validation.
- [x] 2.4 Run reference integrity scan.
## 3. Commit Gate
- [x] 3.1 Confirm OpenSpec artifact completeness.
- [x] 3.2 Confirm proposal -> design -> specs -> tasks alignment.
- [x] 3.3 Create `.committed`.
## 4. Devflow Records
- [x] 4.1 Create `brief.md`.
- [x] 4.2 Create separate `evidence.md`.
- [x] 4.3 Create `decisions.md`.
- [x] 4.4 Create `acceptance.md`.
- [x] 4.5 Update `devflow/index.md`.
@@ -0,0 +1,70 @@
# Decision: 年份筛选采用纯前端派生,不新增数据字段
## Problem
知识索引只能按关键词和标签过滤。当条目跨越多个月份和年份时,列表只会越来越长,而用户缺少一个**粗粒度**的收敛手段——想回看某一年沉淀了什么,只能靠肉眼扫或者记住关键词。
而"年份"这个维度其实**已经躺在数据里**了:每个条目的 `date` 字段(格式 `YYYYMMDD`)是渲染日期时的唯一来源。也就是说这不是一个需要新增信息的需求,而是一个**已经存在的信息没有暴露给用户**的问题。
## Decision
年份从 `ENTRIES[].date.slice(0,4)` 派生,**不新增数据字段**。
- 控件用原生 `<select id="year-filter">`,位置在搜索框下方、标签云上方,与搜索、标签同属一组合并过滤。
- 选项从条目里**实际出现的**年份去重生成、倒序排列;只接受能匹配 `/^\d{4}$/` 的值。默认"全部年份"。
- 过滤并入现有 `applyFilters()` 作为**单一过滤入口**,顺序为 `年份 → 标签 → 搜索`。
- 修改在 `scripts/update-knowledge-index.sh` 的 HTML 模板里完成,再重建 `knowledge-index.html`。
## Alternatives considered
**新增 `year` 字段到条目数据。** 冗余——`date` 已是唯一来源,派生成本为零,多一个字段就多一处可能不一致的地方。而且条目是 `knowledge_*/` 下的手写 markdown,新增字段意味着所有历史条目都要回填。
**引入第三方筛选组件(Select2 等)。** 为 4 行原生 `<select>` 代码引入依赖,与仓库"单文件静态 HTML、零依赖"的约束直接冲突。
**只修改生成后的 `knowledge-index.html`,不改生成脚本。** 更快,但 `knowledge-index.html` 是**生成产物**——下一次重建即丢功能,生成脚本才是真理源。这条在实现过程中确实被识别为"主要风险"(见 `design.md` 的架构审计一节),但**当时没有被记成一条备选**。它是一个真实的、有诱惑力的错误选项,所以补录在这里。
## Consequences
**得到**
- 零依赖、无数据迁移,没有新字段需要维护一致性。
- 与既有搜索、标签过滤自然组合,因为三者走同一个 `applyFilters()` 入口。
- 年份选项只列**实际存在**的年份,不会出现空年份。
- 重建索引不会丢功能——修改落在生成脚本的模板里。
**代价**
- **只有年粒度**:不支持月份、日期范围、时间线视图或自定义排序。
- `<select>` 选项数量随年份**线性增长**。以当前条目量完全可接受;多年后可能需要改成可搜索的下拉。
- 过滤在前端全量进行。条目数量级显著变大时需要改为服务端或预建索引方案。
**已知限制**
- `date` 为空或不匹配 `YYYYMMDD` 的条目:不进入年份选项,在"全部年份"下仍显示,选中具体年份时隐藏。
- 年份比较基于**字符串前四位**,不做真实日期解析——因此 `20260230` 这类非法日期会被当作 2026 年处理。这是有意的取舍:真实解析会引入日期库依赖,而收益只覆盖一个不会出现的输入。
## Verification
以下命令均在仓库根目录执行,路径为相对路径。
**只读(可直接跑,已在本次收尾时实测)**
- 控件同时存在于生成产物与模板两处
`grep -c 'id="year-filter"' knowledge-index.html scripts/update-knowledge-index.sh`
→ `knowledge-index.html: 1`,`scripts/update-knowledge-index.sh: 1`
- 年份过滤确实并入唯一入口 `applyFilters()`(函数体起始于第 217 行)
`grep -n 'selectedYear' knowledge-index.html`
→ `219`(读取控件值)、`228`(判断)、`229`(执行过滤)——三处都在函数体内
- 生成脚本语法完整(只做语法检查,不执行)
`bash -n scripts/update-knowledge-index.sh` → `exit=0`
**有副作用(会重写 `knowledge-index.html`,故未在收尾时运行)**
- 重建后功能仍在
`bash scripts/update-knowledge-index.sh`,然后复跑上面两条 `grep`
**人工**
选择 `2026` → 只显示 `date` 以 `2026` 开头的条目;再激活一个标签 → 两者取交集;选"全部年份" → 年份过滤解除,而标签仍然生效。
@@ -0,0 +1,49 @@
# Decision: 建立旧 devflow 档案的迁移规则
<!-- authorized: 2026-09-18 确认点1通过,用户对话授权("继续"),范围:单样本迁移+本change四件套 -->
## Problem
dev-flow 取消了 devflow 作为"人类档案层"的定位(2026-09-18 重设计),决策档案的唯一落点变为 `openspec/changes/<slug>/decision.md`。但历史遗留 9 个项目、37 个文件仍在 `devflow/projects/` 下,按四套并存的命名约定组织,与 OpenSpec 归档内容大量重复。
真实成本:同一次变更的事实存在两处权威(如 `add-year-filter` 的 design 双写),而最稀缺的内容——备选方案——全库仅 1/37 被记录。不迁移,则 dev-flow 的新真理源布局与旧档案层长期并存,"一个事实只有一个权威"持续被违反;全删,则丢失 ADR-0001 等真实决策资产。
## Alternatives considered
- Q: 全部删除 devflow/projects/? A: 不——ADR-0001(knowledge-index-panel)与部分 decisions.md 的关键取舍是真实决策资产,删了就丢。
- Q: 全部原地保留、只加链接? A: 不——治标;活跃 change 缺 decision.md 的检查缺口仍在,重复权威仍在。
- **只迁移值得留的,骨架删除,以单样本先行定规则。** 全量一次迁移风险不可控(37 文件四套约定);单样本验证规则后再批量。
## Decision
**以"寿命规则"处置旧 devflow 档案:跨变更活的并入新真理源,随变更死的不留;单样本先行,批量另立 change。**(2026-09-18 实际执行)
- 单样本 `2026-05-18-knowledge-index-panel`:ADR-0001 五节转译为 `openspec/changes/knowledge-index-panel/decision.md`(备选转 Q&A 形态,`migrated-from` 注释溯源);PRD 收存为 change 内 `prd.md`(冻结);glossary 引用同步更新
- 首次迁移**不删除**源文件——删除等批量规则稳定后统一执行
- 迁移规则五步(评估→转译→收存→改引用→暂不删)沉淀在 `design.md` 的 Migration Plan,批量迁移按此执行
计划与执行一致,无偏差。
## Consequences
**买到了**:
- knowledge-index-panel 由检查 ✗ 转 ✓,决策资产进入新真理源布局
- 迁移规则经一次真实执行验证,批量迁移(其余 8 项目)有了可引用的依据
- dev-flow 全路径(Think→确认点1→Build→Close)首次完整运行,协议自举验证
**付出了**:
- 旧 ADR-0001 与新 decision.md 双存在,直到批量清理——期间旧文件无入边(glossary 已改指新位置),漂移风险低但非零
- PRD 中 Implementation Decisions 小节与 design.md 内容有重叠——PRD 按历史文档冻结收存,接受
- 迁移是**补录**(retrofit):Alternatives 是从 ADR-0001 转译而非 grill 当场记录,形态合规但时机不理想——这正是它作为"历史迁移"而非"新变更"的本性
## Verification
**只读(可直接跑)**
- `bash scripts/check-dev-flow.sh knowledge-index-panel` → 3 项全过,exit=0
- `bash scripts/check-dev-flow.sh migrate-devflow-archives` → 3 项全过,exit=0
- `grep -c 'decision.md' devflow/glossary/CONTEXT.md` → ≥1(引用已指向新位置)
- `head -3 openspec/changes/knowledge-index-panel/decision.md` → 首行为 `# Decision: 目录名作为日期和标题的真理源`
**有副作用(会重写文件,收尾时不必跑)**
- `bash scripts/check-dev-flow.sh --index`(重生成 devflow/index.md)
@@ -0,0 +1,47 @@
## Context
dev-flow 重设计后,决策档案唯一落点为 `openspec/changes/<slug>/decision.md`。旧 `devflow/projects/`(9 项目/37 文件,四套命名约定并存)需按"寿命规则"处置:**跨变更活的留(并入 decision.md 或 glossary),随变更死的不留(骨架删除)**。
本 change 只执行单样本(`2026-05-18-knowledge-index-panel`),验证规则;批量迁移是后续独立 change。
## Goals / Non-Goals
**Goals**
- knowledge-index-panel 获得合规的 decision.md(迁移自 ADR-0001,五节俱全)
- PRD 独有内容(User Stories、测试决策、Out of Scope)不丢失
- glossary 引用不因迁移产生死链
- 迁移规则本身作为 decision 沉淀,可被批量迁移引用
**Non-Goals**
- 不批量处理其余 8 个项目
- 不删除 devflow/projects/ 任何文件(删除动作在批量规则稳定后)
- 不处理 add-year-filter(已有 decision.md)与 sm-flow-execution-hardening(待其自身 Close)
## Decisions
| 决策 | 理由 | 备选 |
|---|---|---|
| ADR-0001 转译为 decision.md 而非原样复制 | 旧格式(背景/决策/替代方案/后果)→ 新五节骨架,Alternatives 转 Q&A 形态;`migrated-from` 注释保留溯源 | 原样复制(格式两套并存) |
| PRD 收存为 change 内 `prd.md` | User Stories/测试决策/Out of Scope 是 proposal 没有的独有内容;v3.1 规则"复杂需求才留 PRD"在此适用 | 删除(丢失独有内容)/留在 devflow(违反唯一权威) |
| 溯源用 HTML 注释而非正文小节 | 注释不渲染不干扰阅读,机器可查 | 正文"来源"小节(视觉噪音) |
| 首次迁移不删源文件 | 删除是破坏性动作;规则未经批量验证前保守 | 迁移即删(不可逆风险) |
## Risks / Trade-offs
- **devflow/projects 旧文件与新 decision.md 短暂双存在**(至批量清理):接受——单样本期间删除更危险;glossary 已指向新位置,旧 ADR 无入边
- **PRD 中 Implementation Decisions 小节与 design.md 可能重复**:接受——PRD 是历史文档,冻结收存,不回改
## Migration Plan
单样本流程(批量迁移按此规则执行):
1. 评估旧项目文件:有独有决策/备选/取舍 → 并入对应 change 的 decision.md;纯骨架/与 OpenSpec 重复 → 标记待删
2. 转译格式:旧四节 → 新五节,备选转 Q&A 形态,加 `migrated-from` 溯源注释
3. PRD 等独有产物收存进 change 目录(冻结,不回改)
4. glossary 等活文件中的路径引用同步更新
5. 源文件暂不删,批量规则稳定后统一清理
## Open Questions
- 其余 8 个项目中,`dev-flow-skill-evaluation` 的评估结论已沉淀进 workflow.md 演进史,其 todo.md 大概率可删——留批量时判断
- `sm-flow-v3-1-upgrade` 等后期项目的 decisions.md 含真实取舍(术语裁决、产物瘦身决策),逐条评估是否值得并入 sm-flow 归档——批量时逐项目处置
@@ -0,0 +1,26 @@
## Why
dev-flow 重设计(2026-09-18)取消了 devflow 作为独立档案层的定位:决策档案唯一落点为 `openspec/changes/<slug>/decision.md`,随归档冻结;devflow/ 收缩为 glossary + rejected + 派生 index。历史遗留 9 个项目、37 个文件需要按新布局处置,否则新旧两种真理源布局长期并存。
SuperBizAgent-java 实测(46 项目/180 文件)已给出处置口径:压缩 Q&A 与 ADR 段落并入对应归档的 decision.md,骨架文件删除。本仓库先以单样本(`2026-05-18-knowledge-index-panel`)验证规则,再定批量执行。
## What Changes
- 为 `openspec/changes/knowledge-index-panel/` 新建 `decision.md`:内容迁移自 `devflow/projects/2026-05-18-knowledge-index-panel/adr/0001-directory-name-as-truth-source.md`(五节俱全),标注迁移来源
- `knowledge-index-panel-prd.md` 含独有内容(User Stories、测试决策),收存为 `openspec/changes/knowledge-index-panel/prd.md`
- 更新 `devflow/glossary/CONTEXT.md` 中对 ADR-0001 旧路径的引用,指向新位置
- 本 change(`migrate-devflow-archives`)自身按 dev-flow 协议执行,其 decision.md 记录迁移规则本身
- 其余 8 个项目:本次不动(见 Non-Goals)
## Non-Goals
- 不批量迁移其余 8 个项目——单样本验证规则后另行执行
- 不删除 `devflow/projects/` 下任何现有文件——删除等批量规则稳定后统一处理
- 不处理 3 个活跃 change 中另外两个(`add-year-filter` 已有 decision.md;`sm-flow-execution-hardening` 待其自身 Close)
## Impact
- `openspec/changes/knowledge-index-panel/` 新增 2 文件(decision.md、prd.md)
- `devflow/glossary/CONTEXT.md` 改 1 处链接
- `scripts/check-dev-flow.sh knowledge-index-panel` 应由 ✗ 转 ✓
- 迁移规则沉淀在 `openspec/changes/migrate-devflow-archives/decision.md`,作为后续批量迁移的依据
@@ -0,0 +1,11 @@
# Tasks: migrate-devflow-archives
- [x] 1. Think:写 proposal.md + decision.md 的 Problem/Alternatives(迁移规则作为备选记录)
- [x] 2. 确认点 1:汇报方案,获得授权并记录
- [x] 3. 单样本:knowledge-index-panel/decision.md 迁移自 ADR-0001(五节转译,Q&A 备选,migrated-from 溯源)
- [x] 4. 单样本:prd.md 收存进 change 目录
- [x] 5. glossary/CONTEXT.md 的 ADR-0001 引用更新为新路径
- [x] 6. design.md(迁移规则细节)与 tasks.md 落盘
- [x] 7. Close:补齐本 change decision.md 的 Decision/Consequences/Verification
- [x] 8. 验证:`check-dev-flow.sh knowledge-index-panel` 与 `check-dev-flow.sh migrate-devflow-archives` 均通过;`--index` 重生成
- [x] 9. 确认点 2:汇报产物与剩余风险,用户确认归档(2026-09-18,"继续")
@@ -0,0 +1,42 @@
# Decision: 目录名作为日期和标题的真理源
<!-- migrated-from: devflow/projects/2026-05-18-knowledge-index-panel/adr/0001-directory-name-as-truth-source.md (2026-09-18, change: migrate-devflow-archives) -->
## Problem
知识吸收器输出目录遵循 `knowledge_YYYYMMDD_Title/` 命名约定。目录内的 `.md` 文件包含 YAML frontmatter,其中也有 `date`/`created` 和 `title` 字段,但实际使用中发现字段名不一致(`date` vs `created`)且格式有差异。
索引重建脚本需要确定日期和标题的权威来源——两个来源都存在且都可能被读到时,不指定权威就必然漂移。
## Decision
**日期和短标识符 (slug) 的真理源是目录名。显示标题、tags、author 的真理源是 YAML frontmatter。**
- 日期从目录名的 `YYYYMMDD` 部分提取
- 短标识符从目录名的 `Slug` 部分提取(用于文件路径构建,不用于显示)
- 显示标题从 YAML frontmatter 的 `title` 字段提取
- `tags` 和 `author` 从 YAML frontmatter 提取
## Alternatives considered
- Q: YAML 字段全优先? A: 不——字段名不一致(date vs created),脚本要处理变体,漂移点更多。
- Q: 目录名全优先? A: 不——标题中的语义信息在下划线转空格后丢失(如 `mattpocock_skills` → `mattpocock skills`,实际标题更长更精确)。
## Consequences
**买到了**:
- 索引脚本不需要处理日期字段名变体(date vs created)
- 目录名是可见的、可审计的——与 `ls` 输出完全一致
- bash 用 glob 匹配 `knowledge_*` 目录,天然获取了日期和 slug
- 显示标题从 YAML 取,支持完整的、精确的标题文本(含标点、中文)
**付出了**:
- 索引脚本需要解析 YAML frontmatter(复杂度比仅取目录名高)
- 如果目录被重命名,slug 会变化但显示标题不受影响(可接受的行为)
- 知识吸收器 skill 必须严格遵守 `knowledge_YYYYMMDD_Slug` 命名约定
## Verification
**只读(可直接跑)**
- `ls knowledge/entries/ | head -3` → 目录名均形如 `knowledge_YYYYMMDD_Slug`
- `grep -n 'date' scripts/update-knowledge-index.sh | head -5` → 日期提取自目录名而非 YAML
@@ -0,0 +1,57 @@
# PRD: 知识库索引面板 (Knowledge Index Panel)
## Problem Statement
用户每次用 `/knowledge-absorber` 学习后,会在项目根目录生成 `knowledge_YYYYMMDD_Title/` 文件夹。目前有 2 个知识条目,预计每月增长 5-10 个。所有条目散落在根目录,没有跨条目的导航或搜索能力。想找之前学过的内容只能手动翻目录,搜索成本随条目数线性上升。
## Solution
在项目根目录生成一个 **纯静态的 `knowledge-index.html`**,浏览器直接打开即可使用。它能自动发现所有 knowledge 条目,提供标签关联和全文搜索。不需要任何服务器、数据库或外部依赖。
## User Stories
1. As a 学习者, I want to see all my knowledge entries on one page with dates, so that I can quickly find what I studied and when
2. As a 学习者, I want to search across all knowledge entries by keyword, so that I can find "that thing about Redis" in 2 seconds instead of manually opening 10 folders
3. As a 学习者, I want to click a tag like "Claude Code" and see all related entries, so that I can review interconnected topics
4. As a 学习者, I want the index to auto-discover new knowledge entries, so that I don't need to manually update anything after running `/knowledge-absorber`
5. As a 学习者, I want the page to work offline by just double-clicking the HTML file, so that I can use it without internet or any setup
6. As a 学习者, I want to see which entries are related to each other via shared tags, so that I can discover connections between topics I've studied
7. As a 学习者, I want the search to highlight matching text, so that I can see at a glance why an entry matched my query
8. As a 学习者, I want to see a count of entries per tag, so that I know which topics I've studied most
## Implementation Decisions
- **Single HTML file**: All CSS and JS inlined in `knowledge-index.html`. No external files or CDN dependencies
- **Manifest-based discovery**: A JavaScript array inside the HTML lists all known knowledge directory names. Browser security sandbox prevents dynamic directory listing via `fetch()`
- **YAML frontmatter parsing**: Regex-based extraction from `.md` files. Simple key:value parsing only — no full YAML spec support
- **Client-side search**: All `.md` content loaded into memory at page init. Real-time filtering with `String.includes()`, case-insensitive. `<mark>` tags for highlighting
- **Tag system**: In-memory `Map<tag, entry[]>` built at load time. Click to filter, click again to deselect
- **Related Content**: Computed from shared tags, displayed per-entry
- **No pagination**: Designed for < 50 entries. Full list rendered at once
- **UTF-8 encoding**: All files assumed UTF-8. `fetch()` handles encoding detection
## Testing Decisions
- **What makes a good test**: Test external behavior — "user types keyword → correct entries appear" — not internal state
- **Test with real data**: Use existing 2 knowledge entries (`knowledge_20260417_Waza`, `knowledge_20260518_mattpocock_skills`) as test fixtures
- **Edge cases to verify**:
- Missing directory (manifest lists a name that doesn't exist) → skip gracefully
- Malformed YAML → display directory name as fallback
- Empty tags array → no tag badges rendered
- No search results → show "没有找到相关条目" message
- Browser CORS when opened via `file://` protocol → document the workaround
## Out of Scope
- Google Drive / cloud sync
- Editing knowledge entries
- Full YAML 1.2 spec compliance
- Pagination or virtual scrolling
- Fuse.js or other fuzzy search libraries (keep it zero-dependency)
- Dark mode toggle (can add later, not in v1)
## Further Notes
- The manifest maintenance problem (adding new entries) can be solved in a future iteration by modifying the `/knowledge-absorber` skill to auto-append to the manifest array
- The `file://` protocol CORS limitation on Chrome means users may need to serve via `python -m http.server` or similar for full functionality
- Tag counts provide a natural "learning heatmap" — most-studied topics bubble to the top
+141
View File
@@ -0,0 +1,141 @@
#!/usr/bin/env bash
set -euo pipefail
# dev-flow 收尾检查 + index 派生
# 检查模式: check-dev-flow.sh <slug> → 对 openspec/changes/<slug>/ 执行三项收尾检查
# 索引模式: check-dev-flow.sh --index → 扫描 openspec/changes/archive/ 与 openspec/archive/ 生成 devflow/index.md
# 全量模式: check-dev-flow.sh --all → 对所有活跃 change 执行检查
#
# 三项收尾检查:
# 1. decision.md 存在(豁免需显式: decision.md 或提交信息中写明)
# 2. 含 ## Alternatives considered 或显式 <!-- alternatives-not-recorded -->
# 3. ## Verification 无"已确认 X"类不可重跑结论
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
CHANGES_ROOT="$PROJECT_ROOT/openspec/changes"
fail() { echo "✗ $1" >&2; exit 1; }
check_change() {
local slug="$1"
local dir="$CHANGES_ROOT/$slug"
local decision="$dir/decision.md"
local errors=0
[ -d "$dir" ] || fail "change 目录不存在: openspec/changes/$slug"
echo "== dev-flow 收尾检查: $slug =="
# 1. decision.md 存在
if [ ! -f "$decision" ]; then
echo "✗ [1] 缺少 openspec/changes/$slug/decision.md (纯机械改动可豁免,但豁免必须显式写在提交信息里)"
errors=$((errors+1))
else
echo "✓ [1] decision.md 存在"
# 2. Alternatives 强制
if grep -q '^## Alternatives considered' "$decision" || grep -q '<!-- alternatives-not-recorded -->' "$decision"; then
echo "✓ [2] 备选已记录或显式声明未记录"
else
echo "✗ [2] decision.md 缺少 ## Alternatives considered,也没有 <!-- alternatives-not-recorded --> 显式豁免"
errors=$((errors+1))
fi
# 3. Verification 无不可重跑结论
local vtext
vtext="$(awk '/^## Verification/{flag=1;next} /^## /{flag=0} flag' "$decision")"
if echo "$vtext" | grep -qE '已确认|已验证[^,。;(]|测试通过$'; then
echo "✗ [3] ## Verification 含不可重跑的结论(如\"已确认 X 存在\")——改为可重跑的命令或明确的人工步骤"
errors=$((errors+1))
elif [ -z "$vtext" ]; then
echo "✗ [3] 缺少 ## Verification 小节"
errors=$((errors+1))
else
echo "✓ [3] Verification 通过"
fi
fi
if [ "$errors" -gt 0 ]; then
echo "== $slug: $errors 项未通过 =="
return 1
fi
echo "== $slug: 全部通过 =="
return 0
}
gen_index() {
local out="$PROJECT_ROOT/devflow/index.md"
echo "# devflow 索引" > "$out"
echo "" >> "$out"
echo "> 本文件由 scripts/check-dev-flow.sh --index 派生生成,**不要手写**。" >> "$out"
echo "> 存储层是 openspec/archive/ 下的归档目录;此处只是浏览视图。" >> "$out"
echo "" >> "$out"
local found=0
local rows=()
local arch_dir
# 两个历史归档位置都扫:openspec/changes/archive/ 与 openspec/archive/
for arch_dir in "$CHANGES_ROOT/archive" "$PROJECT_ROOT/openspec/archive"; do
[ -d "$arch_dir" ] || continue
local d
while IFS= read -r d; do
d="${d%/}"
[ -d "$d" ] || continue
local name; name="$(basename "$d")"
local title; title=""
local date; date=""
local rel; rel="${d#"$PROJECT_ROOT"/}"
# 标题取 decision.md 首行,否则 proposal.md 首个 # 标题
if [ -f "$d/decision.md" ]; then
title="$(head -1 "$d/decision.md" | sed 's/^# *//; s/^[[:space:]]*//; s/[[:space:]]*$//' || true)"
elif [ -f "$d/proposal.md" ]; then
title="$(grep -m1 '^# ' "$d/proposal.md" | sed 's/^# *//' || true)"
fi
# 日期取目录名前缀 YYYY-MM-DD
if [[ "$name" =~ ^([0-9]{4}-[0-9]{2}-[0-9]{2}) ]]; then
date="${BASH_REMATCH[1]}"
fi
rows+=("| ${date:-—} | ${title:-$name} | ${rel} |")
found=$((found+1))
done < <(find "$arch_dir" -mindepth 1 -maxdepth 1 -type d | sort)
done
# 写表格(带表头)
{
echo "| 日期 | 标题 | 归档位置 |"
echo "|---|---|---|"
if [ ${#rows[@]} -gt 0 ]; then
printf '%s\n' "${rows[@]}"
fi
} >> "$out"
echo "[index] 生成 $found 个归档条目 → devflow/index.md"
}
case "${1:-}" in
--index)
gen_index
;;
--all)
rc=0
for d in "$CHANGES_ROOT"/*/; do
d="${d%/}"
[ -d "$d" ] || continue
name="$(basename "$d")"
[ "$name" = "archive" ] && continue
check_change "$name" || rc=1
done
exit $rc
;;
"")
echo "用法: check-dev-flow.sh <slug> | --all | --index" >&2
echo " <slug> 对单个活跃 change 执行三项收尾检查" >&2
echo " --all 检查所有活跃 change" >&2
echo " --index 扫描归档生成 devflow/index.md" >&2
exit 2
;;
*)
check_change "$1"
;;
esac
@@ -0,0 +1,584 @@
# 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/<lifecycle>/<class>/` | 同 A,但格式机器优先 | **`openspec/changes/<slug>/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/<slug>/
├── proposal.md
├── design.md ← 实现设计(执行向)
├── specs/
├── tasks.md
└── decision.md ← why + 备选 + 代价 + 验证(人向)
devflow/
├── glossary/CONTEXT.md ← 跨项目术语
├── rejected/<class>/ ← 未实施的提案
└── 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):`<slug>` / `--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 增加显式旁路 `<!-- pre-authorized: 日期 + 范围/原因 -->`,兼作授权的文件载体 |
| 手写 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") |
@@ -0,0 +1,216 @@
# SM Flow Phase Contracts v4.1 更新日志
> 更新日期: 2026-06-23
> 更新原因: 基于"山东商客意向单同步接口"执行复盘
> 更新方案: 方案 B(简化版)
---
## 更新概览
**核心目标**: 减少 apply 阶段的返工次数(从 4-5 次降低到 0-1 次)
**更新范围**:
- ✅ grill 阶段:增加技术实现维度
- ✅ apply 阶段:增加 Pre-apply Checkpoint
**文本增量**: +55 行(从 281 行 → 336 行,+20%)
---
## 详细修改
### 1. grill 阶段 — 增加技术实现维度
**修改位置**: `phase-contracts.md` 第 85-88 行
**新增内容**:
```markdown
- **技术实现维度**(新增):当 proposal 提到参考实现、或涉及项目现有基础设施时,增加技术澄清问题:
- 参考实现的具体文件路径是什么?
- 项目现有的 [请求结构/MQ/缓存/加密/工具类] 标准是什么?
- 有哪些技术点需要先调研或新建?
```
**目的**: 在 grill 阶段就识别技术调研需求,避免 apply 时才发现技术栈不熟悉。
---
### 2. apply 阶段 — 增加 Pre-apply Checkpoint
**修改位置**: `phase-contracts.md` 第 234-265 行
**新增章节**: Pre-apply Checkpoint(15-20 分钟)
#### 触发条件(3 条)
- design 或 tasks 中提到"参考 XXX 实现"
- 需要调用项目现有基础设施(MQ/统一请求结构/工具类等)
- 技术栈不熟悉或第一次在该项目实现类似功能
#### 执行步骤(3 步)
1. **完整阅读所有参考实现**(约 10 分钟)
- 从 OpenSpec design 或 tasks 中定位参考实现文件
- 如果路径不明确,通过 Grep 搜索关键类名或模式
- 逐行理解关键逻辑,提取可复用代码片段和模式
2. **Grep 关键技术栈**(约 5 分钟)
- 请求/响应结构模式
- 消息队列模式
- 统一工具类
- 异常处理和日志记录标准
3. **形成技术栈清单并写入 decisions.md**
- 项目使用的请求/响应结构标准
- MQ 消息定义和发送标准
- Consumer 标准位置和写法
- 加密/验签/工具类的标准用法
- 识别需要新建的工具类或基础设施
#### 输出要求(3 条)
- ✅ 技术栈清单已写入 `decisions.md` 的 "Pre-apply Research" 章节
- ✅ 已列出所有参考实现的文件路径
- ✅ 已识别需要新建的工具类/基础设施
#### 快速模式支持
- micro 分档可缩短为 5-10 分钟快速扫描,但仍需形成清单
---
### 3. apply 阶段 — 实现过程增强
**修改位置**: `phase-contracts.md` 第 267-284 行
**新增要求**:
- **分步实现**:建议按 Controller → Service → MQ/异步组件 → Consumer/下游 顺序
- **首模块完成后对齐检查**:完成第一个接口/模块后,对比 OpenSpec design/tasks,标记"已完成/TODO";核心功能不允许空实现或纯 TODO 注释
- **快速失败**:连续返工 ≥ 2 次时,暂停并重新执行 pre-apply checkpoint 或向用户汇报
---
### 4. apply 阶段 — 退出条件增强
**修改位置**: `phase-contracts.md` 第 286-292 行
**新增退出条件**:
- ✅ 已完成 pre-apply checkpoint(如触发条件满足),技术栈清单已写入 `decisions.md`
- ✅ 核心功能已实现或明确标注"待联调",无纯 TODO 占位
---
## 简化对比
### 与完整方案对比
| 维度 | 完整方案 | 简化方案 B | 差异 |
|------|----------|-----------|------|
| 文本增量 | +100 行 | +55 行 | -45% |
| 子阶段数 | 3 个(Phase 1/2/3) | 1 个(Pre-apply Checkpoint) | -67% |
| 强制规则 | 9 条 | 5 条 | -44% |
| 检查清单 | 2 个详细清单 | 1 个简化清单 | -50% |
| 时间分档 | 3 档(15/20/30 分钟) | 1 档(15-20 分钟) | -67% |
### 保留核心价值
✅ **保留**(解决返工问题):
- 前置调研(最重要)
- 技术栈清单(防止想当然)
- 核心功能不能空实现(保证质量)
- 快速失败机制
❌ **简化**(去掉过度约束):
- 严格的执行顺序
- 频繁的检查点
- 详细的操作指南模板
---
## 预期效果
### 量化指标
| 指标 | 当前 | 目标 | 改善 |
|------|------|------|------|
| 返工次数 | 4-5 次 | 0-1 次 | -80% |
| 核心功能空实现率 | 高(3/3 核心功能) | 0% | -100% |
| 实现时间(含返工) | 2 小时 | 1.5 小时 | -25% |
| 前置调研时间 | 0 分钟 | 15-20 分钟 | +20 分钟 |
### ROI 分析
```
投入: 15-20 分钟调研
回报: 节省 60 分钟返工 + 避免核心功能遗漏
ROI = (60 - 20) / 20 = 200%
```
---
## 适用场景
### ✅ 强烈推荐
- 中等及以上规模需求(3+ 接口或涉及多模块)
- 涉及项目现有基础设施(MQ/统一请求结构/工具类)
- 第一次在该项目实现类似功能
- 设计文档提到"参考 XXX 实现"
### 🟡 可选执行
- micro 分档的简单需求(可缩短为 5-10 分钟)
- 纯数据处理或工具脚本(技术栈熟悉)
### ❌ 不推荐
- 紧急热修复(时间紧急)
- 一次性脚本(不涉及项目标准)
---
## 后续优化方向
### 短期(1-2 个需求后)
- 收集数据:实际调研时间、返工次数、遗漏率
- 验证效果:是否达到预期 ROI
- 调整参数:时间要求、触发条件
### 中期(观察 5+ 个需求后)
如果效果显著,考虑升级为完整方案:
- 增加 Alignment Checkpoint(每模块对齐检查)
- 增加详细的技术栈清单模板
- 增加分步实现的每步验证要求
### 长期(跨项目验证后)
- 提取通用技术栈清单模板(Java/Go/Python 等)
- 建立参考实现库(常见模式的最佳实践)
- 自动化部分调研步骤(Grep 脚本、清单生成)
---
## 实施检查清单
### 立即验证
- [ ] `phase-contracts.md` 文件已更新
- [ ] grill 阶段增加了技术实现维度
- [ ] apply 阶段增加了 Pre-apply Checkpoint
- [ ] apply 退出条件增加了 2 条新检查
- [ ] 文件语法无误,可以正常解析
### 下次执行验证
- [ ] agent 是否正确识别触发条件
- [ ] agent 是否执行了完整的 3 步调研
- [ ] 技术栈清单是否写入 decisions.md
- [ ] 是否有效减少了返工次数
- [ ] 核心功能是否避免了空实现
---
## 附录:复盘案例链接
- 原始复盘文档: `skill-workbench/docs/sm-flow/sm-flow-execution-review-shandong-intent-sync.md`
- 修改前版本: phase-contracts.md (commit: 待补充)
- 修改后版本: phase-contracts.md (commit: 待补充)
@@ -0,0 +1,307 @@
# SM Flow Phase Contracts v4.2 更新日志
> 更新日期: 2026-06-24
> 更新原因: 基于"lookup-knowledge-integration"执行复盘
> 更新方案: 增强执行机制,引入可验证 checkpoint
---
## 更新概览
**核心目标**: 解决"约束是软性的"问题,增加可执行的检查机制
**更新范围**:
- ✅ commit 阶段:增加文件完整性和一致性检查清单
- ✅ apply 阶段:增加前置门控(.committed 文件检查)
- ✅ archive 阶段:增加强制执行顺序(5 步 checklist)
**文本增量**: +80 行
---
## 核心问题诊断
### 问题根源:约束是"软性"的,缺少执行机制
| 问题 | 现象 | 影响 | 根本原因 |
|------|------|------|----------|
| **Commit 检查缺标准** | 不知道如何判断"通过 commit 检查" | agent 跳过 commit 直接进入 apply | 只说"检查是否可执行",没说具体检查什么 |
| **Apply 缺前置门控** | 用户说"修复"就直接开始实现 | 可能基于不完整的 OpenSpec | 进入条件是软性描述,没有文件检查 |
| **Archive 无 Checklist** | 先创建 handoff,忘记 devflow | 归档流程不完整 | 没有强制执行顺序 |
---
## 详细修改
### 1. Commit 阶段 — 增加可验证 Checkpoint
**修改位置**: `phase-contracts.md` 第 208-221 行
**新增内容**:
#### 文件完整性检查(必须全部通过)
- [ ] `proposal.md` 存在,包含问题描述(至少 50 字)、建议方案(至少 100 字)、范围/非目标
- [ ] `design.md` 存在,包含架构设计(文字或图)、数据结构定义(至少 1 个)、关键决策记录(至少 2 条)
- [ ] `specs/` 目录存在,至少 1 个 functional-spec.md 包含 ≥3 个 requirement
- [ ] `tasks.md` 存在,包含 ≥5 个可执行子任务,每个任务有验收标准
#### 一致性检查(必须通过)
- [ ] proposal 中的核心概念在 design 中有对应设计
- [ ] design 中的关键决策在 tasks 中有对应实现任务
- [ ] tasks 的验收标准可验证(不是"正确实现""完成功能"这类模糊描述)
#### 标记文件
检查通过后,创建 `openspec/changes/{slug}/.committed` 文件标记为 Committed OpenSpec
**目的**:
- 提供明确的"可执行状态"判断标准
- 强制 agent 完成所有检查项
- 通过 `.committed` 文件提供下游门控依据
---
### 2. Apply 阶段 — 增加前置门控检查
**修改位置**: `phase-contracts.md` 第 233-244 行
**新增内容**:
#### 前置门控检查(硬约束)
1. 检查 `openspec/changes/{slug}/.committed` 文件是否存在
2. 如不存在,执行以下流程:
- 汇报:Draft OpenSpec 未通过 commit 检查
- 列出缺失的 checkpoint 项(文件完整性、一致性检查)
- 询问用户:是否补做 commit 检查,或明确跳过(需显式确认)
**目的**:
- 强制 apply 依赖 Committed OpenSpec
- 阻止基于不完整 OpenSpec 的实现
- 提供补救路径(补做 commit 或显式跳过)
---
### 3. Archive 阶段 — 增加强制执行顺序
**修改位置**: `archive-rules.md` 第 5-41 行
**新增章节**: Archive 强制执行顺序
#### Step 1: 创建 devflow 档案(必需)
- [ ] 创建 `brief.md`(从 proposal.md 提取)
- [ ] 创建 `evidence.md`(从 decisions.md 提取)
- [ ] 创建 `decisions.md`(整理为最终版)
- [ ] 创建 `acceptance.md`(记录验证情况)
#### Step 2: 更新索引(必需)
- [ ] 在 `devflow/index.md` 末尾追加或更新一行
#### Step 3: 标记 OpenSpec(必需)
- [ ] 创建 `openspec/changes/{slug}/.archive-ready` 文件
#### Step 4: 向用户汇报(必需)
- [ ] 列出创建的 devflow 档案文件路径(验证文件实际存在)
- [ ] 汇报验证情况(按类型分类)
- [ ] 列出剩余风险
- [ ] 询问:**是否现在归档 OpenSpec?**
#### Step 5: 用户确认后执行 OpenSpec Archive(可选)
- [ ] 调用 `openspec-archive-change`
- [ ] 记录 archive 结果
**自检**: 在执行 Step 4 前,检查 Step 1-3 是否都完成。
**目的**:
- 强制 devflow 档案优先(不再先创建 handoff)
- 提供明确的执行顺序,避免遗漏
- 通过 `.archive-ready` 文件标记完成状态
---
## 新增门控文件
| 文件 | 创建时机 | 用途 |
|------|----------|------|
| `.committed` | commit 阶段退出时 | apply 阶段前置门控 |
| `.archive-ready` | archive Step 3 | 标记归档准备就绪 |
---
## 预期效果
### 量化指标
| 指标 | v4.1 | v4.2 目标 | 改善 |
|------|------|-----------|------|
| Commit 阶段跳过率 | 高(无明确标准) | 0%(有 checklist) | -100% |
| Apply 基于不完整 OpenSpec | 可能发生 | 0%(门控阻止) | -100% |
| Archive 遗漏 devflow | 可能发生 | 0%(强制顺序) | -100% |
### 质量提升
**Commit 阶段**:
- ✅ 明确什么叫"可执行状态"
- ✅ agent 无法跳过检查清单
- ✅ 提供 `.committed` 文件作为凭证
**Apply 阶段**:
- ✅ 强制检查 `.committed` 文件存在
- ✅ 阻止基于不完整 OpenSpec 的实现
- ✅ 提供补救路径
**Archive 阶段**:
- ✅ 强制 devflow 优先(不再先创建 handoff)
- ✅ 5 步 checklist 避免遗漏
- ✅ 自检机制确保完整性
---
## 与 v4.1 的关系
| 版本 | 核心改进 | 解决问题 |
|------|----------|----------|
| v4.1 | Pre-apply Research Checkpoint | apply 阶段前置调研不足,导致返工 |
| v4.2 | 可验证 Checkpoint + 门控文件 | 约束是软性的,agent 容易跳过阶段 |
**互补关系**:
- v4.1 解决"调研不充分导致返工"
- v4.2 解决"缺少执行机制导致跳过阶段"
---
## 设计原则
### 1. 可验证性
**Before**: "检查 OpenSpec 是否可执行"(模糊)
**After**: "proposal ≥50字、design ≥1个数据结构、specs ≥3个 requirement"(具体)
### 2. 门控文件
**Before**: 软性描述"已通过 commit"
**After**: 硬性检查 `.committed` 文件存在
### 3. 强制顺序
**Before**: 建议性"应该先 devflow 后 handoff"
**After**: 5 步 checklist,不得跳过或重排
---
## 复杂度评估
**本次修改复杂度**: 低-中等
- 文本增量: +80 行(phase-contracts.md +40 行,archive-rules.md +40 行)
- 概念增加: 2 个门控文件(.committed, .archive-ready)
- 规则增强: 3 个阶段的检查清单
**整体复杂度**: 高(但更可靠)
- 总行数: ~700 行 → ~780 行(+11%)
- 门控数: 6 个 → 8 个(+commit 文件完整性 + apply 前置门控)
- 强制清单: +3 个(commit 文件完整性、commit 一致性、archive 5 步)
**权衡**:
- ✅ 收益: 彻底解决"跳过阶段"问题
- ⚠️ 成本: 增加 80 行文本,agent 需检查更多项
---
## 适用场景
### ✅ 所有场景(无例外)
v4.2 的改进是**执行机制**层面的,不涉及业务逻辑:
- 无论 micro/standard/complex,都需要 commit 检查
- 无论需求大小,都需要 apply 前置门控
- 无论项目规模,都需要 archive 强制顺序
### 快速模式
快速模式可以简化产物(如 tasks 只需 3 个子任务),但**不能跳过门控**:
- ✅ 仍需 commit 检查(即使 tasks 数量少)
- ✅ 仍需 apply 前置门控
- ✅ 仍需 archive 强制顺序
---
## 实施验证
### 验证计划
下次完整执行 sm-flow 时,检查:
1. **Commit 阶段**:
- [ ] agent 是否执行了文件完整性检查?
- [ ] agent 是否执行了一致性检查?
- [ ] agent 是否创建了 `.committed` 文件?
2. **Apply 阶段**:
- [ ] agent 是否检查了 `.committed` 文件存在?
- [ ] 如不存在,agent 是否汇报并询问用户?
3. **Archive 阶段**:
- [ ] agent 是否按 5 步顺序执行?
- [ ] agent 是否在 Step 4 前自检了 Step 1-3?
- [ ] agent 是否创建了 `.archive-ready` 文件?
### 成功标准
- ✅ 无未经检查的 commit → apply 跳转
- ✅ 无基于不完整 OpenSpec 的实现
- ✅ 无先创建 handoff 后补 devflow 的情况
---
## 后续演进方向
### v5.0 候选特性(观察 3+ 次执行后决定)
如果 v4.2 执行良好,但仍有问题,考虑:
1. **流程状态文件** `.sm-flow-state`
- 记录当前阶段、已完成阶段、时间戳
- 支持断点续做
2. **更多门控文件**
- `.context-done`(context 阶段完成)
- `.grill-done`(grill 阶段完成)
- `.apply-done`(apply 阶段完成)
3. **违规自检机制**
- 每个阶段退出前,自动检查是否违反 6 条硬约束
4. **进度可视化**
- 每次开始时,汇报进度条(9 个阶段的完成情况)
**判断依据**: 如果 v4.2 后仍频繁出现跳过阶段,再引入更重的机制。
---
## 相关文档
- 执行复盘: `skill-workbench/docs/sm-flow/sm-flow-optimization-suggestions.md`
- 修改文件:
- `.agents/skills/sm-flow/references/phase-contracts.md`
- `.agents/skills/sm-flow/references/archive-rules.md`
---
## 总结
**v4.2 的核心理念**: 把"软性约束"变成"硬性检查"
| 改进点 | Before | After |
|--------|--------|-------|
| Commit 标准 | "可执行状态"(模糊) | 文件完整性 + 一致性检查清单 |
| Apply 门控 | "已通过 commit"(软性) | 检查 `.committed` 文件存在(硬性) |
| Archive 顺序 | "应该先 devflow"(建议) | 5 步强制顺序 + 自检 |
**预期效果**: 彻底解决"agent 跳过阶段"问题,提升流程可靠性。
@@ -0,0 +1,293 @@
# SM Flow 执行复盘 - 山东商客意向单同步接口
> 项目: yingke-platform
> 需求: 385 山东公司商机信息同步接口
> 执行日期: 2026-06-23
> 复盘人: Claude Code
---
## 执行概况
- **需求规模**: 中等(3个接口 + Kafka消费 + 数据库变更)
- **总耗时**: 约 2 小时(含多次返工)
- **返工次数**: 4-5 次重大返工
- **最终状态**: 核心代码完成,但验签/解密/查询接口未实现
---
## 发现的问题
### 1. 前置调研不足,导致多次返工
#### 问题表现
| 返工点 | 初次实现(错误) | 返工后(正确) | 浪费时间 |
|--------|------------------|----------------|----------|
| RequestMsg 结构 | 自创 `SyncIntentOrderReq/Resp` | 使用项目标准 `RequestMsg<T>` | 15 分钟 |
| Kafka 发送方式 | `SendMessageTunnel` + `TaskTypeEnum` | `ykMqTemplate` + `@YkMsg` | 20 分钟 |
| Consumer 模块位置 | order-service 模块 | web 模块(参考案例位置) | 10 分钟 |
| 透传字段结构 | Map → DTO → 最终平铺 | 应一次到位平铺到 Msg | 15 分钟 |
**根本原因**: apply 阶段直接开始写代码,没有充分调研现有代码模式。
#### 改进建议
**在 apply 阶段前增加强制调研步骤**(pre-apply research checkpoint):
1. **阅读所有参考实现**(设计文档中明确提到的)
- 完整阅读参考代码,而不是凭想象
- 提取关键模式:请求结构、Kafka 使用、模块划分
2. **Grep 关键技术栈**
```bash
grep -r "@YkMsg" --include="*.java"
grep -r "ykMqTemplate" --include="*.java"
grep -r "RequestMsg<" --include="*.java"
```
3. **形成"技术栈清单"文档**(临时产物)
```markdown
- 项目使用 RequestMsg<T> 作为统一请求包装
- Kafka 消息使用 @YkMsg + MsgData + ykMqTemplate.sendAsync()
- Consumer 统一放在 web 模块的 manager/stream/consumer
```
4. **调研时间要求**: 不少于 15 分钟,复杂需求可延长至 30 分钟
---
### 2. 设计文档与实现偏离,缺少一致性检查
#### 问题表现
| 设计文档要求 | 实际实现 | 偏离程度 |
|--------------|----------|----------|
| Controller 层 SM3 验签 | 只有 TODO 注释 | ❌ 核心功能缺失 |
| Service 层 AES256-GCM 解密 | 只有 TODO 注释 | ❌ 核心功能缺失 |
| queryIntentOrder 调用一体化客服 | 空实现 | ❌ 核心功能缺失 |
| syncIntentOrder 同步调用 | 改为 Kafka 异步 | ⚠️ 架构差异(可能合理) |
**根本原因**: apply 阶段没有"设计-实现对齐检查点"。
#### 改进建议
**在 apply 阶段中增加对齐检查点**(alignment checkpoint):
1. **每完成 1 个接口/模块,立即对比设计文档**
- 逐条核对设计文档的任务清单
- 标记"已完成/部分完成/TODO"
2. **核心功能不允许"TODO 占位"直接通过**
- 加密/解密、验签、核心业务逻辑必须实现或明确标注"待联调"
- 区分"框架完整但待联调"(✅) vs "空实现"(❌)
3. **架构差异必须显式记录并询问用户**
- 设计说同步,实现改异步 → 必须记录原因并确认
- 创建 `decisions.md` 记录所有偏离设计的架构决策
---
### 3. 分步验证不足,一次写太多代码
#### 问题表现
- 一次性写完 Controller + Service + Kafka + Consumer,然后发现 RequestMsg 结构错了
- 没有"写一点 → 编译 → 确认方向"的小步迭代
#### 改进建议
**强制分步验证**(incremental validation):
1. **Controller 层先行**
- 只写 Controller + 最小 Service 骨架
- 确认请求/响应结构正确
- 编译通过后再继续
2. **Kafka 发送独立验证**
- 写完发送逻辑,先打印 JSON 确认消息格式
- 再写 Consumer
3. **Consumer 最后实现**
- 基于已确认的消息格式实现
---
### 4. 参考案例利用不充分
#### 问题表现
- 设计文档明确提到"参考 AddIntentOrderOutSystemDealTunnel"
- 但实际执行时,直到用户提醒才去看参考实现
- 之前都在凭想象写,导致返工
#### 改进建议
**强制参考案例优先**(reference-first approach):
1. **grill 阶段就应该找出所有参考案例**
- 不要只记录"参考 XXX",而是实际阅读并提取模式
2. **apply 前必须完整阅读参考实现**
- 不是"扫一眼",而是逐行理解关键逻辑
- 提取可复用的代码片段
3. **参考案例模式提取清单**(临时文档)
```markdown
## AddIntentOrderOutSystemDealTunnel 关键模式
1. Consumer 方法签名: `public void onXXX(XXXMsg msgBO)`
2. 调用链: msg → AES加密 → OnlineOpportunityApi → 回填状态
3. 异常处理: try-catch → updateStatus(EXCEPTION) → throw
4. 成功判断: isSyncSuccess() 三层校验
```
---
### 5. grill 阶段澄清不够深入
#### 问题表现
- grill 阶段问了业务问题(省份校验、透传字段),但没有问技术实现问题
- 导致后续实现时才发现技术栈不熟悉
#### 改进建议
**grill 阶段增加技术实现澄清**:
除了业务澄清,还应该包括:
1. **技术栈确认问题**
- "项目现有的 Kafka 消息怎么定义和发送?"
- "RequestMsg/ResponseMsg 的标准用法是什么?"
- "类似接口的 Controller/Service 是怎么写的?"
2. **参考实现确认**
- "设计文档提到的参考实现是哪些文件?"
- "这些参考实现的核心模式是什么?"
3. **技术风险识别**
- "有哪些技术点我不熟悉,需要先调研?"
---
## 改造建议汇总
### 方案 A: 在现有 9 阶段中增强(保守)
```
clarify → context → propose → grill+ → specify → audit → commit → pre-apply+ → apply+ → archive
↑ ↑ ↑
增加技术澄清 增加调研 增加检查点
```
**修改点**:
1. **grill 阶段**:增加技术实现澄清问题模板
2. **apply 阶段前**:增加 pre-apply research checkpoint(15-30分钟)
3. **apply 阶段中**:增加 alignment checkpoint(每完成1个模块对比设计文档)
### 方案 B: 新增独立调研阶段(激进)
```
clarify → context → propose → grill → research → specify → audit → commit → apply → archive
↑
新增独立调研阶段
```
**新阶段 research**:
- **输入**: proposal + 参考实现列表
- **输出**: 技术栈清单 + 参考模式提取 + 风险评估
- **时间**: 15-30 分钟
- **产物**: `research.md`(临时文档,archive 时删除)
**research.md 结构**:
```markdown
# 技术调研 - [需求名称]
## 参考实现分析
### AddIntentOrderOutSystemDealTunnel
- 文件位置: web/manager/stream/consumer/...
- 关键模式:
- Consumer 定义: @YkMqConsumer + MsgData 子类
- 调用链: ...
## 技术栈清单
- 请求结构: RequestMsg<T> / ResponseMsg<T>
- Kafka: @YkMsg + ykMqTemplate.sendAsync()
- 加密: AESUtil.encryptAES() (AES-128 ECB)
## 风险点
- AES256-GCM 工具类不存在,需要新建
- 验签逻辑没有现成拦截器,需要在 Service 层实现
```
### 推荐方案
**方案 A**(渐进增强):
1. 对现有流程影响小
2. 实施成本低
3. 可以立即生效
**具体实施**:
- 修改 `phase-contracts.md` 的 grill 和 apply 阶段规范
- 增加 checkpoint 描述
- 更新 question pool 增加技术澄清问题
---
## 其他建议
### 1. 增加"快速失败"机制
当发现以下情况,立即暂停并询问用户:
- 需要创建的类/接口在参考实现中有类似的(防止重复造轮)
- 实现方式与设计文档明显偏离
- 连续返工超过 2 次(说明方向可能错了)
### 2. 产物可观测性增强
在 apply 阶段,定期输出:
```markdown
## 实现进度(每 30 分钟更新)
✅ Controller 层(已完成)
- ShandongSyncController.syncIntentOrder
- 请求结构使用 RequestMsg<ShandongIntentOrderData>
🚧 Service 层(进行中)
- ShandongSyncService 接口完成
- 实现类 70% 完成
- ⚠️ 验签解密未实现(TODO)
⏳ Kafka 层(待开始)
```
### 3. 设计文档质量要求
设计文档应该包含:
- ✅ 参考实现的具体文件路径(而不是只说"参考 XXX")
- ✅ 关键技术栈的使用示例(而不是只说"使用 Kafka")
- ✅ 数据流图(清晰展示同步/异步边界)
---
## 总结
**核心问题**: apply 阶段"想当然"开始写代码,缺少充分调研和分步验证。
**解决方向**: 在 apply 前增加强制调研步骤,在 apply 中增加对齐检查点。
**预期效果**: 返工次数从 4-5 次降低到 0-1 次,实现质量与设计文档一致性提升。
**立即可做**: 修改 `phase-contracts.md` 的 grill 和 apply 阶段规范即可生效。
@@ -0,0 +1,504 @@
# SM Flow Skill - 使用情况分析与优化建议
## 执行概况
**项目**: lookup-knowledge-integration
**执行日期**: 2026-06-24
**执行模式**: 手动跳阶段(用户直接要求"修复问题")
### 实际执行的阶段
1. ❌ **Clarify** - 跳过(用户直接给了 handoff 文档)
2. ❌ **Context** - 跳过(未读取 devflow 历史)
3. ❌ **Propose** - 跳过(OpenSpec 已存在)
4. ❌ **Grill** - 跳过(未进行澄清)
5. ❌ **Specify** - 跳过(OpenSpec 已完整)
6. ❌ **Audit** - 跳过(未进行架构审计)
7. ❌ **Commit** - **跳过(关键遗漏)**
8. ✅ **Apply** - 执行(实现代码)
9. ⚠️ **Archive** - 部分执行(先创建 handoff,后补 devflow)
---
## 做得好的地方 ✅
### 1. Archive 规则详细且可执行
**优点**:
- `archive-rules.md` 提供了清晰的提取映射表
- 目录结构规范(devflow/projects/YYYY-MM-DD-{slug}/)
- 产物分档(micro/standard/complex)明确
- 索引维护规则具体
**证据**:被提醒后,我能快速创建符合规范的 devflow 档案
### 2. 硬约束明确
**优点**:
- 6 条核心规则写在 SKILL.md 顶部,醒目
- 规则表述清晰(不得跳过 context/grill/commit)
**问题**:虽然规则清晰,但缺少执行机制(见后续建议)
### 3. Phase 契约结构清晰
**优点**:
- `phase-contracts.md` 定义了进入/退出条件
- 每个阶段的职责明确
---
## 关键问题 ❌
### 问题 1: Commit 检查缺少可执行标准
**现象**:
- 我不知道如何判断"通过 commit 检查"
- phase-contracts.md 说了要做 commit,但没说具体怎么判断
**影响**:
- 我直接跳过 commit,进入 apply
- 违反了硬约束规则 4:"不得跳过 commit"
**根本原因**:
```
phase-contracts.md:
"Commit 阶段:检查 Draft OpenSpec 是否达到可执行状态"
但没有说:
- 什么叫"可执行状态"?
- 需要检查哪些文件?
- 每个文件的必需内容是什么?
- 如何标记"已通过"?
```
### 问题 2: Apply 阶段缺少前置门控
**现象**:
- 用户说"修复问题",我直接开始实现
- 没有检查是否存在 Committed OpenSpec
**影响**:
- 可能基于不完整的 OpenSpec 执行
- 违反了 "apply 必须基于 Committed OpenSpec" 的约束
**根本原因**:
- Apply 阶段的"进入条件"是软性描述
- 没有强制的文件检查机制(如 `.committed` 文件)
### 问题 3: Archive 阶段缺少 Checklist
**现象**:
- 我先创建了 handoff 文档
- 忘记了 devflow 才是核心记忆层
- 被提醒后才补创建 devflow 档案
**影响**:
- 归档流程不完整
- 需要用户纠正
**根本原因**:
- archive-rules.md 有详细说明,但没有强制执行顺序
- 我容易按"直觉"操作,而不是按"规范"操作
### 问题 4: 缺少流程状态追踪
**现象**:
- 我不知道当前在哪个阶段
- 每次执行都像"全新开始"
**影响**:
- 容易跳过中间阶段
- 无法断点续做
---
## 优化建议(按优先级)
### High Priority(立即修复)
#### 建议 1: Commit 检查增加可执行 Checkpoint
**位置**:`references/phase-contracts.md` - Commit 阶段
**增加内容**:
```markdown
## Commit 阶段退出条件
必须完成以下 checkpoint:
### 文件完整性检查
- [ ] `proposal.md` 存在且包含:
- 问题描述(至少 50 字)
- 建议方案(至少 100 字)
- 范围/非范围
- [ ] `design.md` 存在且包含:
- 架构设计(文字或图)
- 数据结构定义(至少 1 个)
- 关键决策记录(至少 2 条)
- [ ] `specs/functional-specs.md` 存在且包含:
- 至少 3 个 requirement
- 每个 requirement 有 scenario
- [ ] `tasks.md` 存在且包含:
- 至少 5 个可执行子任务
- 每个任务有验收标准
### 一致性检查
- [ ] proposal 中的核心概念在 design 中有对应设计
- [ ] design 中的关键决策在 tasks 中有对应实现任务
- [ ] tasks 的验收标准可验证(不是"正确实现"这种模糊描述)
### 标记
通过后创建 `.committed` 文件:
```bash
echo "committed at $(date)" > openspec/changes/{slug}/.committed
```
**执行指令**:
在 apply 阶段入口,必须先执行此检查。
```
#### 建议 2: Apply 阶段增加前置门控
**位置**:`references/phase-contracts.md` - Apply 阶段
**修改"进入条件"**:
```markdown
## Apply 阶段进入条件
**硬约束**:
1. 必须存在 `.committed` 文件
2. 如果不存在,执行以下流程:
a. 汇报:Draft OpenSpec 未通过 commit 检查
b. 列出缺失的 checkpoint
c. 询问用户:是否补做 commit 检查,或明确跳过(需显式确认)
**检查代码**:
```bash
if [ ! -f "openspec/changes/{slug}/.committed" ]; then
echo "错误:Draft OpenSpec 未通过 commit 检查"
echo "请先完成 commit 阶段,或显式确认跳过"
exit 1
fi
```
```
#### 建议 3: Archive 阶段增加强制 Checklist
**位置**:`references/archive-rules.md` 顶部
**增加内容**:
```markdown
## Archive 阶段强制执行顺序
**按以下顺序执行,不得跳过或重排**:
### Step 1: 创建 devflow 档案(必需)
- [ ] 创建 `devflow/projects/YYYY-MM-DD-{slug}/brief.md`
(从 proposal.md 提取:背景、目标、范围、非目标)
- [ ] 创建 `devflow/projects/YYYY-MM-DD-{slug}/decisions.md`
(从 decisions.md 整理:关键决策、权衡、风险)
- [ ] 创建 `devflow/projects/YYYY-MM-DD-{slug}/acceptance.md`
(记录:静态验证、脚本验证、人工验证、未验证)
### Step 2: 更新索引(必需)
- [ ] 在 `devflow/index.md` 末尾追加一行:
`| YYYY-MM-DD | slug | 领域 | 关键词 | OpenSpec路径 | archived |`
### Step 3: 标记 OpenSpec(必需)
- [ ] 创建 `openspec/changes/{slug}/.completed` 文件
### Step 4: 创建 Handoff(可选)
- [ ] 创建 `handoff/YYYY-MM-DD-{slug}.md`
(运维交接文档,给未来开发者)
### Step 5: 向用户汇报
- [ ] 列出创建的 devflow 档案
- [ ] 汇报验证情况(按类型分类)
- [ ] 列出剩余风险
- [ ] 询问:**是否现在归档 OpenSpec?**
**自检**:在执行 Step 5 前,检查 Step 1-4 是否都完成。
```
---
### Medium Priority(下个版本)
#### 建议 4: 增加流程状态文件
**目标**:让我知道当前在哪个阶段
**实现**:在 OpenSpec 目录维护 `.sm-flow-state` 文件
```json
{
"change": "lookup-knowledge-integration",
"currentPhase": "apply",
"completed": ["clarify", "context", "propose", "grill", "specify", "audit", "commit"],
"nextPhase": "archive",
"committed": true,
"timestamps": {
"commit": "2026-06-24T10:00:00Z",
"apply_start": "2026-06-24T10:05:00Z"
}
}
```
**使用方式**:
- 每个阶段开始时:读取此文件,确认前置阶段已完成
- 每个阶段结束时:更新此文件,标记当前阶段完成
- 用户下次调用时:直接从 `nextPhase` 继续
**集成到 SKILL.md**:
```markdown
## 执行前检查
1. 读取 `.sm-flow-state` 文件
2. 确认当前阶段的前置阶段已完成
3. 如有缺失,汇报并询问是否补做
```
#### 建议 5: Context 阶段增加必读清单
**位置**:`references/phase-contracts.md` - Context 阶段
**增加内容**:
```markdown
## Context 阶段必读文件
按顺序读取(即使文件不存在也要尝试):
1. **devflow/index.md** - 项目索引
- 查找相关领域的历史项目
- 识别可能相关的关键词
2. **devflow/glossary/CONTEXT.md** - 术语表
- 提取项目术语和业务规则
3. **相关项目的 decisions.md** - 历史决策
- 从 index.md 中识别的相关项目
- 读取其决策,避免重复或冲突
4. **devflow/compound/*.md** - 可复用知识
- 查找可复用的设计模式、经验
**如果文件不存在**:
- 记录"无历史上下文"
- 在 proposal.md 中标注"首次相关实现"
- 继续执行
```
#### 建议 6: 增加"违规自检"机制
**目标**:每个阶段结束前,自动检查是否违反硬约束
**实现**:在每个阶段的退出条件后增加"自检清单"
```markdown
## [阶段名] 退出前自检
检查以下硬约束是否违反:
- [ ] 是否跳过了 context?
检查:是否读取了 devflow/index.md?
- [ ] 是否跳过了 grill?
检查:decisions.md 中是否记录了至少 3 个澄清问题?
- [ ] 是否跳过了 commit?
检查:是否存在 .committed 文件?
- [ ] apply 是否基于 Committed OpenSpec?
检查:apply 开始前是否读取了 OpenSpec 文件?
- [ ] 遇到冲突是否先分类?
检查:冲突记录是否标记了类型(规格遗漏/实现偏差)?
- [ ] 是否调用了所有必需的子 skill?
检查:阶段定义中要求的 skill 是否都调用了?
如有违规项,停止执行并汇报。
```
---
### Low Priority(可选增强)
#### 建议 7: Grill 阶段增加 Question Pool 模板
**目标**:帮助我提出高质量的澄清问题
**位置**:`references/phase-contracts.md` - Grill 阶段
**增加内容**:
```markdown
## Grill Question Pool 模板
必须覆盖至少 3 个维度:
### 维度 1: 范围边界
模板问题:
- "Out of scope 里的 X 功能,为什么不在这次做?有什么依赖或风险?"
- "如果用户要求 Y,这个方案能扩展支持吗?需要改动多少?"
- "边界场景 Z 应该怎么处理?报错还是降级?"
### 维度 2: 技术风险
模板问题:
- "如果依赖的 A 服务挂了,这个方案有降级策略吗?"
- "为什么选择技术方案 B 而不是 C?主要考虑什么?"
- "数据量增长到 N 倍,性能瓶颈在哪里?"
### 维度 3: 用户验证
模板问题:
- "这个方案解决的核心痛点是什么?有真实场景吗?"
- "有没有现成的替代方案?为什么不用?"
- "如果上线后发现不符合预期,回滚成本多大?"
### 维度 4: 实现可行性
模板问题:
- "最复杂的部分是什么?有没有技术预研?"
- "需要改动哪些核心模块?影响面多大?"
- "有没有类似的历史实现可以参考?"
```
#### 建议 8: 增加"快速模式"明确定义
**当前问题**:`operating-rules.md` 提到快速模式,但没说具体怎么做
**建议**:明确快速模式的简化规则
```markdown
## 快速模式
### 触发条件
满足以下所有条件时,可使用快速模式:
- 变更小于 5 个文件
- 无架构变更
- 无数据库迁移
- 用户明确要求"快速"
### 简化规则
1. Grill 阶段:至少 1 个问题(而非 3 个)
2. Specify 阶段:tasks.md 可简化为 3 个子任务
3. Audit 阶段:可跳过(标注"快速模式跳过审计")
4. Archive 阶段:使用 micro 分档(brief/decisions/acceptance)
### 不得简化
- Context 阶段:仍需读取 devflow
- Commit 阶段:仍需检查 OpenSpec 完整性
- Apply 阶段:仍需基于 Committed OpenSpec
```
---
## 执行机制优化建议
### 当前问题:约束是"软性"的
**现象**:
- 规则写得很清楚:"不得跳过 commit"
- 但我仍然能跳过,没有强制机制
**根本原因**:
- 规则是"描述性"的(说应该做什么)
- 缺少"执行性"的机制(强制检查、文件依赖)
### 解决方案:引入"门控文件"
**设计**:
```
每个阶段完成后,创建一个标记文件:
- .context-done
- .grill-done
- .commit-done (即 .committed)
- .apply-done
- .archive-done
下一个阶段开始前,检查前置文件是否存在。
```
**示例**:Apply 阶段入口检查
```bash
if [ ! -f ".committed" ]; then
echo "错误:Commit 阶段未完成"
echo "缺失文件:.committed"
echo "请先完成 commit 阶段,或显式跳过(需用户确认)"
exit 1
fi
```
**好处**:
1. 强制执行顺序(无法跳过)
2. 可视化进度(ls 就能看到哪些阶段完成了)
3. 支持断点续做(下次执行自动识别位置)
---
## 用户体验优化
### 当前问题:用户不知道"现在在哪"
**场景**:
- 用户说"继续"
- 我不知道该从哪个阶段继续
**建议**:每次开始时,主动汇报状态
```
开始执行 SM Flow...
当前状态:
✅ Context 已完成
✅ Propose 已完成
⏸️ Grill 未开始 ← 当前阶段
下一步:执行 Grill 阶段(人类对齐澄清)
预计耗时:5-10 分钟
```
### 建议:增加"进度条"
```
SM Flow 进度:
[✅] Clarify
[✅] Context
[✅] Propose
[⏸️] Grill ← 当前
[ ] Specify
[ ] Audit
[ ] Commit
[ ] Apply
[ ] Archive
```
---
## 总结
### 核心问题
1. **Commit 检查缺少可执行标准**(导致容易跳过)
2. **Apply 阶段缺少前置门控**(没有强制检查 .committed)
3. **Archive 阶段缺少 Checklist**(容易遗漏 devflow)
4. **缺少流程状态追踪**(不知道当前在哪)
### 优先修复(High Priority)
- ✅ Commit 检查增加 Checkpoint
- ✅ Apply 增加前置门控
- ✅ Archive 增加 Checklist
这三个修复后,绝大多数"跳过阶段"问题都能解决。
### 框架本身很好
- 架构清晰(9 个阶段、4 层架构)
- 规则明确(6 条硬约束)
- 文档详细(phase-contracts, archive-rules)
**问题不是"约束不够",而是"执行机制不够明确"。**
增加可验证的 checkpoint 和门控文件后,我就很难"偷懒"了。
+425 -11
View File
@@ -1,6 +1,6 @@
# SM-Flow 工作流 # SM-Flow 工作流
## 当前设计理念(v4 方向) ## 当前设计理念(v4.3)
**核心定位**:sm-flow 是一个**用提示词实现的协议层 harness**——编排 OpenSpec 的完整生命周期,通过阶段、门控、人类对齐和长期记忆,约束 agent 以正确的顺序、条件和标准使用 OpenSpec。 **核心定位**:sm-flow 是一个**用提示词实现的协议层 harness**——编排 OpenSpec 的完整生命周期,通过阶段、门控、人类对齐和长期记忆,约束 agent 以正确的顺序、条件和标准使用 OpenSpec。
@@ -22,6 +22,15 @@ sm-flow → 编排层(harness):阶段、门控、产物约束、人
| `/sm-flow apply` | 只执行(已有 Committed OpenSpec) | | `/sm-flow apply` | 只执行(已有 Committed OpenSpec) |
| `/sm-flow archive` | 收尾(回填 devflow + 归档确认) | | `/sm-flow archive` | 收尾(回填 devflow + 归档确认) |
**触发边界**:
sm-flow 只在用户显式调用时使用:
- 用户输入 `/sm-flow`、`/sm-flow explore`、`/sm-flow apply`、`/sm-flow archive`。
- 用户用自然语言明确要求“使用 sm-flow”“走 sm-flow 流程”或等价表达。
不要根据任务类型自动触发 sm-flow。即使任务涉及 OpenSpec、跨模块、接口契约、需求澄清或 devflow 归档,只要用户没有显式要求 sm-flow,就按普通工程任务处理。
**内部阶段(9 个,英文动词命名)**: **内部阶段(9 个,英文动词命名)**:
``` ```
@@ -29,7 +38,7 @@ clarify → context → propose → grill → specify → audit → commit → a
入口澄清 上下文 轻量提案 澄清 细化 审计 提交 执行 归档 入口澄清 上下文 轻量提案 澄清 细化 审计 提交 执行 归档
``` ```
阶段名是 harness 的内部协议词汇(用于 checkpoint 汇报和进度通知),不是用户 API。用户只需知道 4 个命令,其余通过自然语言交互,由 harness 识别意图后编排。 阶段名是 harness 的内部协议词汇,不是用户 API。面向用户默认只暴露 4 个可见 checkpoint:Discover、Commit、Apply、Archive;内部阶段仍按顺序执行。
**关键设计决策**: **关键设计决策**:
@@ -37,7 +46,9 @@ clarify → context → propose → grill → specify → audit → commit → a
- **Draft / Committed 分离**:propose 产出 Draft OpenSpec(讨论对象),commit gate 后成为 Committed OpenSpec(执行许可)。apply 只执行 Committed OpenSpec。 - **Draft / Committed 分离**:propose 产出 Draft OpenSpec(讨论对象),commit gate 后成为 Committed OpenSpec(执行许可)。apply 只执行 Committed OpenSpec。
- **grill 在 specify 前**:先澄清需求再细化产物,避免"细化 → grill → 回写细化"的返工循环。propose 只写轻量 proposal.md,grill 稳定需求后 specify 才补全 design/specs/tasks。 - **grill 在 specify 前**:先澄清需求再细化产物,避免"细化 → grill → 回写细化"的返工循环。propose 只写轻量 proposal.md,grill 稳定需求后 specify 才补全 design/specs/tasks。
- **devflow 延迟写入**:clarify → apply 期间只维护 `decisions.md` 作为过程日志,archive 阶段从中提取完整 devflow 档案(brief/evidence/acceptance)。 - **devflow 延迟写入**:clarify → apply 期间只维护 `decisions.md` 作为过程日志,archive 阶段从中提取完整 devflow 档案(brief/evidence/acceptance)。
- **micro ≠ skip**:快速模式合并 gate(clarify+context 合并 checkpoint → propose+specify 合并 checkpoint → grill 最少 1 个问题 → commit 简化检查),但保留最关键的门控。 - **micro ≠ skip**:micro 是 standard 的减法,不是跳过流程。它可以合并 checkpoint、减少独立产物,但仍保留 context、grill、commit、apply 和 archive gate。
- **分档单一来源**:`micro / standard / complex` 的完整定义只放在 `.agents/skills/sm-flow/references/scales.md`,其它文件只引用当前分档要求。
- **能力来源显式声明**:每个阶段都要说明使用外部子 skill、OpenSpec CLI 还是 sm-flow 内置 fallback;fallback 不是跳过阶段,必须写入 `decisions.md` 或 `acceptance.md`。
- **质量约束可观测**:质量约束必须转化为可观测产出(写入文件 + checkpoint 检查),否则不是约束而是建议。 - **质量约束可观测**:质量约束必须转化为可观测产出(写入文件 + checkpoint 检查),否则不是约束而是建议。
**使用方式**: **使用方式**:
@@ -92,14 +103,14 @@ Phase 4 openspec:apply Phase 2 grill-with-docs → CONTEXT.md + ADR
## 新增技能的投入产出 ## 新增技能的投入产出
| 技能 | 学多久 | 一次省多少 | 什么时候用 | | 技能 | 接入成本 | 主要收益 | 什么时候用 |
|------|--------|-----------|-----------| |------|--------|-----------|-----------|
| to-prd | 0 分钟(自动综合) | 10-15 分钟 | openspec research 结束后 | | to-prd | 自动综合 | 结构化需求 | openspec research 结束后 |
| grill-with-docs | 替换已有 grill-me | 0 额外时间 + 产出文档 | 需求澄清阶段 | | grill-with-docs | 替换已有 grill-me | 产出文档化澄清 | 需求澄清阶段 |
| zoom-out | 10 秒(一句话) | 避免方向性返工 | grill 完成后、apply 前 | | zoom-out | 低 | 避免方向性返工 | grill 完成后、apply 前 |
| diagnose | 5 分钟了解流程 | 每次 bug 省 20-30 分钟 | apply 中遇到问题 | | diagnose | 低 | 减少猜测式 bug 修复 | apply 中遇到问题 |
| tdd | 5 分钟了解流程 | 减少回归 bug | apply 中写代码 | | tdd | 低 | 减少回归 bug | apply 中写代码 |
| git-guardrails | 0 分钟(被动生效) | 防止灾难性操作 | 全程自动 | | git-guardrails | 被动生效 | 防止灾难性操作 | 全程自动 |
## 为什么这套组合优于单纯依赖 openspec ## 为什么这套组合优于单纯依赖 openspec
@@ -804,7 +815,7 @@ v4:
| # | 问题 | 具体表现 | 分析结论 | | # | 问题 | 具体表现 | 分析结论 |
|---|------|----------|----------| |---|------|----------|----------|
| 1 | propose 阶段越界 | 在 propose 阶段一次性生成了 proposal + design + specs + tasks,跳过 grill 和 specify | 需求小时 agent 本能跳过门控。现有硬约束 #3(不得跳过 grill)和阶段流程顺序已覆盖,属于执行层面问题,不需要改协议 | | 1 | propose 阶段越界 | 在 propose 阶段一次性生成了 proposal + design + specs + tasks,跳过 grill 和 specify | 需求较小场景下 agent 本能跳过门控。现有硬约束 #3(不得跳过 grill)和阶段流程顺序已覆盖,属于执行层面问题,不需要改协议 |
| 2 | 子 skill 伪调用 | grill 阶段读了 grill-with-docs 的 SKILL.md 后自行执行,audit 阶段跳过了 zoom-out | Skill 工具调用和 Read 后执行效果等价,关键是"不能跳过"而非"用什么工具调用"。硬约束 #6 已覆盖,不需要改协议 | | 2 | 子 skill 伪调用 | grill 阶段读了 grill-with-docs 的 SKILL.md 后自行执行,audit 阶段跳过了 zoom-out | Skill 工具调用和 Read 后执行效果等价,关键是"不能跳过"而非"用什么工具调用"。硬约束 #6 已覆盖,不需要改协议 |
| 3 | spec 遗漏用户行为 | spec 写的是"添加 .expanded class"(实现细节),没有写"展开后显示完整正文"(用户可观察行为) | 导致第一版实现只切换了 CSS class,正文内容仍显示截断文本。spec 应描述用户可观察的结果而非实现方式 | | 3 | spec 遗漏用户行为 | spec 写的是"添加 .expanded class"(实现细节),没有写"展开后显示完整正文"(用户可观察行为) | 导致第一版实现只切换了 CSS class,正文内容仍显示截断文本。spec 应描述用户可观察的结果而非实现方式 |
@@ -819,3 +830,406 @@ v4:
### 后续观察项 ### 后续观察项
问题 1 和 2 暂不改协议,如果多次验证中反复出现再考虑加约束。问题 3 需要在下次 specify 阶段验证:spec scenario 是否自然地描述用户行为而非实现细节。 问题 1 和 2 暂不改协议,如果多次验证中反复出现再考虑加约束。问题 3 需要在下次 specify 阶段验证:spec scenario 是否自然地描述用户行为而非实现细节。
## v4.1:Apply 阶段前置调研增强(2026-06-23)
### 背景
基于"山东商客意向单同步接口"的执行复盘(`skill-workbench/docs/sm-flow/sm-flow-execution-review-shandong-intent-sync.md`),发现 apply 阶段存在严重的返工问题:
- **返工次数**:4-5 次重大返工
- **核心问题**:apply 阶段"想当然"开始写代码,缺少充分调研和分步验证
- **主要表现**:
- 参考实现利用不充分(设计文档提到参考实现,但直到用户提醒才去看)
- 技术栈不熟悉(RequestMsg 结构、Kafka 发送方式、Consumer 位置全部返工)
- 设计-实现偏离(验签/解密/查询接口只有 TODO 注释)
### 核心改进:Pre-apply Checkpoint
在 apply 阶段开始前增加强制性调研检查点(方案 B 简化版):
#### 修改 1:grill 阶段增加技术实现维度
在 question pool 中新增"技术实现维度":
```markdown
**技术实现维度**(新增):当 proposal 提到参考实现、或涉及项目现有基础设施时,增加技术澄清问题:
- 参考实现的具体文件路径是什么?
- 项目现有的 [请求结构/MQ/缓存/加密/工具类] 标准是什么?
- 有哪些技术点需要先调研或新建?
```
**目的**:在 grill 阶段就识别技术调研需求,避免 apply 时才发现技术栈不熟悉。
#### 修改 2:apply 阶段增加 Pre-apply Checkpoint
在 apply 阶段开始前增加强制调研步骤:
**触发条件**(3 条):
- design 或 tasks 中提到"参考 XXX 实现"
- 需要调用项目现有基础设施(MQ/统一请求结构/工具类等)
- 技术栈不熟悉或第一次在该项目实现类似功能
**执行步骤**(3 步):
1. **完整阅读所有参考实现**
- 从 OpenSpec design 或 tasks 中定位参考实现文件
- 如果路径不明确,通过 Grep 搜索关键类名或模式
- 逐行理解关键逻辑,提取可复用代码片段和模式
2. **Grep 关键技术栈**
- 请求/响应结构模式
- 消息队列模式
- 统一工具类
- 异常处理和日志记录标准
3. **形成技术栈清单并写入 decisions.md**
- 项目使用的请求/响应结构标准
- MQ 消息定义和发送标准
- Consumer 标准位置和写法
- 加密/验签/工具类的标准用法
- 识别需要新建的工具类或基础设施
**输出要求**(3 条):
- ✅ 技术栈清单已写入 `decisions.md` 的 "Pre-apply Research" 章节
- ✅ 已列出所有参考实现的文件路径
- ✅ 已识别需要新建的工具类/基础设施
**快速模式支持**:micro 分档可按风险缩小调研范围,但仍需形成清单。
#### 修改 3:apply 实现过程增强
**分步实现**:建议按 Controller → Service → MQ/异步组件 → Consumer/下游 顺序,每完成一层验证后再继续。
**首模块完成后对齐检查**:完成第一个接口/模块后,对比 OpenSpec design/tasks,标记"已完成/TODO";核心功能(加密/验签/核心业务逻辑)不允许空实现或纯 TODO 注释。
**快速失败**:连续返工 ≥ 2 次时,暂停并重新执行 pre-apply checkpoint 或向用户汇报。
#### 修改 4:apply 退出条件增强
新增退出条件:
- ✅ 已完成 pre-apply checkpoint(如触发条件满足),技术栈清单已写入 `decisions.md`
- ✅ 核心功能已实现或明确标注"待联调",无纯 TODO 占位
### 预期效果
| 指标 | 当前 | 目标 | 改善 |
|------|------|------|------|
| 返工次数 | 4-5 次 | 0-1 次 | -80% |
| 核心功能空实现率 | 高(3/3 核心功能) | 0% | -100% |
**ROI 分析**:
前置调研的收益来自减少返工和避免核心功能遗漏。v4.3 之后不再用固定投入指标定义投入或收益,改按风险和实现复杂度决定调研深度。
### 复杂度评估
**本次修改复杂度**:中等
- 文本增量:+55 行(从 281 行 → 336 行,+20%)
- 概念层级:+1 层(apply 内部增加 Pre-apply Checkpoint 子阶段)
- 强制规则:+5 条(pre-apply 触发条件、执行步骤、输出要求)
**整体复杂度**:高(但合理)
- 总行数:606 行 → ~700 行(+15%)
- 阶段数:9 个(不变)
- 门控数:4 个 → 6 个(+propose checkpoint, +pre-apply checkpoint)
**简化设计**:
- 采用方案 B(简化版),相比完整方案减少 45% 文本量和 44% 规则数
- 保留核心价值(前置调研、技术栈清单、核心功能质量保证)
- 去掉过度约束(严格执行顺序、频繁检查点、详细操作模板)
### 适用场景
✅ **强烈推荐**:
- 中等及以上规模需求(3+ 接口或涉及多模块)
- 涉及项目现有基础设施(MQ/统一请求结构/工具类)
- 第一次在该项目实现类似功能
- 设计文档提到"参考 XXX 实现"
🟡 **可选执行**:
- micro 分档的简单需求(可按风险缩小范围)
- 纯数据处理或工具脚本(技术栈熟悉)
❌ **不推荐**:
- 紧急热修复(时间紧急)
- 一次性脚本(不涉及项目标准)
### 相关文档
- 执行复盘:`skill-workbench/docs/sm-flow/sm-flow-execution-review-shandong-intent-sync.md`
- 更新日志:`skill-workbench/docs/sm-flow/phase-contracts-v4.1-changelog.md`
- 修改文件:`.agents/skills/sm-flow/references/phase-contracts.md`
## v4.2:可验证 Checkpoint 与执行机制增强(2026-06-24)
### 背景
基于"lookup-knowledge-integration"的执行复盘(`skill-workbench/docs/sm-flow/sm-flow-optimization-suggestions.md`),发现一个结构性问题:
**约束是"软性"的,缺少执行机制**
- **规则清楚但可绕过**:6 条硬约束写得很清楚"不得跳过 commit",但 agent 仍然能跳过
- **标准模糊无法判断**:commit 阶段说"检查是否可执行",但不知道具体检查什么
- **流程无强制顺序**:archive 建议"先 devflow 后 handoff",但 agent 可能先创建 handoff
**核心认知**:规则是"描述性"的(说应该做什么),缺少"执行性"的机制(强制检查、文件依赖)。
### 核心改进:从软性约束到硬性检查
v4.2 不增加新阶段或新规则,而是**把现有约束变成可验证的 checkpoint**:
| 改进点 | Before(v4.1) | After(v4.2) |
|--------|---------------|--------------|
| Commit 标准 | "检查是否可执行"(模糊) | 文件完整性 + 一致性检查清单(具体) |
| Apply 门控 | "已通过 commit"(软性) | 检查 `.committed` 文件存在(硬性) |
| Archive 顺序 | "应该先 devflow"(建议) | 5 步强制顺序 + 自检(必须) |
### 详细修改
#### 修改 1:Commit 阶段增加可验证 Checkpoint
**文件完整性检查**(必须全部通过):
- [ ] `proposal.md` 存在,包含问题描述(≥50字)、建议方案(≥100字)、范围/非目标
- [ ] `design.md` 存在,包含架构设计、数据结构(≥1个)、关键决策(≥2条)
- [ ] `specs/` 目录存在,至少 1 个 functional-spec.md 包含 ≥3 个 requirement
- [ ] `tasks.md` 存在,包含 ≥5 个可执行子任务,每个任务有验收标准
**一致性检查**(必须通过):
- [ ] proposal 核心概念 → design 有对应设计
- [ ] design 关键决策 → tasks 有对应实现
- [ ] tasks 验收标准可验证(非"正确实现"这类模糊描述)
**标记文件**:检查通过后,创建 `openspec/changes/{slug}/.committed` 文件
#### 修改 2:Apply 阶段增加前置门控
**前置门控检查**(硬约束):
1. 检查 `openspec/changes/{slug}/.committed` 文件是否存在
2. 如不存在:
- 汇报:Draft OpenSpec 未通过 commit 检查
- 列出缺失的 checkpoint 项
- 询问用户:是否补做 commit;如用户要求不补做,则中止 apply 或标记为 `emergency-bypass`
#### 修改 3:Archive 阶段增加强制执行顺序
**5 步 Checklist**(不得跳过或重排):
1. **创建 devflow 档案**(必需):brief.md + evidence.md + decisions.md + acceptance.md
2. **更新索引**(必需):在 `devflow/index.md` 追加一行
3. **标记 OpenSpec**(必需):创建 `.archive-ready` 文件
4. **向用户汇报**(必需):列出文件、验证分类、剩余风险,询问是否归档
5. **执行 OpenSpec Archive**(可选):用户确认后调用 `openspec-archive-change`
**自检**:Step 4 前检查 Step 1-3 是否都完成
### 新增门控文件
| 文件 | 创建时机 | 用途 |
|------|----------|------|
| `.committed` | commit 阶段退出时 | apply 阶段前置门控依据 |
| `.archive-ready` | archive Step 3 | 标记归档准备就绪 |
### 预期效果
**解决的问题**:
- ❌ Commit 标准不明确 → ✅ 有具体检查清单,无法模糊通过
- ❌ Apply 可能基于不完整 OpenSpec → ✅ 门控文件强制阻止
- ❌ Archive 容易遗漏 devflow → ✅ 强制顺序确保完整
**量化指标**:
- Commit 阶段跳过率:-100%(有 checklist 无法跳过)
- Apply 基于不完整 OpenSpec:-100%(门控阻止)
- Archive 遗漏 devflow:-100%(强制顺序)
### 设计原则
#### 1. 可验证性
将模糊标准转为可测量的具体要求:
- Before: "检查 OpenSpec 是否可执行"
- After: "proposal ≥50字、design ≥1个数据结构、specs ≥3个 requirement"
#### 2. 门控文件
用文件存在性替代软性判断:
- Before: 描述"已通过 commit"
- After: 检查 `.committed` 文件存在
#### 3. 强制顺序
用 checklist 替代建议性描述:
- Before: "应该先创建 devflow"
- After: "Step 1 devflow → Step 2 索引 → Step 3 标记 → Step 4 汇报"
### 复杂度评估
**本次修改复杂度**:低-中等
- 文本增量:+80 行(phase-contracts.md +40 行,archive-rules.md +40 行)
- 概念增加:2 个门控文件
- 规则增强:3 个阶段的检查清单
**整体复杂度**:高(但更可靠)
- 总行数:~700 行 → ~780 行(+11%)
- 门控数:6 个 → 8 个
**权衡**:
- ✅ 收益:彻底解决"跳过阶段"问题
- ⚠️ 成本:增加 80 行文本,更多检查项
### 与 v4.1 的关系
| 版本 | 核心改进 | 解决问题 |
|------|----------|----------|
| v4.1 | Pre-apply Research Checkpoint | apply 前置调研不足,导致返工(4-5次 → 0-1次) |
| v4.2 | 可验证 Checkpoint + 门控文件 | 约束是软性的,agent 容易跳过阶段 |
**互补关系**:
- v4.1 解决"调研不充分导致返工"(质量问题)
- v4.2 解决"缺少执行机制导致跳过阶段"(流程问题)
### 适用场景
**✅ 所有场景(无例外)**
v4.2 的改进是执行机制层面的,不涉及业务逻辑:
- 无论 micro/standard/complex,都需要 commit 检查
- 无论需求大小,都需要 apply 前置门控
- 无论项目规模,都需要 archive 强制顺序
**快速模式**:可以简化产物(如 tasks 只需 3 个),但**不能跳过门控**。
### 后续演进方向(v5.0 候选)
如果 v4.2 执行良好但仍有问题,考虑:
1. **流程状态文件** `.sm-flow-state`
- 记录当前阶段、已完成阶段、时间戳
- 支持断点续做
2. **更多门控文件**
- `.context-done`、`.grill-done`、`.apply-done`
- 形成完整的阶段间依赖链
3. **违规自检机制**
- 每个阶段退出前,自动检查 6 条硬约束
4. **进度可视化**
- 每次开始时,汇报进度条
**判断依据**:如果 v4.2 后仍频繁出现跳过阶段,再引入更重的机制。
### 相关文档
- 执行复盘:`skill-workbench/docs/sm-flow/sm-flow-optimization-suggestions.md`
- 更新日志:`skill-workbench/docs/sm-flow/phase-contracts-v4.2-changelog.md`
- 修改文件:
- `.agents/skills/sm-flow/references/phase-contracts.md`
- `.agents/skills/sm-flow/references/archive-rules.md`
## v4.3:显式触发、分档单一来源与验证闭环(2026-07-05)
### 背景
v4.2 之后,流程门控更可靠,但 skill 本身开始显得庞大:frontmatter、触发规则、分档规则、fallback、术语解释和阶段契约交织在一起。实际 review 中发现几个风险:
- 触发范围容易被写宽,导致任务只要涉及 OpenSpec、跨模块或 devflow 就自动触发 sm-flow。
- `micro / standard / complex` 的规则散落在多个文件里,后续维护容易不一致。
- `micro`、`standard`、`complex` 的要求同时分布在不同文件中,review 时很难判断哪个是权威。
- 规则中出现固定投入估算,容易把经验值误读成流程标准。
- fallback、checkpoint、Draft/Committed 等词缺少统一词条,解释容易漂移。
### 核心结论
v4.3 保留 v4 的精华,但收紧触发面、降低重复定义,并用真实 change 验证 micro 和 standard 两条路径:
- **只显式触发**:sm-flow 只在用户输入 `/sm-flow`、`/sm-flow explore`、`/sm-flow apply`、`/sm-flow archive`,或自然语言明确要求“使用 sm-flow / 走 sm-flow 流程”时触发。
- **不按需求类型自动触发**:OpenSpec、跨模块、接口契约、需求澄清、devflow 归档都不是自动触发条件。
- **4 个用户可见 checkpoint 保留**:Discover、Commit、Apply、Archive。
- **9 个内部阶段保留**:clarify → context → propose → grill → specify → audit → commit → apply → archive。
- **分档单一来源**:`references/scales.md` 是 `micro / standard / complex` 的唯一完整规则源。
- **fallback 独立成文**:外部 OpenSpec 能力或子 skill 不可用时,使用 `references/fallbacks.md`,并记录 capability source、影响和剩余风险。
- **词条独立成文**:`references/glossary.md` 统一 checkpoint、fallback、Draft、Committed、gate、scale 等术语。
- **不使用固定投入指标**:skill 规则不再用具体投入单位或时间盒定义分档、努力程度或验证阈值。
### 文件结构调整
新增 reference:
```text
.agents/skills/sm-flow/references/
├── fallbacks.md # 外部 OpenSpec/子 skill 不可用时的内置协议
├── glossary.md # checkpoint/gate/fallback/Draft/Committed/scale 等术语
└── scales.md # micro / standard / complex 的唯一完整定义
```
职责调整:
- `SKILL.md`:只保留触发边界、四层架构、6 条硬约束、4 个用户命令、4 个 checkpoint、9 个内部阶段和首次加载规则。
- `phase-contracts.md`:保留阶段进入条件、动作、输出和退出条件;涉及分档时只引用 `scales.md`。
- `operating-rules.md`:保留启动检查、进度汇报、接口影响、devflow 分层和完成标准;不再重复定义分档细节。
- `archive-rules.md`:只定义归档顺序、提取映射和索引规则;产物分档引用 `scales.md`。
- `templates.md`:保留模板和检查表,不再作为分档规则来源。
### 分档验证
#### micro 验证
验证 change:`validate-sm-flow-explicit-trigger`
归档位置:
```text
openspec/archive/2026-07-05-validate-sm-flow-explicit-trigger/
devflow/projects/2026-07-05-validate-sm-flow-explicit-trigger/
```
验证内容:
- 显式触发规则生效:没有 `/sm-flow` 或明确“使用 sm-flow”时,不自动触发正式 sm-flow。
- micro 可以使用内联设计小节,但仍需要 `proposal.md`、`specs/`、`tasks.md`、`.committed` 和 devflow 回填。
- 发现并修复一个真实不一致:部分阶段契约仍硬编码 `design.md`,与 micro 允许等价设计小节冲突;已改为“设计产物”。
- devflow micro 档案使用 `brief.md`、`decisions.md`、`acceptance.md`;证据并入过程日志。
#### standard 验证
验证 change:`validate-sm-flow-standard-change`
归档位置:
```text
openspec/archive/2026-07-05-validate-sm-flow-standard-change/
devflow/projects/2026-07-05-validate-sm-flow-standard-change/
```
验证内容:
- standard 需要完整 OpenSpec 四件套:`proposal.md`、独立 `design.md`、`specs/`、`tasks.md`。
- standard devflow 档案需要 `brief.md`、独立 `evidence.md`、`decisions.md`、`acceptance.md`。
- 分档定义扫描只命中 `references/scales.md`,没有发现其它文件重新定义 standard/micro/complex。
- standard 路径未发现新的规则不一致。
### 验证命令与结果
本轮验证通过:
- `python C:/Users/兜/.codex/skills/.system/skill-creator/scripts/quick_validate.py .agents/skills/sm-flow`
- `references/*.md` 引用完整性扫描
- 旧问题词扫描:固定投入指标、旧跳过语义、旧 conflict 表达、旧固定设计文件组合表达
- 分档重复定义扫描
- micro 和 standard OpenSpec/devflow 文件存在性检查
### 当前取舍
- 保留 3 个分档:`micro`、`standard`、`complex`。它们不是三套流程,而是同一流程在产物和审查强度上的三档覆盖。
- 不引入显式状态文件,例如 `.sm-flow-state`。当前只保留 `.committed` 和 `.archive-ready` 两个必要 gate 文件。
- 不把内部 9 阶段暴露成用户 API。用户交互继续以 4 个 checkpoint 为主。
- 不默认做 OpenSpec archive;archive 仍是用户确认后的动作。
### 对 v4.1/v4.2 的修正
v4.1 的 Pre-apply Research 仍然保留,但不再用固定投入指标描述执行深度。当前规则是:按 `references/scales.md` 的当前分档和实现风险决定调研深度,退出判断以技术栈清单是否足以指导实现为准。
v4.2 的 `.committed` 和 `.archive-ready` 继续保留。v4.3 只是把文件完整性检查改为“按当前分档要求执行”,避免 standard 的独立 `design.md` 要求误套到 micro。
### 相关档案
- `devflow/projects/2026-07-05-validate-sm-flow-explicit-trigger/`
- `devflow/projects/2026-07-05-validate-sm-flow-standard-change/`
- `openspec/archive/2026-07-05-validate-sm-flow-explicit-trigger/`
- `openspec/archive/2026-07-05-validate-sm-flow-standard-change/`
+111
View File
@@ -0,0 +1,111 @@
# value-scan / value-dig · 设计文档(Latest Design)
> **定位**:从**已交付的代码**里逆向萃取「值得讲的价值点」,交人勾选后深挖成可讲、可追问、可被审的文档。
> **适用**:面试/简历素材重建、模块价值盘点、交接文档提级。
> **形态**:两个 skill 接力 —— `value-scan`(广度枚举,停在人工勾选门)→ `value-dig`(深度产出,三件套任选)。
> **战果**(its 仓库实测,2026-09-18):4 轮扫描产出 9 份文档全部通过机械校验;2 条主链路各带 1 个 P0 级实锤缺陷。
---
## 1. 为什么要有这两个 skill
盘点代码价值时,agent 有三个系统性偏差:
| 偏差 | 表现 | 解药 |
|---|---|---|
| **判不了价值** | 把"用了 Redis""有 4 个 handler"当亮点 | 简历行填空测试:`用【机制】解决了【问题】,代价是【取舍】`——机制格填不出就不是价值点 |
| **缺陷导向** | 扫一遍变成挑毛病大会,清单全是负面 | 阶段隔离:S1 只产亮点,缺陷是深挖链路时自然浮现的副产物,归宿在改造方案 |
| **自作主张** | 替用户挑完直接开写 | 门控:产出候选清单后**必须停**,勾选权在人 |
一句话设计哲学:**agent 负责采样与结构化,人负责价值判断**。
## 2. 两段流水线
```
S0 定范围 → S1 枚举 → S2 勾选【硬门:必须停】
↓(人勾选 / 否决改向 A′)
value-dig:①功能点清单 ②设计复盘 ③改造方案(各自独立,可只做其一)
```
### value-scan(广度)
- **三层结构**:域 → 链路 → 机制节点。链路按**触发者**拆(谁在改这行数据),不按业务功能拆——收敛点多半是机制所在。
- **三条硬标准**(全过才进清单):① 核心链路 ② 高级工程师的设计(非框架常识)③ 简历够硬。
- **数量闸**:5–8 条为宜,>12 = 颗粒度掉到实现层,退回重并。
- **两层锚点**:机制级 `路径#方法名`(不写行号,防漂移),深挖级 `文件:行号`(必须读过再写)。
### value-dig(深度)
三份文档三种读者:
| 文档 | 读者 | 灵魂 |
|---|---|---|
| ① 功能点清单 | 自己/接手人 | **主干调用骨架**:整条链压成一段伪代码,每行标方式(`[锁]``[幂等]``[MQ]`),功能点互为索引 |
| ② 设计思路与取舍 | 面试官 | 第一人称复盘 + **"与代码的对照说明"**:判断与代码事实不一致处逐条列出——诚实性是可信度唯一来源 |
| ③ 改造方案 | 架构评审 | 缺陷唯一归属地;**产出门槛**:必须有②加机制/③重构档改造点才立方案,全是补漏档不立(防灌水) |
跨文档资产复用:`tb_order_anomaly` 台账、token 锁工具、巡检 Job——两链路方案共用一套,是"结构必然"不是"省事"。
## 3. 机制设计要点(为什么这样设计)
### 3.1 门控(S2 必停)
价值判断权如果不在人,整个流水线退化成"agent 自嗨产出没人看的文档"。所以:
- 候选清单落盘 + 显式请求勾选("请从 N 条挑 3–6 条");
- 用户禁用提问工具也一样停——请求写成文字;
- **整批否决且未给新目标 = 流程终点**,不强续。
### 3.2 判据外化为填空
"价值"无法定义,但"简历行填得出来吗"可判定。两级:
- **准入**:三条硬标准(反例驱动的剔除表);
- **表达**:机制+问题两格必填,取舍格留给 value-dig(不误杀)。
被剔除的点不丢弃——进「已剔除」表注明未过哪条标准,供复核筛选口径。
### 3.3 机械校验(check.py)与模板外置
- 模板是**活资产**:产出照模板填空,被纠正过就回写模板;
- check.py 十余条规则:引号配对 / mermaid 合法性 / 表格列一致+不缩进 / 章节完整性(模板必备节 ⊆ 产出节)/ scan 专属(无代码围栏、锚点格式、候选数 ≤12)/ dig 专属(骨架行必带方式标记、证据必含行号)/ doc 专属(改造方案必有关键片段);
- FAIL 必须为 0,WARN 允许保留但写明原因。
### 3.4 缺陷的归宿隔离
缺陷只在改造方案出现,且**不是枚举出来的是贴着链路走出来的**——三把刀(按触发者拆链路 / 竞态矩阵 / 幂等键清单+状态流转图)+ 机制模式库(结构性限制 → 可引入机制对照表)+ 三档尺度(补漏⭐/加机制⭐⭐⭐/重构⭐⭐⭐,每缺陷必追问"能否升一档")。
## 4. 实战演化记录(its 仓库 4 轮,2026-09-18)
这轮实战暴露的边界案例与回写(模板活资产的实证):
| # | 事件 | 回写 |
|---|---|---|
| 1 | 用户否决 5 条单点:"都不够硬,直接分析整链路" | value-dig 新增**入口 A′(否决改向)**:否决原因入清单、按 B 重走、产物声明 |
| 2 | 权益域首轮以"机制格填不出"剔除,复评翻案(快照轮询机制实存,藏在 2349 行大类的私有方法群) | "机制格填不出"剔除加**硬门槛**:没读过入口方法向下 ~100 行不得定稿剔除;翻案不删行留痕 |
| 3 | "不够硬"出现两次(单点否决、权益否决) | S2 门控新增**否决即校准**:负反馈记入清单,同域复扫先读否决记录 |
| 4 | 勾选回写两次压列(3 列变 2 列) | 候选清单模板补**回写示例**(3 列不压列);check.py 报错**附行内容摘要** |
| 5 | check.ps1 仅 Windows | 移植 **check.py**(等价回归 8 产物一致);顺带发现初版 `__name__` 损坏静默 exit 0——校验工具自身的静默通过比报错更危险 |
### 实测产出骨架(可作参考样例)
```
docs/
├── 赢客下单-候选价值点.md S1 清单(5 候选 + 5 剔除)
├── 赢客下单-功能点清单.md 7 功能点 + 主干骨架
├── 赢客下单-设计思路与取舍.md 4 不变量 / 7 决策 / 口述版
├── 赢客下单-改造方案.md 6 缺陷(3🔴)→ 3 阶段
├── 全仓其余域-候选价值点.md 二轮 8 候选(含翻案 ★7/★8)
├── 工单全生命周期-{功能点清单,设计思路与取舍,改造方案}.md
```
两个 P0 实锤(深挖才浮现的典型):
- 幂等双关口键不一致:bossOrderId vs requestId,组合穿透 → 重复扣权益;
- `updateConfirmInfo` 条件更新漏 `status=51`:设计是 DB 仲裁,落地是应用层检查 → 人工确认可被自动确认覆盖。
## 5. 已知限制与下一步
| 限制 | 说明 | 候选方向 |
|---|---|---|
| 单域节奏 | 一次一域,全仓扫描靠人反复发起 | 域清单自动切片 + 断点续扫 |
| 判据主观残留 | "简历够硬"仍依赖人对目标岗位的校准 | 按 JD 关键词加权候选排序 |
| 深挖成本 | 一个功能点 ≈ 1–2 份 20KB 文档,人工审读压力大 | 功能点清单先行 + 复盘/方案按勾选再出 |
| 校验器无自检 | check.py 自身损坏会静默通过 | CI 里对已知 BAD 样例断言必 FAIL |
@@ -0,0 +1,115 @@
---
name: value-dig
description: Use when the user has already chosen which mechanisms or value points matter and now wants them written up in depth — "把这个点写成文档", "把这条链路的实现整理成功能点", "写设计思路与取舍", "出改造方案", or when an existing module's design must be reconstructed layer by layer for an interview walkthrough. Read-only — never modifies the scanned project.
---
# value-dig · 深度产出(功能点 / 设计复盘 / 改造方案)
## 一句话
把**已经选定的**机制点写成**能讲、能追问、能被审**的文档:按需产出三件套。
**两条原则**
1. **价值优先 → 深入 → 更优方案。** 缺陷与改造只在「改造方案」里出现;功能点清单与设计复盘以"这个设计为什么好、怎么取舍"为主体。
2. **只读**:不修改被扫描项目的任何文件(新增产物不算)。
## 两种入口
| 入口 | 情形 | 怎么做 |
|---|---|---|
| **A · 有候选清单** | 上游 `value-scan` 已产出且人已勾选 | 直接开工;勾选结果回写候选清单「闸门状态」节(`✅ 已勾选:★N…⟨谁/日期⟩`) |
| **A′ · 候选被否决改向** | 人看了清单说"都不够硬,直接分析整条链路"——否决候选但给出新目标 | 三步:①原清单「闸门状态」记**否决原因原文摘要**(这是筛选口径的校准数据);②按 B 的最小枚举对准新目标重走;③产物头部声明"入口 A′(否决改向)" |
| **B · 直接点名** | 用户直接说"把 XX 链路写成文档",无候选清单 | 只针对该链路按 `value-scan` 的判据做一次**最小枚举**(按触发者拆链路 + 三条硬标准),在产物头部声明"入口 B" |
> **入口 B 不能省粗筛**:跳过判据会把"框架常识/纯业务实现"写成深度文档。
## 三份文档(各自独立,可只做其一)
> 若用户只要"每个点先给个轻理由看看"再决定深挖谁,可用 `assets/价值点报告模板.md` 快速产出一份轻量报告,不必直接进三件套。
| 文档 | 模板 | 内容 | 关键 |
|---|---|---|---|
| ① **功能点清单** | `assets/深度模板/功能点清单模板.md` | 链路总览 · **主干调用骨架** · 各功能点 · 推荐组合 · 附录速查 | **只记功能点,不列缺陷** |
| ② **设计思路与取舍** | `assets/深度模板/设计思路与取舍模板.md` | 第一人称复盘:问题定义 → 不变量 → 怎么拆 → 设计主线 → 逐环节决策表 → 做对的/承接不住的 → 重做改什么 → 面试口述版 | 讲**取舍与代价**,不只讲做法 |
| ③ **改造方案** | `assets/深度模板/改造方案模板.md` | 缺陷(含严重度)→ **改造前链路骨架**(整体调用关系,伪代码)→ 总体思路 → 分阶段(每点含**关键片段**(伪代码/SQL)+ 验收)→ 迁移灰度 → 不变量由谁保证 | **缺陷的唯一归属地**;复用既有资产,不重复建表。**代码讲解要求:交付标准是"照着能讲代码"**——§1 必有改造前链路骨架(写清谁调谁、每步做了什么,可标类名/方法名,**不写路径与行号**)、每个改造点必有「关键片段」(伪代码/SQL,只示形状);只有观点没有片段即不达标。**产出门槛:深挖浮现的缺口中至少存在一个②加机制/③重构档的改造点才立方案;全是①档补漏的(加缓存/加判断/加隔离/改配置类),在设计复盘"重做改什么"里带一句即可,不单独成文——硬写就是灌水** |
### ① 功能点清单的必备件:主干调用骨架
把整条链路的 N 段主干压成**一段连续伪代码**,每行右侧标注方式(`[锁]` `[幂等]` `[策略]` `[MQ]` `[外调]` `[落库]` `[兜底]` `[履历]` `[通知]` `[隔离]` `[验签]`);附方式图例(反向索引)。**每个功能点必须能在骨架上找到**(互为索引)。
### ③ 改造方案的取材工具(深入链路时用)
缺陷**不是枚举出来的,是贴着链路走一遍时浮现的**。深挖时用这三把刀看结构,发现的缺口按「机制模式库」比对出改造方向:
| 刀 | 怎么做 |
|---|---|
| **按触发者拆链路** | 找「同一行数据被几个触发者改」→ 判断收敛/防重是否单点 |
| **竞态矩阵** | 「并发场景 × 后果」穷举表:重复回调 / 回调与兜底并发 / 并发退款… |
| **幂等键清单 + 状态流转图** | 列出链路上所有幂等键并标层级;画状态机——"重复入账"与"状态与事实不符"的发现入口 |
**机制模式库**("结构性限制 → 可引入机制"对照表,改造方案的取材清单;**只有这一份,不复制**):
| 结构性限制(发现) | 可引入的机制 / 重构 |
|---|---|
| 业务写 + 发消息不原子 | 本地事务表 / Outbox + 投递器(业务与消息同事务,投递可重放) |
| 兜底任务不可恢复(poll 即删) | 任务表为权威,队列只做加速(宕机可恢复、积压可观测) |
| 不一致只有日志、无人知 | 一致性异常台账 + 告警 + 处理台(待处理 → 处理中 → 已处理) |
| 状态靠应用层"猜测" | CAS 条件更新 + 影响行数判定(把判断交给数据库) |
| 上游码散落多处、口径不一致 | 码字典化:每码标注「是否受理 / 是否终态 / 可重试」,多处共查一份 |
| "不确定"没有归宿 | 挂起态 + 巡检 + 重放(重放须走同一套分级,因为对方状态可能已变) |
| 对外调用有副作用却被重复调用 | 幂等键(业务唯一键)+ 冲突当命中 |
| 资金出去的方向弱于进来 | 对称化:退款补齐同构的锁 / 短路 / 唯一索引 |
| 重试责任多点(乘法放大) | 重试责任单点 + 显式关闭其他层(应用重试了,MQ 就不重试) |
| 状态写入早于事实 | 中间态 + 以权威回调驱动终态(不以"发起成功"为准) |
| 能力只覆盖一条路径 | 铺开:把一个点的分级铺成一张网(全部写类接口统一) |
| 跨系统没有事务 | 「幂等 + 可重放 + 对账」三件套替代事务 |
| 关键参数散落、取值无解释 | 参数登记与解释:汇总阈值 / 退避 / 分片并说明取值依据 |
### 改进的三档尺度
| 档 | 做法 | 简历硬度 |
|:-:|---|:-:|
| ① 补漏 | 修一个具体的错:加校验、加索引、补 try-catch | ⭐ |
| ② 加机制 | 引入一个新机制,替代"靠人 / 靠自觉"的现状 | ⭐⭐⭐ |
| ③ 重构 / 更合理设计 | 改结构本身:隐式判断变显式判定、口径收敛、方向对称化 | ⭐⭐⭐ |
**硬要求:每个缺陷都追问"能不能上升一档"**;改造方案里 ②③ 档应占多数。改进的固定 5 要素:① 结构性限制 ② 机制/方案 ③ 替代了什么 ④ 代价 ⑤ 为什么不用通用方案。
**缺陷严重度**:🔴 资金/数据错误 · 🟠 静默失败或重复调用 · 🟡 卫生与可维护性。
**边界**:只做系统级结构问题(一致性·幂等·可运营性·可恢复性·职责漂移·口径分散),不做代码风格/坏味道/命名/注释。
## 硬规则(合并版)
| # | 规则 | 为什么 |
|:-:|---|---|
| 1 | **深度闸门**:允许简短的伪代码/关键片段(CAS 语句·锁与短路顺序·状态分支·DDL·Lua 脚本)把机制画实——**行数是参考不是硬限,忠实于机制形状优先**;真正禁止的是大段源码摘录、代码块内行号、逐层讲解。**豁免** = 主干调用骨架(技术地图,压成一行一段) | 禁代码会"太空",贴源码则成"阅读报告" |
| 2 | **证据真实性**:锚点 `路径:行号`,**必须读过再写**;拿不准标【待确认】 | 错锚点毁掉可信度 |
| 3 | **只读**:不改被扫项目任何文件(新增产物不算) | — |
| 4 | **缺陷只进改造方案**:功能点清单与设计复盘不列缺陷表、不标严重度;设计复盘里"承接不住的地方"自然带出即可,不展开成清单 | 价值优先;缺陷集中一处才成体系 |
| 5 | **改进不停在补漏档;不写通用套话**("加监控""上分布式事务");必须贴合业务的具体语义/表/状态,优先复用既有资产 | ②③ 档才是简历上能写硬的 |
| 6 | **诚实性**:"设计对了但落地不完整"要明说;判断与代码事实不一致处逐条列出;文档写的方案必须回代码验是否落地 | 深度文档可信度的唯一来源 |
| 7 | **只做被点单的 1–3 个点**;每点先想清楚归哪份文档,不为凑齐三件套而写 | 实测一个功能点 ≈ 1–2 份 20KB 文档 |
## 格式保证
1. **模板外置**:读 `assets/` 对应模板填空。
2. **机械校验**(与 `value-scan` 共用 `../value-scan/assets/check.ps1`):
```powershell
$ck = .agents/skills/value-scan/assets/check.py
# ① 功能点清单
python $ck dig <产物> --template .agents/skills/value-dig/assets/深度模板/功能点清单模板.md
# ② 设计思路与取舍 / ③ 改造方案
python $ck doc <产物> --template .agents/skills/value-dig/assets/深度模板/<对应模板>.md
```
**FAIL 必须为 0**;WARN 允许保留但写明原因。
3. **偏差回写**:被纠正过就回写模板。
## 触发词与落盘
**触发词**:「把这个点写成文档」「把这条链路整理成功能点」「写设计思路与取舍」「出改造方案」。
**落盘**:`<项目根>/docs/`,与候选清单同目录(可被用户覆盖)。
**上游**:候选清单由 `value-scan` 产出。
@@ -0,0 +1,76 @@
# ⟨域⟩ · 价值点报告(S3 产物)
> **用途**:为 S2 勾选出的每个点写**可讲述的轻理由**(默认交付深度)。
> **上游**:`⟨域⟩-候选价值点.md`(S1)· **勾选来源**:⟨候选清单「闸门状态」节 / 用户消息直接点名⟩
> **证据快照**:基于 ⟨仓库名⟩ `⟨commit 短号 / 分支⟩`,⟨读取日期⟩。**换版本要重核**。
> **判据**:**简历行测试**——填不出机制的退回「附录·待定」
> **路径简写**:`⟨简写⟩/` = `⟨真实路径⟩`(锚点一律用简写前缀)
---
## 每个点 = 7 类内容
> **7 类不是"行数上限"**。关键片段与偏差附录**另有归属,不占这 7 类**。
> **点编号沿用 S1 的 ★ 编号**(便于与候选清单对照)。
### ★⟨N⟩ · ⟨机制名⟩
| # | 行 | 内容 |
|:-:|---|---|
| 1 | **简历行** | 用【⟨机制⟩】解决了【⟨具体问题/场景⟩】,代价是【⟨取舍⟩】 |
| 2 | **Problem** | ⟨不做会怎样 / 原来的做法会出什么问题⟩ |
| 3 | **Pattern** | ⟨机制是什么、怎么起作用⟩ |
| 4 | **Alternatives** | ⟨当时还能怎么做 / 为什么没选⟩ |
| 5 | **Tradeoffs** | ⟨代价:新增复杂度 · 依赖 · 运维负担⟩ |
| 6 | **Evidence** | `⟨简写⟩/⟨路径⟩.java:⟨行号⟩` · ⟨可核对的图/表/配置⟩ |
| 7 | **追问预判** | **问**:⟨高概率追问 1⟩ **答**:⟨一句话⟩<br/>**问**:⟨高概率追问 2(可选,最多 2 条)⟩ **答**:⟨一句话⟩ |
**关键片段 · ⟨片段名⟩**(≤10 行伪代码,把"只有名词"的地方画实)
```
⟨CAS 语句 / 锁与短路顺序 / 状态分支 / DDL⟩
```
**事实强度**(可选,用于区分"已核实"与"推断")
| 结论 | 强度 |
|---|---|
| ⟨…⟩ | **已核实**(读过代码) |
| ⟨…⟩ | **推断**(未核实,需人工确认) |
⟨重复上面 3 块,每点一节⟩
---
# 附录 · 与候选清单的偏差
> **实读代码后必须回头核对 S1 的表述**。S1 是"候选"不是"事实"——**偏差本身就是高价值材料**(往往是简历上最硬的一条)。
| # | S1 怎么写的 | 代码事实 | 处理 |
|:-:|---|---|---|
| 1 | ⟨S1 的原文⟩ | ⟨实读结果 + `路径:行号`⟩ | ⟨纠正 / 标【待确认】/ 升级为独立价值点⟩ |
---
# 报告尾 · 推荐组合
> **先讲哪 3 个**——给"追问密度最高 / 最能体现设计能力"的组合。**内容列必须是上面已写的 ★ 编号。**
| 组合 | 内容(★ 编号) | 适合 |
|---|---|---|
| **主线(推荐)** | ⟨★N + ★M⟩ | ⟨最能体现什么能力,追问密度最高⟩ |
| **完整版** | ⟨★1 + ★2 + ★3 + ★4 + ★5⟩ | ⟨讲清完整链路⟩ |
| **差异化** | ⟨★K⟩ | ⟨少数人会讲的点⟩ |
**建议讲述顺序**:⟨★N → ★M → ★K,并说明为什么这个顺序⟩
---
# 附录 · 待定
> 简历行**填不出机制**的点落在这里(**不删除**——防灌水,也不误杀)。
> ⚠️ **闸门二只在本阶段生效**:进入 S4 的点若机制仍未定,改为在其小节头部标 **【待确认:机制未定】**,**不在 S4 新建「待定」节**。
| # | 点 | 为什么填不出 | 需要补什么才能定 |
|:-:|---|---|---|
| 1 | | | |
@@ -0,0 +1,174 @@
# ⟨域⟩ 域 · 功能点清单
> **用途**:把「⟨链路主题⟩」这条链路按其设计文档与代码实读整理成功能点
> **流程**(与上游一致):**先记录功能点 → 定稿文档 → 再讨论最佳设计与取舍**
> **上游**:`⟨域⟩-候选价值点.md`(S1)+ 勾选结果(S2)
> **素材来源**:`⟨wiki/xxx-spec.md⟩`(⟨N⟩ 行)+ `⟨仓库名⟩` 代码实读
> **路径简写**:`⟨简写1⟩/` = `⟨真实路径⟩`;`⟨简写2⟩/` = `⟨真实路径⟩`
---
# 一、链路总览
**一句话**:⟨统领句——给出这条链路的**主线判断**,不是复述流程⟩
```mermaid
flowchart TD
A["⟨起点⟩"] --> B["⟨★ 机制节点⟩"]
B --> C{"⟨分支⟩"}
C -->|"⟨路径⟩"| D["⟨汇合点 / 分级发生地⟩"]
C -->|"⟨路径⟩"| D
D --> E{"⟨结果类型⟩"}
E -->|"⟨可逆⟩"| F["⟨处置⟩"]
E -->|"⟨不确定⟩"| G["⟨处置⟩"]
```
⟨可选⟩**关键差异表(设计的核心)**
| ⟨维度⟩ | ⟨取值1⟩ | ⟨取值2⟩ | ⟨取值3⟩ |
|---|---|---|---|
| ⟨例:对方结果⟩ | | | |
| ⟨例:可逆性⟩ | | | |
| ⟨例:处置⟩ | | | |
---
## 主干调用骨架(一眼看清哪一步用了什么方式)
> **这是"整条链路的技术地图"**——把 N 段主干压成**一段连续伪代码**,每行标注**用了什么方式**(`[锁]` `[幂等]` `[策略]` `[MQ]` `[兜底]` …)。
> 局部片段回答"一个机制长什么样",这一段回答"**哪些地方用了什么**",以及**哪些地方本该有兜底却没有**。
```java
// ═══ ① ⟨阶段名⟩ ═══
⟨方法名⟩(): ⟨动作⟩ // [锁]
⟨动作⟩ // [幂等]
⟨动作⟩ // [策略]
⟨动作⟩ // [外调]
// ═══ ② ⟨阶段名⟩ ═══
⟨方法名⟩(): ⟨动作⟩ // [验签]
⟨动作⟩ // [MQ]
⟨动作⟩ // [落库]
// ═══ ③ ⟨兜底 / 失败处置⟩ ═══
⟨方法名⟩(): ⟨动作⟩ // [兜底]
⟨动作⟩ // [重试] 只重超时
⟨动作⟩ // [履历]
```
**方式图例(反向索引:一种方式出现在哪些地方)**
| 标记 | 方式 | 出现在 |
|---|---|---|
| `[锁]` | ⟨分布式锁(注解式 / Redisson)⟩ | ⟨…⟩ · ⟨…⟩ |
| `[幂等]` | ⟨状态短路 + CAS + 一次性消费⟩ | ⟨…⟩ · ⟨…⟩ |
| `[策略]` | ⟨策略模式 + 工厂⟩ | ⟨…⟩ |
| `[MQ]` | ⟨Kafka⟩ | ⟨…⟩ |
| `[兜底]` | ⟨延时队列 + XXL-Job⟩ | ⟨…⟩ |
| `[重试]` | ⟨`@Retryable`(**只重超时**)⟩ | ⟨…⟩ |
| `[履历]` | ⟨DB 台账⟩ | ⟨…⟩ |
| `[验签]` | ⟨网关签名⟩ | ⟨…⟩ |
| `[隔离]` | ⟨try-catch / 线程池⟩ | ⟨…⟩ |
| `[外调]` / `[落库]` / `[通知]` | ⟨外部系统调用 / DB 写 / 站内信⟩ | 全链路 |
> **这张骨架的两个用处**:① **评审时一眼看清技术分布**(⟨锁 3 处、幂等 5 处、兜底 4 处⟩);② **横向对比**"同样的机制在别处有没有用"。
---
# 二、功能点(⟨N⟩ 个)
> 每个点:**核心内容** / **这个点在讲什么** / **一句话价值** / **图** / **关键片段(≤10 行伪代码)** / **关键表与字段** / **关键做法与证据**。
> **段落式**,不要压成表格("做了什么"常是 5–7 条,塞进单元格必然被简化)。
## ① ⟨功能点名⟩ ⭐⭐⭐⭐⭐
**核心内容**:⟨1 句,把"形状"说清(一把锁 + 三级短路 + 一条条件更新)⟩
**这个点在讲什么**
- **业务场景**:⟨谁在什么时刻触发了什么,为什么这事难;点出"同一时刻还有谁在改同一行数据"⟩
- **做了什么**(⟨用一句话概括做法⟩):
1. ⟨…⟩;
2. ⟨…⟩;
3. ⟨…⟩。
- **只把 fail 留给"我真的还没处理"**:⟨边界在哪⟩(若适用)
- **临界场景**:⟨并发 / 乱序 / 迟到时的行为⟩(若适用)
- **解决了什么问题**:⟨不做会怎样⟩
**一句话价值**:⟨说清"判断权 / 控制权"落在谁手里⟩
**图 · ⟨图名⟩**
```mermaid
flowchart TD
A["⟨入口⟩"] --> B{"⟨判断⟩"}
B -->|"⟨…⟩"| B1["⟨抢不到锁:直接回 success,让给持锁方⟩"]
B -->|"⟨…⟩"| C["⟨动作⟩"]
C --> D["⟨落库⟩"]
```
**关键片段 · ⟨片段名⟩**(伪代码,只示形状)
```
⟨CAS 语句 / 锁与短路顺序 / 状态分支 / DDL,≤10 行⟩
```
**关键表与字段**
| 表 | 关键字段 | 说明 |
|---|---|---|
| `⟨表名⟩` | `⟨字段⟩` · **`⟨关键字段⟩`** | ⟨说明⟩ |
**关键做法与证据**
| 做法 | 证据 |
|---|---|
| ⟨做法⟩ | `⟨简写⟩/⟨路径⟩.java:⟨行号⟩` |
| ⟨做法⟩ | 同上 `:⟨行号⟩` |
⟨重复 ① 的结构,每个功能点一节⟩
---
# 三、推荐组合
| 组合 | 内容 | 适合 |
|---|---|---|
| **主线(推荐)** | ⟨① + ⑤⟩ | ⟨最能体现什么能力,追问密度最高⟩ |
| **完整版** | ⟨① + ② + ③ + ④ + ⑤⟩ | ⟨讲清完整链路⟩ |
| **差异化** | ⟨④⟩ | ⟨少数候选人会讲的点⟩ |
---
# 四、设计亮点
## 4.1 亮点(面试可直接讲)
| # | 亮点 | 价值 |
|:-:|---|---|
| 1 | ⟨亮点⟩ | ⟨价值——**逐条对着旧实现的病灶**,不是堆框架⟩ |
| 2 | | |
> **本模板不设缺陷表**:缺陷、严重度与改进方案统一在《⟨主题⟩-改造方案.md》中呈现。深挖过程中发现的结构缺口先记到工作笔记,写改造方案时再展开。
---
# 附录 A · ⟨状态 / 结果类型⟩速查
| ⟨类型⟩ | 含义 | 终态? | ⟨处置1⟩ | ⟨处置2⟩ | 重试 |
|---|---|:-:|:-:|:-:|---|
| `⟨枚举值⟩` | | ✅ / ❌ | | | |
# 附录 B · 参数速查
| 参数 | 值 | 出处 |
|---|---|---|
| ⟨锁 leaseTime⟩ | | `⟨路径⟩.java:⟨行号⟩` |
| ⟨重试次数⟩ | | |
| ⟨延时 / 超时⟩ | | |
# 附录 C · 关键类索引
| 类 | 角色 |
|---|---|
| `⟨类名⟩` | ⟨在链路里的角色⟩ |
@@ -0,0 +1,233 @@
# ⟨主题⟩ · 改造方案
> **背景**:现状问题登记在本文第 0 节(**缺陷唯一归属地**);复盘视角的"承接不住"见《⟨主题⟩-设计思路与取舍.md》第 5 节
> **目标**:⟨把「X」从**一条路的设计**,变成**覆盖全部写接口的事实**⟩
> **边界**:⟨不改省侧协议、不引入分布式事务(改造点全在本服务内);DDL 只列关键字段,完整建表脚本另出⟩
> **与其它方案的关系**:⟨一致性异常台账**复用**《⟨其它⟩-改造方案.md》的 `⟨表名⟩`,**不重复建表**,只新增 `⟨列/取值⟩`⟩
> **依据**:全部改造点均**对应代码中已核实的缺陷,非推测**
> **取材**:深挖链路时发现的结构性缺口,按 `value-dig` SKILL 的「机制模式库」(结构性限制 → 可引入机制)比对出改造方向;每个缺陷追问"能否从补漏上升到加机制/重构"
> **代码讲解要求(必读)**:本文交付标准是"**照着能讲代码**"——① §1 先给**改造前链路骨架**(整体调用关系,用伪代码写清"谁调谁、每一步做了什么",可标类名/方法名,**不写文件路径与行号**);② **每个改造点**必带「**关键片段**」(伪代码 / SQL,只示形状、不贴源码)。密度基准:`docs/order-改造方案.md`
> **产出门槛**:缺口中至少存在一个**②加机制 / ③重构**档的改造点(更好设计、重构、引入中间件级)才立本文档;全是①档补漏(加缓存/加判断/加隔离/改配置)的**不产出**——在设计复盘"重做改什么"小节记录即可
---
## 0. 现状问题登记(缺陷唯一归属地)
> 功能点清单与设计复盘**不承载缺陷表**;深挖中发现的问题全部登记在此,后文逐条消化。
**严重度**:🔴 资金/数据错误 · 🟠 静默失败或重复调用 · 🟡 卫生与可维护性
| # | 缺陷 | 证据 | 后果 | 严重度 |
|:-:|---|---|---|:-:|
| 1 | ⟨缺陷⟩ | ⟨可核对的事实:行为 / 字段 / 日志⟩ | ⟨后果⟩ | 🔴 |
| 2 | ⟨…⟩ | | | 🟠 |
| 3 | ⟨…⟩ | | | 🟡 |
**归纳**:这些不是孤立的 bug,而是 **⟨N⟩ 处结构性缺口**:
1. **⟨缺口一⟩** —— ⟨…⟩;
2. **⟨缺口二⟩** —— ⟨…⟩;
3. **⟨缺口三⟩** —— ⟨…⟩。
---
## 1. 总体思路
**改造前链路骨架**(先定位"改的是链路的哪一段"——用伪代码写清谁调谁、每一步做了什么):
```java
⟨入口类#方法⟩()
→ ⟨A类#方法⟩() // 这一步做了什么(对应缺陷 #1)
→ ⟨B类#方法⟩()
→ ⟨C类#方法⟩() // 对应缺陷 #3
```
所以改造是做 N 件事,**而不是调参数**:
1. **⟨把一个点的分级 → 铺成一张网⟩**
2. **⟨把「不确定」从日志提升为一等状态⟩**
3. **⟨把状态推进的时机对齐到权威事实⟩**
```mermaid
flowchart TB
subgraph BEFORE["改造前"]
B1["⟨…⟩"] --> B2["⟨…⟩"]
B3["⟨…⟩"] --> B4["⟨…⟩"]
end
subgraph AFTER["改造后"]
A1["⟨…⟩"] --> A2["⟨…⟩"]
A2 --> A3["⟨…⟩"]
A4["⟨…⟩"] --> A5["⟨…⟩"]
end
```
---
## 2. 阶段一 · ⟨阶段主题:先说止血/可见⟩
> 成本最低、收益最大,**优先做**。⟨N⟩ 处改动都只动本服务内部。
### 2.1 ⟨改造点名⟩(P0,最重要)
- **现状**:⟨…⟩(对应第 0 节缺陷 #⟨N⟩)。
- **后果(真金白银)**:⟨…⟩ 这**违反了 ⟨不变量一⟩**。
- **改造**:⟨…⟩
**关键片段 · ⟨片段名⟩**(伪代码 / SQL,只示形状)
```sql
⟨改造后的语句或结构;与改造前的旧写法形成对照⟩
```
| ⟨对象⟩ | ⟨写/读⟩ | 可逆性 | 处置 |
|---|---|---|---|
| ⟨接口/动作⟩ | 写 | ⟨拒绝可逆、超时不可逆⟩ | ⟨…⟩ |
- **注意**:⟨切换后**必须同步补"超时不可逆"的判断**,否则只是把"归档超时 → 退款"换成"归档超时 → 抛异常 → 同样退款",问题原地不动⟩。
```mermaid
flowchart TD
A["⟨入口⟩"] --> B{"⟨判断⟩"}
B -->|"改造后"| C{"分类"}
B -->|"现状"| Z["⟨旧行为⟩"]
C -->|"⟨可逆⟩"| D["⟨处置⟩"]
C -->|"⟨不确定⟩"| E["⟨处置⟩"]
```
### 2.⟨N⟩ ⟨改造点名⟩
- **现状**:⟨…⟩(对应第 0 节缺陷 #⟨N⟩)
- **改造**:⟨…⟩ **原则:⟨异常类型就是后果分类的载体,不能在中间被抹平⟩。**
- **验收**:⟨人为造一次 ⟨场景⟩,应出现 ⟨可观测结果⟩⟩。
**关键片段 · ⟨片段名⟩**
```java
⟨改造后的分支形状,只示形状⟩
```
### 2.⟨N⟩ 阶段一验收标准
| 指标 | 目标 |
|---|---|
| ⟨…⟩ | ⟨100% 不产生 ⟨错误动作⟩,转 ⟨正确处置⟩⟩ |
| ⟨人为造 X⟩ | ⟨出现可观测的 ⟨证据⟩⟩ |
---
## 3. 阶段二 · ⟨阶段主题:再说可靠/对称/一等状态⟩
> 阶段一保证"不再做错",阶段二保证"⟨挂起能被收走⟩"。
### 3.1 ⟨幂等键改造⟩
- **现状**:⟨没有幂等键 → 可被重复执行;MQ `maxRetry=3` 在异常路径上会重复调用外部⟩(对应缺陷 #⟨N⟩)
- **改造**:⟨唯一索引 · 冲突当幂等命中 · 语义:"同一 X + 同一动作 = 只允许一次对外调用"⟩
- **迁移**:⟨先查存量重复,治理后再加索引⟩
**关键片段 · 索引 + 冲突即命中**
```sql
ALTER TABLE ⟨表名⟩ ADD UNIQUE KEY ⟨uk名⟩ (⟨列⟩, ⟨列⟩);
```
```java
try { ⟨对外调用⟩; }
catch (DuplicateKeyException e) { return; } // 已执行过 → 直接返回,不再调外部
```
### 3.2 ⟨挂起态 + 巡检⟩
- **现状**:⟨…⟩(对应缺陷 #⟨N⟩)
- **改造**:
1. **⟨新增挂起态⟩**,与"失败""成功"并列,**不占用失败的语义**;
2. **巡检任务**(⟨XXL-Job⟩)按"距离挂起时长"分级:⟨<1h 自动重放一次 / 1–24h 告警 / >24h 人工队列⟩;
3. 重放走**同一套分级链路**(不新开代码路径)。
**关键片段 · ⟨片段名⟩**
```java
⟨挂起态写入 / 巡检取单的形状⟩
```
```mermaid
flowchart TD
A["⟨不确定⟩"] --> B["⟨挂起 + 台账⟩"]
B --> C["告警"]
B --> D["巡检任务"]
D --> E{"挂起时长"}
E -->|"⟨短⟩"| F["自动重放"]
E -->|"⟨中⟩"| G["升级告警"]
E -->|"⟨长⟩"| H["人工队列"]
```
**关键设计:重放不是"再调一次接口",而是"重新走一遍分级"。** 因为对方的状态可能已经变了,重放必须能得出"成功"这个结论。
### 3.⟨N⟩ ⟨改造点名⟩
| `⟨anomaly_type⟩` 取值 | 触发场景 | 处置方向 |
|---|---|---|
| `⟨…⟩` | | |
- **收益**:⟨两侧的失败**进同一张台账、走同一套告警和处理台**——运维只需要看一个地方。**这是"复用"而不是"新建"的价值。**⟩
### 3.⟨N⟩ 阶段二验收标准
| 指标 | 目标 |
|---|---|
| ⟨重复调用外部⟩ | 0 次 |
| ⟨挂起单⟩ | 100% 台账可见 + 100% 被巡检捞到 |
---
## 4. 阶段三 · ⟨阶段主题:最后收口卫生问题⟩
| # | 改什么 | 现状证据(缺陷 #⟨N⟩) | 成本 |
|:-:|---|---|---|
| 1 | ⟨…⟩ | ⟨可核对的事实⟩ | 低 |
| 2 | ⟨…⟩ | | 低 |
**⟨某条不是文档工作,是防错工作⟩**:⟨文档漂移会让后来人**按错误的图改代码**,成本远高于改文档。⟩
---
## 5. 实施顺序与成本收益
| 阶段 | 内容 | 成本 | 解决的根问题 | 关键收益 |
|:-:|---|---|---|---|
| 一 | ⟨…⟩ | 低 | ⟨…⟩ | **不再出错** |
| 二 | ⟨…⟩ | 中 | ⟨…⟩ | **不确定可运营** |
| 三 | ⟨…⟩ | 低 | 卫生与可维护性 | 可观测与可维护 |
**顺序逻辑**:先修**会花错钱**的(阶段一),再修**会重复调用外部系统 / 卡住看不见**的(阶段二),最后才是卫生(阶段三)。
---
## 6. 迁移与灰度
1. **⟨逐项切⟩**:先切**风险最高、问题最实**的 ⟨X⟩,观察一周无异常再切 ⟨Y⟩;每次切换**只改一个调用点**,便于回滚。
2. **⟨新增状态先"只记录不流转"⟩**:先写台账 + 告警**观察一周**,确认没有误报,再打开自动重放。
3. **⟨索引先查存量⟩**:先排查存量重复;加索引后**观测冲突命中次数**——这个数就是"原设计漏掉的重复调用次数"。
4. **回滚**:全部改造以"**新增状态 + 新增列 + 开关**"方式落地,回滚只需关开关/停调度,**不动存量数据**。
---
## 7. 改造后:⟨N⟩ 条不变量由谁保证
| 不变量 | 改造前 | 改造后 |
|---|---|---|
| **⟨不变量一⟩** | ⟨只有一条路成立;某路径会被错退⟩ | ⟨全部写类接口统一分类⟩ |
| **⟨不变量二⟩** | ⟨只有一行日志,库里无痕⟩ | ⟨挂起态 + 台账 + 巡检 + 重放⟩ |
| **⟨不变量三⟩** | ⟨实际只有两态(超时被降级抹平)⟩ | ⟨异常类型不被中间层改写⟩ |
---
## 附:与《⟨其它⟩-改造方案.md》的关系
| 项 | ⟨其它侧⟩ | ⟨本文⟩ |
|---|---|---|
| ⟨一致性异常台账⟩ | **建** `⟨表名⟩` | **复用**,只加取值 |
| ⟨Outbox⟩ | **建** `⟨表名⟩` | **复用同表**,`⟨biz_type⟩` 区分 |
| ⟨幂等⟩ | ⟨…⟩ | ⟨…⟩ |
**两边的根因是同一个**:⟨设计了机制,但**没有为"需要人介入"这个信号建自动出口**⟩。所以两套改造共用一套台账与告警,是**结构上的必然,而不是为了省事**。
@@ -0,0 +1,206 @@
# ⟨主题⟩ · 设计思路与取舍(复盘)(S4 产物 ②)
> **视角**:第一人称复盘——**我拿到「⟨需求名⟩」这个需求时,是怎么想、怎么设计、怎么取舍、预判会遇到什么问题的**。贴合现有实现,末尾给改进建议与可直接口述的版本。
> **配套文档**:功能点见同目录《⟨主题⟩-功能点清单.md》;⟨可选的关联文档⟩
> **说明**:文中「我会这样想」是设计时的推理;「实际做法」是代码里的真实实现,**两者不一致处必须标出**。
> **路径简写**:`⟨简写⟩/` = `⟨真实路径⟩`
---
## 0. 我拿到需求,先不写代码:把问题定义清楚
**需求的一句话**:⟨…⟩
**我第一件事是承认 N 个事实**,它们决定了后面所有设计:
1. **⟨例:对方的回答不是二元的⟩。** ⟨…⟩
2. **⟨例:几种失败的"可逆性"不同⟩。** ⟨…⟩
3. **⟨例:我没法从"失败"这个现象本身推出可逆性⟩。** ⟨…⟩
**由此我定下 N 条不变量(当成验收标准)**:
- **不变量一**:⟨例:只有确定对方没接单才退款⟩——⟨为什么⟩;
- **不变量二**:⟨例:不确定的失败不能当成失败处理⟩——⟨为什么⟩;
- **不变量三**:⟨例:每一种失败都必须有归属⟩——⟨为什么⟩。
**再看 N 个我不能改变的前提**:⟨省侧是权威 · 对外调用有副作用 · 没有跨系统事务 · …⟩
**结论**:⟨这不是"加个 try-catch 再套个重试框架"的需求,而是「把异常翻译成后果」的需求。⟩——**这句是我做取舍时反复回到的锚点。**
---
## 1. 我怎么拆这个需求
**第一刀,我按「⟨拆解维度⟩」拆,不按「⟨被否决的维度⟩」拆。**
| 为什么否决另一个维度 | ⟨例:按商品类型拆会得到三块,但三种商品的前置动作不同、汇合点却是同一个;各写一套会得到三份可能走偏的代码⟩ |
|---|---|
拆完是 ⟨N⟩ 条路 + ⟨N⟩ 个汇合点:
| 路径 | ⟨前置动作⟩ | ⟨性质⟩ | 风险 |
|---|---|---|---|
| ⟨…⟩ | | 异步 / 同步 | |
**第二刀,我找「⟨关键定位决策⟩」,这是本需求最关键的一个决策。**
**我的判断是**:⟨…⟩。理由:⟨只有那一层同时拿得到 X 和 Y;再往上一层只能看到一个已被包装过的异常,原始信息已经丢了⟩。
**实际做法与我的判断是否一致**:⟨是 / 否⟩,证据 `⟨路径:行号⟩`。
**这个决策的代价**:⟨例:调用层要维护两套调用方式;推广不全会造成覆盖面缺口(实际就漏了)⟩。
---
## 2. 我的设计主线:⟨一句话概括主线⟩
⟨这是我做的最核心的一个决定:不给 A/B/C 各写一套处理,而是让它们沿一条固定的链往下走,每层只做一件事。⟩
```
① ⟨层名(职责)⟩ → ② ⟨层名(职责)⟩ → ③ ⟨层名(职责)⟩ → ④ ⟨层名(职责)⟩
```
**⟨N⟩ 层不是我拍脑袋凑的,是从"上一版为什么会漏"反推出来的**——每层都对着一个旧实现的具体病灶:
| 层 | 旧实现的病灶 | 我的做法 | 为什么必须在这一层做 |
|:-:|---|---|---|
| ① | | `⟨路径:行号⟩` | ⟨信息只在最底层存在,越往上越不可恢复⟩ |
| ② | | | |
| ③ | | | |
| ④ | | | |
```mermaid
flowchart TD
A["⟨入口⟩"] --> B["① ⟨层⟩"]
B --> C{"② ⟨层⟩"}
C -->|"⟨…⟩"| D["③ ⟨层⟩"]
C -->|"⟨…⟩"| E["③ ⟨层⟩"]
D --> F["④ ⟨归集⟩"]
E --> F
F -->|"⟨可逆⟩"| G["⟨处置⟩"]
F -->|"⟨不确定⟩"| H["⟨处置⟩"]
```
### 2.1 ⟨N⟩ 重判断,才是这个设计的真正内容(标题按实际重数写,如「三重判断…」)
> 比"N 层"更重要的是**层里做的判断**——它们才是经验,层只是载体。
**判断一:⟨…⟩**
⟨用收益 × 概率算的:…⟩ **关键点是"不做什么"比"做什么"更难做对**——⟨因为框架默认什么都做⟩。
**判断二:⟨…⟩**
⟨…⟩ **代价必须自己扛**:⟨你关掉了 X,就必须自己承担 Y 的责任。⟩
**判断三:⟨…⟩**
⟨…⟩ **为什么"⟨反面做法⟩"是错的**:⟨…⟩
**还有一条我特意保留的例外**:⟨…⟩——因为 ⟨…⟩。
### 2.2 ⟨独立工具/组件名⟩ 为什么要写成一个独立⟨工具/组件⟩(若无可删本节)
⟨它看着简单,但它是整个 ⟨机制⟩ 的地基——判错一次,方向就错,后面全走偏。⟩
1. **精确匹配** ⟨…⟩;
2. **兜底模糊匹配** ⟨…⟩;
3. **逐层剥 `cause`**——⟨因为异常常被框架层层包装,真实原因往往在第三、四层⟩。
**这里的取舍我很清楚**:⟨选了"宁可多试一次"——因为重试的成本(多一次调用)远低于漏重试的成本(一单卡死)⟩。
---
## 3. 逐环节决策复盘
| # | 当时的问题 | 我的选择 | 为什么 | 代价 / 风险 |
|:-:|---|---|---|---|
| 1 | ⟨…⟩ | | | |
| 2 | | | | |
| 3 | | | | |
| … | | | | |
> **代价/风险列不可空**——只讲选择不讲代价,就等于没做取舍。
---
## 4. 我预判会遇到的问题(拿到需求时就能想到的)
1. **⟨…⟩。** ⟨…⟩
2. **⟨…⟩。** ⟨…⟩
3. **⟨…⟩。** ⟨这是我设计时预判到了却仍然漏掉的一条⟩
---
## 5. 我做对的 ⟨N⟩ 件事 / 承接不住的 ⟨N⟩ 件事
**做对的**
1. **⟨…⟩**——⟨为什么它最有价值;它是从业务语义推出来的,不是从技术模式套出来的⟩。
2. **⟨…⟩**——⟨…⟩
3. **⟨…⟩**——⟨方向是对的,只是推广范围不够⟩
**承接不住的**
1. **⟨…(最严重)⟩**——⟨后果;这是"设计对了但落地不完整"的典型案例⟩。
2. **⟨…⟩**
3. **⟨…⟩**
---
## 6. 如果让我重做,我会改什么(按性价比排序)
> 复盘视角只给**优先级判断**;分阶段展开、验收标准与灰度见《⟨主题⟩-改造方案.md》,此处不重复。
| 优先级 | 改什么 | 为什么 | 成本 | 收益 |
|:-:|---|---|---|---|
| **P0** | | ⟨**真金白银 / 会花错钱**⟩ | 低 | |
| **P1** | | | 中 | |
| **P2** | | | | |
| **P3** | | ⟨卫生问题⟩ | | |
**一句话排序逻辑**:先修**会花错钱和会重复调用外部系统的**(P0/P1),再做**让"不确定"可运营**(P1/P2),最后才是卫生问题(P3)。**因为前两类是"静默地把事情做错",后者只是"做得不够漂亮"。**
---
## 7. 这套设计里可以复用的方法论
1. **⟨先判"可逆性",再决定"要不要补偿"。⟩** ⟨任何跨系统写操作都适用…⟩
2. **⟨异常分层翻译:真相层 → 重试层 → 履历层 → 归集层。⟩** ⟨每层只做一件事,且必须在能拿到信息的最高层把信息捞住⟩
3. **⟨重试责任单点。⟩** ⟨否则是乘法关系,不是加法⟩
4. **⟨"不确定"必须是一等状态。⟩** ⟨否则会退化成一行日志,等于不存在⟩
5. **⟨分级的上限取决于覆盖面,不是取决于精细度。⟩** ⟨一条路上做四层分级,不如四条路上各做一层⟩
---
## 8. 附:面试口述版
### 8.1 一分钟版(先讲骨架)
> 「⟨需求一句话⟩。我的判断是:⟨核心判断⟩。所以我不能只写 try-catch,得**把 ⟨X⟩ 翻译成 ⟨Y⟩**。
>
> 设计上是 N 层:⟨逐层一句话⟩。调用方只做一件事:⟨…⟩。」
### 8.2 三分钟版(加取舍与代价)
在上一段基础上补三段:⟨取舍一(最看重的一点)+ 它的代价⟩ · ⟨取舍二 + 难在哪⟩ · ⟨要坦白的一点(覆盖面 / 落地不完整)⟩。
### 8.3 追问预判(问题 → 一句话答)
| 追问 | 答 |
|---|---|
| ⟨为什么…?⟩ | ⟨一句话⟩ |
| ⟨既然…,那…?⟩ | ⟨一句话,含"坦白说没有"这类诚实回答⟩ |
| ⟨这套设计最大的风险?⟩ | ⟨一句话⟩ |
---
## 附:与代码的对照说明
| 本文的判断 | 代码事实 | 是否一致 |
|---|---|---|
| ⟨分级放最底层⟩ | `⟨路径:行号⟩` | ✅ 一致,但**未推广** |
| ⟨只重超时⟩ | `⟨路径:行号⟩` | ✅ 一致 |
| ⟨…⟩ | | ⚠️ 部分一致 |
> **诚实性要求**:本文的判断与代码事实**不一致处必须逐条列出**——这是这份文档可信度的来源。
@@ -0,0 +1,112 @@
---
name: value-scan
description: Use when the user wants to inventory the mechanisms worth talking about in code that is already delivered — "盘点这个域/模块的价值点", "扫一下 order 域有什么值得讲的", "提取功能点", "这个项目有什么值得讲的设计", or when interview/resume material must be reconstructed backwards from an existing module. Read-only — never modifies the scanned project. Stops at the human selection gate; deep write-up is a separate skill.
---
# value-scan · 价值点盘点(广度枚举)
## 一句话
从**已交付的代码**里,逆向枚举出**值得讲的机制点**,交人勾选后**停下**。
**三条核心原则**
1. **agent 判不了"价值"**——判据不是分类体系,而是**简历行填空测试**。
2. **价值优先,本阶段不找缺陷。** 缺陷是深入链路时自然浮现的副产物,归 `value-dig`。
3. **只读。** 不修改被扫描项目的任何文件。
## 流程
```
S0 定范围 → S1 枚举 → S2 勾选【终点:产出清单后必须停】
↓(人勾选后)
value-dig(轻理由 → 设计复盘 / 功能点 / 改造方案)
```
| 需求 | 该用 |
|---|---|
| 盘点 / 扫一遍 / 提取候选价值点 | **本 skill** |
| 把选中的点写成深度文档 | `value-dig` |
| 找 bug、修缺陷 | `diagnose` |
## S0 · 定范围
- **快路**:仓库已有域清单(`.aspirecode/sdd/rules.md` §9、`pom.xml`、`wiki/` 目录)→ 直接读。
- **慢路**:陌生仓库 → 按接口路径前缀、`-api` Feign 接口名、controller 清单切出能力面,一次一个 package。
- 范围由**人给定**(一个域/模块),不一次扫全库。
**域是入口锚点,不是物理边界。** 完整链路往往跨模块,用两头夹的办法拼:
- **聚合层(web)定链路形状**:controller / Kafka consumer / XxlJob / callback 四类入口全在聚合层,且分包与路径自带业务语义(`/consumer/fulfillment/`、topic 名、请求路径)——从这里正向切出"有哪些触发者、哪些链路"。MQ 消费、定时任务这类**非 Feign 入口**靠反推找不到。
- **原子域挖机制内容**:锁/幂等/状态机等机制本体大多在原子域的 service 实现,聚合层只有编排——读实现要去原子域。
- **中间用调用图接**(`gitnexus_route_map` / `gitnexus_cypher`);被驱动型域也可用"谁 import 了我的 Feign 接口"反查调用方作兜底。
- 只读链路经过的路径,不通读途径模块。
## S1 · 枚举
### 取材顺序(信噪比递减)
| 顺序 | 来源 | 备注 |
|:-:|---|---|
| 1 | `wiki/*.md`、`.claude/docs/**`、`devflow/projects/**` | 先读「设计说明类」,后读「问题分析类」——先读问题分析会把清单带成缺陷导向 |
| 2 | `git log`:`feat(...)` / `refactor(...)`、带单号、单次大改动 | 有意识的改动藏着设计意图 |
| 3 | `gitnexus_query` / `gitnexus_route_map` | 用图查结构,不读全文 |
| 4 | 代码结构统计 + 关键字 grep(锁/重试/MQ/Job/条件更新/状态机/延时/对账) | 只做清单式定位,不通读代码 |
> ⚠️ 读完文档必须回代码验一遍"文档写的方案是否落地"。**"文档 vs 代码分叉"本身就是高价值点**。
### 怎么看结构:按「触发者」拆链路
不按业务功能拆,按**谁触发**拆:找出「**同一行数据被几个触发者改**」(如回调/查单/取消都改同一行支付流水)——收敛点多半就是机制所在。通常 1–4 条链路,被驱动型模块可到 5–6 条(超过要写一句为什么)。
每条链路挂 1–4 个机制节点。**候选颗粒度 = 机制/能力**,不是注解、类、配置项——"用了 `@LockAction`、有 4 个 handler"是实现清单;跨 ≥2 个写类入口或 ≥2 张表的才够"机制"。
### 判据 · 简历行测试
**一级 · 准入(三条硬标准,全过才进清单)**
| 标准 | 反例(据此剔除) |
|---|---|
| ① **核心链路**(资金/履约/交付这类业务闭环) | 购物车 key 命名、查询接口 |
| ② **高级工程师的设计**(设计决策,非框架常识) | Redis `GETDEL`、Spring 自注入修事务自调用 |
| ③ **简历够硬**(能写成"我设计了 X 机制解决 Y") | 定长文件 + 签名 + SFTP 的对接实现 |
**二级 · 表达**:`用【机制】解决了【具体问题/场景】,代价是【取舍】`——本阶段只试填"机制+问题"两格;填不出机制 → 并入「已剔除」表(标 `机制格填不出`,待复核);填不出取舍**不误杀**(取舍归 `value-dig`)。
> ⚠️ **`机制格填不出` 的剔除门槛(防误杀,实测翻案教训)**:机制本体常藏在实现大类(2000+ 行)的私有方法群里,入口类名/Job 类名只是壳——**没读过入口方法向下 ~100 行,不得以此理由定稿剔除**。剔除非此理由的照常。被剔除后复评翻案的,在剔除表原行标注撤销原因与日期(如"2026-09-18 复评撤销:快照轮询机制实存,升级为 ★N"),不删行——翻案记录本身就是筛选口径的进化证据。
被剔除的点进「已剔除」表(注明未过哪条标准),不丢弃。
### 数量
亮点 **5–8 条**为宜。超过 12 条 = 颗粒度掉到实现层,退回重并。
## S2 · 门控(终点,不可跳过)
1. 候选清单**已落盘**(每条含「一句话价值」与锚点),头部「闸门状态」节写明"S1 已完成 · 待勾选";
2. 回复里**显式请求勾选**("请从这 N 条里挑 3–6 条")。用户禁用提问时也一样停——把请求写成文字,**不是**替他挑完继续写文档。
3. **否决即校准**:人否决候选("不够硬"/"一般")时,把否决原因记入清单(闸门状态或剔除表)——下次扫同域/同仓先读上次的否决记录,同类点不再重复上报;整批否决且未给新目标 = 流程终点,不强续。
## 硬规则(合并版,替代旧的硬规则/反模式/Gotchas 三张表)
| # | 规则 | 为什么 |
|:-:|---|---|
| 1 | **深度闸门**:无围栏代码块(Mermaid 除外,行内反引号可用);不贴源码、不写行号、不逐层拆解、不展开取舍 | 本阶段是广度层 |
| 2 | **不找缺陷、不读"坏味道报告"**;把克制当设计("manager 只有 3 个"可能是有意的) | 缺陷导向会摧毁清单 |
| 3 | **证据真实性**:锚点 `⟨简写⟩/路径#方法名`(机制级可锚到类;不写行号),**读过再写**,拿不准标【待确认】,每条 ≤2 个 | 错锚点毁掉可信度 |
| 4 | **每条链路(含未入选的)都要写「是什么 + 为什么入选/未入选」**;0 机制先问"真没有,还是采样不到位" | 链路是骨架,不因无亮点而省略 |
| 5 | **三层结构**:域 → 链路 → 机制节点,机制必须挂在链路图上 | 并列清单会显得"都是散的" |
| 6 | **只读 + 门控**:不改被扫项目文件;产出后必停 | — |
## 格式保证
1. **模板外置**:读 `assets/候选清单模板.md` 填空,不照印象写。
2. **机械校验**:产出后跑 `python <skills>/value-scan/assets/check.py scan -Product <产物> -Template <skills>/value-scan/assets/候选清单模板.md`(跨平台 Python 版;Windows 下若中文乱码先设 `PYTHONIOENCODING=utf-8`。旧 `check.ps1` 保留但不再维护)。FAIL 必须为 0;WARN 允许保留但写明原因。
3. **偏差回写**:被纠正过就回写模板。模板是活资产。
## 触发词与落盘
**触发词**:「盘点这个模块的价值点」「扫一下 X 域有什么值得讲的」「提取功能点」。
**落盘**:`<项目根>/docs/{域}-候选价值点.md`(可被用户覆盖)。
**下一步**:用户勾选后,用 `value-dig` 接手。
@@ -0,0 +1,268 @@
<#
value-scan / value-dig 产物机械校验(替代人工核对)
------------------------------------------------------------------
用法:
# S1 候选清单
powershell -ExecutionPolicy Bypass -File check.ps1 -Mode scan `
-Product <产物路径> -Template <skills>/value-scan/assets/候选清单模板.md
# S4 功能点清单
powershell -ExecutionPolicy Bypass -File check.ps1 -Mode dig `
-Product <产物路径> -Template <skills>/value-dig/assets/深度模板/功能点清单模板.md
# S4 设计思路与取舍 / 改造方案(整篇级文档,只跑通用校验)
powershell -ExecutionPolicy Bypass -File check.ps1 -Mode doc -Product <path> -Template <path>
退出码:0 = 无 FAIL;1 = 有 FAIL
说明:FAIL = 必错;WARN = 需人判断
#>
param(
[Parameter(Mandatory = $true)]
[ValidateSet('scan', 'dig', 'doc')]
[string]$Mode,
[Parameter(Mandatory = $true)]
[string]$Product,
[string]$Template
)
$ErrorActionPreference = 'Stop'
$script:fail = New-Object System.Collections.Generic.List[string]
$script:warn = New-Object System.Collections.Generic.List[string]
$script:pass = New-Object System.Collections.Generic.List[string]
function Fail($m) { $script:fail.Add($m) }
function Warn($m) { $script:warn.Add($m) }
function Pass($m) { $script:pass.Add($m) }
$prodPath = (Resolve-Path -LiteralPath $Product).Path
$text = [System.IO.File]::ReadAllText($prodPath, [System.Text.Encoding]::UTF8)
if ($text.Length -gt 0 -and [int][char]$text[0] -eq 0xFEFF) { $text = $text.Substring(1) }
$lines = $text -split "`r?`n"
# ---------------------------------------------------------------- 围栏代码块
$fences = @()
$inFence = $false; $fStart = 0; $fLang = ''
for ($i = 0; $i -lt $lines.Count; $i++) {
if ($lines[$i] -match '^\s*```') {
if (-not $inFence) {
$inFence = $true; $fStart = $i; $fLang = ($lines[$i] -replace '^\s*```', '').Trim()
}
else {
$inFence = $false
$fences += [pscustomobject]@{ Start = $fStart; End = $i; Lang = $fLang; Body = ($i - $fStart - 1) }
}
}
}
if ($inFence) { Fail "存在未闭合的代码围栏(起始行 $($fStart + 1))" }
# ---------------------------------------------------------------- 通用 1:引号逐行配对
$oddQuoteLines = @()
for ($i = 0; $i -lt $lines.Count; $i++) {
if ((([regex]::Matches($lines[$i], '"')).Count % 2) -ne 0) { $oddQuoteLines += ($i + 1) }
}
if ($oddQuoteLines.Count -eq 0) { Pass '引号逐行配对' }
else { Fail ("引号未配对的行: " + ($oddQuoteLines -join ', ')) }
# ---------------------------------------------------------------- 通用 2:mermaid 合法性
$mermaidFences = @($fences | Where-Object { $_.Lang -eq 'mermaid' })
$mmBad = 0
foreach ($f in $mermaidFences) {
$body = ($lines[($f.Start + 1)..($f.End - 1)] -join "`n")
$firstLine = (($body -split "`r?`n") | Where-Object { -not [string]::IsNullOrWhiteSpace($_) } | Select-Object -First 1)
$endCount = ([regex]::Matches($body, '(?m)^\s*end\s*$')).Count
if ($firstLine -match 'sequenceDiagram') {
# 时序图:end 收的是 alt/opt/loop/par/critical/break/rect
$blk = ([regex]::Matches($body, '(?m)^\s*(alt|opt|loop|par|critical|break|rect)\b')).Count
if ($blk -ne $endCount) { Fail "mermaid 时序图(第 $($f.Start + 1) 行起)alt/opt/loop 等 $blk 个但 end=$endCount"; $mmBad++ }
}
else {
$sg = ([regex]::Matches($body, '(?m)^\s*subgraph\s')).Count
if ($sg -ne $endCount) { Fail "mermaid 流程图(第 $($f.Start + 1) 行起)subgraph=$sg 但 end=$endCount"; $mmBad++ }
if ($body -match '(?m)^\s*subgraph\s+\S+\s*\[' -and $body -notmatch '(?m)^\s*subgraph\s+\S+\s*\["') {
Fail "mermaid(第 $($f.Start + 1) 行起)subgraph 缺引号标题,必须写 subgraph id[`"标题`"]"; $mmBad++
}
if ($body -match '(?m)^\s*subgraph\s+\S+\s*\[\(') {
Fail "mermaid(第 $($f.Start + 1) 行起)用了 subgraph xxx[(...)],会解析失败"; $mmBad++
}
}
}
if ($mermaidFences.Count -gt 0 -and $mmBad -eq 0) { Pass "mermaid 块 $($mermaidFences.Count) 个通过" }
# ---------------------------------------------------------------- 通用 3:表格列数一致
$ti = 0
while ($ti -lt $lines.Count) {
if ($lines[$ti] -match '^\s*\|') {
$blk = @(); $bs = $ti
while ($ti -lt $lines.Count -and $lines[$ti] -match '^\s*\|') { $blk += $lines[$ti]; $ti++ }
$counts = @($blk | ForEach-Object { ([regex]::Matches($_, '\|')).Count } | Sort-Object -Unique)
if ($counts.Count -gt 1) { Fail "表格列数不一致(第 $($bs + 1) 行起):pipe 数 = $($counts -join '/')" }
}
else { $ti++ }
}
# ---------------------------------------------------------------- 通用 3b:表格不得缩进(嵌套在列表内的表多数渲染器不显示)
$indentedTable = @()
for ($i = 0; $i -lt $lines.Count; $i++) {
if ($lines[$i] -match '^[ \t]+\|') { $indentedTable += ($i + 1) }
}
if ($indentedTable.Count -eq 0) { Pass '表格均顶格(无嵌套缩进表)' }
else { Fail ('表格存在缩进(第 ' + ($indentedTable -join ', ') + ' 行起)——嵌套在列表里的表多数渲染器不显示,必须顶格') }
# ---------------------------------------------------------------- 通用 4:章节完整性(模板必备节 ⊆ 产出节)
if ($Template) {
$tPath = (Resolve-Path -LiteralPath $Template).Path
$tText = [System.IO.File]::ReadAllText($tPath, [System.Text.Encoding]::UTF8)
if ($tText.Length -gt 0 -and [int][char]$tText[0] -eq 0xFEFF) { $tText = $tText.Substring(1) }
$tLines = $tText -split "`r?`n"
$tHeads = $tLines | Where-Object { $_ -match '^\s*#+\s+\S' }
$missingLiteral = @(); $missingPlaceholder = @()
foreach ($h in $tHeads) {
$t = ($h -replace '^\s*#+\s+', '') -replace '\s+$', ''
$hasPh = $t.Contains([string][char]0x27E8)
$sentinel = '@@PH@@'
$phRx = [string][char]0x27E8 + '[^' + [string][char]0x27E9 + ']*' + [string][char]0x27E9
$rx = [regex]::Escape([regex]::Replace($t, $phRx, $sentinel)).Replace($sentinel, '.*')
$hit = $false
foreach ($pl in $lines) { if ($pl -match ('^\s*#+\s+' + $rx + '\s*$')) { $hit = $true; break } }
if (-not $hit) {
if ($hasPh) { $missingPlaceholder += $t } else { $missingLiteral += $t }
}
}
if ($missingLiteral.Count -eq 0) { Pass '章节完整性:模板必备节全部存在' }
else { Fail ('缺章节(字面量,必错): ' + ($missingLiteral -join ' | ')) }
if ($missingPlaceholder.Count -gt 0) { Warn ('示例性章节未匹配(可能条数不同,需人判): ' + ($missingPlaceholder -join ' | ')) }
}
# ---------------------------------------------------------------- 定位辅助
function Get-HeadIndex($pattern) {
for ($i = 0; $i -lt $lines.Count; $i++) { if ($lines[$i] -match $pattern) { return $i } }
return -1
}
function Get-NextHeadIndex($from) {
for ($i = $from + 1; $i -lt $lines.Count; $i++) { if ($lines[$i] -match '^\s*#+\s+\S') { return $i } }
return $lines.Count
}
# ---------------------------------------------------------------- scan 专属
if ($Mode -eq 'scan') {
# 1) 禁止围栏代码块(mermaid 除外)
$nonMermaid = @($fences | Where-Object { $_.Lang -ne 'mermaid' })
if ($nonMermaid.Count -eq 0) { Pass '深度闸门:S1 无围栏代码块(仅 mermaid)' }
else { Fail ("S1 不允许围栏代码块,发现 $($nonMermaid.Count) 个(第 " + (($nonMermaid | ForEach-Object { $_.Start + 1 }) -join ', ') + ' 行起)') }
# 2) 锚点格式:路径#方法名(不带行号,每条最多 2 个)
$badAnchor = @()
$anchorCount = 0
foreach ($l in $lines) {
if ($l -match '^\s*\*\*锚点\*\*\s*[::]\s*(.+?)\s*$') {
$anchorCount++
$v = $Matches[1]
$items = @($v -split '[、,,]' | Where-Object { -not [string]::IsNullOrWhiteSpace($_) })
if ($items.Count -gt 2) { $badAnchor += ("锚点超过 2 个($($items.Count) 个): " + $l.Trim()) }
foreach ($it in $items) {
$a = $it.Trim().Trim('`')
if ($a -match ':\d') { $badAnchor += ("S1 锚点不写行号 -> $a") }
elseif ($a -notmatch '\w[/\\]\w') { $badAnchor += ("S1 锚点须为 路径#方法名(机制级可到类名) -> $a") }
}
}
}
if ($anchorCount -eq 0) { Warn '未找到 **锚点** 行(若产物为空则忽略)' }
elseif ($badAnchor.Count -eq 0) { Pass "锚点格式合规($anchorCount 处,路径#方法名)" }
else { Fail ('锚点格式不合规: ' + ($badAnchor -join ' ; ')) }
# 3) 闸门状态节
if ((Get-HeadIndex '^\s*#+\s*闸门状态') -ge 0) { Pass '有「闸门状态」节(S2 门控有证据)' }
else { Fail '缺「闸门状态」节 —— S2 门控没有证据' }
# 4) 候选条数(提示性:超 12 才 FAIL,无下限硬卡)
$starCount = ($lines | Where-Object { $_ -match '^\s*#+\s*★' }).Count
if ($starCount -le 12) { Pass "候选条数 $starCount(≤12)" }
else { Fail "候选条数 $starCount 超过 12(颗粒度掉到实现层,需重并)" }
if ($starCount -lt 5 -and $starCount -gt 0) { Warn "候选条数 $starCount 少于 5——先确认是否采样不到位,而非真没有" }
}
# ---------------------------------------------------------------- dig 专属
if ($Mode -eq 'dig') {
$skelIdx = Get-HeadIndex '^\s*#+\s*主干调用骨架'
$skelEnd = if ($skelIdx -ge 0) { Get-NextHeadIndex $skelIdx } else { -1 }
if ($skelIdx -ge 0) { Pass '有「主干调用骨架」节' }
else { Warn '未找到「主干调用骨架」节(仅 S4 ① 功能点清单必需)' }
# 1) 局部代码块 ≤10 行(骨架块豁免)
$exempt = 0
foreach ($f in $fences) {
if ($f.Lang -eq 'mermaid') { continue }
$isSkel = ($skelIdx -ge 0 -and $f.Start -gt $skelIdx -and $f.Start -lt $skelEnd)
if ($isSkel) { $exempt++; continue }
if ($f.Body -gt 10) { Warn "局部代码块超过 10 行(第 $($f.Start + 1) 行起,$($f.Body) 行)——行数非硬限,请人判断是关键片段还是源码摘录" }
}
Pass ("局部代码块行数检查完成(豁免骨架块 $exempt 个)")
# 2) 骨架每行必须带方式标记
if ($skelIdx -ge 0) {
$skelFence = @($fences | Where-Object { $_.Start -gt $skelIdx -and $_.Start -lt $skelEnd }) | Select-Object -First 1
if (-not $skelFence) { Warn '骨架节里没有代码块' }
else {
$missTag = @()
foreach ($bl in ($lines[($skelFence.Start + 1)..($skelFence.End - 1)])) {
if ([string]::IsNullOrWhiteSpace($bl)) { continue }
if ($bl -match '^\s*//') { continue } # 分段注释行
if ($bl -match ':\s*$') { continue } # 块头行(xxx(): ),标"谁"不标"怎么做"
if ($bl -notmatch '[(\[]') { continue } # 连接词行(↓ 三路汇合)
if ($bl -notmatch '//') { $missTag += $bl.Trim() } # 其余动作行必须有方式标记
}
if ($missTag.Count -eq 0) { Pass '骨架每行都带方式标记' }
else { Fail "骨架有 $($missTag.Count) 行缺方式标记: " + (($missTag | Select-Object -First 3) -join ' ; ') }
}
}
# 3) 证据须含 行号
if ($text -notmatch '\.(java|xml|yaml|yml|sql):\d+') { Fail '未找到任何 `文件:行号` 证据(本阶段必须有可核对的锚点)' }
else { Pass '存在 `文件:行号` 形式的证据' }
}
# ---------------------------------------------------------------- doc 专属
if ($Mode -eq 'doc') {
# 改造方案识别:含「现状问题登记」节(设计思路与取舍模板不含此节)
$isPlan = (Get-HeadIndex '^\s*#+\s*0\.\s*现状问题登记') -ge 0
if ($isPlan) {
# 1) 必有非 mermaid 代码片段(伪代码 / SQL)
$codeFences = @($fences | Where-Object { $_.Lang -ne 'mermaid' })
if ($codeFences.Count -ge 1) { Pass "改造方案含关键片段 $($codeFences.Count) 个" }
else { Fail '改造方案缺「关键片段」代码块——必须"照着能讲代码"(伪代码/SQL 均可,只禁大段源码摘录)' }
# 2) 片段应覆盖"骨架 + 改造点",只给一块多半只在开头充数
if ($codeFences.Count -ge 2) { Pass "关键片段 $($codeFences.Count) 个(骨架 + 改造点)" }
elseif ($codeFences.Count -eq 1) { Warn '只有 1 个关键片段——可能只有链路骨架,各改造点未给伪代码,需人判' }
}
}
# ---------------------------------------------------------------- 输出
Write-Output ""
Write-Output ("=" * 68)
Write-Output "机械校验 Mode=$Mode"
Write-Output (" product : " + $prodPath)
if ($Template) { Write-Output (" template : " + (Resolve-Path -LiteralPath $Template).Path) }
Write-Output ("=" * 68)
if ($script:pass.Count -gt 0) {
Write-Output ""
Write-Output "[PASS]"
foreach ($m in $script:pass) { Write-Output (" + " + $m) }
}
if ($script:warn.Count -gt 0) {
Write-Output ""
Write-Output "[WARN] 需人判断"
foreach ($m in $script:warn) { Write-Output (" ! " + $m) }
}
if ($script:fail.Count -gt 0) {
Write-Output ""
Write-Output "[FAIL] 必错"
foreach ($m in $script:fail) { Write-Output (" x " + $m) }
}
Write-Output ""
Write-Output ("结果:PASS {0} / WARN {1} / FAIL {2}" -f $script:pass.Count, $script:warn.Count, $script:fail.Count)
if ($script:fail.Count -gt 0) { exit 1 } else { exit 0 }
@@ -0,0 +1,307 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
value-scan / value-dig 产物机械校验(Python 版,等价移植自 check.ps1,跨平台)
------------------------------------------------------------------
用法:
# S1 候选清单
python check.py scan <产物路径> --template <skills>/value-scan/assets/候选清单模板.md
# S4 功能点清单
python check.py dig <产物路径> --template <skills>/value-dig/assets/深度模板/功能点清单模板.md
# S4 设计思路与取舍 / 改造方案(整篇级文档,只跑通用校验)
python check.py doc <产物路径> --template <路径>
退出码:0 = 无 FAIL;1 = 有 FAIL;2 = 用法/IO 错误
说明:FAIL = 必错;WARN = 需人判断
"""
import argparse
import re
import sys
from pathlib import Path
FAIL, WARN, PASS = [], [], []
# ⟨ ⟩ 占位符(U+27E8 / U+27E9)
PH_L, PH_R = '\u27e8', '\u27e9'
def fail(m):
FAIL.append(m)
def warn(m):
WARN.append(m)
def pass_(m):
PASS.append(m)
def read_text(path_str):
p = Path(path_str)
if not p.is_file():
print(f"[ERROR] 文件不存在: {path_str}", file=sys.stderr)
sys.exit(2)
text = p.read_text(encoding='utf-8-sig') # 自动剥 BOM
return text, text.splitlines()
def head_index(lines, pattern):
for i, line in enumerate(lines):
if re.search(pattern, line):
return i
return -1
def next_head_index(lines, start):
for i in range(start + 1, len(lines)):
if re.match(r'^\s*#+\s+\S', lines[i]):
return i
return len(lines)
def line_snip(line, width=40):
"""报错附带的行内容摘要(改进:报错不指内容曾导致误诊)"""
s = line.strip().replace('|', '\\|')
return s[:width] + ('…' if len(s) > width else '')
def main():
ap = argparse.ArgumentParser(description='value-scan/value-dig 产物机械校验')
ap.add_argument('mode', choices=['scan', 'dig', 'doc'])
ap.add_argument('product', help='产物路径')
ap.add_argument('--template', '-t', help='模板路径')
ap.add_argument('-Mode', '-Product', '-Template', dest='legacy', help=argparse.SUPPRESS)
args = ap.parse_args()
prod_path = Path(args.product).resolve()
text, lines = read_text(args.product)
# ------------------------------------------------ 围栏代码块
fences = []
in_fence = False
f_start, f_lang = 0, ''
for i, line in enumerate(lines):
if re.match(r'^\s*```', line):
if not in_fence:
in_fence, f_start = True, i
f_lang = re.sub(r'^\s*```', '', line).strip()
else:
in_fence = False
fences.append({'start': f_start, 'end': i, 'lang': f_lang,
'body': i - f_start - 1})
if in_fence:
fail(f'存在未闭合的代码围栏(起始行 {f_start + 1})')
# ------------------------------------------------ 通用 1:引号逐行配对
odd_quote = [i + 1 for i, line in enumerate(lines)
if line.count('"') % 2 != 0]
if not odd_quote:
pass_('引号逐行配对')
else:
fail('引号未配对的行: ' + ', '.join(map(str, odd_quote)))
# ------------------------------------------------ 通用 2:mermaid 合法性
mermaid_fences = [f for f in fences if f['lang'] == 'mermaid']
mm_bad = 0
for f in mermaid_fences:
body_lines = lines[f['start'] + 1:f['end']]
body = '\n'.join(body_lines)
first = next((l for l in body_lines if l.strip()), '')
end_count = len(re.findall(r'(?m)^\s*end\s*$', body))
if 'sequenceDiagram' in first:
blk = len(re.findall(r'(?m)^\s*(alt|opt|loop|par|critical|break|rect)\b', body))
if blk != end_count:
fail(f"mermaid 时序图(第 {f['start'] + 1} 行起)alt/opt/loop 等 {blk} 个但 end={end_count}")
mm_bad += 1
else:
sg = len(re.findall(r'(?m)^\s*subgraph\s', body))
if sg != end_count:
fail(f"mermaid 流程图(第 {f['start'] + 1} 行起)subgraph={sg} 但 end={end_count}")
mm_bad += 1
if (re.search(r'(?m)^\s*subgraph\s+\S+\s*\[', body)
and not re.search(r'(?m)^\s*subgraph\s+\S+\s*\["', body)):
fail(f'mermaid(第 {f["start"] + 1} 行起)subgraph 缺引号标题,必须写 subgraph id["标题"]')
mm_bad += 1
if re.search(r'(?m)^\s*subgraph\s+\S+\s*\[\(', body):
fail(f'mermaid(第 {f["start"] + 1} 行起)用了 subgraph xxx[(...)],会解析失败')
mm_bad += 1
if mermaid_fences and mm_bad == 0:
pass_(f'mermaid 块 {len(mermaid_fences)} 个通过')
# ------------------------------------------------ 通用 3:表格列数一致(含行内容摘要)
ti = 0
while ti < len(lines):
if re.match(r'^\s*\|', lines[ti]):
bs = ti
blk = []
while ti < len(lines) and re.match(r'^\s*\|', lines[ti]):
blk.append(lines[ti])
ti += 1
counts = sorted({b.count('|') for b in blk})
if len(counts) > 1:
fail(f"表格列数不一致(第 {bs + 1} 行起):pipe 数 = {'/'.join(map(str, counts))}"
f"|首行内容: {line_snip(blk[0])}")
else:
ti += 1
# ------------------------------------------------ 通用 3b:表格不得缩进
indented = [i + 1 for i, line in enumerate(lines) if re.match(r'^[ \t]+\|', line)]
if not indented:
pass_('表格均顶格(无嵌套缩进表)')
else:
fail('表格存在缩进(第 ' + ', '.join(map(str, indented)) + ' 行起)——嵌套在列表里的表多数渲染器不显示,必须顶格')
# ------------------------------------------------ 通用 4:章节完整性
if args.template:
_, t_lines = read_text(args.template)
t_heads = [l for l in t_lines if re.match(r'^\s*#+\s+\S', l)]
missing_literal, missing_ph = [], []
for h in t_heads:
t = re.sub(r'\s+$', '', re.sub(r'^\s*#+\s+', '', h))
has_ph = PH_L in t
ph_rx = re.escape(PH_L) + '[^' + re.escape(PH_R) + ']*' + re.escape(PH_R)
rx = re.escape(re.sub(ph_rx, '@@PH@@', t)).replace('@@PH@@', '.*')
hit = any(re.match(r'^\s*#+\s+' + rx + r'\s*$', pl) for pl in lines)
if not hit:
(missing_ph if has_ph else missing_literal).append(t)
if not missing_literal:
pass_('章节完整性:模板必备节全部存在')
else:
fail('缺章节(字面量,必错): ' + ' | '.join(missing_literal))
if missing_ph:
warn('示例性章节未匹配(可能条数不同,需人判): ' + ' | '.join(missing_ph))
# ------------------------------------------------ scan 专属
if args.mode == 'scan':
non_mermaid = [f for f in fences if f['lang'] != 'mermaid']
if not non_mermaid:
pass_('深度闸门:S1 无围栏代码块(仅 mermaid)')
else:
fail('S1 不允许围栏代码块,发现 {} 个(第 {} 行起)'.format(
len(non_mermaid),
', '.join(str(f['start'] + 1) for f in non_mermaid)))
bad_anchor, anchor_count = [], 0
for line in lines:
m = re.match(r'^\s*\*\*锚点\*\*\s*[::]\s*(.+?)\s*$', line)
if not m:
continue
anchor_count += 1
items = [s for s in re.split(r'[、,,]', m.group(1)) if s.strip()]
if len(items) > 2:
bad_anchor.append(f'锚点超过 2 个({len(items)} 个): {line.strip()}')
for it in items:
a = it.strip().strip('`')
if re.search(r':\d', a):
bad_anchor.append(f'S1 锚点不写行号 -> {a}')
elif not re.search(r'\w[/\\]\w', a):
bad_anchor.append(f'S1 锚点须为 路径#方法名(机制级可到类名) -> {a}')
if anchor_count == 0:
warn('未找到 **锚点** 行(若产物为空则忽略)')
elif not bad_anchor:
pass_(f'锚点格式合规({anchor_count} 处,路径#方法名)')
else:
fail('锚点格式不合规: ' + ' ; '.join(bad_anchor))
if head_index(lines, r'^\s*#+\s*闸门状态') >= 0:
pass_('有「闸门状态」节(S2 门控有证据)')
else:
fail('缺「闸门状态」节 —— S2 门控没有证据')
star_count = sum(1 for l in lines if re.match(r'^\s*#+\s*★', l))
if star_count <= 12:
pass_(f'候选条数 {star_count}(≤12)')
else:
fail(f'候选条数 {star_count} 超过 12(颗粒度掉到实现层,需重并)')
if 0 < star_count < 5:
warn(f'候选条数 {star_count} 少于 5——先确认是否采样不到位,而非真没有')
# ------------------------------------------------ dig 专属
if args.mode == 'dig':
skel_idx = head_index(lines, r'^\s*#+\s*主干调用骨架')
skel_end = next_head_index(lines, skel_idx) if skel_idx >= 0 else -1
if skel_idx >= 0:
pass_('有「主干调用骨架」节')
else:
warn('未找到「主干调用骨架」节(仅 S4 ① 功能点清单必需)')
exempt = 0
for f in fences:
if f['lang'] == 'mermaid':
continue
if skel_idx >= 0 and skel_idx < f['start'] < skel_end:
exempt += 1
continue
if f['body'] > 10:
warn(f"局部代码块超过 10 行(第 {f['start'] + 1} 行起,{f['body']} 行)"
f"——行数非硬限,请人判断是关键片段还是源码摘录")
pass_(f'局部代码块行数检查完成(豁免骨架块 {exempt} 个)')
if skel_idx >= 0:
skel_fences = [f for f in fences if skel_idx < f['start'] < skel_end]
if not skel_fences:
warn('骨架节里没有代码块')
else:
sf = skel_fences[0]
miss_tag = []
for bl in lines[sf['start'] + 1:sf['end']]:
if not bl.strip():
continue
if re.match(r'^\s*//', bl):
continue
if re.search(r':\s*$', bl):
continue
if not re.search(r'[(\[]', bl):
continue
if '//' not in bl:
miss_tag.append(bl.strip())
if not miss_tag:
pass_('骨架每行都带方式标记')
else:
fail(f"骨架有 {len(miss_tag)} 行缺方式标记: "
+ ' ; '.join(miss_tag[:3]))
if not re.search(r'\.(java|xml|yaml|yml|sql):\d+', text):
fail('未找到任何 `文件:行号` 证据(本阶段必须有可核对的锚点)')
else:
pass_('存在 `文件:行号` 形式的证据')
# ------------------------------------------------ doc 专属
if args.mode == 'doc':
is_plan = head_index(lines, r'^\s*#+\s*0\.\s*现状问题登记') >= 0
if is_plan:
code_fences = [f for f in fences if f['lang'] != 'mermaid']
if len(code_fences) >= 1:
pass_(f'改造方案含关键片段 {len(code_fences)} 个')
else:
fail('改造方案缺「关键片段」代码块——必须"照着能讲代码"(伪代码/SQL 均可,只禁大段源码摘录)')
if len(code_fences) >= 2:
pass_(f"关键片段 {len(code_fences)} 个(骨架 + 改造点)")
elif len(code_fences) == 1:
warn('只有 1 个关键片段——可能只有链路骨架,各改造点未给伪代码,需人判')
# ------------------------------------------------ 输出
print()
print('=' * 68)
print(f'机械校验 Mode={args.mode}')
print(f' product : {prod_path}')
if args.template:
print(f" template : {Path(args.template).resolve()}")
print('=' * 68)
for tag, bucket, mark in (('[PASS]', PASS, '+ '), ('[WARN] 需人判断', WARN, '! '), ('[FAIL] 必错', FAIL, 'x ')):
if bucket:
print()
print(tag)
for m in bucket:
print(f' {mark}{m}')
print()
print(f'结果:PASS {len(PASS)} / WARN {len(WARN)} / FAIL {len(FAIL)}')
sys.exit(1 if FAIL else 0)
if __name__ == '__main__':
main()
@@ -0,0 +1,146 @@
# ⟨域⟩ 域 · 候选价值点(S1 产物)
> **阶段**:S1 枚举(**只产出亮点**;缺陷不在此阶段——它是深入链路时自然浮现的副产物)
> **域**:`⟨模块名⟩`(走 S0 ⟨快路 / 慢路⟩:⟨域清单来源⟩)
> **结构**:**域 → 链路 → 链路上的机制节点** 三层
> **筛选标准(三条,全过才进)**:**① 是否核心链路 ② 是否符合高级工程师的设计 ③ 写到简历上够不够硬**
> **深度闸门**:允许「**这个点在讲什么**」的业务语言说明;**禁止围栏代码块(行内反引号可用)、禁止逐层拆解、禁止取舍复盘**(那些属深度阶段)
> **取材**:① 设计说明类文档 ② `git log` ③ 图查询 / 结构统计 ④ 关键字 grep
---
# 闸门状态
> **本节是 S2 门控的证据**——没有它,"停在第几段"无法核查。
| 段 | 状态 | 说明 |
|:-:|---|---|
| S0 定范围 | ✅ | ⟨范围声明一句话⟩ |
| **S1 枚举** | ✅ 已完成 | 候选 ⟨N⟩ 条(**亮点**)+ 剔除 ⟨M⟩ 条 |
| **S2 勾选** | ⏸ **待人工勾选** | **请从下面挑 3–6 条**;本文件到此为止,**未做深度产出** |
> **勾选/否决后回写本表(保持 3 列不压列)**,两种回写形状:
>
> ```
> | **S2 勾选** | ✅ 已勾选 | ⟨勾了哪些(★N…)/ 谁日期⟩ → 产出《⟨产物名⟩》 |
> | **S2 勾选** | ↩️ 被否决改向 | 否决原因:⟨用户原话摘要⟩ → 改挖 ⟨新目标⟩(入口 A′) |
> ```
---
## 一、链路总览
**一句话**:⟨统领句——不是复述流程,而是给出这条链路的**主线判断**。例:"这条链路的每一段都在把外部系统给的不确定,收敛成我方的确定状态"⟩
**读法**:⟨一条端到端链路 = …→…→…;下面每个机制都挂在这张图的某个位置上⟩
**图例**:`★` = 入选的机制节点;**未标 ★ 的链路仍属本链路的一环**(见第二、三节),只是未列为独立机制。
### 端到端链路图(★ = 入选的机制节点)
```mermaid
flowchart LR
subgraph PA["链路 A · ⟨链路名⟩"]
A1["⟨起点⟩"] --> A2["⟨机制节点⟩ ★1"]
A3["⟨兜底 / 分支⟩ ★2"]
end
subgraph PB["链路 B · ⟨链路名⟩"]
B1["⟨起点⟩"] --> B2["⟨机制节点⟩ ★3"]
B2 --> B3["⟨机制节点⟩ ★4"]
end
subgraph PC["链路 C · ⟨链路名⟩"]
C1["⟨起点⟩"] --> C2["⟨终点⟩"]
end
A2 --> B1
A3 -.-> A2
B3 --> C1
C2 -.-> A2
```
⟨可选⟩**关键差异表**(若这条链路的核心是"几种结果后果完全不同",用一张表压住)
| ⟨维度⟩ | ⟨取值1⟩ | ⟨取值2⟩ | ⟨取值3⟩ |
|---|---|---|---|
| ⟨例:对方结果⟩ | | | |
| ⟨例:可逆性⟩ | | | |
| ⟨例:处置⟩ | | | |
---
## 二、链路上的机制节点(⟨N⟩ 个 ★)
> **按链路分组**。每点 4 段,**段落式**(不要压成表格——"做了什么"常是 5–7 条,塞进单元格必然被简化)。
### 链路 ⟨A⟩ · ⟨链路名⟩
## ★1 · ⟨机制名⟩
**核心内容**:⟨1 句:这个机制是什么,把它的"形状"说清(一把锁 + 三级短路 + 一条条件更新)⟩
**这个点在讲什么**
- **业务场景**:⟨谁在什么时刻触发了什么,为什么这事难;点出"同一时刻还有谁在改同一行数据"⟩
- **做了什么**(⟨用一句话概括做法⟩):
1. ⟨…⟩;
2. ⟨…⟩;
3. ⟨…⟩。
- **解决了什么问题**:⟨不做会怎样⟩
**一句话价值**:⟨1 句,可讲述;说清"判断权 / 控制权"落在谁手里⟩
**锚点**:`⟨简写⟩/⟨路径⟩#⟨方法名⟩`
---
## ★2 · ⟨机制名⟩
⟨同 ★1 的 4 段结构⟩
---
### 链路 ⟨B⟩ · ⟨链路名⟩
## ★3 · ⟨机制名⟩
⟨同 ★1 的 4 段结构⟩
---
### 链路 ⟨C⟩ · ⟨链路名⟩(⟨依附型,未列为独立机制 / 未入选⟩)
> **本链路 0 个独立机制,但说明不可省**——否则图上有个框、没人知道里面在干嘛。
**核心内容**:⟨它是什么⟩
**这个点在讲什么**
- **业务场景**:⟨…⟩
- **做了什么**:⟨…⟩
- **依附关系**:⟨它的哪几个设计决策其实是 ★N 在另一个方向 / 另一个域上的复用;判不清就按独立节点处理,不要为了凑数强行依附⟩
- **为什么未入选 / 为什么依附**:⟨★ 必须写清⟩
**锚点**:`⟨…⟩`
---
## 三、已剔除(附理由,供复核筛选口径)
> **被剔除的点不丢弃**——注明**未过哪条标准**。
**「未过的标准」建议取值**:`①核心链路` · `②非设计决策(框架常识 / 通用工程质量)` · `③简历不硬` · `机制格填不出` · `示例数据 / 字典表 / 配置装配`
| # | 被剔除的点 | 未过的标准 | 理由 |
|:-:|---|---|---|
| 1 | ⟨例:key 命名约定⟩ | `①核心链路` | 不落在业务闭环上 |
| 2 | ⟨例:Redis `GETDEL` 用法⟩ | `②非设计决策` | 框架常识用法,非设计决策 |
| 3 | ⟨例:契约模式 / CI / Checkstyle⟩ | `②非设计决策` | 通用工程质量,无设计含量 |
| 4 | ⟨例:表 CRUD / 单表封装⟩ | `机制格填不出` | 弱候选,并入本表待复核 |
---
## 四、待确认 / 覆盖缺口
| # | 项 | 说明 |
|:-:|---|---|
| 1 | **⟨链路名⟩ 0 个节点** | ⟨先问"真没亮点,还是采样不到位"(回看该链路的触发者与写类接口);判不清就写明理由⟩ |
| 2 | `⟨路径⟩#⟨方法名⟩` | 【待确认】⟨拿不准的锚点必须标出,禁止猜⟩ |
| 3 | **文档 vs 代码分叉** | ⟨设计文档写的方案在代码里是否落地?不落地本身就是高价值点⟩ |