feat: POST /hands endpoint + seat in HUD villains (recorder step 1)

- POST /hands: store a structured hand from the recorder; normalize_structured()
  (via store_hand_history) is the shape authority, so the client stays best-effort.
  Enriches villain dossiers from the recorded players, same as the parser path.
  Verified live: best-effort body -> normalized (version, completeness, hero sync).
- _session_villains: surface each player's latest seat so the recorder can
  auto-place known players on the table.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-27 04:11:48 +00:00
parent d7f3ba330a
commit f745ef43a1
3 changed files with 30 additions and 2 deletions
+8
View File
@@ -101,3 +101,11 @@ def test_list_recent_hands_flags_structured(poker):
rows = {r["id"]: r for r in poker.list_recent_hands()}
assert rows[structured_id]["has_structured"] is True
assert rows[flat_id]["has_structured"] is False
def test_hud_villains_carry_seat(poker):
"""The recorder auto-places known players, so the HUD bundle must expose their seat."""
poker.start_session(venue="Meadows", stakes="1/3", buy_in=400)
poker.add_read("3-bets light", seat="BTN", name="Sal", category="risky")
villains = {v["name"]: v for v in poker.hud()["villains"]}
assert villains["Sal"]["seat"] == "BTN"