fix: don't attribute observed hands to the hero

When Brian narrates a hand he watched between OTHER players, the parser was still
filling hero_pos/hero_cards — pinning someone else's cards, position, and result
to him. Now:
- parser prompt adds hero_involved detection: fill hero_pos/hero_cards ONLY if he
  was actually in the hand; a hand he only watched has hero_involved=false and
  null hero fields, with the other players recorded normally.
- normalize_structured enforces it as a safety net (hero_involved=false → null
  hero_pos/cards, hero_net) even if the model slips.
- record_hand tool confirms an observed hand as "not yours" instead of implying
  it was his.

2 tests. Restarting web for the live session.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-04 02:58:02 +00:00
parent d5c80f6153
commit 2be43848a7
3 changed files with 53 additions and 3 deletions
+9 -1
View File
@@ -425,8 +425,16 @@ def _record_hand(args: dict, ctx: dict) -> str:
if not out["id"]:
return "I couldn't parse that hand — give it to me again with a little more detail?"
p = out["parsed"]
hero_in = p.get("hero_involved") is not False and bool(p.get("hero_pos"))
logbus.log("info", "hand reconstructed", id=out["id"], hero=p.get("hero_pos"),
hero_involved=hero_in)
if not hero_in:
# A hand Brian watched between other players — not his.
who = ", ".join(pl.get("name") or pl.get("pos") or "?"
for pl in (p.get("players") or [])[:3]) or "the table"
return (f"Logged hand #{out['id']} — an observed hand ({who}), not yours. "
f"View it at /hand/{out['id']}")
cards = " ".join(p.get("hero_cards") or [])
logbus.log("info", "hand reconstructed", id=out["id"], hero=p.get("hero_pos"))
return (f"Hand #{out['id']} reconstructed — {p.get('hero_pos') or '?'} "
f"{cards}. View/replay it at /hand/{out['id']}")