Code Review
When several branches are in progress, reviewing them can become a separate task. Lattis keeps the branch diff, draft comments, optional agent pass, and review verdict in one workspace.
Review works on any branch with a checkout. It is most useful on the pull requests your team asks you to read.
The three workflows
Section titled “The three workflows”The Review view serves three workflows. Each one has a section on this page.
- Review your own branch. Run an agent pass, dismiss the findings that do not matter, and hand the rest to Auto Fix before you push. Nothing reaches GitHub.
- Review a teammate’s pull request. Open it from the queue, read the diff, accept the findings worth sending as draft threads, and post a verdict with anchored line comments. See Finish the review.
- Respond to a review you received. Read the reviewer’s threads in place. Accept the ones you take into Assist and fix them with Auto Fix, or reply with a reason for the ones you do not. Push, and re-request review. See Respond to review feedback.
One surface connects them: the staging area in the Assist pane. An agent pass fills it, a reviewer’s thread joins it when you accept one, and Auto Fix works through it. Every item in it is yours to edit or dismiss.
One rule connects them too: feedback has one owner. A draft thread lives on your machine, and you manage it in the pane. A posted thread lives on GitHub, and GitHub is the source of truth for it. Lattis changes a GitHub thread only through the GitHub API, and shows you what GitHub reports back.
Open the Review layout
Section titled “Open the Review layout”Two paths open a review:
- From the toolbar — pick Layouts › Review. The layout puts the Review view in the large left pane. Assist and Files share the top-right pane. Conflicts, PR details, and Spend share the bottom-right pane. The PR details tab shows the pull request as GitHub’s Conversation tab does: the description, each comment and review, and a checks summary. The tab appears only when the branch has an open pull request.
- From the queue — click a row in PENDING REVIEWS in the sidebar. Lattis opens the branch and applies the Review layout for you.
The Review layout starts no agent session. The agent pass runs on demand, and Auto Fix launches its agents in the background.
You can also add a Review tab to any pane with the pane’s + menu. The view is off by default, like the Session view.
The pending review queue
Section titled “The pending review queue”PENDING REVIEWS is a sidebar section between Conversations and Projects. It lists every open pull request where GitHub asked you for a review. Lattis refreshes it about once a minute, and immediately after every in-app pull-request action.
Each row shows the pull-request icon, the branch, the age of the request, the pull-request number, who asked you, and the churn. Rows group by project and sort oldest request first, so the request that waited longest sits at the top.
The queue only lists repositories you registered as Lattis projects. Register a project later and its requests appear on the next refresh.
Click a row and Lattis lands you on the branch, ready to read:
- It creates a git worktree for the branch when you have no checkout. It fetches
the branch from
originfirst, then checks it out. - It applies the Review layout.
- It loads the branch diff.
A worktree that Lattis creates this way stays out of the Projects tree while the request is live. Your own branches keep their rows.
When a new request arrives, a modal announces it. Begin Review opens the oldest new request. Every new request joins the sidebar list either way.
Read the branch
Section titled “Read the branch”The Review view renders the whole branch as one diff against the merge base with its base branch. The header carries the branch name, the diff scope, the churn totals, and your progress.
The file rail
Section titled “The file rail”The rail lists the changed files in Guided order: code first, by churn, and low-signal files such as lockfiles last. It groups them into chapters — Core changes, Tests, and Low signal. Switch to Path order when you want to find one known file.
Viewed marks
Section titled “Viewed marks”Mark a file viewed and the rail strikes it through. A mark records the file’s blob id, so it becomes stale when the file’s blob changes. A stale mark shows a hint row and counts as unviewed again. Marks survive a restart.
Two diff bases
Section titled “Two diff bases”The header’s scope chip picks what you read:
| Base | What it shows |
|---|---|
| Branch | Everything past the merge base. The default. |
| Since pass | Only what changed since your last recorded pass. |
Since pass is the incremental read. Come back to a branch that got new commits, and it shows you the new work alone. Your viewed marks are kept.
The diff body
Section titled “The diff body”The diff renders split by default — old on the left, new on the right — and switches to unified from the header. Text wraps at the panel border. Runs of ten or more unchanged lines fold to three above and three below; a thread anchored in a run blocks its fold. Drag the rail boundary and the split seam to resize them. Both widths persist.
Drop into the editor
Section titled “Drop into the editor”Hold ⌘ (Ctrl on Linux) and click any diff line to open the file in an editor
tab at that line — the same gesture that opens a path:line link in a
terminal. The gutter numbers underline while the modifier is held. A removed
line lands where its replacement is. The header’s Open File button, the o
key, and Open File on a file’s right-click menu open the file at its first
changed line. The editor lands beside the diff, never over it.
The diff reads commits, so an edit you save does not show in it until you commit. The rail marks such files with an amber dot, and the header says edited · diff shows the last commit.
Draft comment threads
Section titled “Draft comment threads”Click any diff line, or its hover + chip, to open the composer. Give the comment a kind — issue, question, nit, or praise — write the body, and save it.
Saved threads render under the line they describe. Edit, resolve, reopen, and delete them from the thread itself. Edit reopens the composer with the thread’s text and kind, and Save rewrites it in place. Threads are drafts: they stay on your machine until you post a verdict, so nothing reaches GitHub before you decide. They survive a restart.
Review Assist
Section titled “Review Assist”Assist is the agent companion to Review, and the home of the staging area. It runs one read-only pass over the branch and returns a queue of findings. It never writes to your repository, and it never touches your threads: a finding becomes a draft thread only when you accept it, and code changes only when you launch Auto Fix.
Run a pass
Section titled “Run a pass”Press Start and pick an agent. The menu lists every agent with a read-only one-shot mode, with its binary already resolved — Sawyer, Claude, Codex, Pi, and OpenCode. Re-run keeps the agent that ran last. Stop ends the pass.
The pass gets the branch range diff, read-only file tools, and no shell. It reports each finding through a tool call, so findings stream into the pane as the agent finds them.
What a finding says
Section titled “What a finding says”Every finding answers three questions, in three fields:
| Field | Question |
|---|---|
| What is wrong | The defect, and the concrete fix. |
| Triggers when | The exact input, state, platform, or sequence of events that makes it happen. |
| Impact | Who is affected and how when the trigger fires, and why that earns the severity. |
The pass is told that severity follows from impact, never from how the code looks. A finding it cannot give a trigger and an impact for is one it has not confirmed. Read the two lines under a card to check the ladder against the consequence instead of taking the rank on faith.
The five lenses
Section titled “The five lenses”Every finding carries one dimension:
| Lens | Question it asks |
|---|---|
| Correctness | What happens on the unhappy path — empty, huge, malformed, or duplicate input? |
| Design | Does new code live where its dependencies say it should, and follow a pattern the codebase already has? |
| Compatibility | Will this behave the same on every platform the project ships to? |
| CI / release | Would this survive the project’s own gate — formatters, linters, tests, pins? |
| Tests / docs | Does new branching logic have a test? Did this change invalidate a doc? |
Findings land on a severity ladder: critical, high, medium, low, and nit. Filter the queue by severity to read the worst first.
Anchors you can trust
Section titled “Anchors you can trust”Each finding includes the line it describes. Lattis resolves the path against the files in the changed range and adjusts the line number against the file’s current text. Click a finding to jump to its row. A finding Lattis cannot place lands in a labelled tail section instead of on the wrong line.
The staging area
Section titled “The staging area”The queue under the pass is the staging area. Every item in it takes one of these actions:
- Edit opens the item in place: the title, the severity, and the three fields. Save writes them back. The anchor stays as the pass verified it.
- Dismiss folds the item into the triaged drawer. Undo brings it back.
- Accept as draft mints an attributed draft thread at the finding’s anchor. It then behaves like a thread you wrote. This is the reviewer’s move, so it appears only when the branch is someone else’s: the draft is what a verdict posts to their pull request.
- Auto Fix, from the pane header, hands every item still open to an agent. See Auto Fix.
Each card reads in order: the severity chip and the title, the file and line under it, then what is wrong, then the trigger and the impact on their own labelled rows. Findings render inline code and bullet lists as written. A long body folds after a few lines with Read more. The staging area survives a restart, and it follows the worktree rather than the pane. A re-run of the pass replaces the previous pass’s findings and keeps the reviewer threads you accepted into it.
Discuss the pass
Section titled “Discuss the pass”Discuss, on the verdict strip of a finished pass, reopens the pass’s own conversation as an interactive session beside the Assist pane. Ask why a finding got its rank, what else the agent looked at, or what it missed. The agent that formed the conclusions answers with its context intact. An agent that keeps no transcript starts a fresh session seeded with the queue instead.
The discussion works the queue with you. The agent keeps report_finding, and
gains three more tools: update_finding revises an item’s title, body,
trigger, impact, or severity, dismiss_finding drops one that does not stand,
and list_findings reads the queue as it is now. Every change lands in the
staging area the moment the agent makes it, and the agent is told to say what
it changed and why. An item you accepted as a draft is yours: the agent cannot
dismiss it. Dismissals from the chat carry an Undo, like your own.
What the agent is doing
Section titled “What the agent is doing”One line above the queue says where the pass stands: a state pill, one sentence (what the agent is reading right now, or what it raised), and the facts under it. The chevron at its right opens the activity card: a bar per model round and a ticker of tool calls as they complete. Its Output tab streams the agent’s own stdout, line by line.
The card carries no tokens, cost, or model on purpose. The Context view reports all of those for the same pass session. Context answers what the pass costs. Assist answers what it is doing. The Review layout does not open a Context tab. To see the pass cost, add Context from any pane’s + menu.
Auto Fix
Section titled “Auto Fix”Auto Fix turns the staging area into work. It lives in the Assist pane’s header, beside the queue it works through. It compiles every open item into one numbered prompt and launches the agent you pick on this worktree, in the background. Each item carries what is wrong, its trigger, and its impact, so the agent fixes the cause the trigger names rather than the symptom. A reviewer’s thread travels with its whole conversation.
An item is open for fixing until you dismiss it, the agent fixes it, or GitHub resolves the thread behind it. Accepted findings still count: a finding you drafted into the review is one you stand behind. Draft threads you wrote by hand in the Review pane are review feedback, not fix items. To fix one, stage it by running a pass or accept the reviewer’s thread it answers.
Every item carries a stable id. The agent reports an outcome for each id: fixed, skipped with a reason, or partial. Lattis never guesses an outcome. An item the agent does not report stays open.
As reports land:
- A fixed item folds into the triaged drawer with the agent’s summary.
- A fixed reviewer thread also shows waiting on push in the Review pane. Lattis resolves it on GitHub after your next push. See Fix, push, resolve.
- A skipped item stays open and shows the agent’s reason. The next Auto Fix run includes it again.
The strip above the queue reports the run from launch to exit: the agent, the count, a live tally, and Watch to open the session. Auto Fix needs at least one open item. When the Review pane holds the same branch, Lattis refreshes the feedback from GitHub before the launch. If that refresh fails, the launch stops, so the agent never works from a stale list.
Finish the review
Section titled “Finish the review”Finish review posts to the branch’s pull request. Four verdicts:
| Verdict | What it does |
|---|---|
| Approve only | Records the verdict. Merge stays a manual step. |
| Approve and merge (squash) | Waits for the gate check. It never merges red. |
| Request changes | Posts your draft threads as unresolved, with the verdict. |
| Post comments | Posts your draft threads, with no verdict. |
Lattis posts threads as anchored line comments when GitHub accepts the anchors. If a thread cannot be anchored, Lattis refuses the batch and identifies the affected thread so you can edit or delete it before posting again. If GitHub rejects the batch, Lattis shows the error and keeps your drafts.
The review pins to the revision you read. A push that lands mid-pass therefore cannot shift your comments onto other lines.
GitHub checks the whole batch at once. If GitHub rejects it, Lattis posts nothing and shows the error. Your drafts are kept. Lattis never falls back to a degraded shape.
A branch with no open pull request tells you so: verdicts need a pull request. Open one from the branch menu first.
After the verdict
Section titled “After the verdict”A posted thread changes owner. It now lives on GitHub, and Lattis records its GitHub thread id. From then on the pane shows the live thread, with the state GitHub reports. To resolve it, resolve it on GitHub — the author’s own Lattis does that automatically when the fix lands (see Fix, push, resolve).
A posted verdict also clears the review request on GitHub. Lattis then removes the worktree it created for that review. A checkout you opened yourself is never touched, and a checkout with uncommitted changes asks you first.
Respond to review feedback
Section titled “Respond to review feedback”This is the third workflow: a reviewer requested changes on your pull request, and you fix them.
When the verdict arrives, Lattis announces it. Click through and the Review layout opens your branch with the feedback in place. You can also open the branch yourself at any time.
What the pane shows
Section titled “What the pane shows”- Verdict chips in the header, beside the pull-request pill: one per reviewer, with the verdict.
- The status strip under the header: one line that names the next step, with its action as a button at the far right. The pane shows one strip at a time. From the top of its ladder: a failed GitHub sync (Reconnect), a branch behind origin (Get latest), a running Auto Fix (Watch), commits or resolutions waiting on push (Push), reviewer threads waiting on you (Accept all into Assist), threads staged in Assist, everything resolved and pushed (Re-request review), and new commits since your last pass. A quiet branch shows no strip.
- Reviewer threads, anchored under the diff lines they describe, next to your local threads. Their text is read-only in the pane. Their content and their resolved state come from GitHub.
- Orphan threads in a tail section, “Threads outside the shown diff”. A thread lands there when a rebase or force-push outdates its anchor. Lattis does not guess a new line for it. Auto Fix still receives its full conversation.
Lattis refreshes the feedback about once a minute while the Review tab is visible, and after every post, push, and Auto Fix run. GitHub stays the source of truth: if someone resolves a thread on github.com, it leaves your pane on the next refresh.
Answer each thread
Section titled “Answer each thread”Every reviewer thread that waits on you offers two answers:
- Accept → Assist copies the thread into the staging area as an item for Auto Fix, with its whole conversation. The card then reads staged in Assist, and later fixed or skipped as the agent reports. Edit the item in Assist to add what the agent should know. Dismiss it there if you change your mind.
- Reply with a reason posts your reply on the thread and leaves it open. The reviewer decides what the reason is worth. The card reads replied until the reviewer writes back, and the thread stays out of Accept all.
Threads you posted yourself offer neither. They are questions for the other side.
Fix, push, resolve
Section titled “Fix, push, resolve”- Accept the threads you take into Assist, then run Auto Fix there. The prompt carries every staged item that is still open.
- The agent works through the items and reports each outcome. Fixed reviewer threads flip to waiting on push.
- Push the branch. Lattis then closes the loop on GitHub for each fixed thread: it posts a reply with a short fix summary and the commit id, then resolves the thread. Your reviewer can audit every resolution on GitHub.
Lattis never resolves a thread before the fix commit is on the pull request. A resolved thread with no visible fix would mislead the reviewer.
Until the push, the resolutions wait in a queue. The status strip counts them (“2 resolutions and 3 commits are waiting on push”) and offers the push. The queue survives a restart and replays on the next sync.
Re-request review
Section titled “Re-request review”The “requested changes” chip stays in the header until the reviewer submits a new review. GitHub has no way to retract a verdict, and Lattis does not hide it. Instead, when every thread is resolved and the branch is pushed, the pane offers Re-request review. One click sends the request, and the loop restarts on the reviewer’s side.
Keyboard
Section titled “Keyboard”| Key | Action |
|---|---|
j / k | Previous and next file in the reading order. |
x | Mark viewed, then advance. |
c | Comment on the selected file’s first changed line. |
o | Open the selected file in the editor at its first changed line. |
esc | Close the composer or the open menu. |
Utilities
Section titled “Utilities”The ⋮ menu holds the utilities, never an outcome:
- Copy pass as Markdown — your threads and marks, for an issue or a chat.
- Discard draft threads — drops the drafts. Viewed marks stay.
- Refresh — reloads the branch diff.
Ask for a review
Section titled “Ask for a review”The other half of the loop is asking. Lattis prompts you when you open a pull request that nobody has been asked to review, and the branch menu and the command palette both carry Request Review. The picker ranks candidates by who wrote the code you changed. See Pull Requests & CI.
Limits
Section titled “Limits”- Review verdicts and the pending queue need a connected GitHub account, and repositories on github.com. See Pull Requests & CI.
- The pull-request half needs a pull request. The diff, the threads, and the agent pass all work on a branch without one.
- An agent pass needs an agent. Sawyer ships with Lattis, so a fresh install can run one.
- Pull Requests & CI — open, request, and merge.
- Stoplights & Status — find the branch that needs a review.
- Changes & Spend — what the branch produced, and what it cost.