# 需求工单工作流（Feature Request Workflow）

## 为什么有这份文档

本团队采用 AI-first 开发，团队成员（宏伟、立健等）不只是"接需求 → 写代码"，而是要**自己理解业务、自己设计产品、自己实现**。所以需求不能直接派活——必须走一个**强制的"产品脑训练"流程**：业务问题 → PRD → 契约 → 实现 → 验收。

工单（Gitea issue）是这套流程的**唯一载体**。状态、负责人、产出物、卡点全部挂在工单上。

> 适用范围：所有"新功能 / 新模块 / 业务规则变更"类需求。
> 不适用：Bug 修复（直接走 hotfix）、文档/规范修订（直接 PR）、运维任务（用对应 skill）。

---

## 角色

| 角色 | 职责 |
|---|---|
| **需求提出人**（业务方 / 产品 / 老板） | 提工单。**只描述业务问题，不写解法**。 |
| **负责人**（assignee，如宏伟/立健） | claim 工单，自己走 PRD → 契约 → 实现 → 验收的完整链路。 |
| **审批人**（chentao.jia） | review PRD 是否抓住业务本质，review 契约是否足够支撑实现。**不替负责人想方案**。 |

---

## 工单生命周期（状态机）

```
[需求待澄清] → [PRD 中] → [契约设计中] → [开发中] → [待验收] → [关闭]
       ↓             ↓              ↓             ↓            ↓
    claim         审批人 ✅      doc-review    PR merge    L3 验收 ✅
    assignee     PRD 通过        通过           +L1 过     i18n 双语过
```

每个状态对应一个 Gitea label（`Status/*`），同一时刻一个工单**只能有一个 Status label**。

**辅助状态**（不在主流程，按需叠加）：

- `Status/Blocked`（已存在）：被外部依赖卡住时叠加在当前 `Status/*` 上，评论里写明卡在什么。
- `Status/Need More Info`（已存在）：需求提出人需要补充信息时叠加。
- `Status/Abandoned`（已存在）：负责人放弃，工单不关闭但停止推进，等待新负责人 claim。

### 状态 1：`Status/需求待澄清`

- **触发**：需求提出人按 `.gitea/ISSUE_TEMPLATE/feature-request.md` 提单。
- **产出**：业务问题 + 业务方 + 期望效果三段填完。
- **卡点**：
  - 标题不允许写解法（"加个按钮" / "做个页面" 都拒绝）
  - 期望效果不允许写 UI/字段描述，必须是"用户能做到什么"
- **流转**：负责人 claim（设 `assignee = 自己`，详见 [`17-gitea-issue-handling.md`](./17-gitea-issue-handling.md)）→ 切到 `Status/PRD 中`（按需贴 `Owner/*` label）。

### 状态 2：`Status/PRD 中`

- **触发**：负责人接单。
- **动作**：负责人在 slot 里跑 `plan-feature` skill，产出 `docs/modules/{module}/01-prd.md`。
- **产出**：PRD 文档 + PR（仅文档改动）。
- **审批人 review 重点**（只问，不替对方答）：
  1. **业务方的真正痛点是什么**？（逼负责人回到 why）
  2. **为什么是这个方案，不是别的**？（逼对方想 alternatives 并淘汰）
  3. **什么情况下这个功能反而是负担**？（逼对方想边界 / 反例 / 不做什么）
- **卡点**：审批人未在 PRD PR 上留 ✅ 评论，不允许切到下一状态。
- **流转**：PRD PR merge + 审批人 ✅ → 切到 `Status/契约设计中`。

### 状态 3：`Status/契约设计中`

- **触发**：PRD 通过。
- **动作**：负责人按需补：
  - `06-data-model.md`（涉及 schema 变更必填）
  - `07-api.md`（涉及 API 必填）
  - `05-ui-interaction-spec.md`（涉及前端必填）
  - `04-state-machine.md`（涉及状态机必填）
- **强制检查**：跑 `doc-review` skill，确认"文档够不够支撑实现"。
- **卡点**：`doc-review` 未通过 / 缺关键契约文档 → 不允许动代码。
- **流转**：契约文档 PR merge + `doc-review` 通过 → 切到 `Status/开发中`。

### 状态 4：`Status/开发中`

- **触发**：契约通过。
- **动作**：负责人 `start-feature` 进 slot → `contract-check` → 实现 → L1 集成测试。
- **卡点**：L1 未过不允许提 PR。
- **流转**：PR 合 develop → 切到 `Status/待验收`，工单回填 PR 链接。

### 状态 5：`Status/待验收`

- **触发**：代码已合 develop（或部署到 UAT）。
- **动作**：负责人在工单评论里列**本次开发的可验证项**（不依赖 `10-e2e-test-spec.md`，从 git diff 提取），含 i18n 双语验证。
- **审批人 / 业务方**：按清单逐项过。
- **流转**：清单全部 ✅ → 关闭工单。

---

## 派活原则

### 1. 优先让负责人自己 claim，不要硬派

需求提出人在工单里 `@hongwei.zhang @lijian.dai` 问"这个谁接？"，让他们自己抢。原因：

- 培养主动性（产品意识的一部分是"主动判断这事归不归我"）
- 避免提出人成为分活瓶颈
- 抢不下来的（都说没空）说明优先级排序有问题——这是有用信号，不是问题

硬派只用在两个场景：① 工单 ≥ 2 个工作日没人 claim ② 明确需要某人的领域知识。

### 2. 一个工单只能有一个 assignee

Gitea 支持多 assignee，但本团队不用——**所有权要清晰**。多人协作的工单拆成多个子工单，每个独立负责人。

### 3. 接单事实源 = `assignee`；Owner label 是辅助

