Skip to content

fix(chat): send native turn adjustments from the shared composer - #5368

Merged
huangruiteng merged 1 commit into
mainfrom
codex/app-owner-controls-1001
Sep 30, 2026
Merged

huangruiteng merged 1 commit into
mainfrom
codex/app-owner-controls-1001

Conversation

@huangruiteng

@huangruiteng huangruiteng commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator

Goal and delivered outcome

While a managed Codex turn runs, the App's ordinary composer previously blocked Send and required a separate “Adjust turn” form. This patch lets an instruction such as “Chinese first; do not publish” reach that same turn directly from the shared steward/Goal composer. It never creates a second turn to deliver the instruction.

This is the durable-interaction slice of R2/R3 and GQ08 in App conversations and asynchronous inbox. It changes the managed Codex running-turn default. Attached-host follow-ups retain their next-turn queue; LoopX mode retains its explicit delivery selection; unsupported managed adapters retain drafts with Send disabled.

Scope and continuation

The existing Chat HTTP/runtime ingress owns admission and replay. TypeScript projects the actual session mode and codex_app_server adapter kind; it does not infer execution support from an Agent label. Within the mounted conversation, unknown or mismatched receipts retain the draft and original ingress/turn for retry, including after that turn finishes. Restoring that client retry identity after a full page reload is not qualified by this slice. Confirmed non-delivery can start a new ingress. A successful receipt never erases a replacement draft typed while delivery waits.

Executor receipt is not semantic adoption, delegated-work stop or full GQ08 acceptance. Native owner adoption, scoped stop, installed readback and the two real small-team cycles remain under the existing R2/R3 qualification; this PR does not close them. No new capability, provider, scheduler, Python decision owner or paid model evaluation is introduced.

Validation

  • Tested revision: 2faa6c496e27c37d21a27c388a8fe8ec831a4f58; full scope is nine files.
  • Run state: finished. Input classes: synthetic, public_fixture.
Check kind Result Evidence / limit
static passed npm --prefix apps/presentation/dashboard run build:chat: TypeScript check and verified packaged bundle. Existing chunk-size warning remains.
real_entrypoint passed LOOPX_PERSONAL_WORKSPACE_PACKAGED=1 node examples/personal-workspace-browser-smoke.mjs: all 29 workspace scenarios. Exact native steering, unknown/mismatched receipt retries, completion races, replacement drafts, unsupported adapters, attached queues and existing LoopX controls. Agent output and most API routes are synthetic.
real_backend passed uv run --extra test pytest -q tests/test_chat_turn_steering.py: 10 actual HTTP/file-store/Codex protocol subprocess cases, including stale target, rejection, deduplication and completed-turn receipt replay. Provider subprocess is scripted; no real model interpretation is claimed.
real_backend passed Independently operated packaged composer against a disposable production Chat HTTP server and durable file store: one original turn, one instruction, completed provider response recorded. Synthetic status/catalog and scripted Codex provider. The proxy restart closed the observation stream, so this probe qualifies exact delivery and backend completion, not final-answer rendering.
unit passed npm --prefix apps/presentation/dashboard run test:conversation-returns: session isolation, late return, deduplication and stream preservation.
regression_parity passed Baseline managed Send lockout was reproduced; candidate supports exact steering while the original send promise remains pending. Attached next-turn queues and unsupported-adapter no-effect behavior remain. Fixtures now use production adapter kinds and wait for completed replies when testing genuinely new questions.
static passed Exact-scope change-quality receipt, public-boundary scan and git diff --check; generated assets and private probe evidence excluded.
static passed Goal-qualified risk-based premerge: 3 diff checks and 16 selected checks passed; no failures or skips.
manual not_run Paid model adoption / release evaluation and installed-App promotion: intentionally separate from ordinary PR validation.

Frontend / visual evidence

Before: an in-flight managed conversation disabled the ordinary Send control; adjusting work required opening and submitting another form. After: type the instruction and use the same Send control. Idle layout, navigation and initial CTA are unchanged.

The packaged running state was inspected on desktop and at 390×844: the conversation, truthful elapsed/activity feedback and original-turn interrupt remain visible; the existing composer status states that messages adjust current work. Narrow content fits without horizontal overflow and Send is reachable. Uncertain delivery remains an explicit error with the draft preserved. Public reproduction: the existing composer-session-admission, conversation-activity and attached-host-follow-up browser scenarios; synthetic screenshots were inspected locally; no live/private screenshots are published.

Attention review: remove a redundant form from the ordinary correction path without adding another toolbar or status panel. The backend receipt remains authoritative. The adjacent refactor removes a duplicate frontend active-turn rejection that prevented durable receipt recovery after completion.

Shared-authority fixture impact: N/A; no authority provider, writer fence, persisted schema or storage migration changes.

This changes App product behavior and is left for maintainer merge under repository policy. It is proposed code, not an installed improvement.

Signed-off-by: huangruiteng <huangrt01@163.com>

@huangruiteng huangruiteng 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.

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

精确评审提交:2faa6c496e27c37d21a27c388a8fe8ec831a4f58。未发现本次有界交付的阻断问题。这是可验证的输入体验增量;真实模型采用、完整页面刷新后的追加请求恢复、委派工作的停止和安装后验收仍未完成,不把执行器回执写成整体 GQ08 已达成。

动机

