# L3 · Human Feedback Loop
> 最外层。接收人类的新需求 / 反馈 / 否决,把它**合并进 PRD**,再让 Architect 重算 SDD diff,仅对增量 Unit 触发 L1 + L2。
## 状态机
## 触发渠道
#### ① REST
`POST /api/devloop/projects/:pid/requirement`
JSON body 走 CLAUDE.md 推荐的 `-d @/tmp/req.json` 方式。
#### ② Web UI
DevLoopDashboard 右上角 + NEW REQUIREMENT,弹出 textarea。
#### ③ 自动信号
L1 `blocked` 或 L2 `exhausted` 时,LoopController 主动发 SSE,由前端弹「请补充信息」对话框。
## 增量 Unit 算法
Architect 对比新旧 `units.json`,标记三种变化:
| 变化类型 | 判断 | 处置 |
| --- | --- | --- |
| **added** | 新 unit.id 不在旧 list | status = pending,加入 L1 队列 |
| **changed** | 同 id,`contract_hash` 变化 | status 回退到 pending,加入 L1 队列(旧代码归档到 `history/`) |
| **removed** | 旧 id 不在新 list | 整个 unit 目录归档到 `history/removed/`,从 DAG 摘除 |
| **unchanged** | id 在且 hash 不变 | 保持 passed,**无须重跑**。这是增量化的关键 |
## PRD 增量合并示例
PM Agent 不重写整个 PRD,只追加 `
`,并维护 doc 级 `data-rev` 自增。这样人类能直观看到「这一轮反馈引入了什么」。
```js
用户名密码登录,会话 7 天有效
个人主页:显示用户名 / 邮箱
```
```js
...
...
+ 新增:支持 GitHub OAuth 登录
+ NFR:3rd-party token 刷新 ≤ 5s
```
## 什么时候算「项目结束」
L3 没有自动退出条件。结束信号来自人类的显式动作:
- **显式 sign-off:**`POST /api/devloop/projects/:pid/sign-off` → 项目 status 置 `shipped-final`,停止接收新需求。
- **归档:**30 天无人类反馈,自动归档但保留所有产物。
- **放弃:**`POST .../abandon`,整个项目目录加 `.abandoned` 标记,从 Dashboard 列表移除。