team-skills 1.2.2 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "team-skills",
3
- "version": "1.2.2",
3
+ "version": "1.3.0",
4
4
  "description": "AI Agent Skills framework — Spec-Driven development with directed-graph rollback and quality gates",
5
5
  "type": "module",
6
6
  "bin": {
@@ -14,7 +14,7 @@ const root = execSync('git rev-parse --show-toplevel', { encoding: 'utf8' }).tri
14
14
  const REQUIRED_SECTIONS = [
15
15
  ['角色定位'],
16
16
  ['系统提示词'],
17
- ['推理指引', '路由推理'],
17
+ ['推理检查点', '路由推理检查点', '推理指引', '路由推理'],
18
18
  ['Iron Law'],
19
19
  ['执行步骤'],
20
20
  ['自检门禁'],
@@ -1,38 +1,31 @@
1
1
  # Constitutional Rules(不可覆盖的硬约束)
2
2
 
3
- > 共享规则文件,被所有 Team Skill 引用。这些规则不可被任何任务覆盖。
3
+ > 共享规则文件,被所有 Team Skill 引用。不可被任何任务覆盖。
4
4
 
5
5
  ## 规则列表
6
6
 
7
- > 每条规则追溯到 `_team-rules/first-principles.md` 中的第一性原理(FP-1 ~ FP-4)。
7
+ > 每条规则追溯到 `_team-rules/first-principles.md`(FP-1 ~ FP-4)。
8
8
 
9
- 1. **人类介入是一等公民** — H1-H4 必须暂停等待确认(精简模式下 H1H2 可简化为单句确认,但 H1H4 不可省略)
10
- - **为什么(FP-1)**:AI 的价值在于放大人类判断力而非替代它。跳过人类介入 = 让放大器在无信号源时自激振荡
11
- 2. **有向图回退**发现问题必须回退,禁止"先记着后面修"
12
- - **为什么(FP-4)**:声明不等于事实。"后面修"是一种声明——承诺未来会修复,但没有任何证据保证。问题在发现时最容易定位,延迟修复使上下文流失
13
- 3. **产出必须验证**不信任任何 Agent 的自我声明
14
- - **为什么(FP-4)**:Agent 会无意识地将"我认为通过了"当作"确实通过了"。自我声明是零信息量信号
15
- 4. **Kill Switch** 不可行必须立即暂停,禁止"先做做看"
16
- - **为什么(FP-1 + FP-3)**:人类认知是稀缺资源——在错误方向上投入的每一分钟都是浪费。复杂度是质量的敌人——在不可行的基础上堆叠更多工作只会使失败更难诊断
17
- 5. **分期交付优先**复杂任务必须 P1+P2,禁止一次性全量交付。复杂度判定参考 `team-orchestrator` 的任务规模分级:修改文件 > 3 且有跨模块影响即为 Medium 以上,应分期
18
- - **为什么(FP-3)**:复杂度是质量的敌人。一次性全量交付使得任何单点失败都阻塞整体验收。分期交付将风险隔离到每期的边界内
19
- 6. **自我约束预算** — 超出即砍范围,不放宽预算
20
- - **为什么(FP-3)**:预算是复杂度的量化边界。放宽预算 = 主动邀请复杂度增长
21
- 7. **回退次数上限** — 同阶段 ≤ 2 次,超过触发 H3
22
- - **为什么(FP-1)**:如果两次回退仍未解决问题,说明当前信息不足以做出正确决策。此时需要人类认知介入——继续重试是机械行为而非工程判断
23
- 8. **验证先行** — 声明"通过"必须基于当次新鲜执行的完整输出
24
- - **为什么(FP-4)**:上一轮的通过结果是历史事实而非当前事实。代码在两次运行之间可能被修改、依赖可能变化、环境可能漂移
25
- 9. **TDD 顺序不可逆** — 每个功能点必须先有失败测试(RED + commit)再有实现代码(GREEN + commit)
26
- - **为什么(FP-2)**:编写实现的行为会改变你对"正确"的认知。后写测试 = 测试你构建的东西;先写测试 = 测试需求的东西。这不是仪式,是消除实现偏见的唯一已知方法
9
+ 1. **人类介入是一等公民** — H1-H4 暂停等待确认;精简模式 H1/H2 可简化为单句确认,H1/H4 不可省略(FP-1)
10
+ 2. **有向图回退** 发现问题立即回退,禁止延迟。测试失败 = 事实,忽略只会放大修复代价(FP-4)
11
+ 3. **产出必须验证**不信任 Agent 自我声明,"我认为通过了" ≠ "确实通过了"(FP-4)
12
+ 4. **Kill Switch** — 不可行立即暂停,在不可行基础上堆叠工作只会使失败更难诊断(FP-1 + FP-3)
13
+ 5. **分期交付优先**修改文件 > 3 且跨模块影响 → 分期,每期独立序号和目录。单点失败只阻塞本期(FP-3)
14
+ 6. **自我约束预算** — 超出砍范围,不放宽预算(FP-3)
15
+ 7. **回退次数上限**同阶段 ≤ 2 次,超过触发 H3。两次未解决 = 信息不足,需人类介入(FP-1)
16
+ 8. **验证先行** "通过"声明须基于当次新鲜执行的完整输出,上一轮结果是历史而非当前事实(FP-4)
17
+ 9. **TDD 顺序不可逆** RED + commit 先于 GREEN + commit。后写测试 = 测试你构建的;先写测试 = 测试需求的(FP-2)
27
18
 
28
19
  ## 常见规避借口(不成立)
29
20
 
30
21
  | 借口 | 正确做法 |
31
22
  | ---- | -------- |
32
23
  | "任务很简单不需要完整流程" | 简单任务自然快速通过流程 |
33
- | "我已经知道答案" | 执行 Phase 1 探索,用证据验证 |
24
+ | "我已经知道答案" | 用证据验证 |
34
25
  | "测试上一轮通过了" | 重新执行验证协议 |
35
26
  | "改动太小不需要测试" | 至少运行相关测试 |
36
- | "先实现再补测试" | TDD:先测试再实现 |
37
- | "代码已经写好了,补个测试就行" | 删除实现代码,从 RED 开始。沉没成本不是理由 |
27
+ | "先实现再补测试" | 先测试再实现 |
28
+ | "代码已经写好了,补个测试就行" | 删除实现代码,从 RED 开始 |
29
+ | "先继续后面再修" | 立即修复,修复后重新验证 |
30
+ | "这个失败跟我的改动无关" | 验证无关性(git stash → 运行 → 仍失败 = 确认无关并记录);未验证 = 掩盖 |
38
31
  | "用户没要求写文档" | 文档是流程一部分 |
@@ -0,0 +1,485 @@
1
+ # Markdown Skill Language v1.0
2
+
3
+ > 共享规则文件。所有 SKILL.md 的执行步骤、门禁、状态声明须遵循本规范。
4
+
5
+ ## 设计原则
6
+
7
+ 1. **Markdown 原生** — 仅使用 Markdown 已有语法构造(标题、粗体、反引号、列表、引用块、表格),不引入任何自定义符号或标签
8
+ 2. **零歧义** — 每个 Markdown 构造在 Skill 上下文中有且仅有一个语义解释
9
+ 3. **LLM 可执行** — 控制流、变量、门禁可被 LLM 机械提取并逐步执行,无需"读懂段落"
10
+ 4. **有执行模型** — 顺序流、跳转、循环终止、分支穷尽性有明确定义(§执行模型)
11
+ 5. **有变量模型** — 变量声明、引用、作用域、表达式语法有明确定义(§变量模型)
12
+ 6. **有组合模型** — Skill 间调用、回退、状态持久化有明确协议(§组合模型)
13
+
14
+ ## 12 条语义约定
15
+
16
+ | # | Markdown 构造 | Skill 语义 | 示例 |
17
+ |---|---------------|-----------|------|
18
+ | 1 | `###` 标题 | Step / Phase 作用域边界 | `### Step 1:确定验证命令` |
19
+ | 2 | `**全大写词**` | 语义关键词(指令动词 / 状态) | `**RESOLVE**` `**ASSERT**` `**DONE**` |
20
+ | 3 | `` `反引号` `` | 标识符 / 可求值表达式 | `` `exit_code == 0` `` `` `verify_cmd` `` |
21
+ | 4a | `1. 2. 3.` 有序列表 | 顺序执行(默认语义) | 步骤 1 → 步骤 2 → 步骤 3 |
22
+ | 4b | `**RESOLVE**` + `1. 2. 3.` | 优先级链(首个命中即停) | `**RESOLVE** \`var\``:1. 尝试 A 2. 尝试 B 3. *none* |
23
+ | 5 | `-` 无序列表 + 缩进 | 条件分支(顶层=条件,缩进子项=动作) | 二级缩进 = 二层嵌套 |
24
+ | 6 | `→` | 则(then)— 前面是条件/动作,后面是后续动作 | `失败 → 记录详情 → **GOTO** Step 2` |
25
+ | 7 | `- [ ]` 复选框 | **GATE** 断言条目(必须逐条验证,全部通过才放行) | `- [ ] exit_code == 0` |
26
+ | 8 | `>` 引用块 | WHY / 设计意图(不参与执行,不含关键词指令) | 解释规则存在的工程理由 |
27
+ | 9 | `*斜体*` | 兜底 / 缺省 / 空值 | `*none*` `*not found*` `*default*` |
28
+ | 10 | 表格 | 结构化映射(状态机、类型表、路由表) | 失败模式表、严重级别表 |
29
+ | 11 | `####` 四级标题 | 命名子步骤(用于拆分超过 2 层的嵌套) | `#### 子步骤 4.1:回退路由` |
30
+ | 12 | `[标签]` 方括号 | 条件注解(标记该指令的适用条件) | `[完整模式]` `[精简替代]` |
31
+
32
+ ## 关键词词表
33
+
34
+ 所有关键词以 `**全大写粗体**` 标记,分 5 类。**仅**以下词为关键词——其他粗体词(如概念名称 **YAGNI**、章节强调)不是关键词,LLM 不按指令解析。
35
+
36
+ | 类别 | 关键词 | 语义 |
37
+ |------|--------|------|
38
+ | 数据操作 | `**READ**` `**WRITE**` `**RESOLVE**` `**EXEC**` | 读取文件或输入、写入文件或展示给用户、按优先级链解析变量、执行 shell 命令 |
39
+ | 控制流 | `**IF**` `**ELSE**` `**MATCH**` `**FOR**` `**REPEAT**` `**GOTO**` | 条件、否则、模式匹配分发、遍历集合、有限重试、跳转 |
40
+ | 门禁 | `**ASSERT**` `**GATE**` | 单条件断言(失败则执行 fallback)、多条件检查点(全部通过才放行) |
41
+ | 状态 | `**DONE**` `**BLOCKED**` `**NEEDS_CONTEXT**` `**DONE_WITH_CONCERNS**` | 四态完成状态 |
42
+ | 路由 | `**ROLLBACK**` `**ROUTE**` `**H3**` | 回退到上游 Agent、路由到下游 Skill、触发人类介入 |
43
+
44
+ ### ASSERT 与 GATE 的区分
45
+
46
+ | 维度 | **ASSERT** | **GATE** |
47
+ |------|-----------|----------|
48
+ | 条件数 | 单条件(可用 `&&` 组合) | 多条件(复选框列表) |
49
+ | 失败行为 | 执行 fallback 动作(→ GOTO / ROLLBACK / BLOCKED) | 阻塞——全部通过才放行,不通过则补全后重检 |
50
+ | 典型场景 | 执行步骤中的即时检查 | 阶段转换前的准入门禁、自检清单 |
51
+ | 格式 | `**ASSERT** \`expression\`` + fallback 分支 | `**GATE** 描述` + `- [ ]` 复选框列表 |
52
+
53
+ ### WRITE 的目标区分
54
+
55
+ `**WRITE**` 后面的目标决定动作类型:
56
+
57
+ | 写法 | 含义 | 示例 |
58
+ |------|------|------|
59
+ | `**WRITE** \`filepath\`` | 写入磁盘文件 | `**WRITE** \`06-tdd-log.md\`` |
60
+ | `**WRITE**(对话中)` | 展示给用户,不写文件 | `**WRITE**(对话中)推荐结果` |
61
+ | `**WRITE** checkpoint` | 更新 checkpoint 文件 | `**WRITE** checkpoint:...` |
62
+
63
+ ## 执行模型
64
+
65
+ ### 顺序流
66
+
67
+ `###` Step/Phase 按文档顺序执行。前一个 Step 的最后一条指令完成后,自动进入下一个 Step。
68
+
69
+ 以下关键词中断顺序流:
70
+
71
+ | 关键词 | 效果 |
72
+ |--------|------|
73
+ | `**GOTO** Step N` | 无条件跳转到目标 Step/子步骤 |
74
+ | `**DONE**` / `**DONE_WITH_CONCERNS**` | 终止整个 Skill 执行 |
75
+ | `**BLOCKED**` / `**NEEDS_CONTEXT**` | 终止执行,等待外部输入 |
76
+ | `**ROLLBACK** agent` | 终止执行,回退到上游 |
77
+
78
+ ### `####` 子步骤的返回行为
79
+
80
+ `####` 子步骤执行完后回到父 `###` 的下一条指令——除非子步骤以 GOTO/DONE/BLOCKED/ROLLBACK 结尾。被 GOTO 跳入的 `####` 同理:执行完后不自动返回跳出点。
81
+
82
+ ### GOTO 目标约束
83
+
84
+ 目标必须是当前文件中存在的 `###` 或 `####` 标题名称。跨文件跳转使用 `**ROUTE**`。
85
+
86
+ ### MATCH 穷尽性
87
+
88
+ **MATCH** 的分支必须覆盖所有可能的值:
89
+
90
+ - 提供 `*default*` / `*none*` 兜底分支,或
91
+ - 枚举变量值域的全部值(适用于有限集合如四态状态)
92
+
93
+ 未覆盖的值 = 未定义行为。
94
+
95
+ ### FOR / REPEAT 终止
96
+
97
+ - **FOR**:遍历完集合后回到 FOR 块后的下一条指令
98
+ - **REPEAT** max=N:重试 N 次后触发 `*repeat exhausted*` 兜底(必须提供)
99
+ - FOR/REPEAT 内的 GOTO 立即跳出循环
100
+
101
+ ### 有序列表语义消歧
102
+
103
+ 有序列表(`1. 2. 3.`)在两种上下文中语义不同:
104
+
105
+ | 上下文 | 语义 | 行为 |
106
+ |--------|------|------|
107
+ | 默认 | 顺序执行 | 步骤 1 完成 → 步骤 2 → 步骤 3,全部执行 |
108
+ | `**RESOLVE**` 引导 | 优先级链 | 步骤 1 命中 → 停止;未命中 → 步骤 2;`*none*` = 全未命中 |
109
+
110
+ 判定规则:有序列表前的最近关键词是 `**RESOLVE**` → 优先级链语义。其他情况 → 顺序执行语义。
111
+
112
+ ## 变量模型
113
+
114
+ ### 变量引入
115
+
116
+ 变量通过以下关键词引入:
117
+
118
+ | 引入方式 | 产生的变量 | 作用域 | 示例 |
119
+ |----------|-----------|--------|------|
120
+ | `**RESOLVE** \`var\`` | 命名变量 `var` | Step 作用域 | `**RESOLVE** \`verify_cmd\`` |
121
+ | `**FOR** each \`item\`` | 循环变量 `item` | FOR 块内 | `**FOR** each \`feature_point\`` |
122
+ | `**MATCH** \`var\`` | 匹配目标 `var` | MATCH 块内 | `**MATCH** \`result\`` |
123
+ | `**EXEC** cmd` | 隐式 `exit_code` + `output` | 到下一个 EXEC | `**EXEC** \`git status\`` |
124
+ | `**READ** source` | 隐式读取内容 | 紧随的指令 | `**READ** \`03-sdd.md\`` |
125
+
126
+ ### 作用域规则
127
+
128
+ - **RESOLVE 变量**:从声明点到所属 `###` 末尾。`###` 之前声明的变量可见到文件末尾
129
+ - **FOR 循环变量**:仅在 FOR 块(包括其缩进子项)内可见
130
+ - **EXEC 隐式变量**(`exit_code`、`output`):仅在紧随的条件/断言中有效。下一个 EXEC 覆盖前值
131
+ - **同名覆盖**:后声明覆盖前声明,无警告
132
+
133
+ ### 表达式语法
134
+
135
+ 反引号内可使用以下运算。运算符两侧为标识符或字面值:
136
+
137
+ | 运算 | 写法 | 示例 |
138
+ |------|------|------|
139
+ | 相等 | `==` `!=` | `` `mode == compact` `` |
140
+ | 比较 | `>=` `<=` `>` `<` | `` `failures == 0` `` |
141
+ | 逻辑 | `&&` &#124;&#124; | `` `exit_code == 0` && `failures == 0` `` |
142
+ | 存在性 | `X 存在` `X 不存在` | `` `docs/specs/` 存在 `` |
143
+ | 属性访问 | `.` | `` `READ("file").field` `` |
144
+ | 否定 | `非` `!` | `` `output` 非空 `` |
145
+ | 多值 | &#124;&#124; 在 MATCH 分支 | `` `DONE` \|\| `DONE_WITH_CONCERNS` `` |
146
+
147
+ 逻辑运算 `&&` 的多个反引号子表达式可以分别用独立反引号包裹:`` `exit_code == 0` && `failures == 0` ``。
148
+
149
+ ### 常用变量约定
150
+
151
+ 以下变量名跨 Skill 统一使用(非关键词,是命名约定):
152
+
153
+ | 名称 | 含义 | 典型引入方式 |
154
+ |------|------|-------------|
155
+ | `mode` | `full` / `compact` | RESOLVE |
156
+ | `slug` | 任务标识符 `{NNNN}-{keyword}` | RESOLVE |
157
+ | `exit_code` | 命令退出码 | EXEC 隐式 |
158
+ | `output` | 命令标准输出 | EXEC 隐式 |
159
+ | `verify_cmd` | 项目验证命令 | RESOLVE |
160
+ | `base_branch` | 基准分支名 | RESOLVE |
161
+ | `result` | 完成状态匹配目标 | MATCH |
162
+
163
+ ## 组合模型
164
+
165
+ ### ROUTE 协议
166
+
167
+ `**ROUTE** skill-name` 调用另一个 Skill。调用约定:
168
+
169
+ 1. ROUTE 后跟代码块 = 提示模板,传递给目标 Skill 的执行上下文
170
+ 2. 模板中 `{var}` = 当前作用域变量插值
171
+ 3. ROUTE 后的"完成验证"段落 = 目标 Skill 返回后的后置条件检查
172
+
173
+ ```markdown
174
+ **ROUTE** `team-test`
175
+
176
+ \`\`\`
177
+ 任务 slug:{slug}
178
+ 模式:{mode}
179
+ 输入:docs/tasks/{slug}/ 下的文件
180
+ \`\`\`
181
+
182
+ **完成验证**(产出门禁):
183
+ **FOR** each file in [`09-test-matrix.md`, `10-test-report.md`]:
184
+ - **ASSERT** 文件存在且有效行数 ≥ 5
185
+ ```
186
+
187
+ ### ROLLBACK 协议
188
+
189
+ `**ROLLBACK** agent-name` 回退到上游 Agent。必须携带四要素:
190
+
191
+ | 要素 | 必须 | 示例 |
192
+ |------|------|------|
193
+ | 问题描述 | 是 | "`exit_code != 0`,测试失败 3 个" |
194
+ | 位置 | 是 | "Step 4 产出门禁" |
195
+ | 期望行为 | 是 | "引用 SDD §二.3 条目" |
196
+ | 建议修复 | 是 | "检查边界条件处理" |
197
+
198
+ ROLLBACK 可附带跳转目标:`**ROLLBACK** implAgent(**GOTO** Step 3,附 bug 上下文)`。
199
+
200
+ ### Checkpoint 模型
201
+
202
+ `**WRITE** checkpoint:...` 持久化跨步骤状态,用于断点续传。
203
+
204
+ 标准字段约定:
205
+
206
+ | 字段 | 类型 | 含义 |
207
+ |------|------|------|
208
+ | `current_step` | string | 当前执行到的 Step |
209
+ | `next_step` | string | 下一个待执行 Step |
210
+ | `phase` | string | 当前阶段名 |
211
+ | `completed_steps` | string[] | 已完成的 Step 列表 |
212
+ | `status` | 四态之一 | 任务整体状态 |
213
+ | `rollback_counts` | object | `{source→target: count}` 回退计数 |
214
+
215
+ Checkpoint 在每个 Step 完成后更新,在恢复时通过 `**READ** checkpoint` → `**MATCH** \`checkpoint.status\`` 决定继续点。
216
+
217
+ ## 常见模式
218
+
219
+ ### 模式 1:RESOLVE 优先级链
220
+
221
+ 按优先级依次查找,首个命中即停,末尾 `*none*` 为兜底。
222
+
223
+ ```markdown
224
+ **RESOLVE** `verify_cmd`(首个命中即停):
225
+
226
+ 1. `READ("05-risk.md", "§一验证计划")`
227
+ 2. `READ("CLAUDE.md").test_cmd` / `READ(".cursor/rules/")`
228
+ 3. `READ("package.json").scripts.test` / `READ("Makefile")`
229
+ 4. *none* → **NEEDS_CONTEXT**:请用户提供验证命令
230
+ ```
231
+
232
+ **规则**:每个 RESOLVE 链必须有 `*none*` / `*default*` / `*not found*` 兜底项。
233
+
234
+ ### 模式 2:ASSERT 单条件断言
235
+
236
+ 断言必须为真,否则执行 fallback 动作。
237
+
238
+ ```markdown
239
+ **ASSERT** `exit_code == 0` && `failures == 0`
240
+ - `exit_code != 0` → 记录失败 → **GOTO** Step N
241
+ - warning && `exit_code == 0` → **WRITE** warning 到报告,不阻塞
242
+ ```
243
+
244
+ ### 模式 3:GATE 多条件检查点
245
+
246
+ 多个条件组成的准入门禁,全部通过才放行。
247
+
248
+ ```markdown
249
+ **GATE** 产出前自检(全部通过才放行):
250
+
251
+ - [ ] `06-tdd-log.md` 存在且有效行数 ≥ 5
252
+ - [ ] 每个功能点有 RED → GREEN 序列
253
+ - [ ] `exit_code == 0` && `failures == 0`
254
+ ```
255
+
256
+ ### 模式 4:MATCH 状态分发
257
+
258
+ 根据变量值分发到不同动作。`**MATCH**` 后必须跟反引号变量名。
259
+
260
+ ```markdown
261
+ **MATCH** `result`:
262
+
263
+ - 全部通过 → **DONE**
264
+ - 通过但有 warning → **DONE_WITH_CONCERNS**
265
+ - 验证失败 → 记录失败详情
266
+ - 工具失败 → **BLOCKED**,触发 **H3**
267
+ ```
268
+
269
+ **规则**:`**MATCH**` 后必须跟 `` `变量名` ``(反引号包裹),不用自然语言描述。
270
+
271
+ ### 模式 5:FOR 遍历
272
+
273
+ 遍历集合中的每个元素,对每个执行相同操作。
274
+
275
+ ```markdown
276
+ **FOR** each `feedback_item`:
277
+
278
+ 1. **READ** 实际代码 → 验证技术正确性
279
+ 2. **ASSERT** 验证基于代码证据
280
+ 3. **IF** 技术正确 → 标记待实施
281
+ **ELSE** → 用技术理由推回
282
+ ```
283
+
284
+ ### 模式 6:IF / ELSE 条件
285
+
286
+ #### 条件的两种合法形式
287
+
288
+ | 形式 | 写法 | 适用场景 | 示例 |
289
+ |------|------|---------|------|
290
+ | 反引号 | `**IF** \`expr\`` | 可求值变量/表达式(mode、exit_code、文件是否存在) | `**IF** \`mode == compact\`` |
291
+ | 描述 | `**IF** 描述条件` | 上下文判断、需要人类/LLM 感知的场景 | `**IF** 多组件系统 →` |
292
+
293
+ 描述条件须简短(≤15 字)且可判定。如判定方式不明显,加括号注明:`**IF** 编排模式(任务目录存在)→`
294
+
295
+ #### 守卫 IF vs 分支 IF
296
+
297
+ | 类型 | 形式 | ELSE 要求 | 隐含语义 |
298
+ |------|------|----------|---------|
299
+ | 守卫 IF | `**IF** cond → action`(单行) | 不需要 ELSE | 条件不满足时继续下一步 |
300
+ | 分支 IF | `**IF** cond:` + 缩进子项(多行) | 需要 `**ELSE**` 或 `*default*` | 两条路径都有明确动作 |
301
+
302
+ **守卫 IF**(单行,不需要 ELSE):
303
+
304
+ ```markdown
305
+ **IF** `docs/specs/` 存在 → **WRITE** 合并规格
306
+ ```
307
+
308
+ **分支 IF**(多行,需要 ELSE):
309
+
310
+ ```markdown
311
+ **IF** `mode == compact`:
312
+ - 精简产出,跳过 01-plan 等文件
313
+
314
+ **ELSE**:
315
+ - 完整产出,包含全部 17 个文件
316
+ ```
317
+
318
+ **嵌套形式**(无序列表 + 缩进表达多层条件,最多 2 层):
319
+
320
+ ```markdown
321
+ - `severity == P0` || `severity == P1`
322
+ - `问题在实现层` → **ROUTE** implAgent
323
+ - `问题在规格层` → **ROUTE** specAgent
324
+ - `severity == P2` → 自行修复
325
+ - *default* → 记录但不处理
326
+ ```
327
+
328
+ ### 模式 7:REPEAT 重试
329
+
330
+ 有限次重试,`*repeat exhausted*` 为兜底。
331
+
332
+ ```markdown
333
+ **REPEAT** max=2:
334
+
335
+ 1. 记录失败原因
336
+ 2. 修复 → **EXEC** `verify_cmd`
337
+ - 通过 → **GOTO** Step N
338
+ - 仍失败 → 继续 REPEAT
339
+
340
+ - *repeat exhausted* → **BLOCKED**,触发 **H3**
341
+ ```
342
+
343
+ ### 模式 8:GOTO 跳转
344
+
345
+ 显式跳转到指定 Step/Phase,避免隐式流转。目标必须是当前文件中存在的 `###` 或 `####` 标题名称。
346
+
347
+ ```markdown
348
+ 修复完成 → **GOTO** Step 2(重新执行验证)
349
+ ```
350
+
351
+ ### 模式 9:WRITE 目标区分
352
+
353
+ `**WRITE**` 的目标决定动作类型:
354
+
355
+ | 写法 | 含义 | 示例 |
356
+ |------|------|------|
357
+ | `**WRITE** \`filepath\`` | 写入磁盘文件 | `**WRITE** \`06-tdd-log.md\`` |
358
+ | `**WRITE**(对话中)` | 展示给用户,不写文件 | `**WRITE**(对话中)推荐结果` |
359
+ | `**WRITE** checkpoint` | 更新 checkpoint 状态 | `**WRITE** checkpoint:...` |
360
+
361
+ ### 模式 10:内联守卫
362
+
363
+ 在主指令上附加括号内守卫条件,不影响主指令的后续流:
364
+
365
+ ```markdown
366
+ **EXEC** 创建目录(**IF** 已存在 → 跳过)
367
+ ```
368
+
369
+ 规则:`(**IF** cond → action)` 是附加在主指令上的前置检查。条件不满足时执行 action(通常是"跳过"),然后继续下一条指令。
370
+
371
+ ### 模式 11:条件注解
372
+
373
+ 在 GATE 检查项或指令前标注适用条件,LLM 根据当前上下文选择执行哪段:
374
+
375
+ ```markdown
376
+ - [ ] G1: `[完整模式]` **ASSERT** `01-plan.md` 包含目标澄清
377
+ `[精简替代]` **ASSERT** `03-sdd.md` 包含任务目标
378
+ ```
379
+
380
+ 规则:`[标签]` 方括号注解标记适用条件。同一行的多个注解互斥——根据当前 `mode` 选择匹配的注解段执行。
381
+
382
+ ### 模式 12:多值匹配
383
+
384
+ MATCH 分支条件可用 `||` 合并多个值,匹配任意一个即执行该分支:
385
+
386
+ ```markdown
387
+ **MATCH** `checkpoint.status`:
388
+
389
+ - `DONE` || `DONE_WITH_CONCERNS` → 提示用户任务已完成
390
+ - `BLOCKED` → 触发 **H3**
391
+ - *default* → 恢复执行
392
+ ```
393
+
394
+ ## 形式语法
395
+
396
+ 简化 BNF 参考。不追求 parser-ready,但足够精确地定义每个构造的合法形式。
397
+
398
+ ```bnf
399
+ skill ::= frontmatter section+
400
+ frontmatter ::= '---' NL 'name:' TEXT NL 'description:' TEXT NL '---'
401
+
402
+ section ::= step_heading instruction*
403
+ step_heading ::= '###' step_label ':' title
404
+ step_label ::= 'Step' NUMBER | 'Phase' NUMBER
405
+ substep_heading ::= '####' substep_label ':' title
406
+
407
+ instruction ::= keyword_stmt
408
+ | ordered_list
409
+ | unordered_branch
410
+ | gate_block
411
+ | blockquote
412
+
413
+ (* 关键词语句 *)
414
+ keyword_stmt ::= '**' KEYWORD '**' target action*
415
+ KEYWORD ::= 'READ' | 'WRITE' | 'RESOLVE' | 'EXEC'
416
+ | 'IF' | 'ELSE' | 'MATCH' | 'FOR' | 'REPEAT' | 'GOTO'
417
+ | 'ASSERT' | 'GATE'
418
+ | 'DONE' | 'BLOCKED' | 'NEEDS_CONTEXT' | 'DONE_WITH_CONCERNS'
419
+ | 'ROLLBACK' | 'ROUTE' | 'H3'
420
+ target ::= backtick_expr | write_target | description
421
+ write_target ::= backtick_expr | '(对话中)' | 'checkpoint'
422
+ action ::= '→' keyword_stmt
423
+ | '→' description
424
+
425
+ (* 表达式 *)
426
+ backtick_expr ::= '`' expression '`'
427
+ expression ::= term (logical_op term)*
428
+ term ::= identifier compare_op value
429
+ | identifier existence
430
+ | identifier '.' identifier
431
+ | function_call
432
+ compare_op ::= '==' | '!=' | '>=' | '<=' | '>' | '<'
433
+ logical_op ::= '&&' | '||'
434
+ existence ::= '存在' | '不存在' | '非空'
435
+ function_call ::= identifier '(' string (',' string)* ')'
436
+
437
+ (* 条件 *)
438
+ if_guard ::= '**IF**' condition '→' action (* 单行守卫,无 ELSE *)
439
+ if_branch ::= '**IF**' condition ':' NL body ('**ELSE**' ':' NL body)?
440
+ condition ::= backtick_expr | short_description
441
+ inline_guard ::= '(' '**IF**' condition '→' action ')'
442
+
443
+ (* 分支 *)
444
+ match_block ::= '**MATCH**' backtick_expr ':' NL match_branch+
445
+ match_branch ::= '-' match_pattern '→' action
446
+ match_pattern ::= backtick_expr ('||' backtick_expr)*
447
+ | '*' fallback_label '*'
448
+ fallback_label ::= 'none' | 'default' | 'not found' | 'repeat exhausted'
449
+
450
+ (* 循环 *)
451
+ for_block ::= '**FOR**' 'each' backtick_expr ':' NL body
452
+ repeat_block ::= '**REPEAT**' 'max=' NUMBER ':' NL body NL fallback_branch
453
+
454
+ (* 门禁 *)
455
+ gate_block ::= '**GATE**' description ':' NL checkbox+
456
+ checkbox ::= '- [ ]' (annotation)? assertion
457
+ annotation ::= '[' label ']'
458
+ assertion ::= '**ASSERT**' backtick_expr
459
+
460
+ (* 有序列表 *)
461
+ ordered_list ::= ordered_item+ (* 默认:顺序执行 *)
462
+ resolve_chain ::= '**RESOLVE**' backtick_expr NL ordered_item+ fallback_branch
463
+ (* RESOLVE 引导:优先级链 *)
464
+ fallback_branch ::= '-' '*' fallback_label '*' '→' action
465
+
466
+ (* 非执行 *)
467
+ blockquote ::= '>' TEXT (* WHY / 设计意图,不含关键词 *)
468
+ ```
469
+
470
+ ## 反模式
471
+
472
+ | # | 反模式 | 问题 | 正确做法 |
473
+ |---|--------|------|---------|
474
+ | 1 | 纯段落描述条件逻辑 | LLM 需"读懂段落"才能提取分支 | 用 `**IF**` / `**MATCH**` + 缩进分支 |
475
+ | 2 | 指令动词不加粗大写 | 动词淹没在句子中,无法扫描 | 所有指令动词用 `**全大写粗体**` 标记 |
476
+ | 3 | 优先级链无兜底 | 所有选项都不命中时行为未定义 | 末尾加 `*none*` → 兜底动作 |
477
+ | 4 | ASSERT 无表达式 | "确认测试通过"不可机械验证 | `**ASSERT** \`exit_code == 0\` && \`failures == 0\`` |
478
+ | 5 | 状态声明用自然语言 | "任务完成"歧义——完成还是有保留? | 用四态关键词:`**DONE**` / `**DONE_WITH_CONCERNS**` / ... |
479
+ | 6 | 引用块中含执行指令 | 违反约定 #8(引用块=WHY) | 执行指令移出引用块,引用块仅保留设计意图 |
480
+ | 7 | MATCH 后跟自然语言 | LLM 无法提取待匹配变量 | `**MATCH**` 后必须跟 `` `变量名` `` |
481
+ | 8 | MATCH 分支用 emoji 做标识符 | emoji 与关键词语义重复,LLM 可能匹配 emoji 而非文本 | 分支用文本描述,状态用关键词(`**DONE**` 等) |
482
+ | 9 | 超过 2 层嵌套未提取子步骤 | LLM 丢失层级追踪,解析出错 | 3 层以上嵌套提取为命名子步骤(`####`),用 `**GOTO**` 连接 |
483
+ | 10 | MATCH 缺少兜底且未穷尽枚举 | 未覆盖的值 = 未定义行为 | 提供 `*default*` 兜底或枚举全部值域 |
484
+ | 11 | EXEC 后跳过 exit_code 检查 | "执行了"≠"执行成功" | `**EXEC**` 后必须 `**ASSERT** \`exit_code == 0\`` 或说明无需检查的理由 |
485
+ | 12 | 编排级 ROUTE 无提示模板 | 目标 skill 缺少执行上下文 | 编排器调度子 skill 时,`**ROUTE**` 后跟代码块提示模板。MATCH 内简单路由可省略 |
@@ -6,42 +6,40 @@
6
6
 
7
7
  ```
8
8
 
9
- 1. 确定验证命令(按优先级从高到低获取):
9
+ 1. 确定验证命令(优先级从高到低):
10
10
  - 05-risk.md §一验证计划
11
- - CLAUDE.md / .cursor/rules/ 中的测试命令
12
- - package.json scripts / Makefile / Cargo.toml 中的 test/lint 脚本
13
- - 以上均无 → 状态标记为 NEEDS_CONTEXT,请求用户提供验证命令
14
- - 如果项目无测试/lint/CI 命令:在 10-test-report.md 中标注「项目无自动化验证命令」,改用手动验证(截图、curl 输出、日志对比等可复现证据),不可跳过验证
15
- 2. 执行命令——不使用缓存结果,不引用上一轮输出
16
- 3. 完整阅读输出——不截断,不跳过 warning
17
- 4. 检查退出码 = 0 且失败数 = 0
18
- 5. 只有全部通过才可声明通过,否则记录失败详情
11
+ - CLAUDE.md / .cursor/rules/
12
+ - package.json scripts / Makefile / Cargo.toml
13
+ - 以上均无 → NEEDS_CONTEXT,请求用户提供
14
+ - 项目无自动化验证 10-test-report.md 标注,改用手动验证(截图/curl/日志对比),不可跳过
15
+ 2. 执行命令——不用缓存,不引用上一轮输出
16
+ 3. 完整阅读输出——不截断,不跳过 warning。Warning 处理:退出码 = 0 时 warning 不阻塞通过声明,但必须在验证报告中列出 warning 内容供人类判断
17
+ 4. 退出码 = 0 且失败数 = 0
18
+ 5. 全部通过 → 声明通过。存在失败 → 记录详情,定位根因,修复或路由到对应 Agent,从步骤 2 重新执行完整验证。不可跳过失败项——违反 Rule #2
19
19
 
20
20
  ```
21
21
 
22
- 违反此协议的声明视为无效,reviewAgent MUST 标记为 P0 问题。
22
+ 违反此协议的声明视为无效,reviewAgent MUST 标记为 P0
23
23
 
24
- ## 结构化证据要求
24
+ ## 结构化证据格式
25
25
 
26
- 验证声明必须包含以下结构化证据,直接粘贴到 06-tdd-log.md 或 10-test-report.md 中:
26
+ 验证声明须包含以下证据,粘贴到 06-tdd-log.md 或 10-test-report.md
27
27
 
28
28
  ```
29
29
  验证命令:{实际执行的命令}
30
- 退出码:{$? 的值}
31
- 输出摘要:{粘贴最后 10 行输出,包含 pass/fail 统计}
30
+ 退出码:{$?}
31
+ 输出摘要:{最后 10 行,含 pass/fail 统计}
32
32
  判定:✅ 通过 / ❌ 失败
33
33
  ```
34
34
 
35
- "测试通过"但无法给出退出码和输出行的声明视为未验证。
35
+ 无退出码和输出的"测试通过"声明 = 未验证。
36
36
 
37
37
  ## 工具失败恢复
38
38
 
39
- 验证命令执行失败(超时、进程崩溃、环境错误)时:
40
-
41
39
  1. 记录失败原因和错误输出
42
- 2. 尝试修复环境问题后重新执行(最多 2 次)
43
- 3. 仍然失败状态标记为 BLOCKED,触发 H3 由人类决定下一步(跳过该验证项意味着状态不可为 DONE,只能为 DONE_WITH_CONCERNS)
44
- 4. 不可将"工具失败"等同于"验证通过"
40
+ 2. 修复环境后重试(最多 2 次)
41
+ 3. 仍失败 → BLOCKED,触发 H3(状态不可为 DONE,只可 DONE_WITH_CONCERNS)
42
+ 4. "工具失败""验证通过"
45
43
 
46
44
  ## Iron Law
47
45
 
@@ -51,9 +49,9 @@ NO COMPLETION CLAIMS WITHOUT FRESH VERIFICATION EVIDENCE
51
49
 
52
50
  ## 常见失败模式
53
51
 
54
- | 声明 | 需要 | 不充分 |
55
- | ---- | ---- | ------ |
56
- | 测试通过 | 测试命令输出:0 failures + 退出码 0 | 上一轮运行、"应该能过"、无退出码 |
57
- | Lint 干净 | Lint 输出:0 errors + 退出码 0 | 部分检查、推测、只看最后一行 |
58
- | 构建成功 | 构建命令:exit 0 + 无 error 输出 | Lint 通过、日志看起来对 |
59
- | Bug 修复 | 测试原始症状:通过 + 回归测试通过 | 代码改了、假设修好了 |
52
+ | 声明 | 充分证据 | 不充分 |
53
+ | ---- | -------- | ------ |
54
+ | 测试通过 | 0 failures + 退出码 0 | 上一轮运行、"应该能过" |
55
+ | Lint 干净 | 0 errors + 退出码 0 | 部分检查、推测 |
56
+ | 构建成功 | exit 0 + 无 error | Lint 通过、日志看起来对 |
57
+ | Bug 修复 | 原始症状通过 + 回归通过 | 代码改了、假设修好了 |