---
name: spec-role-contract
description: 技术方案文档的角色契约。把作者 / 实施者 / 验证者三个文档生命周期位置写成显式参数，规定每个位置的可做与不可做，并用落盘的角色记录让边界可核验。与模型品牌解耦——换模型不改变角色边界，同一模型跑不同角色也照样受约束。用于"这份文档现在归谁负责、谁不能做什么"的判定。
disable-model-invocation: true
---

# 文档生命周期角色契约

原件库的技能按**任务**分工（research / review / implement），不按**文档生命周期位置**分工。所以"作者不能自己批准方向""实施者不能改方向""验证者要对照文档而不是对话"这些约束,没有任何一个技能在管。

这个技能管。它不分配模型,只声明位置和边界。

## 三个位置

| 位置 | 负责 | 明确不能做 |
| --- | --- | --- |
| **author** 作者 | 写 `TECH.md`、补研究、接外部草稿 | **不自我批准方向**。草稿的作者不能同时是批准方向的人 |
| **implementer** 实施者 | 按已批准文档写实现 | **不改方向**。发现方向有问题必须回到 `spec-direction-gate`,不能自己改 |
| **verifier** 验证者 | 对照文档验收 | **不对照对话验收**。判定依据是 `TECH.md` 本身,不是"当初说过什么" |

这三个位置可以由同一个模型担任,但**不能由同一次会话兼任 author 和 verifier**。这是唯一不可让步的一条。

## 硬性约束

1. **角色是显式参数,不是隐含的会话假设。** 每一格都要显式声明当前是谁在做。默认角色是 author。
2. **不绑定模型品牌。** 0036 第 110 行已记录"固定模型品牌也没有成为必要条件"。角色边界与用哪个模型无关,反过来也一样。
3. **验证者必须新会话。** 沿用 0035 第 3.2 节已定做法。这条是硬约束,理由见下。
4. **边界靠落盘记录核验,不是靠自觉。** 角色写进 `specs/<id>/ROLE.md`,验收时读文件。

## 为什么验证者必须换会话

author 在写文档时看过所有的权衡、放弃过的方案、对问题的理解。带着这些上下文去验收自己的实现,等于用出题人的答案去判卷。0035 缝二的判断在这里成立:**skill 只能告诉你"这一格跑什么",保证不了"不是同一个会话"**。

需要说清楚的是,库里现有的跨会话机制**不是**会话隔离。`planning-with-files` 靠的是磁盘上的持久 markdown 文件——它能让你在第二次会话里恢复上下文,但它恢复的恰恰是 author 的上下文。恢复得越顺,污染越彻底。所以本技能不依赖它做隔离,只依赖它做持久化;隔离由"换会话"这个动作本身承担。

`code-review` 的并行 sub-agent 是另一个可借的机制:它把 Standards 和 Spec 两条轴分开跑以免互相污染。author 与 verifier 需要的正是这类隔离,只是要跨会话而不是跨 sub-agent。

## 流程

### 第 1 步：声明角色

开工前写明本次是谁在做。落盘到 `specs/<id>/ROLE.md`：

```markdown
# Roles

| 位置 | 谁 | 会话 | 状态 |
| --- | --- | --- | --- |
| author | <名字 / 模型> | <会话标识> | 进行中 |
| implementer | <名字 / 模型> | <会话标识> | 未开始 |
| verifier | <名字 / 模型> | <会话标识> | 未开始 |

## Boundaries

- author 不得批准方向。方向批准由 `spec-direction-gate` 在独立的确认中记录。
- implementer 不得改方向。发现方向错误时回到 `spec-direction-gate`。
- verifier 不得与 author 同会话。验收依据是 `TECH.md`,不是对话。
```

### 第 2 步：按角色约束自己

每次要做的动作先过一遍上表的"明确不能做"。越界了不执行,改走正确路径。

最常被踩的一条:实施中发现了文档里写错的东西。**改文档不等于改方向**——补充实现细节、补行级引用、更新验证方式都属于实施者的合法范围;换了方案、改了目标、改了非目标,才是改方向,必须回关卡。

### 第 3 步：交接时更新状态

从一个位置换到下一个位置时更新 `ROLE.md` 的状态,并记录会话标识换了。

verifier 那一行的会话标识必须与 author 不同。这一栏是 `## Boundaries` 唯一可被机器检查的证据,空着或相同都算违规。

### 第 4 步：验收时核验

verifier 开跑前先读 `ROLE.md` 和 `TECH.md`:

- `TECH.md` 的 `## Approval` 段存在且方向为"通过"——否则没有可验收的批准状态,返回未批准
- `verifier` 与 `author` 不同会话——否则验收结论作废,要求换会话重来
- 判定依据只能是 `TECH.md`。对话里"当时说过以 X 为准"不构成依据

## 机械检查

上面的约束是文字。同目录的 `check-roles.py` 检查其中唯一能靠文件证伪的一条——**verifier 与 author 是否同会话**：

```bash
python3 check-roles.py specs/<id>/ROLE.md
```

退出码 `0` = 边界可核验；`1` = 违规；`2` = 用法错误。被挡住的情况：

- `ROLE.md` 不存在，或没有角色表
- 三个位置没声明全
- 谁或会话标识是占位符（`TBD`、`—`、`未开始填写` 等不算）
- **verifier 与 author 同会话**
- `## Boundaries` 里没写明那条会话隔离规则

**这个脚本的能力边界要说清楚**：它读的是 `ROLE.md` 里声明的会话标识，所以一张写错的表能通过它。它防的是常见的手误——复制角色块时忘了改会话——不是证明隔离真的发生过。真实隔离由"换会话"这个动作承担，脚本只是让漏改的那次露出来。

## 交接给已有技能

本技能不重写任何已有能力,只声明边界。实际动作交给:

- author → `write-tech-spec`（写文档）/ `spec-draft-intake`（接外部草稿）
- 方向批准 → `spec-direction-gate`
- implementer → `implement-specs`
- verifier → `validate-changes-match-specs`（逐条 mismatch）

## 验收用例

- author 试图在同一会话批准自己的方向 → 必须拒绝,要求走 `spec-direction-gate`
- implementer 发现方向错误后直接改文档 → 必须拒绝,改文档与改方向要分开判定
- verifier 与 author 同会话 → 验收结论作废,要求换会话
- 换模型但角色不变 → 边界不变,继续生效
- 同一模型换会话承担 verifier → 边界照常生效
