Notes were written to a file and shown back nowhere — the shape trials.py's own docstring calls this project's signature failure in a new medium. The log now carries the player's comments where they were made. Position is the feature: a remark like "why did that do nothing?" is about the move above it, and collected at the bottom it is a sentence with no subject. round/step cannot order a note against the log because several commands share a step, so the server records how many commands had been played — which it knows exactly — and the page places it there. A comment must not be readable as something the game did. The log is the recorder's vocabulary; notes render in their own block, attributed to the player, quoted. The .note CSS already existed and nothing had ever used it. No column was added to the trial log. trials.py skipped any row that was not five cells, silently, so a sixth column would have made `make trials` report zero notes for every log at once. That latent defect is fixed on its own terms: a wrong column count now raises, and the walk reports the real reason rather than blaming a missing block for every failure. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
499d9fe3d7
commit
4ddff3b17c
8 changed files with 455 additions and 26 deletions
|
|
@ -3,6 +3,7 @@ id: CB-WP-0031
|
|||
kind: product
|
||||
title: "The comment box outlives the game"
|
||||
status: done
|
||||
state_hub_workstream_id: "7b7450cd-3972-4c78-a53c-fba54b3fc02b"
|
||||
---
|
||||
|
||||
# Purpose
|
||||
|
|
@ -69,6 +70,7 @@ answer `409` is a control that exists to be hit.
|
|||
id: CB-WP-0031-T01
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "6b92d470-b3a2-4cde-a307-d20cb6a45ab4"
|
||||
```
|
||||
|
||||
**Controls:**
|
||||
|
|
|
|||
106
workplans/CB-WP-0032-the-comments-in-the-account.md
Normal file
106
workplans/CB-WP-0032-the-comments-in-the-account.md
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
---
|
||||
id: CB-WP-0032
|
||||
kind: product
|
||||
title: "The comments in the account"
|
||||
status: done
|
||||
---
|
||||
|
||||
# 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
|
||||
```
|
||||
|
||||
**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.
|
||||
Loading…
Add table
Add a link
Reference in a new issue