Repository navigation
fix(trajectory): count the page a cancelled turn was still writing in its end marker - #213
Merged
Merged
Conversation
revan-aleti
approved these changes
Oct 15, 2026
psinghal20
approved these changes
Oct 15, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What and why
When a step is cancelled,
following_live_trajectorycancels the turn's follower and writesend.jsonwith the number of events stored. The sink stores a page in a thread, and counts its events only when the write returns to the event loop. If the cancel arrives after the page is stored but before the write returns, the page is stored but not counted:end.jsongivesnext: 0, while00000000-00000002.jsonlholds events 0 and 1. A reader that trustsnextignores a page that is there.test_a_cancelled_turn_is_marked_ended_after_the_events_it_storedfailed on this race in CI (#190).The sink now writes a page and counts its events in one task, which the follower awaits through
asyncio.shield. Thus a cancel stops the follower but not the write.endwaits for a write that is still running before it reads the count.endruns with the 5-second limit of_in_passing, as before. If the page write takes longer than that, for example during its retries,end.jsonis not written in time, and a warning is logged. Before this change,end.jsonwas written, but itsnextcould leave out a page.How it was tested
putstores the page, then waits 0.2 s before it returns, and the step is cancelled in that time. Without the fix, the test fails 3 of 3 times withnext: 0, the same failure as CI. With the fix, the file passes 5 of 5 times.make unit-test: 8084 passed. 2 tests intest_mcp_cli_builder.pyfail locally with and without this change: the CLI that they generate runs with a system Python that has noclick.ruff checkon the changed files: no findings.mainhas 6 other findings until test(sandbox): fix the lint findings in the SmolVM tests #212 merges.

Confidence Score: 5/5
The PR appears safe to merge; no blocking issue remains.Summary
The PR keeps a page write running after the follower is cancelled.
endwaits for that write before recording the number of stored events.Diagram
sequenceDiagram participant F as Follower participant W as Page write task participant S as Object store participant E as Turn cleanup F->>W: Start shielded page write W->>S: Store page Note over F: Follower is cancelled E->>W: Wait for write to finish S-->>W: Write returns W->>W: Update stored event count W-->>E: Finished E->>S: Write end.json with updated countReviews (2) · Last reviewed commit: "Merge remote-tracking branch 'origin/mai..." · Reviewed by Greptile