8.3 KiB
8.3 KiB
name, description
| name | description |
|---|---|
| declarative-openspec-loop | 声明式编程循环 - 用户提供校验方式,Agent 自动 propose/apply/校验并迭代直到通过。Use when the user provides expectations or a verification method and wants the agent to implement, verify, and iterate until expectations pass. Triggers on 声明式编程、按预期循环、做到校验通过、declarative loop. |
声明式 OpenSpec 循环
用户提供判断结果是否符合预期的方式,Agent 按 OpenSpec 流程 propose → apply → 校验,不通过则分析原因并迭代,直到通过。通过后输出变更点与思路。
前置:需要 openspec CLI 及三个子 skill。预期/校验写法的详细说明和端到端示例见 reference.md。
何时使用
- 用户说「按我给的预期/校验方式做,做到通过为止」
- 用户提供了校验命令、预期文档、校验清单或自由描述,并希望自动迭代
- 用户提到「声明式编程」「按预期循环」「做到校验通过」
输入:预期与校验方式
用户必须提供如何判断结果符合预期(可组合):
| 形式 | 示例 |
|---|---|
| 校验命令 | make test-one2,退出码 0 即通过 |
| 预期文档 | docs/tmp/expect_desc.md 中的校验项表格 |
| 校验清单 | 日志须含 阶段2 圆弧起点、阶段3 右边竖边 … |
| 自由描述 | 「拟合轮廓与 PLY 逆时针顺序一致」 |
若用户未给清,必须先问。详细格式说明见 reference.md § 预期/校验方式。
如何调用子 skill(关键)
本 skill 编排三个子 skill,每次调用子 skill 时必须先读取对应 SKILL.md 并遵循其中的完整步骤:
| 步骤 | 子 skill | 读取路径 |
|---|---|---|
| 探索 | openspec-explore | .cursor/skills/openspec-explore/SKILL.md |
| 提案 | openspec-propose | .cursor/skills/openspec-propose/SKILL.md |
| 实现 | openspec-apply-change | .cursor/skills/openspec-apply-change/SKILL.md |
不要凭记忆执行子 skill 的流程,每次都读取最新的 SKILL.md 再做。
主流程
用户输入:目标 + 校验方式
│
▼
1. 初始化:change 名称 + docs/tmp/<name>/ + expectation.md
│
▼
2. [可选] explore:目标复杂/模糊时先探索
│
▼
3. propose:生成 proposal / design / tasks(任务带验收标准)
│
▼
4. apply:按 tasks 实现
│
▼
5. 校验 ──通过──▶ 6a. 完成:输出变更与思路
│
不通过
│
▼
6b. 分级处理(见下)──▶ 回到 4 或 3
迭代分级:失败后怎么做
校验不通过时,根据失败根因选择不同路径,避免小 bug 也走完整提案流程:
Level 1:代码小修复(最常见)
触发:编译错误、运行时 bug、坐标写反、off-by-one、日志格式不对等实现层面问题。
动作:
- 定位出错代码,直接修复
- 重新编译(若适用)
- 回到步骤 5 校验
不需要 explore,不需要修改 proposal/design/tasks。
Level 2:任务遗漏或不完整
触发:某个校验项没有对应的 task、task 描述模糊导致实现偏差。
动作:
- 分析缺失的校验项对应什么工作
- 在
tasks.md中补充或修正 task - 回到步骤 4 apply 执行新增/修正的 task → 步骤 5 校验
Level 3:设计级问题(最少见)
触发:整体方向错误、架构不合适、预期理解有偏差、多个校验项系统性失败。
动作:
- 读取子 skill openspec-explore 并执行:基于校验结果 + 当前 proposal/design 分析根因
- 将分析写入
docs/tmp/<change-name>/iteration_<N>.md - 修订 proposal.md / design.md / tasks.md(在原有 change 上修改,不新建)
- 回到步骤 4 apply → 步骤 5 校验
判断依据
| 信号 | Level |
|---|---|
| 编译报错 | 1 |
| 运行崩溃 / 段错误 | 1 |
| 单个校验项不通过,其余都通过 | 1 或 2 |
| 多个校验项不通过,但原因各异 | 2 |
| 多个校验项不通过,原因相同(方向性错误) | 3 |
| 校验项全部不通过 | 3 |
最大迭代次数
- 默认上限:5 轮(一轮 = 一次 apply + 一次校验)。
- 到达上限后暂停并询问用户:展示当前进度、未通过的校验项、已尝试的修复方向,让用户决定是否继续。
- 用户可在初始化时指定不同的上限(如「最多跑 3 轮」「不限轮次」)。
- Level 1 的小修复(如编译错误修复后重新编译)不计入轮次,仅 apply+校验 计一轮。
编译失败处理
对于需要编译的项目(C/C++、Rust、Go 等):
- apply 完成后、运行校验命令前,先编译(或校验命令本身触发编译)。
- 若编译失败:属于 Level 1,直接修复编译错误,重新编译,不计入迭代轮次。
- 若编译成功但校验不通过:按正常分级处理。
- 编译错误的修复不需要 explore 或修订 proposal。
重复失败检测
若连续 2 轮校验结果中,同一个校验项以相同原因失败:
- 停止自动迭代
- 向用户报告:哪个校验项、什么错误、已尝试的两次修复各做了什么
- 请用户给出新方向或手动介入
避免 Agent 在同一个坑里反复打转。
恢复 / 续接
对话中断后重新进入时:
- 检查
docs/tmp/<change-name>/下已有的iteration_*.md→ 确定当前轮次 - 检查
openspec/changes/<name>/tasks.md中[x]/[ ]→ 确定 task 进度 - 读取最近一轮的
iteration_<N>.md和check_result_<N>.txt→ 了解上次失败原因 - 从上次中断的步骤继续,不从头开始
TodoWrite 跟踪
整个循环过程中用 TodoWrite 跟踪进度:
示例 todo 列表:
- [x] 初始化 change + expectation.md
- [x] propose: 生成 proposal/design/tasks
- [in_progress] 第 1 轮 apply + 校验
- [ ] 校验通过 → 输出变更摘要
每轮 apply + 校验 为一个 todo;校验不通过时更新 todo 内容(如「第 1 轮:3/8 校验项通过,Level 2 修复中」)。
过程数据存储
根目录:docs/tmp/<change-name>/
| 文件 | 内容 |
|---|---|
expectation.md |
校验方式摘要(或引用路径) |
iteration_<NNN>.md |
每轮:apply 要点、校验结果、失败项、分级、修复动作 |
check_result_<NNN>.txt |
校验命令原始输出 |
iteration_final.md |
通过后的最终摘要(可选) |
若 docs/tmp 不存在,先创建。
输出模板(校验通过时)
## 声明式循环完成
**Change:** <change-name>
**校验方式:** <摘要>
**迭代轮次:** N
### 变更摘要
- <文件 1>:<改动>
- <文件 2>:<改动>
### 思路
<设计取舍、与预期的对应、关键实现要点>
### 过程数据
`docs/tmp/<change-name>/`
Guardrails
- 未提供校验方式时:不进入循环,先问用户。
- 每轮校验结果必须落盘:至少记录通过/不通过与未满足项。
- 优先复用同一 change:修订 proposal/design/tasks,不盲目新建。
- 任务带验收标准:propose 时每个 task 尽量带可执行的验证步骤。
- explore 只分析不改代码:改代码通过 apply 或 Level 1 直接修复。
- 最大轮次到达时停下问用户:不自动放弃也不无限跑。
- 重复失败时升级:同一错误连续 2 轮 → 停下问用户。
- 用户可随时中断:暂停并汇报当前状态。