正在运行的 Codex 工作原来把普通发送按钮锁住,用户需要另开“调整本轮”表单才能纠偏。对“给 LoopX 做份社区问卷,先给我草稿”这样的工作,途中再说“先做中文,别发布”应该使用当前输入框。这次把共享管家和 Goal 的普通输入接到已有精确回合控制,减少一次找控件、重述内容的操作;R2/R3 的完整采用与小团队验收继续开放。

改动思路

我比较了保持现状、直接解锁发送和复用已有 steering 三种方案。直接解锁会提交新 Turn,与单回合准入冲突;保持原表单保留了已证明的操作负担。当前实现复用同一个回调、HTTP transport 和后端 durable ingress,界面只根据实际 Session 模式与 adapter kind 展示入口,后端判断回合及执行器是否真的可接受。搜索了基线与当前提交的普通输入、调整控件、attached queue 和 LoopX mode 调用点,未发现新增第二套执行权或管家特化决策源。

具体改动

关键代码讲解

  • chatSessionSupportsSteering(src/data/chat.ts:707)按 codex_app_server 和 Session 关系派生可用性。独立真实后端探针暴露了之前 fixture 用 Agent 名代替 adapter kind 的问题;本次一并把公共 fixture 改成真实运行时词汇。
  • sendMessage(personal-workspace-page.tsx:1631)为普通追加消息固定原 Session、Turn 和 ingress。未知或不匹配回执保留同一请求重试,明确未送达才允许新的 ingress;成功也只清理原来提交的草稿,保留等待期间新输入的文字。原发送 promise 还在等回复时,新的纠偏不再被它锁住。
  • onSteerConversationTurn(dashboard-page.tsx:2950)供普通输入和既有调整表单共同使用。移除了前端重复的 active-Turn 拒绝,允许后端对已结束原回合的 delivered ingress 做准确读回;用户消息仍按 ingress 去重。

五个既有浏览器回归/fixture 文件补足未知回执、错误 target、完成竞态、原 promise 未结束、替换草稿、不支持的 adapter 和 attached queue 对照。真正的新问题等待前一回复完成,避免被误当成当前工作的指令。RFC 明确披露 managed Codex 运行中 Send 的默认变化及回执的能力边界;没有新增协议版本、Python 决策源、生成资源或迁移分支。

对主干的风险

最强反例是原消息可能已经送达,回执丢失之后原回合结束、甚至另一个回合开始,此时重试不应重复工作或改变目标。打包场景覆盖完成后的同 ingress 重试;实际 HTTP/file-store/Codex 协议子进程测试还拒绝同 id 换目标或换内容,并验证并发投递去重。不支持的执行器不获新 effect,恢复真实 adapter 后可继续完成原回合;attached 仍排队,LoopX mode 的显式 delivery 不变。

本次实际执行:TypeScript 校验与 source-verified chat bundle、29 个打包 workspace 场景、10 个真实 HTTP/file-store/脚本化 Codex 子进程测试、conversation-return 单测,以及 3 个 diff 检查和 16 个风险 premerge 检查,均通过且没有跳过必需项。提交前验证的代码树与此提交逐文件相同,提交后的精确 scope quality receipt cqr_2c124c55dfe42e976e3b 已重新读回为 valid。未查询或等待 CI。

独立操作的打包输入框还接过一次隔离的真实 Chat HTTP/store:只有一个原 Turn、一条追加指令及记录的完成答复。该探针使用脚本化 provider;代理重启关闭了观察流,所以它只证明投递与后端完成,不证明最终答复在真实代理 UI 中正确呈现。桌面与 390×844 打包运行态已检查,输入和发送可达、无横向溢出;没有把本机私有数据或截图上传。

语义与 CI 对齐

复用既有 Session/Turn/live_steering 词汇,默认变化写进 RFC 与回归场景,接受提示只说“执行器已接收”。这里是当前回合控制,不授予 peer 生命周期、Goal 写权限或团队停止能力,也没有将硬性规则改称建议。普通重试身份只在本次挂载的对话中保留;完整页面刷新后的该身份恢复尚未验收,不能用后端 durable receipt 自动推断前端也已恢复。

我的整体评价

有界交付对持续执行和用户体验均有正向价值:纠偏不创建第二份工作,未知回执有准确的恢复目标,用户使用同一个输入框即可调整当前任务。附带重构删除了重复准入判断,保留的 attached/native 路径对应不同真实关系,不是无证据的旧数据兼容。整个差异 195 行新增、53 行删除,主要增量用于现有回归;没有为了后续设计新增闲置层。本次 APPROVE 仅针对这个可回滚的共同输入路径,真实采用、刷新恢复及安装行为仍由已有 P0/R2/R3 后续验收负责。涉及 App 产品行为,按仓库规则留给维护者合入,未自行合并。

English verdict: APPROVE - 2faa6c496e27c37d21a27c388a8fe8ec831a4f58. Shared managed Codex composer reaches existing exact-turn steering with pinned retry identity and draft preservation. Packaged, real HTTP/store/scripted-provider and risk-based checks pass. Executor receipt is not semantic adoption; full reload restoration, installed promotion and live team acceptance remain open. Maintainer merge required.

@huangruiteng
huangruiteng merged commit 3156771 into main Sep 30, 2026
31 of 34 checks passed
@huangruiteng
huangruiteng deleted the codex/app-owner-controls-1001 branch September 30, 2026 20:08
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.

1 participant