# 任务板协议 v1

## 1. 工作单字段（YAML front-matter）

| 字段 | 必填 | 含义 |
|---|---|---|
| `id` | ✅ | `WO-YYYYMMDD-NNN`，与文件名一致 |
| `title` | ✅ | 一句话说明要交付什么 |
| `state` | ✅ | proposed / accepted / working / review / done / rejected |
| `requester` | ✅ | 派单方 |
| `owner` | ✅ | 当前负责推进的人/agent |
| `priority` | ✅ | P0 紧急 / P1 高 / P2 普通 / P3 低 |
| `created_at` / `updated_at` | ✅ | ISO-8601 时间戳 |
| `idempotency_key` | ✅ | 全局唯一；同一键重发不重复执行 |
| `human_approval` | ✅ | required / granted / not_required |
| `budget_minutes` | ✅ | 允许投入的最大分钟数 |
| `budget_tokens` | ✅ | 允许投入的最大 token 预算（0=不限） |

## 2. 状态机

```
proposed ──→ accepted ──→ working ──→ review ──→ done
    │            │           │          │
    │            │           │          └──→ working（验收不过，返工）
    │            │           └──────────────→ rejected（阻塞且无法继续）
    │            └───────────────────────────→ rejected
    └────────────────────────────────────────→ rejected
```

- **done** 必须同时有非空的「交付记录」和「验收记录」。
- **rejected** 必须有「退回原因」。
- 不允许 `proposed → done`、`accepted → done` 这种“跳关”。

## 3. 幂等与预算

- `idempotency_key` 全仓唯一，格式：小写字母/数字开头，可含 `._:-`。
- 收到重复通知时先查幂等键：已存在同键工作单，就只更新日志，**不得重复执行**。
- 达到 `budget_minutes` 或 `budget_tokens` 后必须停下并说明：继续、缩减范围，还是退回。
- `budget_tokens: 0` 表示不限；分钟数必须大于 0。

## 4. 人工批准

- `required`：有副作用，批准前只能调查/写草案，不能执行。
- `granted`：已获批准，必须在正文「授权记录」写明谁、何时、原话。
- `not_required`：只读、内部文件、可逆且无外部影响的操作。

## 5. 验收标准

验收标准必须**可观察、可复跑**，避免“优化一下”“弄好一点”。

好例子：
- `python3 scripts/board.py validate` 输出 `OK: N 单通过`。
- 打开 `index.html` 可见 6 个状态列，且每单有幂等键与负责人。

坏例子：
- 页面更漂亮。
- 协作更顺畅。

## 6. 交付与退回

### 交付记录
写实际产物路径、命令输出、版本号、截图或链接；不能只写“已完成”。

### 验收记录
由验收方逐条引用验收标准，并写证据。**执行者不能替验收方签字。**

### 退回原因
写清缺什么、为什么、怎样重提；退回后可在新工作单引用原幂等键加 `-r2` 后缀。
