Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

The files

One seat’s whole working tree, readable and commentable: the tree, a read-only reader over each file, and the comments dropped on what was read, listed beside the reader. It is reached by its URL, by the back link in its header, and by the strip’s files slip on the seat’s own page - one place, and the tree follows the seat. The drawing it is held against is web-files.html, beside this page.

Two halves, like the review page’s: the Files tab is the tree, the reader and the comments rail - which carries the dropped list and the finish and is that tab’s alone - and the Conversation tab is the seat-tree scope’s rounds, newest first, taking the whole row: the same conversation the review page draws of a branch, through one component both pages use.

It lives at /session/{org}/{project}/{label}/files. The tree is the seat’s own: a worker’s worktree when the seat is a worker, the lead’s checkout on the lead, which is the directory the record already reports as the seat’s scanning cwd. Nothing here reads the launch directory, and the tree needs no new walk: the seat’s file index - what the composer’s @ list already reads - is the tree.

Where a comment is filed

A comment dropped here is filed under a seat-tree scope, spelled tree:{org}/{project}/{label} - a third scope beside the branch scopes and the document scopes the rest of the review plumbing uses. The scope is the seat and never the branch, so a worker that commits, or rebases, or moves its branch keeps its comments; a comment threads, replies, resolves and seals into rounds exactly as one on a diff does, and the worker addresses it through the same review MCP when it has the family. When the reader seals a round, finish review files a submit_review and pushes Review #N ready - scope tree:{org}/{project}/{label}. Read it back under that scope, or hand the scope to your lead if you do not have the review tools into the seat’s chat, the review page’s own line.

What it draws

RegionShowsRead from
Headerthe back link to the seat, Files, the seat’s resolved tree and its file count, N to read while any thread waits on the reader, the Conversation / Files tabs, and the narrow doorsthe record’s state.scan_cwd, its file_index, and the seat-tree threads
Conversationthe rounds newest first, each with its age, tally chips, summary and threads - state chip, path:line, the turns with edit, and respond / resolve / reopen / delete (an accepted thread collapses to its marker, opened by a press, where only reopen, collapse and delete sit); parked threads above in an Outdated group with their captured linesthe record’s tree_reviews; the page’s own drafts and reply box
Treethe seat’s whole index as its own Project pane: the project row carrying the project’s name with the seat’s path beside it, then a row per directory and per file, folders before files at every level, indented by depth, each row wearing the 16px glyph the material icon theme gives its filename, extension or folder name (folder tints included). A folder holding a file starts folded; a folder holding only folders starts open, so the first view is the tree’s shape with no file rows inside folders (root files still draw). A filter stands every fold down so its matches show, and a jump from the comments rail clears the filter and opens the folders above its file. With the current file marked, a pill per file carrying its comment count, and a filterthe record’s file_index and state.scan_cwd; the filter ranks by the @ list’s own matching; the glyphs come from material-icon-theme’s manifest
Readerthe file’s head - its path, and what the per-format policy says it is: a grammar and line count, plain text - no syntax for this file, a mime and its dimensions, or a mime and size - then the file itself: a commentable editor for markdown, code and text, a bounded picture, a PDF’s pages, or a notice naming a type no viewer draws; the target line carries the tint and the gutter +the document_read answer for the open path: its bytes
A threadunder the line it was written on: its state chip, where it is, its turns through the review page’s own turn renderer, edit on a turn the reader wrote, and respond / resolve / reopen / delete; a resolved one collapses to its marker line, opened by a pressthe record’s tree_reviews threads and their landings, and the page’s own drafts
A comment boxunder the line a press landed on, the caret already in it; Enter comments, Shift+Enter keeps the newlinethe page’s own comment shelf
Commentsevery thread in the scope as one list, by path and then by line: the state chip, path:line, the first words, and delete; a row jumps back to its linethe record’s tree_reviews threads
Parkeda thread whose landing could not place it - the code moved too far, or no landing was carried - says so on its row, its captured lines kept; it is never droppedthe landing’s outdated word, or none carried
Finishthe round’s summary - a roomy, resizable box, present by default in the rail’s bottom, its own mic like every box - over finish review (N), which seals the sitting into one round; a refusal keeps the wordssubmit_review’s reply, and the round’s number
Statesreading; a seat the server refused, in its own words; a tree with no files; no match for the filter; a file with no viewer, in a notice naming its type and size; a file read refused with its own sentence; a seat-tree review read that failed or answered a shape this build cannot name, drawn in its own line rather than folded to the clean empty pagethe record’s and the read’s own outcomes