工单是否被接，**唯一事实源是 `assignee` 字段**——任何 label（`Status/*` / `Owner/*` / `Status/待领取`）都不能代替。详见 [`17-gitea-issue-handling.md`](./17-gitea-issue-handling.md) §「核心规则」。

claim 时**必做**：

- 设 `assignee = 自己`

claim 时**按需补**（看板视图优化，不补也算接走）：

- 贴 `Owner/Hongwei` / `Owner/Lijian` / `Owner/Chentao` —— 方便按 label 做"看板分组"
- 进入 PRD 阶段时切 `Status/PRD 中`

若工单原本贴了 `Status/待领取`，接走时顺手清掉，避免看板视图矛盾。

### 4. 标题永远写"是什么"，不写"谁做"

不允许 `[宏伟] xxx` / `[立健] xxx`——assignee + Owner label 已经表达了。理由：

- 改派时要改标题，容易漏，commit 历史里全是噪音
- 标题进 PR title / commit message 后跟代码一辈子，没必要

---

## 优先级排序

工单必须有且只有一个 `Priority/*` label：

| Label | 含义 | SLA |
|---|---|---|
| `Priority/Critical` | 阻塞业务，必须立刻做 | 当天进入 PRD 中 |
| `Priority/High` | 重要，本周交付 | 本周内 |
| `Priority/Medium` | 计划内，本月交付 | 本月内 |
| `Priority/Low` | 有空再做 | 无承诺 |

需求提出人在模板里**给建议**，最终优先级由审批人 + 负责人讨论后决定。

---

## 看板视图（建议在 Gitea 上保存的 filter）

| 视图 | filter |
|---|---|
| 我的工单 | `is:open assignee:@me` |
| 待 review（PRD） | `is:open label:"Status/PRD 中"` |
| 进行中 | `is:open label:"Status/开发中"` |
| 等我验收 | `is:open label:"Status/待验收"` |
| 宏伟的活 | `is:open label:"Owner/Hongwei"` |
| 立健的活 | `is:open label:"Owner/Lijian"` |
| 紧急 | `is:open label:"Priority/Critical","Priority/High"` |

---

## 与现有 skills 的对应关系

工单状态机 = skill 流程的外化。负责人照工单走，AI 照 skill 走，两边咬合：

| 工单状态 | 对应 skill |
|---|---|
| 需求待澄清 → PRD 中 | `plan-feature` |
| PRD 中 | `plan-feature`（产出 PRD）+ `doc-review`（PRD 实现就绪度） |
| 契约设计中 | `database-main` / `docs-main` / `doc-review` |
| 开发中 | `contract-check` → `start-feature` → `backend-main` / `frontend-main` → `test-backend` / `test-frontend` |
| 待验收 | `test-main`（L2/L3）|

---

## 反模式（别这样做）

| 反模式 | 为什么不行 |
|---|---|
| 工单标题写解法（"加个 quota 进度条"）| 锁死了方案，剥夺负责人产品思考的机会 |
| 跳过 PRD 直接写代码 | 培养产品意识的核心环节，**必须**经过 |
| 审批人在 PRD review 时直接给方案 | 你给一次，下次他还是想不清楚——只问问题，不替他想 |
| 多人 assignee | 所有权稀释，出了问题没人负责 |
| 标题带人名前缀 | 改派 / 历史噪音 / commit 污染 |
| 工单一直停在 `Status/开发中` 几周没动 | 缺乏阶段切换 → 没人发现卡住了。被外部依赖卡住的，叠加辅助 label `Status/Blocked` 显式标记 |
| 关闭工单时没补验收清单 | 下次类似需求没法复用 |

---

## 前置：Gitea label 初始化

本工作流依赖以下 label 已在 Gitea 仓库上存在（本仓库 `FFAIWorkspace/workspace` 已创建完毕；新仓库或 label 被误删时按下表补建）：

| Label | 颜色 | 说明 |
|---|---|---|
| `Status/需求待澄清` | `#fef3c7` | 工单刚提，待补业务问题/业务方 |
| `Status/PRD 中` | `#fcd34d` | 正在撰写 PRD，等待 review |
| `Status/契约设计中` | `#f59e0b` | 补数据模型 / API / UI 契约 |
| `Status/开发中` | `#3b82f6` | 已进入实现阶段 |
| `Status/待验收` | `#8b5cf6` | PR 已合并，等待人工 L3 验收 |
| `Owner/Hongwei` | `#1f6feb` | 负责人：hongwei.zhang |
| `Owner/Lijian` | `#0e7490` | 负责人：lijian.dai |
| `Owner/Chentao` | `#5b21b6` | 负责人：chentao.jia |

Gitea 内置已有的 `Priority/Critical|High|Medium|Low`、`Kind/Feature`、`Status/Blocked` 等直接复用。

补建方式（API 单条创建示例）：

```bash
GITEA_TOKEN="${GITEA_API_TOKEN}"
curl -X POST -H "Authorization: token $GITEA_TOKEN" -H "Content-Type: application/json" \
  http://43.130.59.228/api/v1/repos/FFAIWorkspace/workspace/labels \
  -d '{"name":"Status/需求待澄清","color":"fef3c7","description":"工单刚提"}'
```

---

## 制度演进

这套工作流是起点不是终点。运行过程中如发现：

- 某个状态长期空挂（没人用）→ 简化
- 某个状态频繁卡住 → 加自动化提醒
- 某类工单不适合走完整流程（如纯 UI 微调）→ 加快速通道（如 `Kind/Enhancement` + `Priority/Low` 跳过 PRD）

修订时同步更新本文档 + `.gitea/ISSUE_TEMPLATE/feature-request.md`，两份保持一致。
