Disco DeDisco a6ce20761b Sig countdown: run the post-countdown confirm as a Celery task + auto-reconnect the room WS — TDD
The flaky tray→thumbnail→hex animation after the 12s countdown.

Root cause: the confirm ran in a threading.Timer thread inside the web process,
and _fire broadcast polarity_room_done / pick_sky_available via
async_to_sync(group_send) from an ephemeral per-call event loop. With the Redis
channel layer that publish is unreliable across loops (the production analog of
the "broadcast must originate in daphne" test trap), so the live events reached
the client only sporadically — the server-side state (sig assignment,
SKY_SELECT) still committed, which is why a refresh always showed the concluded
hex but the animation usually didn't play.

Fix (chosen: migrate to Celery — the path the tasks.py docstring already called
for): _fire becomes the @shared_task confirm_polarity_room, enqueued by
schedule_polarity_confirm via apply_async(countdown=seconds). The worker is a
stable long-lived process whose channel-layer singleton is never shared with a
serving loop, so its group_send reaches daphne reliably; it also survives
web-worker restarts. No task revocation needed — cancellation/supersession ride
the existing cache token guard (cancel just deletes the token; a stale queued
task no-ops). Dropped threading.Timer + the _timers registry.

Test settings get CELERY_BROKER_URL='memory://' so apply_async queues without a
live Redis and without running the task (no worker) — mirrors the old timer that
was scheduled but never fired inside a sub-12s test. NOT eager: eager would
ignore the countdown and assign significators synchronously during the ready
POST. test_tasks rewritten: confirm_polarity_room called directly (task body),
schedule asserts the enqueue + countdown + fresh-token supersession; the
broadcast itself stays IT-uncoverable under InMemory (known channels limit).

Also: room.js now auto-reconnects the room WebSocket with capped exponential
backoff (1s→30s, reset on open, halted on beforeunload). A dropped socket (proxy
idle-timeout, blip, server restart) previously stayed dead until a manual
refresh, silently losing every live event — an independent reliability gap that
compounded the "sporadic" feel.

602 epic ITs + 18 task UTs green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 14:52:21 -04:00
feat: import Minchiate Fiorentine 1860-1890 deck assets (98 PNGs, alpha-channel transparent bg) + naming convention v2 + pngquant optimization tooling. Public-domain 1860-1890 lithograph scans sourced from Wikimedia (single download series + trump 11 Il Gobbo individually-sourced from same era series); user removed white backgrounds in Photoshop to leave irregular card-shape with transparent canvas. Filenames v2-conformant per [[reference-card-image-naming-convention]] (revised from v1 of 2026-05-24): deck slug carries -1860-1890 publication-year suffix so future Minchiate Fiorentine variants from different publishers/eras coexist cleanly; courts use rank-number-prefix (batons-11-page not batons-page) for linear sort key; trumps carry both numeric rank AND italian-name suffix (trumps-01-papa-uno, trumps-11-il-gobbo) for forensic identification across variant decks the user plans to sell. Il Matto (unnumbered Fool in Minchiate tradition) assigned rank 00 to give it a sortable position. Five trump filenames had elided-apostrophe slugs restored from the download source (-lacqua-l-acqua etc.). Card-back at <deck-slug>-back.png sorts alphabetically before all suit categories — no separate card-back/ subdir needed. pngquant 2.17.0 installed at C:\Users\adamc\AppData\Local\Programs\pngquant\, added to user PATH (effective next session) for future deck imports; ran with --quality=65-85 --speed=1 --strip --skip-if-larger for 57.6% size reduction (86.6 MB → 36.7 MB total, 935 KB → 383 KB avg). Second pass at --quality=40-65 hit pngquant's floor (only 0.5% further reduction — re-quantizing an already-quantized image has little headroom). Il Gobbo from Wikimedia was a dimensional outlier (1426x2366 vs siblings ~620x1024) — resized via System.Drawing HighQualityBicubic to 620x1029 before optimization. Format32bppArgb alpha channel verified intact across samples after optimization pass. Visually validated by user: cards must fill entire screen before any pixelization visible. Sprint A precursor — DeckVariant.has_card_images toggle + image-rendering template branch per [[project-image-based-deck-face-rendering]] follows in subsequent commits, will consume these assets in 6 surfaces (my_sign, my_sea, both billboard applets, room, game_kit). Asset set also unblocks downstream Sprint C+B [[project-deck-segment-model]] (admin form will require image upload + enforce naming convention) and Sprint D [[project-card-deck-icon]] (uses -back.png as the deck-stack icon's repeating card-face). Future: when Sprint B's admin form ships, wire pngquant into an optimize_card_images management command so admin uploads auto-optimize on save. Gitignore line src/apps/epic/static/apps/epic/images/cards-faces/minchiate-fiorentine/ dropped — v1 staging dir deleted (was only ever the rename-staging set; superseded by v2-named optimized set). Total disk delta: +36.7 MB binary content. No code changes — pure asset + convention import
2026-05-24 22:39:21 -04:00
2026-01-13 20:58:25 -05:00
Description
No description provided
160 MiB
Languages
Python 45.5%
JavaScript 36.1%
HTML 9.6%
SCSS 8.6%
Jinja 0.1%