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
+42 -13
View File
@@ -117,6 +117,21 @@ def _log_stack(args: dict, ctx: dict) -> str:
return f"Stack ${amount:g} logged" + (f" (net {net:+.0f})." if net is not None else ".")
def _update_session(args: dict, ctx: dict) -> str:
sid = poker.review_session_id()
if sid is None:
return "No session to edit yet."
fields = {k: args.get(k) for k in ("venue", "stakes", "game", "format",
"buy_in_total", "cash_out", "mantra", "mood") if args.get(k) not in (None, "")}
if not fields:
return "Tell me what to change (venue, stakes, game, buy-in, etc.)."
s = poker.update_session(sid, **fields)
if not s:
return "Couldn't find that session."
changed = ", ".join(f"{k}={v}" for k, v in fields.items())
return f"Session #{sid} updated — {changed}."
def _undo_last(args: dict, ctx: dict) -> str:
what = (args.get("what") or "").strip().lower()
aliases = {"hands": "hand", "stacks": "stack", "reads": "read",
@@ -143,11 +158,11 @@ def _scar_note(args: dict, ctx: dict) -> str:
cls = (args.get("classification") or "").strip().lower() or None
if cls and cls not in ("punt", "cooler", "standard"):
cls = None
try:
poker.log_ritual("scar", content=content, classification=cls,
hand_id=args.get("hand_id"))
except ValueError:
return "No live session — start one and I'll keep the scar notes."
sid = poker.review_session_id() # live, or the most-recent session (post-game review)
if sid is None:
return "No session yet — start one and I'll keep the scar notes."
poker.log_ritual("scar", content=content, classification=cls,
hand_id=args.get("hand_id"), session_id=sid)
return f"Scar note logged{f' ({cls})' if cls else ''}."
@@ -155,10 +170,10 @@ def _confidence_bank(args: dict, ctx: dict) -> str:
content = (args.get("content") or "").strip()
if not content:
return "Nothing to bank — tell me the good process."
try:
poker.log_ritual("confidence", content=content, hand_id=args.get("hand_id"))
except ValueError:
return "No live session — start one and I'll run the confidence bank."
sid = poker.review_session_id()
if sid is None:
return "No session yet — start one and I'll run the confidence bank."
poker.log_ritual("confidence", content=content, hand_id=args.get("hand_id"), session_id=sid)
return "Banked. 💰"
@@ -174,10 +189,10 @@ def _alligator_blood(args: dict, ctx: dict) -> str:
def _reset_ritual(args: dict, ctx: dict) -> str:
content = (args.get("content") or "").strip() or None
try:
poker.log_ritual("reset", content=content)
except ValueError:
return "No live session to reset."
sid = poker.review_session_id()
if sid is None:
return "No session to reset."
poker.log_ritual("reset", content=content, session_id=sid)
return "Reset logged. Clean slate — this is a new session in your head."
@@ -389,6 +404,20 @@ TOOLS.update({
"add_buyin": {"handler": _add_buyin, "spec": _f(
"add_buyin", "Record a rebuy / additional buy-in in the live session.",
{"amount": {**_N, "description": "Amount added"}}, ["amount"])},
"update_session": {"handler": _update_session, "spec": _f(
"update_session",
"Edit details of the current/most-recent session — during or after play. Use "
"when Brian corrects something ('change the stakes to 2/5', 'venue was actually "
"Bellagio', 'I bought in for 600', 'cashed out 1240'). Only pass fields that change.",
{"venue": {**_S, "description": "Casino/room"},
"stakes": {**_S, "description": "e.g. '1/3', '2/5'"},
"game": {**_S, "description": "NLH, PLO, ..."},
"format": {**_S, "description": "cash | tournament"},
"buy_in_total": {**_N, "description": "Total bought in"},
"cash_out": {**_N, "description": "Final cashout (recomputes net)"},
"mantra": {**_S, "description": "Pre-session focus/anchor"},
"mood": {**_S, "description": "Mental-game note"}},
[])},
"undo_last": {"handler": _undo_last, "spec": _f(
"undo_last",
"Undo/delete the most recent logged entry in the live session when Brian says "