clay-borg/workplans/CB-WP-0031-the-comment-box-outlives-the-game.md
tegwick 4ddff3b17c
Some checks failed
ci / check (push) Failing after 4s
CB-WP-0032: the comments in the account
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>
2026-08-07 16:09:36 +02:00

4.1 KiB

id kind title status state_hub_workstream_id
CB-WP-0031 product The comment box outlives the game done 7b7450cd-3972-4c78-a53c-fba54b3fc02b

Purpose

structural tier  S   (one channel reopened on an existing page; no new
                      decision, no new dependency, no budget moved)
chaos            d8 = 2  → no override
declared tier    S

Declaration 2 of chaos window 3, opened 2026-08-07 by ADR-0017.

The report

"Before we move on, i want to be able to add comments after the game finished."

What was actually broken, and it was two things

The channel closed at the moment it is worth most. A player who has just seen the outcome is the one with something to say — "so that is why that failed", "I never understood what that card did" — and that is the reading the whole trial protocol (GameDesign §5) exists to collect. It was collectable at every moment of the game except the one after it.

Two independent defects, either of which alone shuts the channel:

where what
doc::ending never rendered the comment box at all
hotseat::serve_end had no POST /note arm — a hand-built post fell through to 404 the game is over

Fixing either alone leaves it shut, which is why the test asserts both and why a markup-only test would have passed against a server that still refused.

The thing that needed deciding: what a post-game note is bound to

A note is bound to a position by state_hash (ADR-0014 D3), and the position is genuinely the final state. But round and step say when the player said it, and a note written after the outcome is on screen is not an observation made at the last decision point.

RoundStep has an End variant — the last step of a round, not the end of the game. Logging a post-game note under it would file an after-the-fact reading as an in-play one: a value that is correct about the wrong subject, which is the family ADR-0018 was written for two hours earlier.

So record_note takes the step as an argument rather than reading it off the state, and the post-game path passes "after the end" — which cannot collide with a Debug identifier.

No box where there is nothing to bind to

A game that stopped without a result has no final position. The box is not offered there, and the page says why. Offering one that would answer 409 is a control that exists to be hit.

Task: reopen the channel

id: CB-WP-0031-T01
status: done
priority: high
state_hub_task_id: "6b92d470-b3a2-4cde-a307-d20cb6a45ab4"

Controls:

  • the test fails on each half separately — mutation-proven: blanking the form gives "the ending page offered no comment box", removing the server arm gives 404; both green when restored;
  • a note must not end the session — every other POST in serve_end breaks the loop, and a player must be able to write a second note and then still press play again. The test posts a command after the note and requires it to still work;
  • the redirect carries the token, which is the defect that twice made a saved note read as a failed one;
  • the log distinguishes when it was written from the position it binds to.

Done 2026-08-07.

note_form extracted and shared by both pages — a hand-written twin is how one of them quietly stops posting anywhere useful. The placeholder differs, and only that: what a player has to say mid-turn and what they have to say having seen the result are not the same prompt.

A test-harness defect worth recording. The first draft wrote Content-Length: 21 beside a 22-byte body; the server read 21 bytes and answered 400 unrecognised field, which looked exactly like the feature being broken. The fix was to derive the length from the body in the shared post helper — a hand-written length is a second copy of a fact the body already carries, the same shape as the 62 untagged literals facts-check counts.

Not done here

  • Notes are still not shown back to the player. Neither page echoes what has been written; the trial log is the only place they exist. That is a real gap and it is not this report.