Repository navigation
fix(chat): preserve whitespace in original-project peer briefs - #7445
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: actor_kind=model_agent; model=gpt-6.1-sol; provider=OpenAI; declaration_source=runtime_reported; reasoning_effort=max.
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
动机
向既有私有项目会话交付结构化 peer brief 的请求方,会遇到输入被改写的问题。
旧版在发送前折叠空白,导致 brief 中四格缩进、连续空格和不换行空格丢失;本次保留 peer 输入原文,使实际 native input 与获准的 brief 一致。
已验证的结果是原始 brief 完整到达既有会话,同时保留普通消息规范化、空白拒绝、当前授权检查和结果返回。
本次不新增会话、Goal、权限、UI 或协议版本,也不把合成模型响应等同于真实接收方理解和采用。
已安装 App 与真实 provider 的自然接收、独立采用和用户最终任务成果,仍由原有项目协作验收继续资格验证。
改动思路
输入保真属于现有 Codex native adapter 的发送边界;授权、FIFO、修订和返回仍复用共享协作 owner,没有理由增加第二套状态或消息通路。
本 PR 修复 send(project_collaboration=True) 的输入保真,并通过既有 File/SQLite 原会话链路验证;不扩大项目协作权限或宣称父级协作目标完成。
共享协作 owner 先验证 source/recipient grant,再把当前 request 放进原 Session FIFO。execute 读取当前 brief,以 revision/digest 绑定 native write;send 仅在明确的 project_collaboration 模式保留原始字符串。普通输入继续原来的规范化。接收后的 decision 与 return 仍经既有存储返回请求方,没有增加另一条消息或状态通路。
不修改 serializer、全局消息清洗或 UI 可以更直接定位缺陷:JSON 中的空格在 native adapter 被再次规范化才产生损坏。这一修复没有增加用户导航、复制、重复输入或确认轮次;原有明确 source grant 保持必要的权限边界。
具体改动
两文件仅有生产 +2/-2、测试 +4。新增断言读取真实 fake app-server 子进程捕获的 turn/start,并将其中 brief 与提交的原始结构比较,能发现仅检查 revision/digest 或结果文字会漏掉的数据损坏。
先于 diff 阅读的规范:docs/architecture/rfcs/app-conversation-and-async-inbox-v0.md,固定修订 bb150595664fe0e910db9587cff22ea3b471f5ee。下列标签用于本次条款映射,不冒充规范原有编号。
- PEER-IDENTITY:implemented。既有 Session/native thread 与 null Goal 保持不变。
- PEER-CURRENT:implemented。当前 revision-bound brief 完整到达,并经过原 assessment/result owner 返回。
- PEER-FENCE:implemented。native write 时的撤权、身份、修订与取消检查保留;重试仍恢复同一请求和 Turn。
- MODEL-ADOPTION:deferred。packaged/installed provider 交付和自然接收方采用仍按原父级验收继续。
关键代码讲解
CodexChatAgentSession.send:project_collaboration=True 使用原字符串;False 继续space-join(split())。strip()只判断全空白拒绝,没有把处理后的字符串发送出去。bound_owner、execution_mode、read_only_review、output_schema 的现有拒绝条件保持不变。OriginalConversationRequests.execute:现有唯一 production caller 拼装指令与完整 JSON,传入 project_collaboration=True。start_guard 在写入时重新读取当前授权、recipient 和 revision,输入保真不会绕过它。_complete_answer:继续核验当前 revision/digest、独立 decision 和原返回路线;已保存 answer 的重试不再次调用模型。
独立验证:PASS,test_original_conversation_peer.py、test_chat_agent.py、test_chat_ordinary_project.py 合计 497 项。File/SQLite 的新增原文断言在 immutable base 均 FAIL,在 head 均 PASS,准确暴露缩进、双空格和 NBSP 被改变。另有 22 个独立 send 用例 PASS,覆盖 code fence、换行、Unicode 空白、普通模式、全空白拒绝及非法 recipient 配置;相同 oracle 在 base 因原文被折叠而失败。
对主干的风险
最强反例是启用 peer 模式后绕开普通输入约束,或在撤权/修订之后继续把旧 brief 送入 native Turn。现有明确模式和 bound_owner 检查未变,独立用例验证普通模式仍输出原来的规范化结果;全空白输入和非法配置在写入前拒绝。File/SQLite 生产链路还覆盖 native-write 时撤权、修订竞争、取消、FIFO 并发重试、队列丢失、完成后更正、restart 和 lost-return 恢复。
标准 premerge 的 6 个 direct、2 个 selected 检查均 PASS;DCO sign-off 和完整两文件差分已检查,没有引入私有数据、绝对路径或新词汇。未查询、轮询或等待 GitHub CI。此次执行跨真实本地存储与 native adapter,app-server/model 响应为合成;它证明输入和协议链路,真实接收者是否理解、独立采用及已安装 App 行为仍需原验收证据。
语义与 CI 对齐
本 PR 使用已有 typed recipient、grant、revision 和 project_collaboration 模式,没有新增状态或通过字符串分类决定权限。peer input 保真是明确的默认行为修复;ordinary 分支保持兼容。两个文本语义不同的现有调用分支值得保留,另加 sender/helper 会扩大维护面。
我的整体评价
未发现新增阻断 finding。结论为 APPROVE;交付判断是 justified_increment。long_horizon 与 user_experience 均为 preserved:更正和返回继续由原 owner 恢复,输入损坏得到修复,普通会话没有额外准备和确认负担。这里的完整性证据覆盖原始数据到 native input,不把模型的合成回答当作自然采用。
已检查 chat_agent.py、既有 collaboration 页面调用与两文件差分;此修复只改变 native input,不改变页面渲染和布局。
此次独立验证使用真实本地存储和 native adapter、合成 app-server 响应;已安装 App 的自然接收体验仍未在本次复验。
现有 boolean 分支与共享协作 owner 的 placement 合理,当前无需引入新抽象。保留普通消息兼容行为,也保留原 request/revision/answer 的持久格式。该 head 的源代码审阅与本地检查可批准;merge readiness、maintainer merge authorization 和安装资格继续独立核验。本评审固定 head 0104c10808f3daf0b7a31f8a3a7a1735ec51095f,发布前再次核对 head。
English verdict: APPROVE at 0104c10; no blocking finding. Exact peer input, ordinary-mode parity and File/SQLite recovery pass; installed-provider adoption remains outside this source qualification.
Goal And Delivered Outcome
A structured peer brief sent to an existing project conversation could lose code indentation, repeated spaces and non-breaking spaces before reaching Codex. The request still completed with its original revision/digest, masking that the receiver had consumed different content. This was reproduced on both File and SQLite against #7419 and current main.
Preserve the serialized peer input in
CodexChatAgentSession.send(project_collaboration=True), while retaining the existing ordinary-conversation normalization and blank-input rejection. The existing recipient integration case now compares the native input's complete brief with the accepted request.Related to #7419. Intended base:
loopx-project/loopx:main.Author Declaration
Written by: model_agent — OpenAI Codex.
Implemented against the existing peer-recipient acceptance in
docs/architecture/rfcs/app-conversation-and-async-inbox-v0.md, “Next implementation boundary: a project conversation as peer recipient”, atbb150595664fe0e910db9587cff22ea3b471f5ee.CodexChatAgentSession.send; exact native-input brief assertion on File/SQLiteScope And Continuation
Complete for the reproduced input-fidelity defect. Reuses the existing adapter, request, revision, source-grant, FIFO and return owners; adds no protocol, configuration or UI surface. No additional helper or refactor is justified at this boundary.
The broader original-project recipient journey remains subject to its existing installed-App and actual receiver-adoption acceptance. This proposal is independently reversible and does not certify that parent outcome or resolve historical validation/review holds on #7419.
Validation
0104c10808f3daf0b7a31f8a3a7a1735ec51095f.bee2f29b34f8f53a4dcdd31e1e00a5e2bc10a43a; its changes do not touch this adapter or integration fixture. Branch merge base remainsbb150595664fe0e910db9587cff22ea3b471f5ee.uv run --extra test python -m pytest tests/control_plane/test_original_conversation_peer.py -k explicit_grant_and_returns -q.test_original_conversation_peer.py,test_chat_agent.py,test_chat_queue_preparation.pyandtest_chat_ordinary_project.py; before the final behavior-equivalent one-line conditional formatting. Final affected integration rerun: 2 passed.cqr_66246256ee53840eb5e7, fingerprint66246256ee53840eb5e70ce7c9d64baa5e8ae8c8cdc68c69c7fe973bd95c209a. Two files, no review safe-fix pass, zero blockers/warnings/advisories.loopx canary premergeagainst the pinned target-main snapshot: six direct checks, two selected canaries, exact receipt valid, no manual holds. Earlier stale-receipt attempts remain failed observations.The native execution evidence qualifies transport and recovery with synthetic inference. It is not a measurement of model quality, full cost, natural adoption or installed behavior. Current required CI and exact-head review remain separate from these author checks.
Frontend / Visual Evidence
UI impact: none. This repairs bytes supplied to the existing conversation executor; no rendered controls or visual states change.
Type of Change
Boundary Checklist