fix(codex): continue after source-reply delivery instead of terminating turn#107274
fix(codex): continue after source-reply delivery instead of terminating turn#107274wangyan2026 wants to merge 1 commit into
Conversation
882f40a to
58e7ff1
Compare
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
Codex review: needs real behavior proof before merge. Reviewed July 14, 2026, 8:57 PM ET / July 15, 2026, 00:57 UTC. Summary PR surface: Source -1, Tests +34. Total +33 across 2 files. Reproducibility: yes. from source with high confidence: current main marks an omitted-final delivered Codex source reply terminal, and the linked v2026.7.1 report identifies the resulting release log and stopped Discord turn. A live reproduction was not independently run during this read-only review. Review metrics: 1 noteworthy metric.
Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Risk before merge
Maintainer options:
Next step before merge
Maintainer decision needed
Security Review detailsBest possible solution: Land one canonical Codex bridge fix that requires explicit final intent for inferred termination, preserves exactly-once recovery telemetry, and demonstrates a live Discord progress message followed by a later tool call and one final delivery. Do we have a high-confidence way to reproduce the issue? Yes from source with high confidence: current main marks an omitted-final delivered Codex source reply terminal, and the linked v2026.7.1 report identifies the resulting release log and stopped Discord turn. A live reproduction was not independently run during this read-only review. Is this the best way to solve the issue? Yes at the code level: correcting the Codex-owned termination classifier while preserving recovery telemetry is narrower and more maintainable than adding configuration or a parallel message schema. Live delivery proof and selection of one canonical overlapping branch remain merge gates. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 525db34f80f4. Label changesLabel justifications:
Evidence reviewedPR surface: Source -1, Tests +34. Total +33 across 2 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (23 earlier review cycles; latest 8 shown)
|
68cf8e9 to
e726f9d
Compare
e726f9d to
b80d0bc
Compare
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
b80d0bc to
eebf5d6
Compare
…inating turn Delivered and receipt-confirmed source replies in message_tool_only mode no longer set terminate=true on the dynamic tool response, matching the generic embedded-runner behavior established by PR openclaw#92343. - Remove deliveredSourceReply/receiptConfirmedSourceReply from withDynamicToolTermination conditions - Only final=true + actual source reply explicitly terminates - toolConfirmedSourceReply (tool-returned terminate:true) still terminates unless overridden by final=false - sourceReplyFinal telemetry: still true when final omitted (preserves completed marker for stranded-reply recovery) - Model-facing final guidance updated to explain progress semantics (incorporated from openclaw#107388) Related to openclaw#106961
eebf5d6 to
717146d
Compare
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review |
|
Thanks @wangyan2026 for the original fix attempt and detailed regression analysis. You correctly traced the immediate termination to the Codex source-reply classification and established that omitted-final progress should continue. We landed the maintainer replacement at #108487. It preserves that central direction while adding a canonical success/failure settlement point for omitted finality, ensuring successful turns produce one final reply without breaking failure recovery or explicit final controls. Closing this as superseded by the merged root-cause fix. Thank you for helping isolate the affected path and advance the solution. |
Fixes #106961
Summary
Codex-backed agent turns prematurely terminated after an intermediate source-reply message send, preventing subsequent tool execution; this fix removes the implicit terminate-on-delivery classification so the turn continues until the normal Codex turn/completed lifecycle.
message_tool_onlymode, a successful message-tool send to the source channel setterminate=trueon the dynamic tool response, causingscheduleTurnReleaseAfterTerminalDynamicToolto interrupt the turn before subsequent tools could execute.deliveredSourceReplyandreceiptConfirmedSourceReplyfrom thewithDynamicToolTerminationconditions; only an explicitfinal=trueargument now terminates the turn, matching the generic embedded-runner behavior from PR fix(agent): continue after source message tool replies #92343.extensions/codex/src/app-server/dynamic-tools.ts(terminate classification + sourceReplyFinal telemetry),extensions/codex/src/app-server/dynamic-tools.test.ts(updated assertions + new regression test)shouldReleaseTurnAfterTerminalDynamicTool,resolveTerminalDynamicToolBatchAction,shouldBlockTerminalReleaseForNonTerminalDynamicToolResult, generic embedded-runner suppression logic, finalize path, any config/env/schema surfaceChange Type (select all)
Scope (select all)
Linked Issue/PR
Motivation
Issue #106961 reports a Codex-specific recurrence of premature message-tool turn termination on v2026.7.1. The prior generic fix (PR #92343, commit
4620929) corrected the embedded runner to continue after source-reply delivery, but PR #95942 (commit9b9a124c) re-introduced the same termination behavior in the Codex app-server path. Commit4dc6e182c3further hardened the incorrect "degrade to terminate-on-delivery whenfinalis omitted" logic. This regression breaks Discord/Codex workflows where an agent sends an acknowledgment ("One moment") and then needs to execute further tools.Real behavior proof (required for external PRs)
Behavior addressed: Codex dynamic tool bridge terminates the turn immediately after a successful source-reply message send, preventing subsequent tool calls in the same turn.
Real environment tested: Linux, Node v24.13.1, branch
fix/codex-source-reply-terminate-106961Exact steps or command run after this patch:
Proof A runs the actual patched
createCodexDynamicToolBridgedirectly vianode --import tsx— the same function the real OpenClaw runtime uses, not a copied boolean classifier. Proof B runs the standard vitest suites.Evidence after fix:
The key regression test "continues after an intermediate message-tool-only source reply without final" validates the exact #106961 scenario:
sourceReplyDeliveryMode=message_tool_onlyresult.terminate === undefined— turn is NOT releasedsuccess === truetelemetry.didDeliverSourceReplyViaMessageTool === true— delivery recordedsourceReplyFinal=trueis preserved for all source-reply sends (stranded-reply recovery safety)Observed result after fix:
What was not tested: Live Discord/Codex run with a real Codex-backed agent; requires Crabbox/Testbox + Discord credential. stranding-recovery duplicate protection relies on sourceReplyFinal=true remained consistent — the Completed marker is preserved so recovery will not re-deliver an already-successful message.
Root Cause
PR #95942 (commit
9b9a124c) added Codex app-server source-reply support by includingdeliveredSourceReplyandreceiptConfirmedSourceReplyin thewithDynamicToolTerminationconditions. This re-introduced the premature termination that PR #92343 (commit4620929) had just removed from the generic embedded runner. Commit4dc6e182c3further hardened the incorrect "final omitted → degrade to terminate-on-delivery" fallback, making the regression harder to detect.Regression Test Plan
pnpm test extensions/codex/src/app-server/dynamic-tools.test.ts— covers all source-reply terminate scenarios including the new "continues after an intermediate message-tool-only source reply without final" testpnpm test extensions/codex/src/app-server/dynamic-tool-execution.test.ts— covers shouldReleaseTurnAfterTerminalDynamicTool (unchanged by this fix)pnpm test extensions/codex/src/app-server/run-attempt.dynamic-tools.test.ts— covers terminal diagnostics (unchanged)pnpm test src/agents/embedded-agent-runner/run/message-tool-terminal.test.ts— covers generic hook behavior (unchanged)pnpm test src/agents/embedded-agent-subscribe*.test.ts— covers duplicate-output suppression (unchanged)User-visible / Behavior Changes
Codex-backed Discord agents will no longer stop executing after sending an intermediate acknowledgment message. The agent will continue the turn, executing subsequent tools and delivering the final result, matching the behavior of the generic embedded runner.
Security Impact
Best-fix Verdict
AI Assistance
Risks and Mitigations
Highest-risk area: Duplicate channel messages after fix — if the generic-layer suppression (
suppressMessageToolOnlySourceReplyOutput) does not correctly receive thedidDeliverSourceReplyViaMessageToolflag, the agent could send both the intermediate message and the final output to the source channel.Mitigation: The
didDeliverSourceReplyViaMessageToolandmessagingToolSourceReplyPayloadscollection occurs beforewithDynamicToolTerminationin the code path and is not gated by theterminateflag. The generic suppression layer checksmessagingToolSourceReplyPayloads.length > 0to activate suppression, which remains correct. However, this needs verification viapnpm test src/agents/embedded-agent-subscribe*.test.tsin a full build environment.Compatibility impact: Backward compatible. No config/env changes. No new schema. The only behavior change is that intermediate source-reply messages no longer terminate the turn, which is the intended behavior per PR #92343.
Compatibility / Migration