- 零第三方依赖,Node >=20 原生 ESM - 团队式编排引擎:拆解/路由/执行/审查/合并全真实 LLM - 阶段心跳、单一权威清单守卫、all-keys-failed 如实上报 - H4 会话视图/amend/watchdog 有界重试/产物区 artifacts.json - H5 零依赖三栏控制台
16 KiB
16 KiB
众测任务创建表单内容
① 众测框架选择
选择:云端 Claude Code
② 任务标题
调度网关 P0 生产化基线加固(状态机/Repository/幂等/取消/死信/回调/事件/健康检查/测试,共11项任务)
③ 首轮 Prompt
你正在参与 scheduler-gateway-epoch 6.0.0 的第一阶段 P0 生产化基线开发。
## 项目背景
这是一个 DSH 调度网关:中心网关 + 任务队列 + 节点协议(gw-node/1)+ 真实 LLM 多智能体编排(planner→workers→reviewer→merger)。当前是可演示、可验收的单机原型,需要工程化加固为可长期运行、可恢复、可审计的执行平台。
项目特点:Node.js >= 20,原生 ESM,零第三方运行时依赖。
## 必读文件
开工前必须先阅读以下文件,确认现有行为后再修改:
- README.md — 项目总览与快速开始
- ARCHITECTURE.md — 架构与协议
- IMPLEMENTATION.md — 实现细节与验证方式
- ADR.md — 关键决策记录
- PHASE-1-UNIFIED-TASK.md — 完整任务书(你的主要参考)
- src/server.js — HTTP 网关、节点协议、任务 API
- src/store.js — 任务/节点/审计/事件存储
- src/scheduler-core.js — 调度、领取、结算、重试、死信
- src/protocol.js — 状态常量、节点协议、鉴权
- src/wal.js — JSONL WAL
## 技术约束(必须遵守)
1. Node.js >= 20,原生 ESM,零第三方运行时依赖
2. 保持现有 API 兼容,不破坏既有接口语义
3. 保持 REAL/OFFLINE/fixture 诚实标记
4. 不得泄漏任何密钥(key/token/password/secret)
5. 不得修改 归档-*、out、work、evidence 中已有历史产物
6. 不得通过任意 task.state = ... 绕过状态机
7. 不得通过放宽断言、增加无限重试、忽略异常来制造全绿
8. 新增模块优先放在 src/domain、src/application、src/adapters、src/platform
9. 先包裹旧实现,再逐步迁移调用方;不要一次性重写 server.js 或 orchestrate.js
## 需要完成的 11 个任务
### 任务 A:任务状态机
新增 src/domain/task-state-machine.js:
- 定义当前任务所有合法状态和迁移(queued/running/done/succeeded/failed/dead/rework/waiting_approval/canceled)
- 提供 canTransition(from, to)、transition(task, to, context) 等接口
- 迁移失败抛出稳定错误码 INVALID_STATE_TRANSITION
- 迁移时追加历史记录(操作者/原因/时间/attemptId/requestId)
- 将 server.js、store.js、scheduler-core.js 中直接修改状态的关键路径迁移到状态机
- 重复 settle、过期 lease settle、已取消任务回报等场景必须拒绝或转为幂等成功
### 任务 B:Repository 抽象
新增 src/domain/repositories.js + src/adapters/storage/file-repository.js:
- 至少抽象任务、节点、事件、审计、死信和产物索引访问
- 现有 GatewayStore 可作为兼容实现,但业务服务不得继续依赖 Map 的内部结构
- 保留 persist:false 的干净内存测试模式
- 保留现有 JSON 落盘和 WAL 能力
- Repository 方法必须区分"找不到""冲突""非法状态""存储失败"
- 为未来 SQLite/PostgreSQL 实现保留异步接口
### 任务 C:幂等键和租约
- 创建任务支持 Idempotency-Key;重复请求返回同一任务
- claim 生成唯一 leaseId,记录 leaseExpiresAt、nodeId、attemptNo
- settle 必须校验 lease;重复提交同一 leaseId + 相同结果幂等返回;不同结果拒绝并审计
- lease 过期后任务可重投,但旧节点迟到回报不得覆盖新结果
- retry、cancel、approve、amend 具备幂等行为
- 不得用进程内 Map 作为唯一幂等数据来源
### 任务 D:统一错误、审计和请求关联
- 新增稳定错误码集合(INVALID_ARGUMENT / TASK_NOT_FOUND / INVALID_STATE_TRANSITION / LEASE_NOT_FOUND / LEASE_EXPIRED / IDEMPOTENCY_CONFLICT / TASK_ALREADY_TERMINAL / STORAGE_ERROR / REVISION_CONFLICT)
- 每个 HTTP 请求生成或透传 X-Request-Id
- 每个任务运行生成或透传 runId、taskId、attemptId、nodeId
- 审计记录至少包含:时间、动作、对象、结果、操作者/来源、requestId、runId、错误码
- API 错误统一为 { error: { code, message, requestId, details } }
- 保持现有接口状态码兼容
### 任务 E:健康检查和配置校验
新增 src/platform/config.js + src/platform/health.js:
- 统一读取端口、host、数据目录、WAL、节点 token、TLS、LLM provider 和超时配置
- 新增 gateway check 或等价检查命令
- 新增 /healthz(进程存活)和 /readyz(数据目录/WAL/Repository 可写性、必要配置)
- 生产模式检测到默认节点 token 时必须给出明确警告;安全模式可直接拒绝启动
- 检查结果必须脱敏
### 任务 F:补齐测试和验证脚本
新增或扩展测试:
- 状态机:合法迁移、非法迁移、重复终态、取消竞态
- Repository:内存态、文件态、WAL 开关、损坏文件、恢复后读取
- 幂等:重复创建、重复 claim、重复 settle、冲突 settle、过期 lease
- 故障:进程中断、节点掉线、旧节点迟到回报、回调失败、磁盘不可写
- 安全:错误响应不泄漏密钥,requestId 和审计不泄漏敏感字段
- 回归:现有 npm test、npm run test:conversation、npm run e2e-team 能继续运行
### 任务 G:任务版本与乐观锁
- 每个任务带 revision(整数,初始 1),每次 transition/settle/update 成功后自增
- transitionTask、settleTask、updateTask 必须接受 expectedRevision;不匹配返回 REVISION_CONFLICT
- 重复提交相同 leaseId + 相同结果时,revision 不变,幂等返回当前终态
- 不同结果或不同 attemptId 的 settle 必须因 revision/lease 校验失败而拒绝
- revision 必须随任务持久化,重启后恢复
- 审计记录每次 revision 变化
### 任务 H:事件持久化与 SSE 重连
- 事件通过 EventRepository 持久化(FileRepository 先落 JSONL)
- 每个事件带 seq(全局递增)、type、aggregateId、revision、at、requestId
- SSE 支持 Last-Event-ID:客户端断线重连时从 Last-Event-ID + 1 开始补播
- 事件保留期可配置(默认 7 天或 10000 条)
- 进程重启后 seq 必须继续递增,不能回退
### 任务 I:回调机制加固
- 回调必须有 HMAC-SHA256 签名:X-Signature: t=<timestamp>,v1=<hmac>
- 回调失败按指数退避重试(至少 3 次:1s / 5s / 30s);全部失败后进入回调死信队列
- 回调必须幂等:接收方可用 X-Callback-Id(= taskId)去重
- 回调 payload 必须包含 taskId、runId、state、revision、result、finishedAt
- 密钥不得出现在日志、审计、导出或错误消息中
### 任务 J:任务取消传播
- cancel 必须将取消信号传播到持有当前 lease 的执行节点
- 取消后任务进入 canceled 终态;执行节点的迟到回报在任务已 canceled 时必须被拒绝
- 如果任务有子任务(parentRun / dependencies),取消父任务时必须级联取消未完成的子任务
- 取消操作本身必须幂等:对已 canceled 的任务再次 cancel 不报错
- 取消必须审计:记录谁取消、为什么取消、取消传播到了哪些子任务
- 如果节点不在线或取消信号投递失败,任务仍应进入 canceled 终态(取消不依赖节点确认)
### 任务 K:死信队列加固
- 每条死信记录必须包含:deadLetterId、taskId、originalTaskId、deadReason、retryCount、firstDeadAt、lastDeadAt
- 死信重投有上限:maxDeadRetries(默认 3);超过后标记 exhausted
- exhausted 死信只能通过人工 POST /api/deadletter/:id/force-retry 重投,且必须记录操作者
- 死信队列支持按 deadReason / retryCount / originalTaskId 查询
- 死信重投必须生成新的 attemptId 和 leaseId,不能复用旧 lease
- 死信归档:exhausted 超过保留期后自动归档
## 验收标准
### 功能验收
- [ ] 所有关键状态迁移经过统一状态机
- [ ] 业务层不再直接依赖 GatewayStore 的内部 Map 结构
- [ ] create/claim/settle/retry/cancel/approve 支持幂等或冲突检测
- [ ] 任务拥有 leaseId、leaseExpiresAt、attemptId 等执行关联字段
- [ ] 旧 lease 的迟到回报不能覆盖新 attempt
- [ ] /healthz、/readyz 和配置检查可用
- [ ] 错误响应包含稳定错误码和 requestId
- [ ] 审计能够还原一次任务从创建到终态的完整过程
- [ ] 任务带 revision,并发 settle 只有一个成功,REVISION_CONFLICT 正确返回
- [ ] 事件持久化到 Repository,SSE 断线重连后能补播断线期间的事件
- [ ] 回调有 HMAC 签名、失败重试 3 次、全部失败进死信队列
- [ ] 取消信号传播到执行节点,已取消任务的迟到回报被拒绝,子任务级联取消
- [ ] 死信带 retryCount/originalTaskId/deadReason,超过 maxDeadRetries 标记 exhausted
### 回归验收
所有命令退出码为 0:
npm test
npm run test:conversation
npm run e2e-team
npm run recovery-demo
npm run stress
### 性能验收
- 在现有压测规模下,任务无重复领取、无永久丢失、无重复终态
- 新增状态机、Repository、审计后,现有 stress 测试吞吐下降不超过 10%
- 必须提供改造前后的 baseline 对比数据:吞吐(task/s)、P95/P99 排队延迟、P95/P99 执行延迟、重复领取数、丢失任务数
- 事件持久化不能阻塞调度主路径
### 安全验收
- 错误、审计、状态、导出、日志中均不存在 key/token/password/secret 明文
- 默认 token、非法路径、非法状态、伪造 lease、越权 settle 均有拒绝结果
- 不引入新的 shell 拼接、动态代码执行或不受限文件路径
## 交付物格式
每个模型必须提交以下内容:
1. 修改文件清单
2. 实现摘要
3. 状态迁移表
4. Repository 接口说明
5. 幂等和 lease 语义说明
6. 测试命令与实际结果
7. 未完成项和已知风险
8. 与其它模型合并时的冲突点
禁止只提交"已完成""测试通过"等无证据结论。
## 执行步骤建议
1. 先读 README.md、ARCHITECTURE.md、IMPLEMENTATION.md、ADR.md、PHASE-1-UNIFIED-TASK.md
2. 读 src/server.js、src/store.js、src/scheduler-core.js、src/protocol.js、src/wal.js,理解现有任务生命周期
3. 按以下顺序实现:状态机(A) → 错误码(D) → 版本乐观锁(G) → Repository(B) → 事件持久化(H) → 幂等lease(C) → 取消传播(J) → 回调加固(I) → 死信加固(K) → 健康检查(E) → 测试(F)
4. 每完成一个任务,运行 npm test 确认没有回归
5. 全部完成后运行回归验收的 5 条命令,记录实际退出码
6. 按交付物格式提交结果
注意:你是四个并行模型之一,使用完全相同的任务书。你的目标是提交可合并代码。保持 Node >=20、零第三方运行时依赖、REAL/OFFLINE 诚实标记和现有 API 兼容。不得修改归档目录,不得删除用户已有改动,不得泄漏任何密钥。完成后必须运行对应测试,报告实际命令、退出码、修改文件和剩余风险。
④ Rubrics 描述
## 评估维度与判定标准
### 1. 功能完整性(权重 30%)
优秀:
- 11 个任务(A-K)全部实现并接入真实任务路径
- 所有功能验收项(13 项)全部通过
- 状态机覆盖所有合法/非法迁移,重复终态和取消竞态正确处理
- Repository 抽象完整,业务层不再依赖 Map 内部结构
- 幂等和 lease 在并发、重复、过期场景下行为正确
- 事件持久化 + SSE 重连正常工作
- 回调有签名、重试、死信
- 取消传播到节点和子任务
- 死信有 retryCount/上限/归档
合格:
- 核心任务(A/B/C/D)完成,其余任务部分完成
- 主要功能验收项通过,少数边缘场景未覆盖
- 代码可运行,测试大部分通过
不合格:
- 关键任务(状态机/Repository/幂等)未实现或未接入
- 功能验收项超过 3 项不通过
- 代码无法运行或测试大面积失败
### 2. 代码质量(权重 20%)
优秀:
- 新增模块结构清晰(domain/application/adapters/platform 分层)
- 函数职责单一,命名清晰,注释充分
- 错误处理完善,不吞异常
- 与现有代码风格一致(ESM、零依赖)
- 没有死代码、重复代码或过度工程
合格:
- 模块结构基本合理,有少量设计瑕疵
- 命名和注释基本到位
- 错误处理覆盖主要路径
不合格:
- 模块结构混乱,职责不清
- 大量复制粘贴或死代码
- 异常被静默吞掉
- 引入了第三方运行时依赖
### 3. 测试覆盖(权重 20%)
优秀:
- 每个新增功能都有对应测试
- 测试覆盖正常路径、边界条件、错误场景
- 并发和竞态场景有专门测试
- 现有测试全部通过(npm test 等)
- 新增测试覆盖状态机、Repository、幂等、lease、取消传播、死信加固、事件持久化
合格:
- 主要功能有测试覆盖
- 现有测试基本通过(允许少量已知 flaky)
- 边界场景覆盖不完整但有计划
不合格:
- 没有新增测试
- 现有测试被破坏
- 通过放宽断言或删除测试来制造全绿
### 4. 兼容性(权重 15%)
优秀:
- 现有 API 完全兼容,不改变接口语义
- 现有测试(npm test / test:conversation / e2e-team / recovery-demo / stress)全部通过
- 现有面板、插件、看板桥和团队编排功能未被破坏
- WAL 和持久化行为保持兼容
合格:
- 现有 API 基本兼容,有少量非破坏性变化
- 现有测试大部分通过
不合格:
- 破坏现有 API 语义
- 现有测试大面积失败
- 面板、插件或团队编排功能被破坏
### 5. 安全性(权重 15%)
优秀:
- 错误、审计、状态、导出、日志中均不存在 key/token/password/secret 明文
- 默认 token 检测和警告到位
- 非法路径、非法状态、伪造 lease、越权 settle 均有拒绝结果
- 回调签名(HMAC)正确实现
- 不引入新的 shell 拼接、动态代码执行或不受限文件路径
合格:
- 主要安全检查到位
- 密钥脱敏基本覆盖
- 个别安全场景未覆盖但有计划
不合格:
- 密钥泄漏到日志/审计/导出
- 默认 token 在生产模式下不警告
- 缺少基本的安全校验
### 综合判定
- 优秀:5 个维度均为优秀或合格,且至少 3 个为优秀
- 合格:5 个维度均为合格及以上,且不超过 2 个为不合格
- 不合格:任意 2 个及以上维度为不合格
⑤ 上传附件(Workspace)说明
必须上传的文件/目录
src/ 所有源码(含 src/nodes/、src/taskboard/、src/team/)
test/ 所有测试(含 test/fixtures/)
web/ Web 面板
scripts/ 工具脚本
lib/ DSH 插件封装
package.json
README.md
ARCHITECTURE.md
IMPLEMENTATION.md
ADR.md
PHASE-1-UNIFIED-TASK.md
DEVELOPMENT-ROADMAP.md
cordis.patch.yml
.env.example
.gitignore
gateway POSIX 启动器
gateway.cmd Windows 启动器
不要上传的
node_modules/ 零依赖项目不需要
out/ 运行产物,可重新生成
evidence/ 运行证据,可重新生成
work/ 工作目录,可重新生成
state/ 运行时状态
归档-* 归档目录,任务不需要
.env.live 含 API 密钥,禁止上传!
_*.mjs / _*.js / _*.html / _*.txt 临时脚本
*.docx / *.png 大二进制文件
_merge_work/ 合并工作目录
打包建议
把项目根目录下需要上传的文件/文件夹打成一个 zip,保持原始目录结构:
# 在项目根目录执行
zip -r workspace.zip src/ test/ web/ scripts/ lib/ \
package.json README.md ARCHITECTURE.md IMPLEMENTATION.md \
ADR.md PHASE-1-UNIFIED-TASK.md DEVELOPMENT-ROADMAP.md \
cordis.patch.yml .env.example .gitignore gateway gateway.cmd
然后上传 workspace.zip 作为 Workspace。