feat: view past sessions, edit session details, log rituals while reviewing

- View any past session as a read-only HUD: /session?id=N (hud(session_id) +
  /session/data?id=); /history rows now link there. Closed sessions show played
  duration + final net; recap link when one exists.
- Edit session details during or after play: poker.update_session (recomputes net
  when buy-in/cash-out change), PATCH /session/{id}, an update_session tool ("venue
  was actually Bellagio", "I bought in for 600"), and an inline ✎ Edit form on the HUD.
- Rituals attach to the most-recent session post-close (poker.review_session_id),
  so scar/confidence/reset work while reviewing after you rack up.
- Edit form is poll-safe (won't clobber mid-edit); past-session view doesn't poll.
- test_modes.py +3 (edit, review rituals, past-session HUD); 49 green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-21 05:12:13 +00:00
parent cca8322ee2
commit 559faaed30
7 changed files with 224 additions and 29 deletions
+49 -6
View File
@@ -179,9 +179,10 @@ def test_undo_last_and_delete_entry(lyra):
_, poker, modes, tools = lyra
assert "undo_last" in modes.CASH.tools
poker.start_session(venue="Meadows", stakes="2/5", buy_in=500)
h1 = poker.log_hand(position="UTG", hole_cards="AA")
h2 = poker.log_hand(position="BTN", hole_cards="72o")
poker.log_stack(600); poker.log_stack(420)
poker.log_hand(position="UTG", hole_cards="AA")
poker.log_hand(position="BTN", hole_cards="72o")
poker.log_stack(600)
poker.log_stack(420)
poker.log_ritual("scar", content="punted")
poker.log_ritual("confidence", content="good fold")
@@ -215,6 +216,48 @@ def test_undo_last_tool(lyra):
assert "one of" in tools.dispatch("undo_last", {"what": "banana"}, {}).lower()
def test_update_session_edit(lyra):
_, poker, modes, tools = lyra
assert "update_session" in modes.CASH.tools
sid = poker.start_session(venue="Meadows", stakes="1/3", buy_in=300)
s = poker.update_session(sid, stakes="2/5", buy_in_total=600, cash_out=900, venue="Bellagio")
assert s["stakes"] == "2/5" and s["venue"] == "Bellagio"
assert s["buy_in_total"] == 600 and s["cash_out"] == 900
assert s["net"] == 300 # recomputed from cash_out - buy_in
# via the tool (edits the live/most-recent session)
out = tools.dispatch("update_session", {"mood": "locked in"}, {})
assert "updated" in out.lower() and poker.get_session(sid)["mood"] == "locked in"
assert "what to change" in tools.dispatch("update_session", {}, {}).lower()
def test_review_session_and_post_close_rituals(lyra):
_, poker, _, tools = lyra
sid = poker.start_session(venue="Meadows", stakes="2/5", buy_in=500)
poker.end_session(cash_out=720)
assert poker.live_session() is None
assert poker.review_session_id() == sid # most-recent closed session
# rituals attach to the closed session during review (no live session needed)
out = tools.dispatch("scar_note", {"content": "should've folded turn", "classification": "punt"}, {})
assert "logged" in out.lower()
tools.dispatch("confidence_bank", {"content": "good thin value river"}, {})
assert len(poker.list_rituals(session_id=sid, kinds=("scar",))) == 1
assert len(poker.list_rituals(session_id=sid, kinds=("confidence",))) == 1
def test_hud_for_past_session(lyra):
_, poker, _, _ = lyra
sid = poker.start_session(venue="Meadows", stakes="2/5", buy_in=500)
poker.log_hand(position="BTN", hole_cards="AKs")
poker.end_session(cash_out=650)
# a *new* live session so live HUD != the one we query
poker.start_session(venue="Wynn", stakes="1/3", buy_in=300)
past = poker.hud(sid)
assert past["session"]["id"] == sid and past["session"]["is_live"] is False
assert past["session"]["net"] == 150 and len(past["hands"]) == 1
assert poker.hud()["session"]["venue"] == "Wynn" # live one unaffected
def test_list_and_delete_session(lyra):
_, poker, _, tools = lyra
keep = poker.start_session(venue="Meadows", stakes="1/3", buy_in=300)
@@ -244,9 +287,9 @@ def test_recent_sessions_tool(lyra):
assert "Meadows" in out and "+220" in out
def test_rituals_require_live_session(lyra):
def test_rituals_require_a_session(lyra):
_, poker, _, tools = lyra
# tools degrade gracefully (no exception) when nothing is open
assert "no live session" in tools.dispatch("scar_note", {"content": "x"}, {}).lower()
# with no session at all, the tool degrades gracefully (no exception)
assert "no session" in tools.dispatch("scar_note", {"content": "x"}, {}).lower()
with pytest.raises(ValueError):
poker.log_ritual("scar", content="x")