Repository navigation
fix(lark): isolate recovery drafts and restore verified failure notices - #6906
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; gpt-6.1-sol; OpenAI; runtime_reported; effort=max; active_turn_verified=false
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
动机
受影响的是向已绑定私聊 Bot 发送请求、经历过失败后自动续办的用户。用户已收到失败提示,恢复后却看到这条旧提示又变成“处理中”;结果送达后仍留着未结束的草稿。修复后原失败提示保留,续办通过新草稿展示并回传本轮完整回复。原 Bot 的续办使用独立草稿;已经被旧版误改的通知由同一 worker 在核验后自动修正。本 PR 不改变请求的执行资格、模型调用或业务完成判定,也不让维护者代办原请求。生产升级后的真实 provider 回读及更广泛积压业务验收仍需在部署后完成。不修改默认通路,用户就仍需重新询问或依赖维护者手工改消息;仅有本地回执不变,不能证明用户看到的通知没有被覆盖。
改动思路
继续复用原服务扫描器、原请求锁和 Inbox 更新器。续办按现有版本号选择新的草稿与游标,最终回复只编辑本次草稿;原消息已确认后不再重新标为处理中。旧版造成的展示欠账由既有已核验通知、最终回复和草稿凭证推导,不引入业务队列或新的执行权限。最强反对理由是自动修旧消息可能覆盖别人的修改,因此更新前必须确认当前来源、规范 Turn,以及 provider 当前正文等于确切前文或目标正文;修复失败不能另发消息。这个已有 provider IO 边界足以完成修复,无须新消费者或 Core 策略。
新增选择只负责展示投影与不可省的 provider 编辑意图;执行授权和重试队列仍由原拥有者负责。本 PR 修复续办消息的展示,不改变执行资格,也不承诺全部积压业务已完成。
源码推导对照(本次提交;实际行为另由 provider 状态断言验证):
| 场景 | 旧通路 | 本次通路 |
|---|---|---|
| 失败后续办 | 复用原通知和游标 | 新草稿与独立游标 |
| 本轮回复形成 | 版本阶段漏过最终编辑 | 原新草稿更新为完整回复 |
| 已发生的旧误改 | 无默认修正 | 原 worker 按确切凭证仅编辑修正 |
具体改动
独立规范依据是 docs/architecture/rfcs/app-conversation-and-async-inbox-v0.md,修订 b5a1a816a266ddd251da7b277b20f6e57147aad7。按修改前的约定核对:unchanged-failure-notice 对应原失败 Turn 与通知不变;original-source-result 对应独立冻结的原来源回复;existing-scanner-owner 对应既有扫描器与同 Session 队列;uncertain-write-hold 对应不明写入保留原意图。四项在本次实现,新增 RFC 段落只是说明实施边界,不被当成自证的独立规范。
关键代码讲解
presentation_stream从既有恢复版本派生游标位置,保留旧 stream;相同规则给接收、进展和最终阶段加作用域。legacy_recovery_repairs只从原通知、不同 ID 的已核验最终回复及已确认草稿推导修复。归档续段与当前草稿均保留,不从显示文字猜业务状态。_deliver将阶段种类和存储键分开,恢复原有最终编辑语义;edit_only关闭另发消息的回退,普通委托首轮进展继续使用原规则。_repair_recovery_presentation在原请求锁内核对当前 Core 请求、Turn 和来源,再复用 Inbox;不调用 recover/enqueue,不改变原失败或新最终回执。update_lark_inbox_reply的新选项默认为关闭,仅本次历史修复要求正文等于已知前文或目标正文。已应用但回执丢失时只读回确认,不再编辑或重发。
变更为6文件、336增/28删:生产代码141增/28删,测试176行,双语说明19行。持久化兼容分支确有已存在的旧 provider 消息作为消费者;仅修未来命名空间会留下这些已发生的误改。复用现有模块和 effect owner,比维护手工修复清单或第二个消息处理器更小。
对主干的风险
主要风险是错误修复旧通知、误把本轮回复当成全部业务完成,以及普通委托的初始回执提前关闭后续进展。代码保持原来源/当前授权与 Turn 校验,修正通知只陈述“本轮回复已回传”;普通委托仍保留后续 stream。来源或正文改变、grant 撤销、Turn 不一致、凭证无效、编辑次数耗尽均保留待办,不能推导成已完成,也不能进入另发消息或重新执行业务的路径。
源分支491项相关回归通过;合并当前主干后的真实安装包通过27项、42项未选,覆盖新草稿、旧误改、续段、丢失回执与重启,同时保留原失败字节及最终回执并断言零新增执行/消息。源代码与安装包关键模块逐字节一致;正确签名的当前提交与该安装包测试提交全树相同,当前提交另有6个直接检查和11个仓库检查通过。基线反例实际把旧失败通知改成“已开始处理”,而非只检查元数据。早期开发中暴露的已确认来源反馈及委托关闭问题均被回归覆盖。模型与 provider 是合成边界,不能据此宣称线上积压已清空。按当前矩阵不查询或等待 GitHub CI。
语义与 CI 对齐
现有 recovery/delivery 术语仅在私有 provider 展示层扩展,不新增业务状态、义务、Goal 或授权。词汇扫描无支持的新载体;该扫描本身有限,实际仍核对了来源、意图、重试与关闭语义。仓库 placement、semantic、模块上限、双语及公开边界检查通过。
我的整体评价
未发现阻塞项,结论 APPROVE,审查范围是 ebba631c42568a5f81f7713faac9c096534b5352。长期执行(long_horizon)改善在于重启能确认同一次消息修复,已回复请求不会重新进入模型或业务队列;用户体验(user_experience)改善在于旧失败和新进展各自真实,回复之后不会继续留下伪装成执行中的旧通知。这是对更大恢复目标的一项完整、适度增量。兼容逻辑保留有真实持久化消费者,不需要另一套控制面;生产安装、真实 provider 回读及所有剩余业务请求继续作为独立验收,不从本次通过的测试或回执推断完成。
English verdict: APPROVE for ebba631c42568a5f81f7713faac9c096534b5352. The existing worker now isolates continuation presentation and repairs only proven legacy provider drafts, with exact-body readback, no business replay, and no new-message fallback. Local and packaged checks pass; production adoption and broader backlog acceptance remain separate.
Recovered private Bot requests reused the original progress message and cursor, allowing a later draft to overwrite an already-delivered failure notice. A versioned terminal phase also missed the normal final-edit path, leaving misleading drafts beside the result.
Scope continuation admission/progress/final presentation and cursors by recovery version, preserve the acknowledged source reaction journal, and replace only the new draft with the final. The original worker also repairs proven legacy presentation using exact prior-or-desired provider readback, current source/Turn checks, and edit-only intents. It cannot enqueue work, resend a result, or overwrite a changed body.
Validation: 491 focused private conversation, native steward, progress, and Inbox reply tests passed. The unchanged base reproduces an actual provider failure notice becoming a processing draft. The installed wheel passed 27 targeted cases; 42 unrelated cases were deselected. The repository gate passed 6 direct and 11 selected checks. The signed exact head also passed the full repository gate; live adoption remains a separate acceptance step. Both RFC language mirrors document the boundary.