feat: poker session history — browse, delete, and Lyra lookup

Answers three gaps: no way to delete a single poker session (only clear_all),
no way to browse past sessions, and Lyra could only see aggregate stats.

- poker.list_sessions() (per-session summary + hand count + recap flag) and
  poker.delete_session() (removes a session + its hands/reads/observations/
  stacks/rituals; keeps the persistent villain file).
- /history page (date, stakes, venue, net, hours, recap link, per-row delete with
  confirm) + /history/data + DELETE /history/{id}. Nav links from chat + HUD.
- recent_sessions read tool, added to the shared lookups so Lyra can answer
  "how'd my last few sessions go?" in either mode.
- Delete is UI/CLI only — deliberately not a Lyra tool.
- test_modes.py +2 (list/delete, recent_sessions); 44 green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-20 00:21:48 +00:00
parent 35c973df05
commit e1e89c07e4
8 changed files with 223 additions and 3 deletions
+37
View File
@@ -205,6 +205,43 @@ def clear_all() -> dict:
return counts
def list_sessions(limit: int | None = None, include_review: bool = False) -> list[dict]:
"""Past + live sessions (newest first), each with a hand count + recap flag.
Excludes the standing 'Hand Reviews' bucket unless include_review."""
sql = "SELECT * FROM poker_sessions"
if not include_review:
sql += " WHERE status != 'review'"
sql += " ORDER BY started_at DESC, id DESC"
if limit:
sql += f" LIMIT {int(limit)}"
rows = [dict(r) for r in _c().execute(sql).fetchall()]
for r in rows:
r["hands"] = _c().execute(
"SELECT COUNT(*) n FROM poker_hands WHERE session_id = ?", (r["id"],)
).fetchone()["n"]
r["has_recap"] = bool(r.get("recap_md"))
return rows
def delete_session(session_id: int) -> dict:
"""Delete one session and its hands/reads/observations/stack/rituals. Leaves the
persistent villain file (poker_players) intact. Returns rows removed per table."""
conn = _c()
counts: dict[str, int] = {}
with conn:
for t in ("poker_hands", "player_observations", "player_reads",
"poker_stack_log", "poker_rituals"):
counts[t] = conn.execute(
f"SELECT COUNT(*) n FROM {t} WHERE session_id = ?", (session_id,)
).fetchone()["n"]
conn.execute(f"DELETE FROM {t} WHERE session_id = ?", (session_id,))
counts["poker_sessions"] = conn.execute(
"SELECT COUNT(*) n FROM poker_sessions WHERE id = ?", (session_id,)
).fetchone()["n"]
conn.execute("DELETE FROM poker_sessions WHERE id = ?", (session_id,))
return counts
def live_session() -> dict | None:
"""The current open session, if any."""
r = _c().execute(