Reading

The read is the document read - the server carries the file’s bytes, the client draws them - so it resolves against the seat’s tree, refuses with its own sentence (missing, unreadable, over the ceiling, outside the tree) and answers the file’s bytes. A file that does not decode is a binary read rather than a refusal: the page draws its notice. The reader shows the bytes from when the file was opened and re-reads on a re-select: an open file is a snapshot, never rewritten under the reader’s eyes while a worker edits it.

What a file is comes from one policy, shared with the chat’s Read rows (client/src/format/policy.ts): the extension, then a filename (Justfile is just, Makefile is make, Dockerfile is docker, a .env file is dotenv), then a shebang, then whether the bytes decode as UTF-8. Markdown, code and text draw in a read-only CodeMirror instance, coloured by the same shiki highlighter the chat’s code panels use, in the github-dark family (Oniguruma; the wasm loads when a code file is first opened, and that open waits on it rather than colouring in after a plain draw). Each language has two layers, neither guessed: structure and folding from the CodeMirror org’s own package where one exists, and the colouring from shiki’s grammar either way; .svelte and .toml are colour-only. A text file no grammar names draws plain, and the head says plain text - no syntax for this file. Grammars load one file at a time from shiki’s lazy set, so the reader carries the whole catalogue without downloading it up front, and the chunk - CodeMirror, the bridge - is pulled only when the reader first draws a text file. A picture draws itself, bounded, with its mime and dimensions; a PDF draws its pages; anything else draws a notice naming its type and size, and saying it is still in the tree and reviewable as a file. A reader that could not be built - a chunk or a grammar failed - draws that reason rather than an empty editor.

The reader draws by one policy; the document hand-off does not, by design. The read answers the hand-off’s extension kind and its commentable set; it does not widen. The reader’s UTF-8 drawing classification is the client policy above. So an SVG is a picture here and a .svg document in a hand-off, and an extensionless Justfile opens as just here and read-only in a hand-off - the hand-off’s set is what a reader may comment on, not what this page can draw. A file whose commentable extension is not UTF-8 is refused with the read’s own sentence; bytes outside that set are a binary read.

A press on any line is a comment: the line takes the tint and the gutter +, and the box opens under it with the caret in. Doors are press targets at every pointer, and the reader’s own scroll is capped by the sheet’s rule that nothing scrolls sideways.

The thread, and the round

An anchor captures what the review page’s anchors capture - the file’s path, the line, the line’s whitespace-collapsed hash, and its neighbours as context - from the same lines the reader drew. The landing is resolved by the server, because the client has no working tree to re-scan: the record carries, per thread, either the line it sits on now (with the line it moved from, when it moved) or the resolver’s own reason it could not be placed. A thread whose file has vanished, or whose seat has no resolvable cwd, is carried with no landing and parks.

respond appends the reviewer’s turn and flips the thread toward the worker; resolve marks it read; reopen returns it and nudges the seat. Every write re-reads the record, because a review change is not pushed - the reviews ride the record, and a record re-read is what carries them. The Conversation tab answers over the same calls a diff review does - reply, resolve, reopen - and a rail row opens its file at its line in the reader.

A comment is editable and retractable wherever its card is drawn (Ved, 2026-10-17): edit on a turn the reader wrote opens the page’s own box over that turn’s words - the same mic and take as every box - and save upserts the text with the turn’s identity kept; delete removes the whole thread, and it asks before it writes, because a delete cannot be undone. Both write through the review plumbing every other change rides.

The two widths

At 1600 the page is three columns: the tree, the reader, the comments. At 430 the reader is the page and the other two are sheets behind two buttons in the header - tree and comments (N) - each pushing a history entry so the hardware Back closes what it opened, with done and Escape as the other doors.

The slip

The seat’s own page carries a files slip in the strip above the composer, before the tree row: a bare door, the files mark and the label naming the tree it opens - walk · files for a seat in a worktree of its own, plain files for the project’s checkout. A press opens the page, and there is no count and no panel: the slip IS the door. It is the one mandatory segment - every seat has a tree - where the tree row beside it keeps its rule of staying away when nothing has moved.