Skip to content

fix(chat): retain native completion before response parsing - #7986

Merged
huangruiteng merged 2 commits into
mainfrom
codex/steward-durable-native-result-20261103
Nov 3, 2026
Merged

huangruiteng merged 2 commits into
mainfrom
codex/steward-durable-native-result-20261103

Conversation

@loopx-agent

@loopx-agent loopx-agent commented Nov 3, 2026 •

Copy link
Copy Markdown
Collaborator

A completed native answer could remain unrecoverable after the upstream host cleared its trajectory: Core retained only the parsed prefix, so the original reply worker could no longer prove and return the full answer. This change retains the original completion facts privately before response parsing and lets the existing worker use them to repair a completed Turn’s text after cleanup or restart.

The Antigravity adapter records only the exact input, final text, step identity/status and normal-stop facts. Core freezes one private artifact under the original running Turn and upstream invocation; it is excluded from public Turn and event projections. Capture I/O failure logs only its error type and preserves the valid primary-answer path; invocation mismatch and immutable-result conflicts still reject. Recovery reuses the existing source, anchor/hash, execution, time and normal-terminal checks, followed by the existing typed conversation rule and original delivery receipt. Failed-Turn recovery keeps its live/latest-input requirement. Unknown effects and sends remain pending.

Validation: 486 relevant Python regressions, 17 selected retention/I/O cases and three independent original-queue probes pass. Coverage includes the native HTTP boundary and original private-reply worker with long Unicode text, later input, cleared native history, restart/event compaction, unavailable provider, changed source/closed session, mismatched anchor/execution/invocation, failed Core and lost delivery acknowledgement. An identical independent original-queue probe fails on the target base because no full result is returned after cleanup and passes on this change. Original Turn/events remain byte-identical and no model invocation is replayed. Standard pre-merge checks pass with an inherited unrelated maintainability advisory.

This protects results captured by the new service. It does not reconstruct completion evidence already lost by older versions, complete unknown-effect work, or qualify separate thinking-summary and desktop acceptance changes.

Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>

@loopx-agent loopx-agent left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewer: model_agent; gpt-6.1-sol; OpenAI; runtime_reported; reasoning_effort=max

Approval conclusion (author-owned PR; GitHub blocks formal self-approval)

动机 / Motivation

没有发现阻塞当前提交的缺陷。受影响的是通过原私聊等待 Antigravity 已完成答复的用户。原生执行正常结束、解析正文被截短、随后上游清理轨迹时,原回复 worker 即使仍有请求也无法补回完整答案;本变更在原执行结束时保留必要事实,恢复后仍经原 worker 返回。

已在真实 native HTTP 边界、Core 文件状态和原私聊 provider 夹具中验证:长文跨后续输入、事件压缩和重启后完整送达,重复扫描不重发业务或答案。本 PR 不重建旧版本已丢失的终态证据,不放宽失败请求的重放条件,也不交付新的思考摘要或桌面呈现。旧记录缺证、真实上游模型与安装后端到端验收仍需原维护流程继续完成。

改动思路 / Approach

事实采集和文件 IO 留在原 provider/Chat store,恢复资格继续由既有 TypeScript 规则决定,发送仍使用原回执事务。当前边界是捕获、私有持久化、严格读回和原投递这一条完整链;保留失败及未知效果,父级消息闭环继续开放。正常终态后,adapter 在解析前只保留原输入、最终文本与步骤身份/状态;Core 把它作为私有事实写入原 Turn 的文件区域,不把原 prompt 或原始文本塞进公开事件。后续补回继续走同一个原回复 worker,无须用户再次描述任务或授权一次重复业务。

不做修改会继续依赖上游保留历史;只修 parser 无法补回已被清理的事实。完整轨迹归档又会额外保存工具输出和 reasoning。本实现复用共同验证器和现有发送事务,没有第二条队列、调度器或 Python 资格判定 owner。补充存证发生 IO 错误时,主答复照常完成;身份或不可变证据冲突仍拒绝。

具体改动 / Changes

按 accepted specification docs/architecture/rfcs/app-conversation-and-async-inbox-v0.md、spec_revision=ac74f90c4778381b6fcedd5d76059522591c3f42 的原有合同审查;固定版本原文未由本 PR 改写。下表使用原文行段作为 criterion_id:

criterion_id 当前提交的处置
L28-L30 implemented:provider/文件 IO 留在 Python,资格判断继续归原 typed owner。
L67-L77 implemented:沿原 Turn 与冻结发送意图恢复;丢失回执不盲重发。
L92-L101 implemented:每次补回仍重新核原来源和绑定,关闭或改源后拒绝。
L270-L285 implemented:只投递既有结果,不重新受理输入或调用模型。
L103-L105 deferred:安装后真实 provider/App 资格由既有维护流程继续验证。

