Solo CARTE sig-select runs the real per-polarity countdown — TDD

A CARTE gamer owning multiple seats was capped at one SigReservation per
room by the (room, gamer) unique constraint, and sig_reserve had a solo
immediate-commit shortcut that wrote seat.significator on OK and never ran a
countdown. Together they 409'd the second sig: after OK-ing one seat, switching
to another and clicking OK was blocked — a gamer could only ever pick one sig.

The countdown/confirm machinery (sig_confirm + the threading-timer task) was
already per-seat-row based — it iterates every ready reservation in a polarity
and seats each. So the fix is to let one gamer hold one reservation PER SEAT:

- Constraint (room, gamer) -> (room, gamer, seat) (migration 0018). The
  (room, card, polarity) constraint still enforces a distinct sig per seat.
- Demolish the solo immediate-commit shortcut in sig_reserve — it predated the
  countdown mechanism. Reserve now always just creates a provisional row.
- Scope the reserve guard, release, and idempotency lookups to the acting seat
  via a new _acting_sig_seat(room, user, ?seat) helper; add a guard against
  re-using a card already held for another of the gamer's seats.
- sig_ready resolves the acting seat the same way (?seat) and looks up the
  per-seat reservation; data-ready-url + user_ready now carry/reflect the seat.

Now a solo CARTE tester reserves + readies all 3 sigs per polarity and each
room fires its own 12s countdown, then both confirm -> SKY_SELECT.

Tests: new SigReserveCarteMultiSeatTest (no-NVM per-seat reserve; same-seat 409
retained; 3-levity-ready fires one countdown); rewrote the model constraint
test + the CARTE FT to the new behaviour. Multi-gamer path unchanged (one row
per gamer) — epic 595 + gameboard 319 + epic channels 5 + jasmine all green;
full 1663-test suite green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Disco DeDisco
2026-06-05 02:29:12 -04:00
parent bedc489d7b
commit c2b244d796
7 changed files with 188 additions and 89 deletions

View File

@@ -756,8 +756,8 @@ class SigReservation(models.Model):
class Meta:
constraints = [
UniqueConstraint(
fields=['room', 'gamer'],
name='one_sig_reservation_per_gamer_per_room',
fields=['room', 'gamer', 'seat'],
name='one_sig_reservation_per_gamer_per_seat',
),
UniqueConstraint(
fields=['room', 'card', 'polarity'],