fix(chat): keep deferred work distinct from delivered replies - #5172
Conversation
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
huangruiteng
left a comment
There was a problem hiding this comment.
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
Exact head: 0a7e979f89eb258fa36fa150b00d9e0c22dcb025
动机
这解决的是一个真实但有界的误导:接收方暂缓或拒绝交办后,“回复送达”不能变成“任务已完成”。原有接收方判断和传输回执已分别持久化,缺口在 owner 私有对话的投影和卡片措辞。此 PR 是 App RFC G0/R3 的可独立回退增量,不是整个 Steward→worker→独立验收旅程的完成证明。
改动思路
沿用已有请求、接收方判断和送达状态,展示接收 Goal/Agent 与原因,而不是再增加一套完成状态。私有读取范围复用已有 TypeScript conversation scope;还要通过原 Session 和 client Turn 的精确绑定。外部回复只改变中性前缀,不把 owner 私有原因送出。延期原因提高了下一轮继续推进时的可理解性,但不会自动执行被暂缓的工作。
具体改动
模型只增加两个可选展示字段;卡片分别显示判断、原因和 queued/delivered/explicit_unverified,不从结论 phase 推导完成。新增的 Python 回归与浏览器恢复场景覆盖延期原因、未核验送达及手机布局;双语 RFC 和 golden query 明确真实用户验收还需包含交办、修订、worker 采用和回传。
关键代码讲解
project_collaboration(presentation.py:10)使用已有私有 scope,随后核对 route 的 session/client_turn_id;Goal 与原因来自已有请求/判断回执,展示值递归脱敏。读取失败仍不改保存的对话。CollaborationCard(collaboration-card.tsx:24)独立选择接收方判断和传输状态,并显示 Goal/Agent 与原因;没有把 defer/reject 或一次 reply 当作完成验收。drain(roundtrip.py:292,前缀分支 :359)仍校验原会话、授权目标和初始 Turn 完成,沿用确定性消息 ID 与传输去重;只将未来 conclusion 回复的标题改为“协作回复”,不重写旧记录。
对主干的风险
主要风险是私有原因泄漏到外部会话、展示范围扩大导致串话,或措辞变化触发重发。独立真实 HTTP/File oracle 覆盖三类渠道×四种判断;head 的私有卡片保留判断、原因和 Goal,外部无卡片或原因泄漏,重启及并发 drain 保持一个回复、一个原始 Turn。复制同一回执到四种新会话也不能扩大读取范围。相同 oracle 在 base 明确失败,证明不是仅迎合新增测试。
源码与 packaged chat-recovery 浏览器 smoke、两侧构建、head 36/base 27 项 Python 测试、2 项 typed scope 测试、Ruff 和 docs governance 均通过。桌面和手机截图已检查。浏览器使用合成 API;真实 worker 的执行、独立验收和真实 Lark 网络送达未在这里证明。
语义与 CI 对齐
复用已有 typed scope 与判断/送达词汇;扩展展示不是新增执行或隐私授权。不存在用“guidance”掩盖新增机器义务,也没有改变默认调度或 quota。按当前 review policy 不等待远端 CI;上述结论来自本人在 exact head 的本地验证。
我的整体评价
long_horizon 与 user_experience 均改善:延期/拒绝可以跨重启如实回读,用户不再从送达标签误判完成。新增字段是回执的派生投影,无第二份人工同步状态;共享 scope 的复用就是本次有界 future-facing refine,未发现还需扩张的重构。范围与成本相称。支持合入这个展示修复,但不据此关闭完整多 Agent 旅程验收;未执行合并。
English verdict: APPROVE - The exact head preserves receiver disposition independently of reply delivery, with scoped private readback and independently validated retry/privacy behavior. This does not qualify the complete live worker journey.
Problem and result
A receiver may defer or reject a request and then return an explanation. The return transport calls that phase
conclusion; the App and external transcript presented every such reply as a completed conclusion. Users could not distinguish “reply delivered” from “work completed”, and Goal Chat lacked the collaboration readback available in the steward.Show the recipient's existing decision and bounded explanation separately from reply delivery. Scope the same readback to private steward and Goal conversations using the existing typed conversation owner. Name newly sent transcript replies neutrally; never expose private decision reasons to external audiences. Existing receipts, immutable replies, permissions and work lifecycle are unchanged. Historical messages are not rewritten or resent.
The bilingual App RFC/roadmap and golden queries now identify the nearest complete G0/R3 pilot: request a community-survey draft, route to the qualified existing owner, adopt a correction, recover after reload and return a readable draft without manual owner lookup or result relay. Existing G1 two-cycle team acceptance follows; this PR does not claim either live journey passed.
Validation
0a7e979f8| Risk-based premerge | Checks passed; original gate stale | All 16 selected and 5 direct checks passed; zero test failures/manual holds. Concurrent main advancement invalidated the original quality receipt. The unchanged final diff was reviewed against base
af3e7f1f0, recorded ascqr_eddfbd94cd0b53cc5412, and exact receipt verification now passes. The full premerge run was not repeated; this is not a claim that its earlier overall gate passed. |Quality scope: 11 files, fingerprint
eddfbd94cd0b53cc5412addb310fd2ac69d73d7ac74918d397e31e3b52cb4e71. Safe fix allowed, no additional safe-fix pass applied; zero recorded blockers, warnings or advisories. Receipt verification pins the reviewed base commit so unrelated concurrent fetches cannot silently change the scope.Presentation and boundaries
Existing conversation cards retain their structure; no homepage, primary navigation or first-screen entry changes. The reason earns space by explaining whether the requested work is actually happening. Routine brief details remain collapsible. Narrow screenshots show wrapped labels without horizontal overflow. English and Chinese copy share the same component.
Future-facing pass: reuse
conversation_scopeand the shared TypeScript card instead of adding manager-specific classification or a new state/RPC layer. Python remains the existing bounded IO/projection adapter; no new domain decision owner. The next acceptance is the installed owner-to-result journey, reusing current recovery/GoalRef and #5170 continuity work. This is an independently reversible presentation fix, not live execution or adoption certification. Maintainer merge required.