关键代码讲解

  • AntigravityAdapter._run_turn 在既有正常终态分支后发出私有 completion facts。只保留验证所需输入、最终文本与 metadata,不保存原生工具输出或思考字段。
  • event_sink 私下消费该回调;retain_native_result 在原 running Turn 锁内核 upstream identity,按 0600 原子冻结且禁止覆盖。仅补充 IO 的 OSError 会降为脱敏类型日志,避免把有效答复误判失败。
  • completed_result_observation 让 live 与 retained 两种取证方式共用输入 hash、时间、execution、覆盖和正常 stop 检查;_original_native_result 仅为 completed 原文恢复选择 retained facts。failed 请求继续要求 live/latest 证据,之后仍须原 typed/current-source 判断与发送回执。

完整 diff 为五文件 +244/-23:生产代码四文件 +99/-22,测试一文件 +145/-1。旧记录没有 artifact 时仍保留原 live 路径,原 Turn 与事件不因补回而重写。

对主干的风险 / Risks

最危险的情况是把旧快照当成现时上游状态,或让额外存储失败拖垮本来可用的主答复。这里保留的只是原次观察;它不证明当前 latest input、容量或重放许可。专门验证了目录被占用时原答复仍正常送达、没有 cancel/resend,并且日志仅含错误类型。source/anchor/execution/invocation 不符、Core failed、Session closed 和未知发送仍分别保持原有拒绝或待核状态。

验证 结果与边界
五个相关 Python 测试文件 PASS,最终提交 486 项通过。
原消息保留与 IO 定向测试 PASS,17 项;含长 Unicode 正文、真实 HTTP 协议、清理后的历史、重启/事件压缩、provider 不可用和丢失 ack。
独立原队列反例 相同原流程在 base 无法补回答案,在当前提交通过;另验证 immutable/异 invocation、原 source 恢复到期后继续,以及主答复 IO 非回归。
标准合入检查 PASS,六项 direct 与两项 catalog;有一个与本改动无关的原有 maintainability advisory。

原有 advisory 在固定 base 与审查源得到同一个 machine_section_projection.render_canonical_todo_sections 超长函数签名;当前 diff 不改变其因果路径,未调宽门槛。最终源码和 PR 正文公开边界扫描通过。CI 按当前合同未查询、轮询或等待。

语义与 CI 对齐

私有 turn.native_result 回调及 provenance 标签属于现有 native result 的本地 IO 扩展,不是新 actor、任务或权限。原生结果、Core completion、投递确认继续分开;typed 恢复规则未更改。此为默认修复,没有 opt-in/default-off 声明。发现源恢复后仍需到既有 discovery backoff 到期才继续的行为保持不变,没有用重复空查绕过。

我的整体评价 / Verdict

这是 justified_increment:long_horizon 与 user_experience 在所测原回复链路上改善,补回无需新增用户操作。本次只改变内部结果保留与既有消息恢复路径,没有修改 renderer、版式或交互组件;消息正文沿用已有富文本发送器。实际桌面和真实 provider 的视觉表现未在本 PR 重新验收。

生产机制与问题相称;保留旧 live reader 是因为确有未捕获旧请求和 failed 请求,而非增加版本分支。当前证据支持这条原路径的捕获、读回和幂等返回,不代表旧历史或父级 Bot 任务全部闭环。合并资格、真实安装采用和外部模型仍分别验收。评审头与远端完整代码 diff 已再次核对。

English verdict: APPROVE — head 0eccdae; no blocking finding. Original-result retention and primary-answer IO safety pass current local validation; missing historical proof and installed/model acceptance remain explicit.

@huangruiteng
huangruiteng merged commit 6020ddf into main Nov 3, 2026
22 of 27 checks passed
@huangruiteng
huangruiteng deleted the codex/steward-durable-native-result-20261103 branch November 3, 2026 11:57
yanfeng98 pushed a commit to yanfeng98/nano-loopx that referenced this pull request Nov 4, 2026
The native-retention journeys added in loopx-project#7986 request the imported
`language_server` pytest fixture by name, which ruff reports as F811.
Keep the fixture injection and annotate both journeys, matching the
existing imported-fixture convention in the test suite.

Signed-off-by: lusendong.6789 <lusendong.6789@bytedance.com>
Co-authored-by: TRAE CLI <traecli@bytedance.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants