文档:DirectProject 命令入队化与待发消息队列归宿主设计定稿
- 新增 ADR:命令=入队、放行归 Thread Manager、待发消息队列作为运行态事件归宿主 - 新增实施计划:五步落地顺序、标识符映射表、每步不变式与验收证据 - CONTEXT.md:接单/拒单词条替换为入队/入队失败/放行,新增待发消息队列与待发消息词条 - docs/README.md 补两条索引;decision-log.md 追加同日决策记录
This commit is contained in:
@@ -9578,3 +9578,36 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
|
||||
- 验证:`cargo test -p module-runtime --lib agc_models::`(4 passed)、`cargo test -p api-server --bin api-server agc` 与 `llm::`、AGC 客户端 `configuration::`、admin-web 页面定向 Vitest 与 typecheck、两套 workspace 的 `cargo fmt -- --check`、`check:encoding`/`check:doc-index`/`check:spacetime-schema`/`git diff --check`。
|
||||
- 验证(真实上游 smoke,本地 dev DB):清空 `agc_model_catalog` 后启动 api-server → 日志 `已按上游模型列表初始化 AGC 模型目录 revision=1 model_count=6`;登录后 `GET /api/llm/models` 返回同一批模型、`displayName` 即上游原名、默认项为排序后第一项;上游不可达/非 2xx 时启动只记录 error、AGC 接口 `503` 且目录保持未初始化;目录已存在时重启不重写。
|
||||
- 边界(未验证/残留):上游在售模型超过 32 条时同步会失败(目录项上限未改);`qwen-image-3.0` 这类图像模型会一起进入目录,是否对 AGC 隐藏由 owner 在后台停用;混合版本期间未升级的 api-server 会把自己的 AGC 接口打到 `503`,module 与 api-server 必须同批发布/回滚。
|
||||
|
||||
## 2026-09-24 命令入队化与待发消息队列归宿主:放行归 Thread Manager,CLI 直连入口退役
|
||||
|
||||
- 决策(词表):「接单 / 拒单」退役,命令边界的成功与失败改叫「入队 / 入队失败」;旧「接单」的语义角色
|
||||
(这一轮真正成立的那一刻)改叫「放行」。所以旧句"接单成立 ⇔ 事件流里有开始有结束"改成"放行成立 ⇔ …",
|
||||
逐处按角色改、不做字面替换;`features/agent-runtime` 的"拒单文案"属另一个域,改"请求被拒"。
|
||||
- 决策(命令 = 入队):`chat_with_game_creator_direct_codex` 改义改名(暂定 `enqueue_direct_codex_turn`),
|
||||
把今天"接单前"那条检查链原样跑完(身份 → 工作流恢复 → 用户条目校验 → prompt 投影 → 前置条件 → 工程准备),
|
||||
通过后只入队:不登记占用、不落盘用户条目、不发回合事件、不起 codex;失败走命令返回的 typed 载荷
|
||||
(`DirectTurnRejection` → `DirectTurnEnqueueFailure`)。入队按 `clientTurnId` 幂等(判重范围 = 在队 ∪ 在跑)。
|
||||
- 决策(队列归 Thread Manager):每项目一条 FIFO,只支持按顺序追加与按身份移除;队列的成员与顺序就是事件列表本身
|
||||
(`queue.enqueued` 在队期间不可回收、离开队列后可回收),`subscribe` 的 live-set bootstrap 因此天然把当前队列
|
||||
交给中途加入的订阅者;上限 5 只数在队条目,由 Rust 持有。
|
||||
- 决策(线上形状):`queue.enqueued{clientTurnId,userItem,creationType?,at}` + `queue.removed{clientTurnId,reason}`,
|
||||
`reason` 是 ts-rs 导出的 typed 枚举(`cancelled|dispatched`),不用字符串;事件不带 prompt——
|
||||
prompt 是入队检查的产物,只留在宿主的队列条目里。
|
||||
- 决策(放行):Thread Manager 在回合收口之后原子地「取队首 → 登记占用 → `turn.started` + `queue.removed{dispatched}`」,
|
||||
再落盘用户条目、下发用户条目、起整轮。**放行不重跑检查、不存在放行失败**,放行之后的一切失败都是回合失败,
|
||||
走既有 `turn.completed.failure`,不新增通道。kick 点 = 回合任务收尾(含 drop 守卫盖 panic)+ 中止路径 + 入队之后,
|
||||
幂等且在临界区里认领队首;入队不取 `DirectTaonierActiveInvocationGuard`(它必须整轮持有,是这一轮的调用身份)。
|
||||
- 决策(前端):不再持有队列副本,chip 只由事件投影,入队失败只由命令返回值给反馈(保留提示文案与"不丢草稿");
|
||||
埋点句柄改由宿主在放行时开。
|
||||
- 决策(顺带退役):`--direct-codex-chat` 整个退役——它唯一的实际消费者是手工夹具
|
||||
`scripts/direct-execution-production-fixture.mjs`(PR #439 引入、不在 CI、无 npm/harness 注册、无测试钉它),
|
||||
夹具一并退役;`TurnAlreadyRunning` 与前端"同一轮消息仍在处理中"分支随之删除。
|
||||
`DirectTaonierActiveInvocationGuard` 的身份与 Thread Manager 的 `active_turn.turn_id` 是同一件事的两份记录,
|
||||
CLI 退役后让那五个读者改读 Thread Manager,再在第二步删掉守卫与它的 60 秒卡死兜底
|
||||
(删前必须保住"回合卡死可被取消解开"这条由 `d833ca9d3` 事故换来的保证)。
|
||||
- 代价:入队即写盘(引用 UI 设计文档的条目会生成 `ui/generated-<stem>.js`,取消不撤);检查是时间点事实、
|
||||
放行不重跑(manifest / 权限 / 目录变化后照旧放行,偏差落到回合失败);队列随进程消失,不做跨进程持久化;
|
||||
失去"真实二进制驱动执行层生产验证"这条手工路径。
|
||||
- 验证方式(设计稿,尚未实施):`docs/adr/【ADR】DirectProject命令入队化与待发消息队列归宿主-2026-09-24.md`、
|
||||
`docs/technical/【实施计划】DirectProject命令入队化与待发消息队列归宿主-2026-09-24.md`。
|
||||
|
||||
Reference in New Issue
Block a user