--- id: CB-WP-0032 kind: product title: "The comments in the account" status: done state_hub_workstream_id: "71d744f9-7e40-49c3-994e-f3fb007a1430" --- # Purpose ``` structural tier S (one existing renderer gains a second input; no new decision, no dependency, no budget moved) chaos d8 = 6 → no override declared tier S ``` **Declaration 3 of chaos window 3.** ## The report > *"Commenting after the game is a good practice. We could show the > comments in the log. I would think that as useful."* This closes the gap [CB-WP-0031](CB-WP-0031-the-comment-box-outlives-the-game.md) named and did not fix: notes were written to a file and **shown back nowhere**. `trials.py`'s own docstring calls that shape *"this project's signature failure in a new medium"* (ADR-0014 D6) — and the note channel had it, in the interface, for as long as it has existed. ## The decision: what a comment is positioned against A note carries `round`, `step` and `state_hash`. **None of them can order it against the log**, because the log is a sequence of *commands* and several commands share a step. Positioning by round would put a comment *somewhere in* the right round — for a remark about a specific move, the wrong position stated confidently. So the server records **how many commands had been played** when the note was written, which it knows exactly (`journal.len()`), and the page places it there. `after = 0` is *before anyone moved*, which is a real thing to have an opinion at. ## The thing that must not happen **A comment must not be readable as something the game did.** The log is the recorder's vocabulary — `record::to_step`, what the scenario file will say — so a note styled as a log line would be a sentence the game never produced, sitting in the account of what the game produced. ADR-0014 D4 turns on that distinction being visible: raw notes stay in this repo, and only a human promotes one to a finding. Notes render in their own `.note` block, attributed *"you — round N, step"*, with the words in quotes. **The `.note` CSS already existed and was never used by anything** — defined for this, and left unwired. ## What was NOT done, and why it is the interesting half **No column was added to the trial log**, though `after` is genuinely the anchor and persisting it would let a later reader interleave. `trials.py` skipped any row that was not five cells — with `continue`, in silence. A sixth column would have made `make trials` report **zero notes for every log at once**, which is verbatim the failure the parser's own docstring says it exists to prevent. `after` is therefore held in memory for the session and the file format is untouched. **The latent defect was fixed on its own terms**: a wrong column count now raises, and the walk that wraps it reports the *real* reason instead of blaming a missing block for every failure. ## Task: show the comments where they were made ```task id: CB-WP-0032-T01 status: done priority: high state_hub_task_id: "31f60440-e049-45f7-99fa-87c01c00adb7" ``` **Controls:** - **placement is asserted, not just presence** — mutation-proven: append the notes at the end instead of interleaving and the test goes red; - **a comment cannot be read as a game event** — asserted on its own marking and its attribution; - **a comment past the end of the log still appears**, because a post-game note is written when every command has been played and a dropped comment is the failure the channel exists to avoid; - **the round trip, not the write** — the `cb-play` test posts a note and then GETs the page, which is the path a player takes. **Done 2026-08-07.** `Account { lines, notes }` replaces the bare `&[LogLine]` on both pages — a struct because `document_with_log` was already at seven arguments, and because the two are only meaningful together, which is the point. `trials.py` hardened as described above, with two new controls: a wrong-shaped row raises, and the walk names the reason. ## Not done here - **Nothing lets a player edit or delete a comment.** A note is a record of what they thought at the time and rewriting it would defeat that, but a typo is a real case and there is no answer for it yet. - **The ending page shows the same interleaved account**, so a long game puts the post-game comment at the bottom of a long log. Whether that is where a reader looks for it is untested.