CB-WP-0016: the drop target that was never there
Some checks failed
ci / check (push) Failing after 4s

Provenance (tier S, one paragraph in lieu of survey and ADR): the human
check that kept INTENT stage 1 open was run and the drag was broken.
Root cause, worth more than the instance: drop targets were ids, and an
id must be unique, so exactly one element could ever be seat-0. The
relationship-graph circle took it and the seat card that every action
card's own text points at -- 'drag Attack onto a seat' -- silently had
none. A seat is drawn twice and both drawings are the seat; the document
model could not express that.

Drop keys are now data-drop. Any number of elements may carry the same
key, so a seat is droppable on its card and on its graph node. Measured
on a live server: seat-0/1/2 each appear twice, id survives only on
cb-status which is the one element the script looks up, and
down=action-attack&up=seat-1 returns ok.

Second defect: a drop on nothing returned without posting and without
touching the status line, so a broken target was indistinguishable from
a working page. resolve already refuses rather than defaulting, which is
right; refusing SILENTLY is not. The page now reports the raw fact --
'took action-attack, let go over nothing droppable' -- which names
elements, not moves, so ADR-0007 control 5 holds.

And the honest part: the general check added here -- every offered
affordance names a key that exists, driven through Policy::choose over
four real bot games -- does NOT catch the reported defect. seat-0 did
exist, on the graph circle. It is kept because a wholly absent target is
a real class, and paired with a targeted regression test that does catch
it. Three mutations, each red for its stated reason, including the
reported defect reintroduced; only the targeted test fires on that one.

A cb-play assertion matched id="action-ground" as a substring while
describing itself as checking the page; rewritten through drop_keys.

make all exits 0. Stage 1 stays open: verified by tests, mutation and a
live server, not by a human dragging.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
tegwick 2026-08-02 20:48:18 +02:00
parent 4df2d0a4ae
commit bf72a1863a
9 changed files with 496 additions and 27 deletions

View file

@ -2,7 +2,7 @@
id: CB-WP-0016
kind: product
title: "The drop target that was never there"
status: todo
status: done
---
# Purpose
@ -67,7 +67,7 @@ green tests two passes ago.
```task
id: CB-WP-0016-T01
status: todo
status: done
priority: high
```
@ -84,11 +84,26 @@ inventing a new id vocabulary in the page is not.
must produce the same command, and a test must go red if either stops
resolving.
**Done 2026-08-02.** The aliasing was not needed, because the constraint
that caused the defect was removed instead.
**Drop keys are now `data-drop`, not `id`.** An `id` must be unique, so
exactly one element could ever be `seat-0` — the graph circle took it and
the card went without. Any number of elements may carry the same
`data-drop`, so a seat is droppable on both of its drawings. Measured on
the live page: `seat-0/1/2` each appear **twice**, and `id` survives on
exactly one element, `cb-status`, which is the only one the script looks
up. `down=action-attack&up=seat-1` against a real server returns `ok`.
The mutation that reintroduces the reported defect — the seat card losing
its key — goes red, **and only the targeted test fires**; the general
existence check stays green. That is the point of T03's finding.
## Task: a gesture that lands nowhere must say so
```task
id: CB-WP-0016-T02
status: todo
status: done
priority: high
```
@ -105,11 +120,22 @@ Make the outcome visible. Keep ADR-0007 control 5 intact — whatever the
page reports must still be raw pointer facts with no game vocabulary, and
the existing body-shape assertion must still hold.
**Done 2026-08-02.** The page now writes *"took action-attack, let go over
nothing droppable"* to the status line. It names elements, not moves, so
control 5 holds and the body-shape assertion is untouched. Restoring the
bare `return` turns
`jsrun::tests::a_drop_on_nothing_reports_instead_of_going_quiet` red with
*"a drop on nothing said `\"\"`"*.
The JS DOM stub had to grow a real `getAttribute` and a null-parent node
to model a pointer landing on nothing — it previously could not express
the case at all, which is part of why the silence was invisible.
## Task: the check that closes the class
```task
id: CB-WP-0016-T03
status: todo
status: done
priority: high
```
@ -134,3 +160,22 @@ Then `evidence/CB-EV-0014-*.md`:
say plainly whether the figure has settled.
- **Chaos: declaration 11 of 12.** The calibration window closes next
declaration.
**Done 2026-08-02.**
[CB-EV-0014](../evidence/CB-EV-0014-the-drop-target.md). `make all`
exits 0.
- **The general check does not catch the reported defect, and the evidence
says so plainly.** `seat-0` existed — on the graph circle — so an
existence check over the whole document cannot tell that the element the
user is *pointed at* is not the one that works. It is kept because a
wholly absent target is a real class, and paired with a targeted
regression test that does catch it.
- **Three mutations, each red for its stated reason**, including the
reported defect reintroduced.
- **Stage 1 does not close here either.** The fix is verified by tests, by
mutation, and against a live server — not by a human dragging, which is
the standard that found it.
- **A cb-play assertion drifted**: it matched `id=\"action-ground\"` as a
substring and silently described itself as checking the page. Rewritten
through `doc::drop_keys`.