Repository navigation
refactor: split the agent turn loop and the TUI app into modules - #251
Merged
Merged
Conversation
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
hakula139
force-pushed
the
refactor/split-turn-and-app
branch
from
October 16, 2026 07:30
b438c42 to
528a0f8
Compare
Move `agent.rs` under the engine and split it by concern: `engine/turn.rs` holds the turn loop and stream collection, `engine/dispatch.rs` holds the tool round with its permission gate and approvals, and `engine/compaction.rs` absorbs the auto-compaction trigger beside the summarization request. `engine/abort.rs` holds `TurnAbort` and `await_unless_aborted`, which the turn loop, the tool round, and compaction share, so the dispatch module no longer imports from the turn module that calls it. The turn fixtures join the engine fixtures in `engine/testing.rs`, and each test sits beside the code it covers. The post-compact message helpers move to `session/post_compact.rs`, since the session history strips the prefix on resume and must not import from the engine above it. The moved items are only used inside the engine, so they narrow to `pub(super)`. The module map drops the Agent layer, and the design-doc Sources point at the new files.
`tui/app.rs` keeps the `App` state and its event loop. Terminal input and the actions and ops it produces move to `app/dispatch.rs`, engine and git probe events with the turn lifecycle they drive move to `app/events.rs`, and frame drawing moves to `app/render.rs`. Each test moves beside the code it covers, and the fixtures that several modules share live in `app/testing.rs`, which also replaces a duplicate in-test writer with `crossterm_test_terminal`. Methods called across the new modules widen to `pub(super)`, the render snapshots follow their test module, and the design-doc Sources point at the new files. A new test covers the modal gate passing mouse scrolls through to chat.
hakula139
force-pushed
the
refactor/split-turn-and-app
branch
from
October 16, 2026 13:45
528a0f8 to
89cc0e4
Compare
hakula139
enabled auto-merge (squash)
October 16, 2026 13:45
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.
Summary
As the first part of #148, this splits the two largest files by concern without changing behavior. The slash-command move into a core command module will follow in a separate PR.
agent.rsmoves under the engine. The turn loop and stream collection move toengine/turn.rs, while the tool round, its permission gate, and approvals move toengine/dispatch.rs. The auto-compaction trigger moves toengine/compaction.rswith the summarization request.TurnAbortandawait_unless_abortedare shared by all three modules, so they move toengine/abort.rsto keep the dispatch module from importing the turn module that calls it. Since the moved items are used only inside the engine, their visibility narrows topub(super).SUMMARY_PREFIXand the helpers that write and strip the synthetic post-compact message move tosession/post_compact.rs. On resume, session history strips the prefix. This move also removes its import from the engine layer above it.tui/app.rsretains theAppstate and its event loop. Terminal input, along with the actions and ops it produces, moves toapp/dispatch.rs. Engine and git probe events, together with the turn lifecycle they drive, move toapp/events.rs. Frame drawing moves toapp/render.rs. Methods called across these modules have their visibility widened topub(super).engine/testing.rs. The app fixtures live intui/app/testing.rs, and the app's render snapshots move with their test module. Two existing tests change: the approval-event check now asserts the exact event list, and the duplicate in-test writer is replaced with the sharedcrossterm_test_terminalfixture.Part of #148.
Test plan
cargo fmt --all --check,cargo clippy --all-targets -- -D warnings, andcargo testpass. The test count matchesmain, with one new test.modal_gate_lets_mouse_scrolls_reach_chat, verifies that the modal gate passes mouse scrolls through to chat. It fails if the gate swallows them.pnpm format,pnpm lint, andpnpm spellcheckpass.mainappear as patch misses. Most are test assertion arms that run only when a test fails: the overflow-retry check in the compaction tests, thereply_offixture's panic, and the text-block check in the post-compact tests. Thetest_appfixture's browser stub runs only if a test opens a browser. The jump overlay's guard for a pill wider than the chat area cannot trigger because the label is truncated to fit.