Repository navigation
Recover App to Lark delivery after a transcript restore - #8653
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.
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
Reviewer: model_agent · gpt-6.1-sol · OpenAI · runtime_reported · max
本次评审对应提交 954e16cc3787fb948de52f619aecfcae09ed396e。
动机 / Motivation
从 App 接续原 Lark 私聊的用户。App transcript 恢复后,即使内容已增加,只要文件大小和 mtime 与上一份快照相同,Lark worker 就会跳过待投递的消息。当前提交识别同大小同 mtime 的替换和原地恢复;隔离的真实 Chat HTTP 提交与 File Chat Store 读回中,两轮 App 输入与回答共四条,各向原 Lark 私聊投递一次。验证使用 macOS 本地 File Chat、真实 HTTP 与 Core、合成 Lark provider 和退出可控的模型替身。未访问 hosted CI、真实 Lark、已安装服务或原生 Windows。
改动思路 / Approach
复用 File Chat 已有的文件变更检测,避免在 Lark adapter 再定义一套 stat 规则。外部发送仍由原有私聊 worker 和回执控制。 缓存只避免重复读取。命中 stamp 不能代替当前 Session、binding 或 provider 身份验证。
具体改动 / Changes
关键代码讲解
- 发现与回执:原逻辑只比 size 与 mtime;新 stamp 加入 inode、ctime 和设备身份。不可得时继续按原入口读取。
- 原有发送 owner:仍按 canonical message id、当前绑定和原私聊收件人推进。撤销/更换 Bot 身份后,即使已有 outbox 也零投递。
- 仓库回归:保留坏 journal 原字节并在 reader 恢复后重新发现,未把读取失败视为已投递。
按 docs/architecture/rfcs/app-conversation-and-async-inbox-v0.md 的 708c68e7040559b2a4368002439570b90bc080b2 版核对两项:App-mirror(原私聊逐条回读)和 Private-source-fence(每次发送前核验当前来源)。
对主干的风险 / Risks
同一合成源分别做原子替换、同 inode 覆盖、暂缺再恢复及无 stamp 四个对照:主干均零投递,候选均四条各一次。重复扫描和重建 worker 未重复发送。Windows 上 helper 无可靠 mutation token 时会走 fresh read;模拟该分支可读回四条且不会重投,原生长 transcript 的开销未测。
语义与 CI 对齐
现有 App 与 Lark 的 Session、投递顺序和当前 authority 未换 owner。9 项相关测试、两端各 7 项独立对照、两端禁用检查与 6 项直接及 10 项选定 premerge 检查通过。
我的整体评价 / Verdict
APPROVE。未发现阻塞问题。修复恢复后漏投;原收件人、回执及零额外执行已独立验证。本次评审覆盖现有宿主与 CLI 行为。验证使用 macOS 本地 File Chat、真实 HTTP 与 Core、合成 Lark provider 和退出可控的模型替身。未访问 hosted CI、真实 Lark、已安装服务或原生 Windows。
English verdict: APPROVE. Same-size and same-mtime transcript restores are rediscovered at 954e16c; the original audience and per-message receipts remain verified with no repeated send or Turn.
The App to Lark delivery worker can miss committed App messages when a running Chat service sees a restored transcript with the same size and modification time as the previous file. The worker skips the replacement even though it now contains an App input and answer that still need to reach the original Lark chat.
Reuse the File Chat mutation fingerprint for the existing discovery hint. Replacing the file triggers a new scan while the existing source verification and delivery receipts still govern what gets sent.
The regression reproduces the lost discovery on the base. On this commit, the restored input and answer reach the original private chat once each. An isolated steward run also exercised App discovery and admission over the real Chat HTTP routes and verified both delivery receipts without starting another Turn during recovery.
The related discovery tests now verify that an unreadable journal stays intact and returns to the scan once the reader recovers. Their previous expectation that a single read error aborts discovery also failed on the base.