Declaration 12 of chaos window 2, which CLOSES IT. Structural M (imports
another edition file under AM-4's budgets), chaos d8=4, no override.
Tokens.csv turns out to carry more than names. Every token has a
`quantity` -- 6 Protection, 5 Denied, 12 relation links -- and a component
count is a limit a simulation does not have unless it is told. protection
is saturating_add(1) at lib.rs:986 with no upper bound, against an edition
that ships six tokens for six players. T03 measures whether that matters
rather than assuming either way.
And `sides` is the second interesting column: Freedom and Focus/Blame are
each ONE DOUBLE-SIDED TOKEN, not two states. The engine holds Focus in a
map and Blame in a list; whether those can disagree with a single physical
token is worth checking.
T03 is shaped against a specific error: whatever it finds is a FINDING,
not a fix. A component limit the rules do not state is underdetermined and
belongs to ground-game, and the engine must not start enforcing a bound
nobody ruled. CB-WP-0023 exists because SOLVE was offered where it could
not act; inventing a limit is the same error in the other direction.
The workplan also names the window-2 verdict as DUE. Its retirement
condition was untestable throughout -- eleven declarations, zero 8s, zero
overrides -- and recording that is a change to how the loop constrains
itself, so it is its own tier-M pass rather than a task here. Named so it
is not lost between passes, which is how the ten rulings went uncollected.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Tier S (fixes inside a boundary; chaos d8=3, no override). Two
observations from play, both about what the page says has happened.
The controls moved BELOW the log: you read what happened, then decide what
to do next. They were above it, which asks for the decision first.
And sealing now marks the WHOLE PAGE inert, not just the controls. A
greyed-out button beside a full-colour table still reads as a live game
with one broken control; the session has ended and everything on screen is
a record of it. The status line stays legible on purpose -- it is the one
thing still worth reading.
THE STUB NEEDED A BODY classList TO MAKE THAT TESTABLE. Without it "the
session visibly ended" would have been a claim about CSS with nothing
checking it, which is precisely CB-WP-0016's finding: a stub too thin to
express a failure is how the failure survives. The harness reports the
sealed page through the status channel with a NUL-separated marker --
ugly, deliberate, and documented, because widening the return type would
touch every caller for one boolean.
Both directions asserted: a `closed` reply seals the page, an `ok:
dealing` reply does NOT -- otherwise the seal test would pass for a page
that greys itself whenever it is touched, breaking `play again`.
63 render tests, 26 cb-play, check and loop-lint clean.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Tier S (a fix inside a boundary; chaos d8=7 from the previous roll stands
for this continuation). Two observations from play that are ONE defect.
`play again`, `end session`, `pass` and the move buttons carried `.pick`,
which is cursor:grab. The stylesheet has .btn{cursor:pointer} BEFORE
.pick{cursor:grab}, so grab won.
A GRAB CURSOR INVITES A DRAG. A drag released over nothing posts nothing,
so the player picked up the button, let go, and the page did nothing. It
looked dead because the affordance told them to do the one thing that does
not work. Reported as two separate things -- "the button shows a hand to
pick up that it probably shouldn't" and "I can't start another game or
stop the server" -- and the first causes the second.
The click path itself was never broken: driving again->again and
done->done through the JS harness posts correctly. The logic was fine and
the invitation was wrong.
Click targets now carry `.tap` -- pointer cursor, same press affordance.
This extends CB-WP-0017's rule (interactive and inert must not look
identical) to: click and drag must not look identical either. The test
asserts both directions, because checking only that buttons lost `.pick`
would pass for a page with no affordances at all.
Registered F20 (applied) and F21.
F21 IS THE ONE I COULD NOT REPRODUCE: dragging did not work until after
the first note was saved. Ruled out the plausible mechanisms -- the
gesture logic posts correctly against the served page, the drag ghost
carries pointer-events:none so it cannot intercept the drop, and the
markup is identical before and after since the 303 re-renders the same
page from the same state. Remaining candidates are a <details> toggle
shifting layout mid-drag, a first-load timing difference, or browser-level
pointer capture. Reproducing it needs a browser, which no test here has --
the same gap F19 named. Recorded as unreproduced rather than given a
speculative fix.
And the fourth observation is confirmation, not a bug: "drawing my cards
from the deck is not implemented, I did not need to do that" is exactly
what CB-WP-0028 T04 determined and deliberately did not build. It is the
first evidence that importing the card text closed the comprehension gap
that produced the earlier click-the-deck request.
make all: exit 0. 62 render tests, 26 cb-play.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>