clay-borg/workplans/CB-WP-0034-who-you-are-bonding-with.md
tegwick 82aead6cea
Some checks failed
ci / check (push) Failing after 4s
CB-WP-0035: a session that answers nothing
Two reports, one cause: the script's fetch had no .catch. When the server
had exited the promise rejected, the chain never ran, and not even the
status line moved — so a dead server and a click that did nothing were
indistinguishable. play again read as a dead button, and the linger
timeout was invisible.

Now a rejection says the session is gone and seals the page, and a
5-second heartbeat against a new /alive notices it without needing a
click, which is what the timeout case requires. The beat carries the
token, and does not extend the linger: that deadline is absolute.

The harness had the same hole. jsrun's fetch stub had no .catch, so the
branch that notices a dead server would have been unreachable in every
test — the very defect the stub's own comment records from CB-WP-0024.
Teaching it __failing, .catch and a recorded setInterval was the fix;
writing the script defensively would have repeated the trap.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 20:31:32 +02:00

3.8 KiB

id kind title status state_hub_workstream_id
CB-WP-0034 product Who you are bonding with done bde0c1d5-a76c-4431-a48a-a9fa81f4d0cc

Purpose

structural tier  S   (rendering only -- no rule, no dependency, no budget,
                      no artifact contract moved)
chaos            d8 = 4  → no override
declared tier    S

Declaration 5 of chaos window 3.

The report, three times

"RespondToSupport is unclear as i cant see whos support i accept." — 2026-08-06

"i can not [see] the player i bond or not-bond with. We should change that." — 2026-08-07 15:58

"But i still cant see the player i am bonding with." — 2026-08-07 16:12

Three sessions, two days, and it survived a whole UI rebuild.

It was not styling

The move button's label was format!("{c:?}"). The player was reading

RespondToSupport { response: AcceptBond }

— Rust struct syntax, with no name anywhere in it. And GroundCommand::RespondToSupport { response } does not carry the counterparty, so nothing rendering the command alone could have named them. It comes off the view: whoever played Support targeting this seat.

Four more fields on the seat panel had the same defect, including the one the report names — support AcceptBond, an answer with nobody attached. CB-WP-0020 fixed exactly this for selections and left its four neighbours as they were.

Task: name who

id: CB-WP-0034-T01
status: done
priority: high
state_hub_task_id: "d8429ce2-991a-45df-9fcd-6b70b0e81511"

Controls:

  • the seat is named, and the raw command name never reaches the page;
  • an unseen offer is not given an invented name — a confidently wrong seat is worse than an honest gap (ADR-0018);
  • no catch-all arm, so a new command cannot silently fall back to Debug;
  • mutation-proven both ways.

Done 2026-08-07.

The exhaustiveness control paid for itself immediately, before any test ran: GroundChoice::RejectReverse and SupportResponse::BreakRivalry both failed to compile. Two moves that would have shipped as struct dumps, caught by the absence of a _ =>.

These are clay-borg's words, not the edition's. The Action cards carry the game's own rules_text (ADR-0015); nothing vendored names these control moves, and Glossary is unvendored (F18). If it lands, this is a caller to revisit.

The finding underneath: a gate that pinned the defect

every_view_field_is_classified_in_the_emitted_document — the probe that exists to prove every view field reaches the player — was matching

"problem: 7 }"   "player: Some(PlayerId(1))"   "members: [PlayerId(1)"

It was proving the field reached the page by matching Rust struct syntax. A gate written to protect the player's view of the game had been certifying the defect as coverage, and would have gone red if anyone had fixed it.

Second confirmation of CB-WP-0024's finding, from the other side. That pass found a probe naming a presentation does not survive a rendering change. This is the sharper case: a probe naming Debug output actively holds the defect in place.

Probes now name facts — Ground & Restate, P2 + P3, accepted P3's Support. The fixture gained a visible Support offer so the probe can name a seat rather than a response with nobody attached.

Not done here

  • The unknown-supporter path is untested against a real game. It is reachable only if RespondToSupport is offered while the Support is not visible in the responder's view; whether the rules permit that is a question for ground-game, and the page currently says it cannot see rather than guessing.
  • Other Debug output may remain outside the two surfaces audited here (the move buttons and the seat panel). The exhaustive match guards commands only.