bug: next-to-act flash stuck on the last folder when their fold closes a called all-in (fold + runout + hand_ended in one snapshot)

Đang mở
#968 1 bình luận 0 reaction 1 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

@bitcoinbrisbane đang làm issue này rồi.

Từ ngày 6/11/2026.

Đánh giá

Issue này chưa được đánh giá.

Mô tả

animation bug game-flow sit-and-go UI Week 2

Symptom

Wednesday 2026-11-04 Texas HODL $2 SNG, table 0xaafb3807d3c36469fe5423d37eae670fd066f938f7e0042beb80ab295065e1db, hands 10 and 12. In both hands a player went all-in and got called, with other player(s) still to act behind. After the last player folded, the UI kept the flashing next-to-act indicator on that player as if the table was still waiting on them — but their fold had committed on chain. Reported by the players at the table; the folder themselves confirmed they folded.

Chain evidence — the chain is correct, this is a rendering bug

Action timelines reconstructed from action_performed events (tx_search on node.texashodl.net; full query at the bottom).

Hand 10 (blocks 898333–898350) — flop bet, all-in call for less, third player folds, fold+runout+hand_ended all in ONE tx:

idx=300 h=898348 b521s8aug…  bet   900        tx=5B10860838
idx=301 h=898349 b5219dj7…   call  15 (all-in for less)  tx=81E86B0128
idx=302 h=898350 b5210fw5…   fold             tx=67512FAA90  ← hand_ended fires in THIS SAME TX

Result: full runout Th 2c Ad Qd Ah, showdown, 1 winner. The fold at idx=302 closed the betting, so the engine dealt turn+river and ended the hand inside one snapshot.

Hand 12 (blocks 898373–898381) — preflop all-in raise, call, two behind; the last fold again lands in the same tx as hand_ended:

idx=331 h=898374 b521p78923…  raise 580       tx=7594DDADE1
idx=337 h=898379 b521p0tkyw…  call  580       tx=6104521BCF
idx=338 h=898379 b521fh8ke9…  fold (SB)       tx=2CFA733305
idx=339 h=898381 b5219dj7…    fold (BB)       tx=388939138B  ← hand_ended fires in THIS SAME TX

Common fingerprint: the final fold both (a) closes the betting against a called all-in and (b) triggers the all-in runout + hand_ended in a single chain snapshot. The turn indicator then stays flashing on the seat that folded.

Suspect

This is exactly the single-frame scenario expandFrames (src/bus/expandFrames.ts) splits into per-street synthetic sub-frames, and the runout slow-down shipped in #873 / #874 (closed 2026-10-30, days before this game) changed the pacing of that path. Likely mechanisms to check:

  1. The synthetic sub-frames (projections between prev and next) carry a stale nextToPlay-equivalent pointing at the folder, and the seat-highlight (utils/turnClock.ts, components/playPage/Table/components/PlayerSeating.tsx + seat/Player components) renders it during the held runout choreography.
  2. The turn indicator reads the rendered track while the hold (showdownHold / runout minDisplayMs) is active, and nothing clears the "waiting on seat N" state when the terminal frame's fold is part of the same commit.
  3. A derive-events gap: deriveEvents(prev, next) may not emit a playerActed/fold transition for the folder when the same diff also contains street advances + winners, so whatever state the flash keys off never updates.

What exists today (file paths)

  • Bus runout expansion: ui/src/bus/expandFrames.ts (+ docs/plans/2026_09_09_runout_frame_expansion.md)
  • Event derivation: ui/src/bus/deriveEvents.ts
  • Turn/flash rendering: ui/src/utils/turnClock.ts, ui/src/utils/timerUtils.ts, ui/src/components/playPage/Table/components/PlayerSeating.tsx
  • Related prior art: #57 (turn ring with no active hand, closed), #873/#874 (runout pacing feature this likely regressed from)

Repro / test plan

  1. Playwright + PVM stub (packages/e2e): inject prev snapshot = 3-way pot, player A all-in, player B all-in-call-for-less, player C to act; inject next snapshot = C folded + full runout + winners (one frame, as the chain sends it). Assert the next-to-act flash is NOT on seat C during or after the runout choreography (window.__B52_BUS__.commitLog for frame assertions).
  2. Unit-test expandFrames for this input: every synthetic sub-frame must carry a cleared/-1 next-to-act once the folder's action is part of the source diff.
  3. Same scenario via deriveEvents: assert a fold event is emitted for C even when the diff spans fold→runout→winner.

Raw data

GAME=0xaafb3807d3c36469fe5423d37eae670fd066f938f7e0042beb80ab295065e1db
# per-hand actions (hands 10, 12):
curl -G "https://node.texashodl.net/rpc/tx_search" \
  --data-urlencode "query=\"action_performed.game_id='$GAME' AND action_performed.hand_number='10'\"" \
  --data-urlencode per_page=100 --data-urlencode "order_by=\"asc\""
# indexer hand records:
curl "https://indexer.block52.xyz/api/v1/hands/$GAME/10"
curl "https://indexer.block52.xyz/api/v1/hands/$GAME/12"
Ngôn ngữ chính
TypeScript
Star
2
Fork
5
Merge trung bình
21 giờ 38 phút
Pull request đã merge (30 ngày)
105

Chuẩn bị môi trường

Chúng tôi chưa kiểm tra các tệp thiết lập môi trường của dự án này. Hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của block52/ui

Tất cả issue của block52/ui

Issue tương tự

Thêm issue về TypeScript

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.