An anchor is an exact quote
The reviewer was told to copy each passage character for character, and the engine takes that literally. The first code block records a note only when it has both a quote and a comment, and computes anchored with one plain test: is the quote a substring of the section text the reviewer read? First the quote loses its leading and trailing whitespace, and that trimmed quote is both what is stored and what is searched for. Beyond that trim there is no fuzzy matching and no normalizing. A reviewer that paraphrases instead of quoting still produces a note, which is kept, shown, and flagged as not found: the web adds (not found in the text), the phone (not found). The first version test pins both outcomes with one note whose quote is in the version and one whose quote is not.
Keeping the unanchored note is a choice. The comment may be right even when the quote was copied badly, and dropping the note would hide a reviewer's insight along with its mistake. The flag lets the reader weigh it.
Marked where it points
Dad reads a version with its notes painted onto it. Both clients join the version's sections with a blank line and pass that text, with every note on the version, to markNotes: the web's lives in frontend/src/momentState.ts (second code block), and the phone's Swift twin in MomentState.swift names the web's in its doc comment. The function finds each quote, keeps a list of spans, and cuts the text into plain runs and marked runs. Two notes on exactly the same passage share one span. A note whose passage overlaps a span already taken gets no mark of its own, though it stays in the review's list. The result is a flat list of runs any renderer can draw. The web wraps marked runs in a <mark> element with the comments as its tooltip, and the phone paints an attributed string. A suspect note turns its run red, and naturalness notes stay amber.
Revise: the same seat writes again
Once the notes are in, Dad can press Revise with notes. The route, POST /api/moments/{id}/versions/{turn}/revise, answers 409 while the version is still being written. Otherwise it opens a new version turn copied from the earlier one: the same brain, effort and model, the same purpose and language, the same job and seat number, the same reviewer list, and a revises_turn pointing back. Both clients disable the button while the version has no notes, or while a review or another revision of it is running.
run_version then runs exactly as in Lesson 2, with two more inputs for each section, gathered by the code you saw there: the earlier version's translation of that section, and every note a reviewer left on that section of the earlier version. The third code block shows how version_prompt lays them out. The instruction attached to the notes is the heart of this track: fix what they rightly flag, and where a note is wrong about the meaning, keep what the source says.
That sentence closes the loop Lesson 4 opened. The reviewer flagged passages without the source, and the writer judges them with the source in hand. A suspect note can be right, and the writer fixes the passage. It can also be wrong, because a faithful translation of an odd original can read oddly, and then the source wins.
Nothing is overwritten
A revision is a new version beside the old one. The earlier turn and its sections stay exactly as they were, and the revision test asserts that the turns holding sections are the earlier one and the revision, both. The revision wears a revision chip on both clients, and because it copied the reviewer list, its own cold reviews follow when it finishes. Dad can revise a revision too. Every step stays readable, side by side, in the moment's record.
Lineage beside the seat, never over it
One small field decision keeps revisions honest. When a version finishes, run_version records answered_model and answered_effort from the last envelope, beside the seat's own model and effort, and never writes over them. The comment gives two reasons. The seat's own model is often none, which means the vessel's default, and that is what a revision should ask for again. And a model id a vessel reports is not always one the vessel accepts back as a request.
The revision test checks both halves: the revision's call goes out with model still None, and the earlier turn holds model as None beside an answered_model of m-1. The web shows the answered model next to the seat label, so Dad sees what ran, and the record still remembers what he chose.
Inkwell Quest tells the same story from the author's side, in its lessons on the reviewer who holds no pen and the author who may stet.