Repository navigation
feat(chat): edit and cancel pending queue messages - #8096
Conversation
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent; model=gpt-6.1-sol; provider=OpenAI; reasoning_effort=max; declaration_source=runtime_reported
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
动机 / Motivation
浏览器中等待当前回合完成、又需要纠正下一条输入的用户会遇到这个问题:在当前回合执行期间,用户发现待处理输入有错,只能查看或插入当前回合,无法在启动前修改或取消。错误输入可能继续执行,或需要等待、追加说明。同一条带附件的待处理消息,现在可以 More → 编辑 → 保存,或取消排队;修改确认丢失后刷新,仍能核对同一操作。实际 HTTP 与打包页面验证了文本修改、附件保留、取消历史标记,以及旧修订拒绝后草稿保留。
这是一条完整的 pending-input 修正路径,不需要重新选择附件、覆盖主输入草稿,或增加一次权限确认。More 隐藏低频操作,保存提交明确的新文本;取消直接作用于原待处理项。未知确认才需要“核对修改”。不声明整个工作区交付、安装态、真实模型收益或自动接续显示问题已完成。
改动思路 / Approach
修改复用原队列的 Session→Turn 锁;Session 是原对话,Turn 是其中一轮工作。TS owner 判断来源、是否仍排队、输入修订和操作身份,Python 按计划修改原用户记录。先持久化待完成操作,再写文本、历史、事件和最终修订;部分写入会使该项暂停自动出队及 steering。只有同一个操作和同一份意图能完成恢复,不能用新操作替换未知写入。
现有 TS queue owner 决定资格、修订与重放;Python 只执行有锁的 journal IO,React 只保留用户草稿和原操作,没有第二个执行或权限 owner。沿用现有 queue API mixin、完整分页且经过 audience 投影的历史读取和历史 reducer,避免新增 raw-input 读取通道。保留原文本用于 admission 重试身份比较,不把修正后的文本当作另一次发送。
| 触发 | 验证后的结果 |
|---|---|
| 尚未启动、原 web 输入、修订匹配 | 编辑原文本或取消原项,附件及历史保留 |
| 旧修订、已经启动、来源失效或不同 Session | 拒绝修改,保留编辑草稿 |
| 部分写入、确认丢失 | 保留原操作恢复,不重新发送消息 |
| 未执行新操作 | 原队列、busy 拒绝、重复 admission 与原输入保持 |
本次完成尚未启动的 web 输入编辑、取消和原操作恢复;既有自动接续显示缺口、安装版、真实模型与 macOS IME 不在通过结论内。
具体改动 / Changes
评审对象为 7774095,固定基线为 4b7afef。先读基线的 docs/integrations/session-runtime-control-plane-adapter.md 队列与快捷键契约,再读完整 18 文件 diff。新增 22 行文档是本提案的操作说明,未拿它反向认证实现。以下 CHAT 标记只是给既有未编号条款加的评审索引:
- CHAT-IDENTITY:原 Session、client_turn_id、附件与“接受不等于执行”。编辑后原 admission 重试仍返回同一个 Turn;独立 HTTP 验证了取消后原 admission 重试也不会重发。
- CHAT-FIFO:复用原队列消费边界。编辑/取消与 claim 的两种串行顺序均验证,当前回合不被打断,不跨 Session 修改。
- CHAT-RECOVERY:未知结果保留原身份。实际服务端提交后人为丢弃浏览器确认,刷新后核对同一操作;存储故障发生在提交前,实际修改请求数为零。
- CHAT-KEYS:普通 Enter 排队、Shift+Enter 换行、Command+Enter 插入语义保留;编辑区 Command+Enter 保存自己的草稿。已跑键盘单测及实际 Enter/Command+Enter;真实 macOS 中文 IME 没有资格化。
关键执行位置:
planQueuedChatMutation:拒绝来源、状态、修订或操作意图冲突;完成操作可按原身份重放。mutate_queued_input:在消费锁内执行 reservation→原用户行及历史→事件→Session cache 时间→Turn 提交,部分写入可恢复。QueuedMessage:提交前保存恢复身份;确认校验 session、Turn、action、operation、revision;旧状态拒绝时保留草稿。reconcileConversationReturns:只接受同一用户行的更新修订,不让旧读取、其他角色/Turn/Session 覆盖取消或实时答案。
18 文件 +612/-33 包含 3 个测试文件 +224/-1、文档 +22,其余是相互依赖的决策、journal、UI 与 readback。没有新增模块、配置、provider 或平行 Python 决策实现。新状态有具体生产者:用户选择产生不可推断的操作意图;有锁执行产生 pending/completed receipt 和历史;列表只是投影。旧记录缺省修订为 0,不能因前后端共同部署而删除持久历史兼容性。
对主干的风险 / Risks
主要风险是混合写入后错误出队、重复发送、旧修订覆盖,以及界面丢草稿。独立验证覆盖了实际 HTTP、真实文件 Chat journal、TS effect owner、并发锁和进程重开,脚本化 stdio host 替代模型。本轮结果如下;没有查询或等待远程 CI。
| 验证 | 结果与边界 |
|---|---|
| 队列、ordinary project、preparation、steering 回归 | head 153 passed;基线 145 passed,共同用例全部通过,新增 8 项;File/SQLite 是 canonical Goal 上下文,Chat journal 仍是 File |
| TS queue / history reducer / keyboard | queue 5 passed,history reducer 与 composer 键盘单测通过 |
| 无新操作的固定基线对照 | 完整 queue、Turn、原用户行、重复 admission、busy/GET 拒绝、无 native IO 的观察向量一致;只规范化生成身份、时间、临时 fixture 根及已核对的两个新增缺省字段,未删错误/权限/文本语义 |
| 独立新操作敏感性 | 基线 POST input 返回 404 且不改原输入;head 编辑、同操作重试、stale 拒绝、取消、旧 edit 重放及取消后 admission 重试均符合预期,无 native 重发 |
| 打包 UI + 实际 owning backend | 编辑/取消、附件、lost ACK→刷新→核对、存储故障零请求、旧修订拒绝保留双草稿,desktop/390px 展开检查通过 |
| 严格 TS、dashboard build、Ruff、diff/双语/公开边界 | 通过;build chunk-size 提示保留 |
| 标准 premerge | FAIL:todo-readmodel-boundary-smoke.py line 101 访问不存在的 loopx.status.open_todo_items;固定基线与 head 的完整 traceback 相同,仅替换 checkout 根。另有相同基线 maintainability advisory;不写成全绿或合并就绪 |
另一个既有缺口也必须保留:对刷新恢复的对话,在原回合完成、下一条已由后端开始时,界面可能仍显示旧轮结束并缺少 Stop。基线与 head 的实际打包页面均复现;再刷新后,Stop 都准确命中新一轮 durable-turn-2。这不是本 PR 引入的回归,也不能支持正文中“自动接续到新回合控制已全面验证”的更强结论。它属于原接续/显示路径的后续修复,不能用本次编辑/取消通过来关闭。
我的整体评价 / Verdict
APPROVE,未发现本次 diff 新增的阻塞性问题;author-owned 账号通过 COMMENTED 承载批准结论。独立证据支持有用且可回退的 pending-input 编辑/取消交付,不能推导到合并、安装、完整工作区或长期成本验收。标准 premerge 失败和既有接续显示缺口仍然保留。
实际打包页面中,待处理列表、More、附件、取消标记和主输入同屏可辨;长输入按需展开。展开编辑区需要内部滚动,错误可在该区域下方读到;未把无横向溢出等同于视觉验收。检查使用长重复中文输入、两条待处理项、附件、活动回合和混合错误状态;390px 展开输入和附件可读。作者测试版与本 head 的 18 个文件 blob 全部一致,且独立构建和浏览器检查在本 head 完成;复用截图没有扩大版本边界。
安装版桌面、真实 macOS 中文 IME、Lark/CS-Notes 未验证。刷新恢复后自动接续时,基线与 head 均可显示旧轮结束而缺少 Stop,需再刷新;这是既有缺口,未视为本 PR 已修复。相应的当前回合控制还需要原显示 owner 修复;本提案没有提高权限或改变该 owner。完整净收益和真实模型采用也没有测量。
English verdict: APPROVE — the explicit pending-input edit/cancel path is verified. The unchanged local validation failure and pre-existing follow-up display gap remain; this is not merge or installation authorization.
Goal And Delivered Outcome
待处理消息此前只能查看或插入本轮,发现输入有误后无法在启动前修正或取消。现在可在该条消息的“更多”菜单中编辑或取消排队;取消保留历史标记,编辑保留附件。确认丢失时可核对原操作,避免重复执行。
main,已核对4b7afef2215067dd1171f308b93c9336e1c6e5d9。不关闭更大范围的工作区交付任务。Author Declaration
docs/integrations/session-runtime-control-plane-adapter.md的 queued-input 契约,修订见本 PR。loopx/control_plane/turn_driver/chat_queue_steering.tsloopx/chat_ingress.pyconversation-queue.tsx/channel-timeline.tsxScope And Continuation
本 PR 完成 pending web input 的编辑、取消、恢复与历史 readback。部分写入先持久化 reservation,自动出队和 steering 使用同一 Session/Turn fence;只有原 operation 和 intent 可完成或重放。外部、绑定、协作及 LoopX execution 输入沿原入口处理。
同域整理将路由放回现有 queue API mixin,并移除一用即弃的 runtime wrapper 与多余的 raw-input reader;完整输入复用原有 audience-projected paged history。没有提高模块预算。
更大范围的原生前景/后台与安装版验证仍沿现有工作区交付流程推进。安装、发布与合并不在本次操作范围内;本提案可独立审阅、测试和回退。
Validation
4647ffc40c4dece167e42f95cc02b2c099db8c41;最终 head7774095cf61287ff891ba6daa52080736ba20f13仅重放到最新已核对 main,18 文件 patch 比对完全一致。最终 head 重新严格构建、质量资格和 quick premerge。tests/presentation/test_chat_turn_queue.py25 项;真实 HTTP、文件 Chat journal、TS effect owner,两种 claim 顺序、丢失提交恢复、权限与 Session 拒绝、附件实际派发。隔离 File/SQLite canonical Goal 上下文均通过;不表示 Chat journal 改为 SQLite。Frontend / Visual Evidence
runner_invalid,不计分、不推断 benchmark 增益;没有运行新 benchmark 或上传原始轨迹。03d6ab2864a54e86ab4f97854854d0e4acd7dd48,After4647ffc;最终 rebase 不改这 18 文件 patch。附件编辑后保留并可展开,主草稿保留:
Type of Change
LoopX Area
Technical Direction
现有 roadmap S5 的原会话/回合、重连、重复操作与 stale 拒绝边界;这里仅交付原队列输入操作,不声明整个阶段完成。
Shared-authority RFC fixture impact
N/A:未声明 TypeScript migration 或 shared Goal Authority RFC 的阶段进度;未改变 canonical Goal provider、promotion、routing 或 legacy compatibility。
Boundary Checklist