feat: live mental-game rituals in Cash mode

Brian's own rituals (mined from his logs) become first-class, live tools instead
of post-hoc recap sections:

- Scar Note — instructive mistakes with the punt/cooler/standard distinction.
- Confidence Bank — good process, banked regardless of result.
- Alligator Blood — invokable adversity state; she suggests it when he's
  card-dead/short/stuck, and her coaching register shifts while it's on (live
  state injected into context per-turn via chat._mode_state_note).
- Reset — tilt circuit-breaker; mental marker only, stats stay continuous.

poker_rituals table + log_ritual/list_rituals/set_alligator/alligator_active;
4 tools added to the Cash toolset and taught in the mode card; HUD gains a 🐊
banner + Confidence Bank + Scar Notes panels; recap grounded via _rituals_block.
tests/test_modes.py +5 ritual tests; 41 green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-19 06:24:28 +00:00
parent dfb6425395
commit 974ee33f71
8 changed files with 340 additions and 2 deletions
+78
View File
@@ -117,6 +117,51 @@ 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 _scar_note(args: dict, ctx: dict) -> str:
content = (args.get("content") or "").strip()
if not content:
return "Nothing to log — give me the scar."
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."
return f"Scar note logged{f' ({cls})' if cls else ''}."
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."
return "Banked. 💰"
def _alligator_blood(args: dict, ctx: dict) -> str:
on = bool(args.get("on", True))
try:
poker.set_alligator(on)
except ValueError:
return "No live session to set that on."
return ("🐊 Alligator Blood ON — hang around, refuse to die, no forced miracles."
if on else "Alligator Blood off. Back to standard register.")
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."
return "Reset logged. Clean slate — this is a new session in your head."
def _log_hand(args: dict, ctx: dict) -> str:
fields = {k: args.get(k) for k in poker._HAND_FIELDS if args.get(k) not in (None, "")}
hid = poker.log_hand(**fields)
@@ -288,6 +333,39 @@ TOOLS.update({
"Tracks his stack over time and his live net while he's still sitting.",
{"amount": {**_N, "description": "Current total chip stack, in dollars"}},
["amount"])},
"scar_note": {"handler": _scar_note, "spec": _f(
"scar_note",
"Log a SCAR NOTE — a painful or instructive mistake to study later. Use when "
"Brian punts, gets too attached, or makes a leak — or when he flags one. "
"Classify honestly: 'punt' (his error), 'cooler' (unavoidable), or 'standard' "
"(correct play, bad result). The punt-vs-cooler distinction matters to him.",
{"content": {**_S, "description": "What happened and the lesson, in Brian's terms"},
"classification": {**_S, "description": "punt | cooler | standard"},
"hand_id": {**_N, "description": "Linked hand id, if this scar is a logged hand"}},
["content"])},
"confidence_bank": {"handler": _confidence_bank, "spec": _f(
"confidence_bank",
"Log a CONFIDENCE BANK entry — good PROCESS regardless of result: a disciplined "
"laydown, clean value bet, catching a leak in real time, sticking to the plan. "
"Bank it when he does something right, especially when the result didn't reward it.",
{"content": {**_S, "description": "The disciplined / good-process play to bank"},
"hand_id": {**_N, "description": "Linked hand id, if applicable"}},
["content"])},
"alligator_blood": {"handler": _alligator_blood, "spec": _f(
"alligator_blood",
"Toggle ALLIGATOR BLOOD mode — Brian's adversity state: hang around, refuse to "
"die, don't force miracles, make opponents beat him correctly. Turn it ON when he "
"invokes it, or SUGGEST it (then turn on if he agrees) when he's card-dead, short, "
"stuck, or grinding through a downswing. Turn OFF on reset or when he's back in rhythm.",
{"on": {"type": "boolean", "description": "true to engage, false to stand down"}},
[])},
"reset_ritual": {"handler": _reset_ritual, "spec": _f(
"reset_ritual",
"Log a RESET — a deliberate mental circuit-breaker after a loss or tilt spike, "
"treating the rest of the night as a fresh start (the stats stay continuous). "
"Use when he resets, or when you've talked him through one.",
{"content": {**_S, "description": "Optional note on what prompted the reset"}},
[])},
"log_hand": {"handler": _log_hand, "spec": _f(
"log_hand",
"Log a hand in the live session. All fields optional — capture whatever Brian gives you, even terse.",