端点清单
| 方法 | 路径 | 说明 | 触发的 Loop |
|---|---|---|---|
POST | /api/devloop/projects | 创建项目,传入初始需求 | L3 启动 |
POST | /api/devloop/projects/:pid/requirement | 追加人类反馈,触发 PRD 增量更新 | L3 |
POST | /api/devloop/projects/:pid/run | 启动 / 续跑 LoopController | L1 + L2 |
GET | /api/devloop/projects/:pid/state | 返回 units.json + 当前 loop 阶段 | UI 轮询 |
GET | /api/devloop/projects/:pid/stream | SSE — 实时推送 Agent 输出 / 状态变更 | UI 流式 |
POST | /api/devloop/projects/:pid/sign-off | 人类显式 sign-off,状态置 shipped-final | L3 终止 |
POST | /api/devloop/projects/:pid/abandon | 放弃项目(保留数据,从列表移除) | L3 终止 |
Request / Response 示例
# 创建项目 # 严格按 CLAUDE.md 警告:先写 /tmp/req.json,再 -d @file curl -X POST http://localhost:3010/api/devloop/projects \ -H "Content-Type: application/json" \ -d @/tmp/create.json # /tmp/create.json — 单行紧凑 {"company_id":"c-lemonv-001","name":"Auto Auth System","requirement":"需要一个邮箱密码登录的系统"} # 响应 { "project_id": "p-731042", "status": "prd_drafting", "stream_url": "/api/devloop/projects/p-731042/stream" }
# 追加新需求 curl -X POST http://localhost:3010/api/devloop/projects/p-731042/requirement \ -H "Content-Type: application/json" \ -d @/tmp/feedback.json # /tmp/feedback.json {"text":"再加 GitHub OAuth","origin":"yibo"} # 响应(即刻返回,PM 是异步跑) { "accepted": true, "queued_rev": 3, "eta_seconds": 30 }
# 查询状态 curl http://localhost:3010/api/devloop/projects/p-731042/state { "project_id": "p-731042", "prd_rev": "3", "sdd_rev": "5", "current_loop": "L1", "units": [ { "id": "auth-be", "status": "passed" }, { "id": "auth-fe", "status": "testing" }, { "id": "oauth-be", "status": "pending" } ], "l2_rounds": 0, "l2_budget": 3, "agents_active": ["tester:auth-fe"] }
# SSE 流(浏览器或 curl --no-buffer)
curl -N http://localhost:3010/api/devloop/projects/p-731042/stream
event: unit.state
data: {"unit_id":"auth-fe","from":"coding","to":"testing"}
event: agent.stream
data: {"agent":"tester","unit_id":"auth-fe","chunk":"PASS tests/login.spec.ts > valid creds\n"}
event: agent.stream
data: {"agent":"tester","unit_id":"auth-fe","chunk":"FAIL tests/login.spec.ts > invalid pwd\n"}
event: unit.state
data: {"unit_id":"auth-fe","from":"testing","to":"failed","retries":1}
event: prd.updated
data: {"rev":4,"changeSummary":"+ NFR: session timeout 1h"}
routes/devloop.js 骨架
// server/routes/devloop.js · NEW · ~200 行 const express = require('express'); const { loopController } = require('../src/core/loop-controller'); const { docStore } = require('../services/doc-store'); const { unitRegistry } = require('../services/unit-registry'); const { sseBroker } = require('../services/sse-broker'); const router = express.Router(); router.post('/projects', async (req, res) => { const { company_id, name, requirement } = req.body; const pid = await loopController.createProject({ company_id, name }); loopController.onHumanFeedback(pid, { text: requirement, origin: req.user?.id }); res.json({ project_id: pid, status: 'prd_drafting', stream_url: `/api/devloop/projects/${pid}/stream` }); }); router.post('/projects/:pid/requirement', async (req, res) => { loopController.onHumanFeedback(req.params.pid, req.body); res.json({ accepted: true }); }); router.get('/projects/:pid/state', (req, res) => { res.json(loopController.getState(req.params.pid)); }); router.get('/projects/:pid/stream', (req, res) => { sseBroker.subscribe(req.params.pid, req, res); }); module.exports = router;
挂载到 server/index.js
仅 1 行改动:
// server/index.js 第 90 行后追加 app.use('/api/devloop', require('./routes/devloop'));
认证
沿用 routes/auth.js 的 JWT 中间件:
- POST 类端点:必须带
Authorization: Bearer <jwt>,校验req.user.company_id与 path 中的 cid 匹配。 - GET state / stream:同上。
- Open API 调用(无人类 cookie,纯 server-to-server):使用现有的
OPEN_API_KEYS环境变量 +X-API-Keyheader。
初版不做 RBAC(任何登录用户都能创建项目)。多用户隔离靠 cid。这是已知简化,P5 再加。