···11+# Code Review View Design
22+33+## Overview
44+55+Add a dedicated code review view that allows users to review changesets file-by-file, mark each file as reviewed, and approve the changeset when complete. Review is tied to a specific commit_id, so changes to the diff invalidate prior review progress.
66+77+## Architecture: Top-level Routing
88+99+The app gains a top-level route concept:
1010+1111+```ocaml
1212+module Route = struct
1313+ type t =
1414+ | Log
1515+ | Code_review of { change_id : string; commit_id : string }
1616+end
1717+```
1818+1919+`lens_tui.ml` becomes a router:
2020+- `Route.Log` renders the existing log app (with its own Focus state machine)
2121+- `Route.Code_review` renders the review component full-screen
2222+2323+Both screens share `store`, `exit`, and `dimensions`. Route state/setter are threaded through.
2424+2525+### Entry Trigger
2626+2727+When the user selects a change in the log view, check if they have a pending review request for that change AND no valid approval (where valid means an approval with `operation_id` matching the current `commit_id`). If so, automatically transition to `Route.Code_review`.
2828+2929+### Exit
3030+3131+Escape returns to `Route.Log`. Review progress is kept in memory, keyed by `(change_id, commit_id)`.
3232+3333+## Review View Layout
3434+3535+Horizontal split-pane:
3636+3737+```
3838++-- Files ------------+-- Diff -----------------------------------+
3939+| check src/foo.ml | diff --git a/src/bar.ml |
4040+| > src/bar.ml | --- a/src/bar.ml |
4141+| src/baz.ml | +++ b/src/bar.ml |
4242+| | @@ -10,3 +10,5 @@ |
4343+| | let foo = ... |
4444+| | -let bar = old_thing |
4545+| | +let bar = new_thing |
4646++---------------------+-------------------------------------------+
4747+| [Shift+R] Mark reviewed [j/k] Navigate [Esc] Exit |
4848++---------------------------------------------------------------- +
4949+```
5050+5151+- Left pane (~25% width): file list from Diff_stat.entries, with review status indicators
5252+- Right pane (~75% width): unified diff for selected file, scrollable
5353+- Footer: context-sensitive keybindings
5454+5555+### Keyboard Handling
5656+5757+- `j`/`k`: Navigate file list
5858+- `Shift+R`: Mark current file as reviewed, auto-advance to next unreviewed file
5959+- `Escape`: Exit to log view (progress kept)
6060+- Page Up/Down, Ctrl-U/D: scroll diff pane
6161+6262+## Review State
6363+6464+### In-memory Progress
6565+6666+A `Map` from `(change_id * commit_id)` to `String.Set.t` (set of reviewed file paths), stored at the route level so it survives component mount/unmount cycles.
6767+6868+### Staleness Detection
6969+7070+The `commit_id` changes whenever the change's content changes (jj creates a new commit for any modification). When entering review view, compare saved `commit_id` with current. If different, clear saved progress.
7171+7272+### Approval Flow
7373+7474+When all files are marked reviewed:
7575+1. Show confirmation prompt: "All files reviewed. Approve? [Enter] Yes [Esc] Cancel"
7676+2. On Enter: call `Store.approve` with `commit_id` as `operation_id`
7777+3. Return to log view
7878+4. On Esc: stay in review view
7979+8080+### Re-review Requirement
8181+8282+Check if any approval's `operation_id` matches the current `commit_id`. If not, the change needs re-review (auto-transition triggers again).
8383+8484+## Data Layer Changes
8585+8686+### New: `Jj.fetch_file_diff`
8787+8888+```ocaml
8989+val fetch_file_diff : change_id:string -> path:string -> string Lwt.t
9090+```
9191+9292+Runs `jj diff -r <change_id> <path> --git` and returns raw unified diff text. Parsed minimally for Catppuccin coloring.
9393+9494+### Store
9595+9696+No schema changes. Existing `Store.approve` takes `operation_id` which we populate with `commit_id`. Add helper:
9797+9898+```ocaml
9999+val is_approved_by : t -> Change_id.t -> User_id.t -> commit_id:string -> bool Lwt.t
100100+```
101101+102102+## File Structure
103103+104104+### New Files
105105+- `lib/tui/code_review_view.ml` — review view component
106106+107107+### Modified Files
108108+- `lib/tui/lens_tui.ml` — Route type, top-level routing, auto-transition
109109+- `lib/tui/jj.ml` / `jj.mli` — `fetch_file_diff`
110110+- `lib/backend/store.ml` / `store.mli` — `is_approved_by` helper