le-spec v1.0.0:Le SPEC 智能需求分析与 SPEC 生成总控 skill——真实集成 grilling/grill-with-docs(domain-modeling) + think + openspec(CLI 1.16.1 + 7 个 openspec-* skills,均经 skills.sh 装入 ~/.agents/skills 并软链四 runtime);七阶段工作流(识别/十类分拣/Grill 访谈/Think 挑战/反向验收/OpenSpec 生成/四视角审查)复杂度三档自适应;状态 state.md + 调用账本 ledger.jsonl 双持久化支撑中断恢复与真实调用核验;依赖检查 deps_check.py 分级报缺+精确安装命令,ledger.py append/check/tail;四类回合终止停点(批准前不编码为硬约束);测试 A-I 九项全过:两场景 fresh-context 子代理多轮实测(4 轮访谈+变更+中断恢复+strict validate 双项目通过),账本 28 条真实调用(grilling×9/think×2/openspec CLI×14),独立子代理审查实测抓出自审遗漏的 2 blocking;已知限制 7 项如实入库(reports/test-report.md)

This commit is contained in:
leroy
2026-11-08 12:00:02 +08:00
parent 4ec81e253f
commit b47dcf2ff2
12 changed files with 750 additions and 0 deletions
+36
View File
@@ -0,0 +1,36 @@
# Phase 4:需求反向验收规程
**问题意识**:Phase 4 检查的不是"文档漂不漂亮",而是**需求是否明确到足以形成规格**。核心一问:
> "一个完全没有参与讨论的资深工程师现在接手开发,哪些重要产品行为仍然需要他自己猜测?哪些必须回头找需求负责人确认?"
## 执行方式(按优先级)
1. **子代理独立审查(首选)**:用 Agent 工具派 fresh-context 子代理(general-purpose 或 Explore)。提示词要点:
- 角色:资深开发工程师,第一次见到这个项目;
- 输入:只给 state.md 路径(+ 已有 openspec specs 路径,如有)——**不给会话历史、不给 Le SPEC 的阶段叙事**,确保视角独立;
- 任务:逐条检查下列清单,输出"我会被迫猜测/必须确认"的清单,每条注明影响哪个功能点与后果严重度;
- 产出格式:问题列表(问题/影响/严重度建议/建议澄清方式)。
2. **无子代理能力时的降级**:自审前显式重置角色("放下前文立场,作为首次接手的工程师仅凭 state.md 判断"),只允许引用 state.md 与项目文件内容。**必须在产出中声明"本轮为同上下文自审,独立性弱于子代理审查"**——不装作独立。
## 检查清单
- [ ] 用户流程有断点(走不到下一步/回不去)
- [ ] 功能之间缺关联规则(A 发生时 B 如何)
- [ ] 数据关系歧义(谁拥有谁、一对多还是多对多、删除级联)
- [ ] 状态机不完整(缺状态、缺转换、缺终态)
- [ ] 权限与业务边界不明(谁能做什么、越界怎样)
- [ ] 异常场景缺处理原则(失败/超时/并发/空数据)
- [ ] 需求间冲突(同一对象两种定义)
- [ ] 未经确认的重要默认假设(state.md 里的 [默认] 项逐条复核用户知情度)
- [ ] 验收判据缺失(做完了怎么算"对")
## 分级与处置
| 级别 | 判定 | 处置 |
|---|---|---|
| blocking | 不澄清就无法实现核心行为 / 两种理解导致完全不同的产品 | 终止回合向用户澄清(用 grilling 单轮格式,记账本) |
| major | 影响正确性但可从已确认决策推导 | 推导入 state.md 并标注依据;推导不了升 blocking |
| minor | 边缘场景、可延后 | 记开放问题,进 SPEC 的"非阻塞事项" |
更新后**只复核受影响项**,不重跑全清单。清零 blocking → 进 Phase 5。
+100
View File
@@ -0,0 +1,100 @@
# 依赖真实调用协议
Le SPEC 的价值建立在三个外部能力**真实运行**之上。本文件定义每个依赖的本体位置、调用条件、调用方式、上下文交接与失败处理。
## 0. 调用方式总则(skill 类依赖)
所有 skill 类依赖(grilling / domain-modeling / think / openspec-*)按以下顺序选择调用方式:
1. **宿主 Skill 工具**:若当前 runtime 提供 Skill 工具且该依赖已在可用列表中,用 Skill 工具按名调用。
2. **文件直读**:否则用 Read 读取依赖原始 `SKILL.md` **全文**,把其内容作为当前回合的执行指令遵循。这不是降级——skill 的本质就是指令文档,宿主 Skill 工具内部做的也是加载原文;直读与工具调用在语义上等价,前提是**读原文、遵循原义**(包括其引用的 references 子文件,如 think 的 mode-evaluation.md)。
两种方式都必须:
- 先记入调用账本(`ledger.py append --dep <name> --kind skill-load --method skill-tool|file-read`);
- 遵循原文机制,不自拟替代提示词(例如 grilling 的 frontier 轮次格式 ❓Q/➡️推荐、think 的 Simplicity Gate、openspec-propose 的 artifact 循环)。
## 1. grilling —— 访谈引擎
| 项 | 值 |
|---|---|
| 来源 | github.com/mattpocock/skills(productivity/grilling) |
| 本体 | `~/.agents/skills/grilling/SKILL.md`(软链解析后读真源) |
| 入口语义 | `grill-me` = 只调 grilling;`grill-with-docs` = grilling + domain-modeling。Le SPEC 按此原义路由:**全新项目 → grilling;已有代码/文档 → grilling + domain-modeling** |
| 调用时机 | Phase 2 全程(simple 档也走它,只是轮数少) |
| 输入交接 | state.md 的「已确认决策」「开放问题」两节——已确认项不得再问;开放问题构成 design tree 的初始节点 |
| 原生机制(必须保留) | design tree、frontier(前置决策已定的可问集合)、每轮问整个 frontier 并给推荐答案、答案重塑树、"事实自己查(可派子代理)、决策问用户"、frontier 空且用户确认共识才算完 |
| 产物 | 每轮问题(❓Q1… ➡️推荐格式);用户回答由 Le SPEC 写入 state.md |
**Le SPEC 叠加规则**(不与原义冲突):
- 每轮用户回答后:决策入 state.md,轮次 +1;每约 4 轮做一次检查点(见 workflow.md Phase 2)。
- grilling 的"会话结束条件 = frontier 空"之外,Le SPEC 用需求收敛标准(workflow.md)做结束判定;两者取先到者,且需向用户确认共识后收口。
- 已有项目时叠加 domain-modeling:访谈中发现术语模糊 → 按其"Sharpen fuzzy language"当场澄清;硬决策按其三条件(难逆转/无上下文会困惑/真实取舍)写 ADR。GLOSSARY.md/ADR 由 domain-modeling 机制管理,Le SPEC 不另建。
## 2. think —— 方案分析引擎
| 项 | 值 |
|---|---|
| 来源 | github.com/tw93/Waza(skills/think) |
| 本体 | `~/.agents/skills/think/SKILL.md` |
| 调用时机 | Phase 3:出现重大产品分歧、技术选型、架构取舍、过度设计疑虑、值不值得判断。**simple 档且无实质争议 → 跳过并注明** |
| 模式选择(遵循其原生定义) | 定义清楚的修复计划 → Lightweight Mode;价值/存废判断 → 读 references/mode-evaluation.md;批量诉求 → mode-triage.md。默认全模式 |
| 输入交接 | state.md 已确认需求 + 约束 + 已否定方案 + 待选方案。think 的 "Durable Context Preflight" 要求读项目 AGENTS.md/CLAUDE.md 索引——照做 |
| 原生机制(必须保留) | 先查官方方案、推荐单一方案+理由+一个替代、premise collapse(最脆弱假设)、attack angles(外部依赖/并发/迁移时)、Simplicity Gate、批准前不动代码 |
| 产物 | 推荐方案 + 关键决策 + 风险 + 被否替代 → 写入 state.md「已确认决策」(待用户批准的标 [待批准]) |
**回流规则**:think 发现新的重大需求不确定性(Blocking ambiguities)→ 带回 Phase 2 用 grilling 格式做**针对性**追问(不是重启访谈),解决后回到 Phase 3 继续。
## 3. OpenSpec —— 规格工程引擎(CLI + skills 双通道)
| 项 | 值 |
|---|---|
| 来源 | github.com/Fission-AI/OpenSpec(npm: @fission-ai/openspec) |
| CLI | `openspec`(PATH 中,≥1.3 可用 artifact 工作流;本 skill 按 1.16.x 验证) |
| skills | `~/.agents/skills/openspec-{propose,new-change,update-change,verify-change,archive-change,apply-change,explore}/SKILL.md` |
| 调用时机 | Phase 0(context 探测)、Phase 5(生成)、Phase 6(validate)、Phase 7 后的变更与归档 |
**Phase 5 标准路径**(遵循 openspec-propose 原生步骤,Le SPEC 已备齐输入故跳过其澄清步):
```bash
openspec context --json # 定位根;root:null → 见下"项目初始化"
openspec new change "<kebab-name>" # 脚手架(默认 spec-driven schema)
openspec status --change "<name>" --json # artifact 顺序与路径
openspec instructions <artifact> --change "<name>" --json # 逐个:proposal → specs → design → tasks
# 按 template + instruction 撰写每个 artifact 文件
openspec validate "<name>" # 必须通过
```
- **artifact 分工是 OpenSpec 原生的**:`specs/` = 产品需求(行为契约、Requirement/Scenario)、`design.md` = 技术设计(HOW,conditional)、`tasks.md` = 开发任务(checkbox)、`proposal.md` = Why/What/Capabilities。不混写。
- **项目初始化边界**(遵循其 Project check 原义):`root:null` 且用户未提 OpenSpec → 停下问用户:init(`openspec init --tools none`,工具注入由用户后续决定)/ 走 store / 不用 OpenSpec 本次降级输出。绝不让 `new change` 的副作用悄悄创建根。
- **变更管理**:SPEC 已批准后的需求变化 → openspec-update-change 工作流(新 change 或修订现有),归档 → openspec-archive-change。Le SPEC 交接到此为止,apply 交给 Coding Agent。
## 4. 依赖检查与失败处理
`scripts/deps_check.py`(--json 供脚本、默认人读输出):
| 依赖 | 级别 | 缺失时 |
|---|---|---|
| grilling skill | required | 停止访谈阶段,输出安装命令(下表),不降级为普通问答 |
| think skill | required(Phase 3 入口) | 方案分歧时停止并提示安装;无分歧场景不受影响 |
| openspec CLI | required(Phase 5 入口) | 停止规格生成,提示 `npm install -g @fission-ai/openspec` |
| openspec-* skills | recommended | CLI 工作流仍可走(Phase 5 标准路径即 CLI 驱动),但提示安装以获得完整工作流指令 |
| domain-modeling skill | recommended(已有项目时升 required) | 已有项目的访谈照常,但声明"术语沉淀与 ADR 不可用" |
| grill-me / grill-with-docs | optional(入口薄壳) | 不影响——Le SPEC 直接路由到底层组合 |
安装命令(真实可执行,2026-11 验证):
```bash
npx skills@latest add mattpocock/skills --skill grilling grill-me grill-with-docs domain-modeling -g
npx skills@latest add tw93/Waza --skill think -g
npx skills@latest add Fission-AI/OpenSpec --skill openspec-propose openspec-new-change openspec-update-change openspec-verify-change openspec-archive-change openspec-apply-change openspec-explore -g
npm install -g @fission-ai/openspec@latest
```
**失败语义**:CLI 非零退出 ≠ 永远失败(如 `openspec list` 在无根项目返回非零,那是"未初始化"的答案不是崩溃)——读 JSON 输出判断,不盲目重试。skill 加载失败(文件不存在/为空)→ 记账本(method=file-read, exit=1)→ 按缺失处理。**任何情况下不得用模拟输出冒充调用成功。**
## 5. 防重复机制
- grilling 问过的 → state.md「已确认决策」,think 直接消费;
- think 已否定的方案 → state.md「已否定方案」,Phase 4/6 审查不再重提,除非发现新证据;
- OpenSpec artifacts 已写内容 → Phase 6 审查对照 state.md 检查一致性,不重新发起需求讨论;
- 每阶段入口先读 state.md 的阶段标记,已完成阶段不重做(中断恢复同理)。
+35
View File
@@ -0,0 +1,35 @@
# Phase 6:SPEC 独立质量审查规程
**问题意识**:Phase 4 检查"需求是否明确到足以形成规格";Phase 6 检查**"规格是否准确到足以指导开发和测试"**。审查对象是 OpenSpec artifacts(proposal/specs/design/tasks),不是重新审需求——需求问题应已在 Phase 4 清零。
## 审查组成(三路并行)
1. **四视角子代理审查**(首选 fresh-context 子代理;降级规则同 acceptance.md,须声明独立性等级)。输入:change 目录全部 artifact 路径 + state.md 路径 + (已有项目时)相关既有 specs 路径。四视角各答各的:
| 视角 | 追问 |
|---|---|
| 产品 | 完整表达真实需求了吗?有无遗漏功能?有无混入用户未确认的新要求(对照 state.md 逐条溯源)? |
| 架构 | 与现有系统/既有 specs 冲突?重大技术风险?不必要的复杂度(对照 design.md 的 Decisions 与 think 结论)? |
| 开发 | 还要猜什么?缺数据/流程/状态定义?互相矛盾的要求(specs 内部 + specs↔design↔tasks)? |
| 测试 | 每条 Requirement 的 Scenario 可执行可判定的吗?正常/异常/边界覆盖?有没有判不了 pass/fail 的模糊表述? |
2. **CLI 校验**:`openspec validate "<change>"`(严格模式可用则用)+ `openspec status --change "<name>"` 确认 artifact 齐全。
3. **账本核对**:`ledger.py check` 确认 grilling/think/openspec 均有真实调用记录;缺失 → 回补(真实调用)或如实声明。
## 产出格式(每问题一行,不许无依据打分)
```markdown
| # | 视角 | 严重度 | 问题(引 artifact 行文) | 影响 | 修正建议 | 阻塞? |
```
严重度:blocker(规格错误/矛盾/无法实现或测试)|major(会导致误解或返工)|minor(措辞与边缘)。
## 修正循环
blocker/major 逐条修正 artifact → 只复验受影响项(重跑 validate + 相关视角复查)→ 清零或全部降为 minor 后出结论:
```markdown
审查结论:blocker 0 / major 0 / minor N(列表,随 SPEC 一并呈交)
```
修正时保持铁律 2:修正只动规格文本与事实呈现,不重启需求讨论;发现规格确实承载不了的需求歧义 → 回 Phase 4 流程处理。
+106
View File
@@ -0,0 +1,106 @@
# 七阶段工作流规程
阶段是逻辑流。每阶段入口先读 state.md 阶段标记,已完成的跳过。
## Phase 0:项目识别与上下文理解
1. 判任务类型:全新产品 / 已有产品加功能 / 已有功能修改 / 复杂业务模块 / 架构重构 / 探索性想法。
2. 有代码库时只读检查(按复杂度控制深度,simple 档可缩到 3-5 分钟扫读):
- 项目结构、技术栈、入口文件;已有文档与 `openspec/specs/`(`openspec context --json` 探测);GLOSSARY/ADR(domain-modeling 的管理物);近期 git log 的设计决策线索。
- **能从代码和文档确认的事实,绝不进访谈问题**(grilling 原义:事实自己查,决策问用户)。
3. 复杂度定档(可随讨论动态升降级,升降级写入 state.md 并注明理由):
| 档 | 特征 | 流程 |
|---|---|---|
| simple | 字段/筛选/文案级修改,影响单一界面或接口 | 0 → 1 → grilling 单轮(≤1 轮)→ (跳过 3)→ 清单式 4 → 5(propose,design 多为 skip)→ 快速 6 → 7 |
| medium | 新功能模块(日历、用户管理级) | 全流程,3 按需 |
| complex | 全新产品、多角色/多流程系统、架构重构 | 全流程;3 必用于重大决策;访谈允许多轮充分展开 |
## Phase 1:原始需求理解
对用户原始输入做**十类分拣**,产出写入 state.md:
1. 明确需求 2. 目标与期望结果 3. 用户角色与场景 4. 未定想法 5. 用户假设 6. 约束(产品+技术) 7. 矛盾描述(列出冲突双方与出处) 8. 重要缺失信息 9. 已否定方案 10. 明确不做
规则:保留原始措辞的关键短语与来源(哪条消息);不擅自增需求;临时想法标注 [未定];AI 推荐方案标注 [建议],不得记为已批准。矛盾不在此阶段裁决——入开放问题,Phase 2 问。
state.md 初始化模板:
```markdown
# Le SPEC 状态 — <项目/功能名>
更新: <日期> | 阶段: Phase 1 | 复杂度: <档>(理由)
## 项目
类型: <全新/加功能/修改/…> | 目标: <一句话>
## 原始输入摘要
- (来源: 首条消息) <要点,保留关键原话>
## 已确认决策
| # | 决策 | 内容 | 来源 | 状态 |
|---|------|------|------|------|
## 已否定方案
- <方案> — 否定原因 <来源>
## 开放问题
- [ ] Q1 <问题>(影响: 核心/边缘;依赖: -)
## 假设(待验证)
- <假设>(依据)
## 访谈计数
轮次: 0 | 检查点: -
## 下一步
- <具体动作>
```
## Phase 2:Grill 深度访谈
入口动作(顺序固定):
1. 读 [dependencies.md](dependencies.md) 第 1 节,按调用方式总则**真实加载 grilling**(已有项目叠加 domain-modeling),记账本。
2. 以 state.md 开放问题 + 十类分拣中的矛盾/缺失为 design tree 初始节点。
访谈中 Le SPEC 叠加于 grilling 原义之上的规则:
- **每轮结束**(用户答完):新决策入表、开放问题更新、轮次 +1、增量写 state.md。
- **检查点**:每逢第 4、8、12…轮答完,附一段 ≤6 行小结(已确认 N 项 / 开放 M 项 / 收敛判断:继续|接近|已达标)。有 blocking 问题默认继续,不要求用户批准继续;已达标主动提议收口。
- **收敛标准**(全部满足才收口):目标明确 | 范围明确(含不做) | 角色明确 | 核心流程闭环 | 业务规则明确 | 数据关系与权限边界明确(适用时) | 异常边界已有处理原则 | 无阻塞实现的重大未决。非关键细节可用「明确标注的默认方案」填充(标注 [默认] 进 state.md),不无限追问。
- **用户控制权**:随时可换模块、改需求(记录影响范围,受影响的已确认项重开并注明)、看草稿、暂停(state.md 存「下一步」)、先谈技术(跳 Phase 3 再回)。
- 关键需求仍有歧义时不得自行拍板;重大未决可出「标注风险的草稿」但明示未经审查。
## Phase 3:Think 方案分析与挑战
1. 无实质方案争议(simple 或方案唯一且用户已定)→ state.md 记"Phase 3 跳过(无分歧)",进 Phase 4。
2. 否则按 [dependencies.md](dependencies.md) 第 2 节**真实加载 think**(含其 Preflight:读项目 AGENTS/CLAUDE 索引与相关规则),记账本。
3. think 产出推荐方案 → 向用户呈现(推荐+理由+一个替代+风险+最脆弱假设)→ **终止回合等决断** → 批准则入 state.md [已批准],新不确定性回流 Phase 2。
## Phase 4:需求反向验收
详见 [acceptance.md](acceptance.md)。核心:fresh-context 子代理扮演"没参与讨论的资深工程师",只读 state.md + 已确认材料,回答"由我实现的话,哪些产品行为还得靠猜?"。产出 blocking / major / minor 问题清单:
- blocking → 以 grilling 单轮格式向用户澄清(记账本 dep=grilling, summary=acceptance-driven)→ 更新后**只复核受影响项**;
- major → 能由已确认决策推导的当场补进 state.md 并标注推导依据,推导不了的升级 blocking;
- minor → 记入开放问题,随 SPEC 的"非阻塞事项"呈现。
清零 blocking 才进 Phase 5。
## Phase 5:OpenSpec 生成正式 SPEC
按 [dependencies.md](dependencies.md) 第 3 节标准路径执行(每条 CLI 命令记账本)。要点:
- change 名 kebab-case,从需求导出;同名已存在 → 问用户续用还是新建(遵循原生 guardrail)。
- 逐 artifact:先 `instructions`,按其 template + instruction 撰写;内容全部来自 state.md(已批准决策/已确认需求/[默认] 项如实标注),**不编造规则**;验收场景用 Requirement/Scenario 结构,可测、可观察。
- `design.md` 遵循其 conditional 规则(跨切面/新依赖/数据模型等才写);Phase 3 有 think 结论的,方案与已否替代直接沉淀为 Decisions。
- `openspec validate` 必须通过;失败按输出修正后重跑。
- SPEC 语言聚焦"系统做什么、表现什么行为、如何判断正确"——实现机制进 design/tasks(OpenSpec config 的 product-language 约定同理)。
## Phase 6:SPEC 独立质量审查
详见 [review.md](review.md)。四视角(产品/架构/开发/测试)独立审查 artifacts + `openspec validate` 复跑 + 账本核对。问题分级(blocker/major/minor)→ 修正 → 只复验受影响项 → 出审查结论(无事实依据的分数不打)。
## Phase 7:用户确认与交接
确认包含:正式 SPEC 位置与摘要、核心功能与范围、关键决策(含被否方案)、明确不做、尚存风险与非阻塞问题、审查结果摘要、账本统计(grilling/think/openspec 各 N 次真实调用)。
**呈交后终止回合。** 用户批准 → 更新 state.md 阶段为"已交接",提示后续:实现用 openspec-apply-change 工作流、需求变化用 openspec-update-change、完成后 openspec-archive-change。用户要改 → 只更新受影响 artifact 并复验(不重跑全流程)。
## 中断恢复
任何会话重入:`openspec context --json` → 读 `<root>/openspec/le-spec/state.md` → 校验其「下一步」与 OpenSpec 实际状态(`openspec status --change` 或 `openspec list --json`)一致 → 从断点继续。state.md 阶段标记与实际不符时以实际产物为准并修正状态。