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

157 lines
7.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 condition** — *retire 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/117** — **eight 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.**