文档:接单化 review 收口第二轮写进 ADR、实施计划与共享记忆
- ADR 的后续更新补第二轮:§4 的拒单载荷 `kind` 收成 typed 枚举与并发拒单身份改成回合身份、§5 的回合身份口径覆盖拒单载荷、§6 的可留痕判据收掉 `ProjectRootUnanchored`、§7 的"同级提示"补上认不出的拒单 - 实施计划加「review 收口第二轮(2026-09-24)」一节,记下拒单表与界面提示口径的现状 - 决策记录追加同日第二条:五条决策、明确不做、两条待决策(连接收束时序、接单后落盘失败的双通道)与影响范围 / 验证证据
This commit is contained in:
@@ -146,3 +146,10 @@
|
||||
后续更新(2026-09-24,接单化 review 收口):§2 补"终态的写点在整轮结束之后"与"封口返修要求不是回合
|
||||
失败"两条不变式;`docs/technical/【技术方案】DirectProject Codex原始历史与异常恢复-2026-09-04.md` 的
|
||||
"终态由事实判定"一段同步改写;`docs/project-memory/shared-memory/decision-log.md` 追加同日条目。
|
||||
|
||||
后续更新(2026-09-24,接单化 review 收口第二轮):§4 的拒单载荷 `kind` 收成 typed 枚举
|
||||
(`DirectTurnFailureKind`,线上形状与取值不变)、并发拒单的两个身份改成回合身份;§5 的"回合身份由
|
||||
`clientTurnId` 推导"补上"命令边界的拒单载荷也不例外";§6 的可留痕判据收掉 `ProjectRootUnanchored`
|
||||
(它与 `ProjectRootUnusable` 同类,是用户自己就能修的文件系统事实);§7 的"同级提示"补上认不出的
|
||||
拒单(拒单不产生终态事件,聊天里必须由命令边界补一条说明)。失败说明的可见文案口径记在
|
||||
`docs/project-memory/shared-memory/decision-log.md` 同日第二条。
|
||||
|
||||
@@ -1,5 +1,48 @@
|
||||
# 决策记录
|
||||
|
||||
## 2026-09-24 接单化 review 收口(第二轮):失败载荷分类、拒单身份与提示口径
|
||||
|
||||
- 决策(失败载荷的 `kind` 收成 typed 枚举):新增 `DirectTurnFailureKind`(`Serialize + Deserialize + TS`,
|
||||
`kebab-case`,7 个变体,含先前两份名单都漏登记的 `turn-interrupted`),`DirectTurnError::wire_kind`
|
||||
返回 `Option<DirectTurnFailureKind>`。线上仍是 `{kind, message}`、取值不变,只有 TS 侧从裸 `string`
|
||||
变成可穷尽收窄的联合类型;全仓没有按 `failure.kind` 分流的代码,它只给界面选语气。
|
||||
- 决策(并发拒单的两个身份是回合身份):`DirectThreadManager::accept_turn` 冲突时返回占用对象的
|
||||
`turn_id`,`DirectTurnReservation::accept` 把这一轮请求的 `clientTurnId` 传成
|
||||
`incoming_invocation_id`。改动前这两项是进程内 UUID,`TurnAlreadyRunning` 的"同一轮仍在处理中"
|
||||
分支永远命中不了,也与"回合身份由 `clientTurnId` 推导"的口径冲突。占用对象自己的 `token` 仍是
|
||||
UUID(`complete_direct_thread_turn_if_reserved` 靠它配对),只换错误载荷里的两项。
|
||||
- 决策(目录锚不定的拒单不再写诊断):`DirectTurnError::ProjectRootUnanchored` 从 `is_reportable()`
|
||||
拿掉,与 `ProjectRootUnusable` 同类——符号链接 / 权限 / 目录被删都是用户自己就能修的文件系统事实。
|
||||
改动前它被命令边界覆写成 `direct-codex-failure:v2` 收口文案,界面上那句"无法锚定 Direct 调用项目
|
||||
目录:{cause}"被内部诊断串顶掉;现在界面按 `Display` 显示,也不再进 `.agent/runtime/errors`。
|
||||
可留痕的拒单只剩 `environmentNotReady` / `hostStateUnavailable`。
|
||||
- 决策(认不出的拒单也要在聊天里有同级提示):`environmentNotReady` / `hostStateUnavailable` 除上报 +
|
||||
横幅外,再补一条与用户消息同级的提示——拒单没有接单、不产生 `turn.completed`,否则那条乐观用户
|
||||
气泡后面永远没有解释(改动前的注释"宿主已经把它放进了 `turn.completed.failure`"对拒单不成立)。
|
||||
文案走 `projectRuntimeVisibleRejectionError`:取宿主收口文案里已脱敏的摘要与建议,**不套阶段标签**
|
||||
(拒单这一轮没有开始,阶段只会是默认值);非结构化错误仍只走横幅(它可能发生在接单之后)。
|
||||
- 决策(失败说明的文案口径):`projectRuntimeVisibleError` 补上宿主 `Display` 事实句的模式
|
||||
(`执行通道已断开` / `等待模型回合结束达到硬上限` / `宿主任务提前结束` / `收尾历史失败` 一族),
|
||||
并给落盘那档补上不带"失败"二字的事实句;不回落宿主原文(`TransportClosed` 的原文带 `exitStatus=` /
|
||||
`stderrClass=`)。同时修掉收口文案的版本口径:解析只认 `v1`、宿主发的是多一段 `code=` 的 `v2`,
|
||||
脱敏摘要一直命中不了。口径定为"不加模式就只会看到通用文案",写在 `directTurnFailure.ts` 的注释里。
|
||||
- 明确不做:不改线上载荷形状与 `kind` 取值;不加新的失败阶段取值(拒单仍落默认阶段);不动
|
||||
`ProjectRootUnanchored` 之外的拒单分类。
|
||||
- 待决策(本轮没改代码,见交接清单):① "失败事实先于连接收束"的时序保证
|
||||
(`fail_game_creator_codex_app_server_connection` 先置 `inner.closed` 再 `record_execution_turn_failure`,
|
||||
200ms 看门狗可能抢先把它收束成 `Interrupted`);② 接单之后历史落盘失败仍从命令返回 `Err`,
|
||||
同一个失败经事件与命令两条通道下发(前端模型把 `Err` 当"这一轮没开始")。
|
||||
- 影响范围:Rust `apps/ai-game-creator-shell/src-tauri/src/agent/{direct_turn_error.rs,direct_turn_failure.rs,direct_turn_accept.rs,direct_thread_manager.rs,direct_runtime/user_input.rs}`;
|
||||
前端 `src/features/agent-runtime/model.ts`、`src/view/project-development/chat/{conversation/directCodexConversation.ts,conversation/directTurnFailure.ts,controller/useDirectProjectChatController.ts}`、
|
||||
`src/view/project-development/chat/generated/DirectTurnFailureKind.ts` 与
|
||||
`tests/{agentRuntimeModel.test.ts,directThreadChat.test.ts,appSurface/chat-composer.suite.ts,appSurface/project-conversation.suite.ts}`;
|
||||
文档 `docs/adr/【ADR】DirectProject命令接单化-2026-09-23.md`、`docs/technical/【实施计划】DirectProject命令接单化-2026-09-23.md`。
|
||||
- 验证:Rust `cargo test --bins "agent::"`(900 passed / 5 ignored)、定向
|
||||
`cargo test --bins "agent::direct_turn_error"`(15 passed)、`cargo fmt`;前端
|
||||
`npx vitest run tests/{appSurface.test.ts,directRunAnalytics.test.ts,directProjectTurn.test.tsx,agentRuntimeModel.test.ts,directThreadChat.test.ts}`
|
||||
(277 passed / 9 skipped)、`npm --prefix apps/ai-game-creator-shell run typecheck`、`npm run check:encoding`、
|
||||
`git diff --check`。真实客户端观感未复核。
|
||||
|
||||
## 2026-09-24 接单化 review 收口:终态写点、返修控制流、终止判据与失败投影
|
||||
|
||||
- 决策(终态的写点在整轮真正结束之后):Direct 回合先固定终态判定的上下文,`turn.completed` 的写出
|
||||
|
||||
@@ -80,3 +80,17 @@
|
||||
- `cargo test export_bindings` 会重写全部 `chat/generated/`(引号风格漂移),跑完要 `git checkout --`
|
||||
掉不是本次新增的文件。
|
||||
- 本机 rust 全量 `--bins` 测试会挂在 mock server 的 `inet_csk_accept` 上,用 `--bins "agent::"` 之类过滤跑。
|
||||
|
||||
## review 收口第二轮(2026-09-24)
|
||||
|
||||
第 3 步的拒单表与第 4 步的界面口径按 review 收口后的状态为准:
|
||||
|
||||
- 失败载荷的 `kind` 从裸 `string` 收成 typed `DirectTurnFailureKind`(7 个变体,含先前漏登记的
|
||||
`turn-interrupted`);线上形状与取值不变,TS 侧只是变成可穷尽收窄的联合类型。
|
||||
- 并发拒单(`TurnAlreadyRunning`)的两个身份改成回合身份:`existingInvocationId` 是占用对象的
|
||||
`turnId`、`incomingInvocationId` 是这一轮请求的 `clientTurnId`;占用对象自己的 `token` 仍是 UUID。
|
||||
- 可留痕的拒单只剩 `environmentNotReady` / `hostStateUnavailable`:`projectRootUnanchored` 归到
|
||||
"用户自己就能修"那一档,不再写诊断、界面按 `Display` 显示。
|
||||
- 聊天里的提示分两条通道:认得的拒单给 `Display` 原文;认不出的拒单(宿主 / 环境事实)除上报 + 横幅
|
||||
外也补一条同级提示,文案取宿主收口文案里的脱敏摘要与建议(不带阶段标签)。失败说明的文案映射
|
||||
口径见 `docs/project-memory/shared-memory/decision-log.md` 与 `conversation/directTurnFailure.ts`。
|
||||
|
||||
Reference in New Issue
Block a user