- On a gallery booth the marks panel moves into a sticky verdict aside
beside the set. The aside comes first in the document, so a narrow screen
stacks the question above the work; grid areas place it on the right when
wide. Nothing in an ordered collection moves. Boards are unchanged.
- The flag tray lists flagged items by tile number: the declared change
from the panel list's (created, id). The standalone marks page keeps the
list.
- Inline group headers are divs, never figure.item.
- Every mark-dependent element is a data-region: the verdict, each tile,
the rail's filter counts. There is also a server-rendered status line.
- The in-place script (base.html) POSTs with an explicit JSON Accept, then
on 204 swaps every region from a fresh GET. Live media and per-viewer view
state are carried across the swap, so there is no layout jolt and no
stopped track. It never re-POSTs: on failure it says so and reloads. Tile
controls re-bind after a swap, and the grid cursor survives it.
- The `n` key opens the tile's closed note disclosure before focusing it.
- test_embed_browser's keyboard-flag test expected a navigation, which is
the defect R2 removes. It is updated as declared in the contract, and
tightened: a window marker must survive, proving no reload.
Browser tests: flag in place, with no reload and no scroll jump, and the
tile, tray and rail count all updated; and a failed save that reloads
without re-POSTing. Two mutations turn them red (no carry, no rail region).
700 passed.
- list_booths gains open_since (parsed, never compared as text), flags,
landed_at (content only; a new, differently named clock, INV-5),
viewed_at, and a four-image preview that keeps blur.
- The index renders needs you / new since you looked / everything else,
always in that order. Needs you includes unreadable marks, so a damaged
judgment file cannot hide. Everything else keeps list_booths' order
rather than stating a second rule. An empty section renders nothing.
- The side column holds live benches (a damaged registry says so),
bookmarks from BOOTH_LINKS_BOARD with booth URLs left out (capped at 8),
and the pickup form.
- test_booth's kept-lane test is rewritten as the contract declared: kept
is a fact on each row, not a lane.
Two of the new tests were VACUOUS on their first draft, and mutation-
checking caught both. The clocks test used a future t0, so a hand-set
marker outranked every real write. The look-then-judge test followed the
flag's 303, and the resulting GET recorded a fresh look. Both are fixed
and now go red under their mutation.
- wants_json: true only for an exact `application/json` entry with q > 0.
Absent, empty, wildcard, application/*, near misses, q=0 and malformed
headers all fall through to the 303.
- The four mark routes share one exit, _mark_done: 204 with no body for the
in-place client, otherwise _mark_redirect unchanged.
- back=view lands on /b/<name>/view?f=<rel>#rail, only for a media item of
this booth. It is built from the resolved rel and never echoed. Anything
else takes the no-`back` landing.
- tests/golden/r2_mark_303.json: 108 responses recorded from the PRE-R2
code (6 route cases x back absent|marks x 9 non-JSON Accepts), replayed
byte for byte (INV-4). Two mutations (q>=0, substring match) turn it red.
- The contract now states the q=0 rule.
Triaged, not adopted wholesale. Folded:
- Reviewing refreshes .viewed, as it already did. It is now stated, so the
two clocks cannot read as disagreeing.
- INV-4 is scoped to pre-R2 request shapes. back=view is the declared
exception.
- back=view lands on the review only for media items. Anything else falls
back to the booth page.
- In-place regions: every element whose content can depend on marks is a
region, including the rail counts, the filmstrip and the tape. The stage
never is.
- The script never re-POSTs. A lost response must not duplicate a note or
re-date an answer.
- The dangling "invariant 5" now points at the Booth's CLAUDE.md invariant 5.
- "M" is defined once. Needs-you is picks only. Every key is suppressed in
editable fields.
- The toggle and the narrow collapse are classified against INV-3.
- Every Booth state file is a dotfile, stated. So are "no generated
thumbnails" and the audio placeholder.
- The requirement wording is tightened, and C7 records the voice and emblem
rulings.
Ordinal is appended, not inserted. The quote() guard stays, and skipped
items take no ordinal. Empty Desk sections do not render; this carries
forward the negative half of the kept-lane pair. The 1:1 toggle is bound
only when the stage is an image.
PROPOSED. Ruled by the operator 2026-09-23 (flow: a_b, compare this_arc,
voice plain, emblem no). Compare is not in this contract; it follows as r3.
Seam-reviewed against the live module surfaces before the cross-frontier
contract panel returned. Four findings are folded in: Mark.created is a
string, the board is BOOTH_LINKS_BOARD, the bench-read error state, and an
unreadable marks file counting as needing the operator.