TCASH.CA  ·  Code Review
One file beats a thread
Tue  ·  28 Apr 2026
A review you can hold in one hand

Annotated PR
review, in one file.

An HTML diff with the reviewer's notes pinned in the margin beside the exact lines beats a comment thread every single time, and your agent can produce it.

Beat
Code Review
Reading
~6 minutes
Filed
28 Apr 2026
Output
one .html file
The problem with the thread

A pull-request comment thread is where review context goes to die. Notes scatter down a page, detached from the lines they're about by the time you scroll. The good ones get resolved and collapsed. The whole conversation evaporates when the branch merges. And the most valuable part of any review: the reviewer's reasoning is the first thing the format loses.

The fix is small and a little unfashionable: have the agent emit the review as a single self-contained HTML file. The diff down the middle, the reviewer's notes pinned in the margin next to the exact lines, each one severity-tagged, with a one-screen summary on top. One artifact you can open, send, and keep.

§ 01
The shape of the artifact
§ 02
Why one file wins
§ 03
Getting your agent to produce it
§ 04
Where it doesn't fit
§ 01  ·  the shape

Three parts: a verdict on top, the diff in the middle, the notes in the margin.

The artifact has a fixed shape, and the shape is the whole trick. A summary header states the verdict and the counts, how many blockers, how many nits, so the reader knows in one screen whether to merge. The diff sits in the body, hunk by hunk. And the margin notes pin to specific lines, each one tagged by severity, so the reasoning lives next to the code it is about instead of a thousand pixels below it. Here is a fragment, rendered the way the file renders:

src/auth/session.js Verdict: changes requested · 1 blocker
41 const token = req.cookies.session;42- if (token = lookup(token)) {42+ if ((token = lookup(token))) {43 return token.user;
Blocker

Assignment in a condition. The original = was almost certainly meant to be ===. The fix wraps it in parens to silence the linter, but it preserves the bug: this still overwrites token and treats any truthy lookup as valid. Decide which you meant.

58+ const ttl = 60 * 60 * 24 * 30; // 30d
Nit

Pull this to a named const beside the other session settings, SESSION_TTL_SECONDS reads better than a bare arithmetic literal.

73+ await db.transaction(() => revoke(id));
Praise

Good call wrapping the revoke in a transaction: the previous version could half-revoke on a crash.

PR #318 SHA a1f9c2e 3 files · +84 −19 1 blocker · 1 nit · 1 praise
A fragment of the real thing, self-contained, every note line-anchored, the verdict and counts traceable to a commit. It opens on a double-click and prints clean.
§ 02  ·  why it wins

One file is complete, portable, and it survives the merge.

Property 01

Complete.

  • Diff, reasoning, and verdict in one place.
  • No scroll-and-lose-context; the note is beside the line.
  • The reader never reconstructs what the reviewer meant.
Property 02

Portable.

  • Opens anywhere: no login, works offline.
  • Email it, attach it to the ticket, print it.
  • The contractor without repo access can still read it.
Property 03

Durable.

  • Survives the merge that collapses the thread.
  • An artifact you can grep next quarter.
  • The "why we did this" outlives the branch.

This is also the one place the format argument resolves cleanly. A review like this is read rendered: that is its whole value, but it is generated from a diff that lives in git as text. The truth stays reviewable line by line; the view stays readable by a human. The document and the source of record never get confused, because the document is plainly a view of the source. see "Stop handing me the markdown your agent had to fight"

§ 03  ·  the instruction

Give the agent a severity vocabulary and a fixed shape.

The instruction is short and the output is consistent once you pin two things: the structure and the tags. Tell the agent to take the diff, emit a single HTML file with all CSS inlined so it opens on a double-click, anchor every note to a line range, lead with a verdict and counts, and tag each note from a fixed set, blocker, nit, question, praise. The vocabulary is what makes the result scannable: a reader can find every blocker in one pass and skip the praise until they have time for it.

The header is the part people skip and shouldn't. Put the PR number and the commit SHA in it. That one line is what turns the file from a screenshot into a record: six weeks later you can tie the review back to exactly the code it judged.

What the file must contain
  • Self-containedno network
    All CSS inline; no script, no external fetch. It is a document, not an app: opens offline, safe to email.
  • Line-anchorednote ↔ lines
    Every note names the lines it is about. The reasoning sits next to the code, not a page below it.
  • Severity-taggedfixed vocabulary
    blocker · nit · question · praise. Counts in the header so the verdict is a glance, not a read.
  • TraceablePR + SHA
    The header carries the PR number and commit. The review can be tied back to the exact diff it judged.
§ 04  ·  the limits

It is for the one-pass review you hand back, not for everything.

Where the thread is still the right tool

Three times I reach for GitHub instead.

The one-file artifact optimizes for reading a review. When the job isn't reading a finished review, use the thread.

  • A 2,000-line diff is not a review, it's a refactor. No artifact saves it. Break the change up before anyone, human or agent, looks at it.
  • Genuine back-and-forth belongs in-thread. When a review is a multi-day conversation between people, GitHub's inline review is built for exactly that. This is for the single pass you deliver, not the negotiation.
  • Never make the file your source of record. It is a view of a diff that lives in git. Regenerate it; don't edit it and call it truth.

The comment thread is optimized for the person writing the review: quick to type, quick to resolve. The one-file artifact is optimized for the person reading it. On the reviews that matter: the ones a second person has to understand, sign off on, or find again later: the reader is the point. Hand them the file.