Skip to content

test(codex): pin the stopped-send receipt rule where #30403 moved it (fix red main) - #30865

Merged
nwparker merged 2 commits into
mainfrom
nwparker/fix-codex-dispatch-boundary-main
Oct 19, 2026
Merged

nwparker merged 2 commits into
mainfrom
nwparker/fix-codex-dispatch-boundary-main

Conversation

@nwparker

@nwparker nwparker commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 2 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​55 $\color{#cf222e}{\Huge{\mathbf{−}}}$​3 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​52
Prod 0 0 0 0

ELI5

Two tests on main went red because two PRs that landed the same day disagreed about where a rule is checked. The rule: a message you stopped or that Codex refused must never later be shown as delivered. That rule still holds in the app. One PR moved the check to a different place, and the other PR's tests were still looking for it in the old place. This PR updates those tests and adds a test that pins the rule where it now lives.

What Changed

Before (main): src/main/codex/codex-structured-dispatch-boundary.test.ts fails "stops a refused steer before its fallback write" and "abandons only the stopped message while waiting for a previous turn to open". Each asserts that the Codex adapter passes on nothing when Codex echoes the id of a stopped send.

Why they fail: #30403 changed the Codex adapter so that every exact echo of a message id is passed on, which lets a second echo retry a receipt whose first save failed. The "a send that is already settled stays settled" decision moved into the chat journal's queued write (JournalSubmissionWriter.acceptLate), which writes nothing for a send that is already rejected or accepted. #30403 deleted the matching adapter-level assertions in the other Codex test files. #28046 added these two tests in parallel, so the two changes crossed.

Is this a production bug? No. A Stop during a send makes the host record that send as a final rejected (cancelled) answer (dispatchSafely / cancelledDispatch in structured-agent-session-handover.ts). A later receipt for it is dropped by the journal. A send Stop withdrew before it was ever written can't be echoed by Codex, because its id never reached Codex. The one remaining race (an echo arriving before the host writes the cancelled row) can only record accepted when Codex has actually proved it holds the message, which is the honest answer. That ordering is already intended and covered ("publishes acceptance during a pending send and never reopens it for retry").

Changes (tests only):

Why

Both PRs' guarantees survive: #28046's "a stopped or refused send is never delivered or confirmed" is now pinned end to end through the host's Stop path, and #30403's "either of Codex's echoes saves the receipt" is unchanged. Restoring the adapter-level filter was rejected: it would bring back the bug #30403 fixed (a failed first receipt save could not be retried), and it would duplicate the journal's single source of truth.

Both #28046 and #30403 are by @brennanb2025. Credit for both behaviours goes to them; this PR only reconciles the tests.

Linked Issue

None. Fixes red main (introduced by 43abd59, #30403, crossing 5319125, #28046).

Visual Proof

N/A, test-only change with no UI or behaviour change.

Testing

  • src/main/codex/codex-structured-dispatch-boundary.test.ts and structured-agent-session-late-settlement.test.ts: 13/13 pass. The new host test fails when the journal's acceptLate guard is removed.

  • All of src/main/codex/ single-worker: 282 files, 2884 tests pass.

  • The local static analysis job steps from pr.yml all pass (import boundaries, lint, anti-slop, native and type-aware code quality, changed-code gate, React Doctor, typecheck:ci, reliability gates, every ratchet including focus-read).

  • Codex review (gpt-6.1-sol, high) found nothing on both heads. An independent Opus review agreed it is not a production bug. Its low finding (the test did not pin the writer guard itself) and its naming nits are fixed.

  • Nothing was verified live: test-only.

  • I manually tested these changes locally

  • Automated tests added/updated, or explained why not below

Agent skill upstream boundary

  • Not applicable, or this change copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

Test-only. No effect on security, platforms, SSH, mobile or wire compatibility.

…since #30403

#28046's dispatch-boundary tests pinned that the Codex adapter drops an echo
for a stopped or refused send. #30403 moved that rule to the journal's queued
late-accept write. Pin it there through the host's Stop path, and keep the
adapter tests asserting what still holds at the adapter: no fallback or second
turn/start write, and the earlier send's receipt survives an abandoned wait.
@coderabbitai

coderabbitai Bot commented Oct 19, 2026

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 1c414af9-88ab-4fb7-8325-40301eb36dee
📥 Commits

Reviewing files that changed from the base of the PR and between bd7633f and 8a68d51.

📒 Files selected for processing: 2
  • src/main/codex/codex-structured-dispatch-boundary.test.ts
  • src/main/native-chat/agent-session-wire/structured-agent-session-late-settlement.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 0 remain after this review.

📝 Walkthrough

The tests now expect settlement receipts for exact echoes of stopped and earlier admitted messages. A new test covers cancellation of an unwritten send while provider dispatch is pending. It verifies that a late provider receipt does not add a dispatch journal row or change the cancelled rejection.

Priority: ⬇️ Low

Merge Risk: ⚪ Minimal · up to 8a68d

The tests protect the stopped-send receipt behavior, and no issue requiring a fix before merge was found.

Pre-merge checks: Passed 5
Check name Status Explanation
Title check Passed The title clearly identifies the test-only change and the stopped-send receipt rule it covers. It is specific and related to the main changes.
Description check Passed The description covers the main required sections, including the plain-language summary, changes, rationale, testing, visual proof, and scope notes. It does not provide a linked issue and does not inc…
Docstring Coverage Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description covers the main required sections, including the plain-language summary, changes, rationale, testing, visual proof, and scope notes. It does not provide a linked issue and does not include the repository checklist, but the description is otherwise complete and focused.

Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2 files.

✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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