clay-borg/evidence/CB-EV-0018-the-table-you-can-read.md
tegwick fe3852e093 CB-WP-0021: correct the declaration before writing any code
The declaration claimed importing the edition data would resolve GR-E01.
Measured across all four scenarios: GR-S01 deals 2/3/4 problems by player
count, not all five, so 4/6/9 points are in play against thresholds of
5/7/9 -- unreachable at 2p and 3-4p with the REAL data, in the same shape
as the stand-in's 3/6/10. So GR-E01 unreachable below 5 seats is a real
property of the game and gr-e01-threshold-unreachable-2p asserts
something true.

The error was the cheap kind: 12 points exist in the file, so I assumed
12 are in play. One command over the CSV settled it and was not run until
after the declaration was committed -- this project's characteristic
error, in the pass that followed a ruling obtained because of it.

CB-EV-0018 corrected too: 'confirmed as the stand-in's doing' was
overstated. The zero came from no Problem being claimed at all.

T03 now owes ground-game a sharper question than a retirement: either
GR-S01's deal count is wrong or GR-E01's thresholds are, and no dataset
can reconcile them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 20:35:39 +02:00

7.7 KiB
Raw Permalink Blame History

CB-EV-0018 — four human checks, four sets of defects no test could reach

CB-WP-0020 T06. Measured 2026-08-03 at 5e06a7d+. Pass kind product, tier S (structural S; chaos d8 = 8 → OVERRIDE, drawn S). Declaration 3 of chaos window 2.


1. What the check found, and what the suite said about it

Seven items. Item 1 passed — the resting affordance reads without touching anything. Every other one was a defect, and make all was green for all of them.

# reported cause
2 "as if we have two cards now", the line break vanishes the ghost was a textContent copy of the card
3 "upper and left borders … hidden", seat highlight "quite large" outline + outline-offset drew a second rectangle; an SVG viewport clips it
4 "replacing the content … breaks the visual clue" the explanation replaced the ghost's label
5 status line "switches only if i put back a card" see §3 — not reproduced, and fixed anyway
6 "cant follow the actions of the other players" seat cards rendered Selection { action: Solve, … }Debug on a player surface
7 "game over" wrong when the group succeeded; no way to play again the ending was written for one outcome and one game

Could any of them have been caught mechanically?

Honestly, two of the seven, and neither by a check that existed:

  • #6 is the same {:?}-on-a-player-surface defect the log fixed in CB-WP-0018, in a place that pass did not look. A grep for {:?} in emitted output would find it, and that check does not exist. Worth building.
  • #7's headline is a branch nobody wrote a case for; a test asserting the ending page differs on group_success would have caught it.

The other five cannot be caught here and saying otherwise would be the error this project keeps naming. #2, #3 and #4 are about what a layout looks like; #5 is about which element a browser reports under a pointer. QuickJS has no layout engine and no hit-testing, and a stub that grew one would be asserting against my model of a browser rather than a browser.

2. The border moves, nothing else does

Adopted as instructed: a legal target restyles its existing border rather than drawing a new box.

.dropok{border-style:dashed;border-color:#9cf;background:#1d2a33}
.dropok circle,.dropok rect{stroke:#9cf;stroke-dasharray:5 3}

That is the whole fix for the missing top and left edges — an outline on an SVG <g> is clipped by the viewport, and on a card it collided with the neighbour's margin. It also removes the oversized seat highlight, because the border was always the right size. A border already in the layout cannot move the layout, which is what "more stable and less complicated" was asking for.

3. The report I could not reproduce, and what I did instead

Item 5 said the "nothing droppable" message never appears. The harness test for it passes, the page has real gaps to drop into, and I have no browser — so I could not reproduce it, and the task said not to fix a message that already works.

The likeliest explanation is not the message but which element the browser reports: for touch and pen a browser implicitly captures the pointer to the pointerdown target, so e.target on pointerup is the element you started on wherever you release. That would make every drop look like a drop-on-itself — which is exactly the other half of the report, "switches only if i put back a card, then showing action-attack -> action-attack".

So the fix is to stop asking the event and ask the document: document.elementFromPoint(clientX, clientY). That is correct under both explanations — with a mouse it returns the same element e.target would; with capture it returns the truth instead of the capture target.

Recorded as unreproduced, not as diagnosed. If item 5 still misbehaves after this, the cause is something else and this note is the starting point.

And the refusal was written in element ids. action-attack -> action-attack is not a legal move here is the vocabulary of the DOM on the one surface a player reads when something goes wrong. It now says "Attack needs to be dropped on something" or "Attack on P2 is not a move you can make right now", and a test asserts no action- id leaks into it.

4. Two defects my own tests found while fixing these

The selection renderer dropped a field. selection_words matched on (target, problem) and showed only the target when both were set. The 42-path coverage gate failed the build: "claimed rendered, but absent from the emitted document: selections.*.problem". The aggregate does not currently produce both — but a renderer that silently drops one is the omission class this crate exists to guard against, and the gate does not care whether the case is reachable today.

"Play again" moved the game to a new port. The first version worked end to end and would have been useless: run_game bound a fresh listener per game, so dealing a second game left the player's tab pointing at a dead port — the CB-WP-0018 defect returning by a different route. The listener is now bound once per session.

play_again_deals_a_second_game catches it, and it asserts the second game is a different deal, not merely that a second game happened — a seed that did not advance would have satisfied a naive count.

5. Chaos: the first override at d8, and it changed nothing

d8 = 8 fired on the second roll at the new rate and drew S, which is what the structural derivation already said.

That is one half of window 2's retirement conditionretire if an override changes nothing twice running. One. If the next override also changes nothing, the mechanism goes.

Worth stating plainly so it is not mistaken for evidence either way: an override firing on roll 2 of 12 at a 1-in-8 rate is unremarkable luck, and drawing the structural tier is a 1-in-3 outcome. Neither number says anything about whether d8 was the right rate. The window needs its twelve.

6. Cost

pass kind responses cost $/response
CB-WP-0019 meta 117 $38.54 0.329
CB-WP-0020 product provisional — not quoted

Read by re-running make status at the moment of writing, per the rule CB-WP-0019 wrote. CB-WP-0019 was last reported at $34.80/107 and has settled at $38.54/117eight for eight, and the first one under 20%, which is what re-running at quote time is supposed to do.

Meta budget: back under the line — CB-WP-0020 is product work, which is what the 27% breach called for.

7. Open

  • The human check is four for four. Every run has found something the suite called green. Its cost is one maintainer session per pass; its yield so far is a broken drag, a lying affordance list, an invisible ending, and this set. It should stay a gate on stage 1.
  • A {:?}-in-emitted-output check would have caught item 6 and does not exist. Cheap; owed.
  • The engine still has not imported the edition data, now that GROUND-WP-0002 T01 has ruled it authoritative. That is the next product pass, and it is what makes the ending's 0 scores and winners nobody meaningful — confirmed as the stand-in's doing, not a scoring bug. CORRECTED 2026-08-03 (CB-WP-0021): overstated. The 0 came from no Problem being claimed at all. The threshold gap is independent of the dataset — GR-S01 deals 2/3/4 of the five problems, so 4/6/9 points are in play against thresholds of 5/7/9, unreachable at 2p and 34p with either dataset.
  • ground-game owes ten rulings (U1U10) and SOLVE's legality.
  • Chaos: 3 of 12 in window 2, one override, changed nothing.