Skip to content

Correct the transposed E-W double-dummy rows at the ingest door - #413

Merged
Rick-Wilson merged 1 commit into
mainfrom
fix/dd-table-ew-at-ingest
Sep 8, 2026
Merged

Correct the transposed E-W double-dummy rows at the ingest door#413
Rick-Wilson merged 1 commit into
mainfrom
fix/dd-table-ew-at-ingest

Conversation

@Rick-Wilson

Copy link
Copy Markdown
Collaborator

What

The Game Analysis double-dummy table shows ACBL club boards with its East and West rows swapped. Stoneridge Creek board 12, 2026-09-02:

shown actual
E ♥ 10 11
W ♥ 11 10

North and South are unaffected, which is why it reads as subtle rather than obviously broken. The solver at bridge-craftwork.com/bridge-solver/ gets the same deal right, which is how it surfaced.

Why it happens

The extension's two ACBL adapters map the EW: double-dummy row West-first. ACBL publishes a pair — and the two digits of a slash form like 3/4H — in the order the direction label itself reads, so E-W means [East, West]. That is the same convention seat-order-contract.md already pins down for ew_pair.players, and this is the third time the same flip has turned up in a different field.

The producer fix is a store release away. This corrects it at the door, where a deploy reaches every current user this week.

Two boundaries, not one

Every 1.3 envelope in existence was stamped by seatOrder.js's previous version, which corrected players and knew nothing about the table — and the ingest page archives what it corrects, so club_games is full of 1.3 games whose table is still transposed.

Folding the new correction in under the old < 1.3 gate would have skipped every one of them permanently. So:

schema_version players double_dummy
below 1.3 swap swap
exactly 1.3 correct swap
1.4 and up correct correct

The extension goes 1.2 → 1.4, with 1.3 reserved for our own restamp. That half is in a separate bridge-classroom-fetch PR; this one stands alone and needs no coordination to deploy.

Evidence

Per the contract's own rule — seat changes are verified against a deal, never against a document:

  • All 88 distinct deals in the extension's fixtures/my-acbl solved with bridge-solver. Of the tokens whose two seats differ, 22 of 22 on the EW row match East-first and 14 of 14 on the NS row match North-first. Nothing contradicts either.
  • End to end: a 1.1 envelope carrying board 12's table exactly as the page showed it, run through this helper and then the analysis page's own encoder, renders 3625335243a7b8a97a89 — byte-identical to the solver's output for that deal.

Scope

seatOrder.js is the single copy of the rule — scripts/build-site.sh copies it to dist/ingest/seat-order.js for the static ingest page, and the SPA imports it for the archive read path. Neither call site's signature changed.

What this cannot reach: a game already handed on and cached in the Game Analysis app's sessionStorage or event cache. Re-sending it from the extension refreshes it. The server-side archive is fine — it is corrected on read.

Tests

735 passing. seatOrder.test.js gains the table cases (including a stored 1.3 row whose table is fixed while its already-correct players are left alone); useClubGames.seatOrder.test.js covers the same on the archive read path.

🤖 Generated with Claude Code

The Game Analysis double-dummy table has been showing ACBL club boards with
its East and West rows swapped: on Stoneridge Creek board 12 of 2026-09-02 it
put 10 hearts on East and 11 on West, where the deal gives East 11 and West 10.
North and South are unaffected, which is why it reads as subtle rather than
obviously broken.

The cause is in the extension's two ACBL adapters, which map the `EW:`
double-dummy row West-first. ACBL publishes a pair -- and the two digits of a
slash form like `3/4H` -- in the order the direction label itself reads, so
`E-W` means [East, West]. That is the same convention seat-order-contract.md
already pins down for `ew_pair.players`, and this is the third time the same
flip has been found in a different field.

The producer fix is a store release away, so correct it here, where a deploy
reaches every current user this week.

Two boundaries, not one. Every 1.3 envelope in existence was stamped by this
file's previous version, which corrected players and knew nothing about the
table -- and the ingest page archives what it corrects, so club_games is full
of 1.3 games whose table is still transposed. Folding the new correction in
under the old `< 1.3` gate would have skipped all of them permanently. So
players gate on `< 1.3` and the table on `< 1.4`, and the extension goes 1.2 to
1.4 with 1.3 reserved for our own restamp.

Deal-proved, per the contract's rule that seat changes are verified against a
deal and never against a document: all 88 distinct deals in the extension's
fixtures/my-acbl were solved with bridge-solver, and of the tokens whose two
seats differ, 22 of 22 on the EW row match East-first and 14 of 14 on the NS
row match North-first, with nothing contradicting either. End to end, a 1.1
envelope carrying board 12's table as the page showed it now renders
3625335243a7b8a97a89 -- byte-identical to the solver's own output for that deal.

What this cannot reach: a game already handed on and cached in the Game
Analysis app's sessionStorage or event cache. Re-sending it from the extension
refreshes it. The server-side archive is fine -- it is corrected on read.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Rick-Wilson
Rick-Wilson merged commit d18ae41 into main Sep 8, 2026
1 check passed
@Rick-Wilson
Rick-Wilson deleted the fix/dd-table-ew-at-ingest branch September 8, 2026 04:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant