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
+23
View File
@@ -45,6 +45,29 @@ def test_stamps_version(poker):
assert out["schema_version"] == poker.HAND_SCHEMA_VERSION
def test_observed_hand_never_attributed_to_hero(poker):
# Brian narrated a hand between two other players — hero_involved=false.
out = poker.normalize_structured({
"hero_involved": False,
"hero_pos": "CO", "hero_cards": ["Kx", "Kx"], # model slipped these in
"players": [{"pos": "CO", "cards": ["Kx", "Kx"]}, {"pos": "BB", "cards": ["Ax", "Ax"]}],
"result": {"pot": 600, "hero_net": 300},
})
assert out["hero_pos"] is None # not pinned to Brian
assert out["hero_cards"] == []
assert out["result"]["hero_net"] is None # a pot he wasn't in
assert not any(pl.get("hero") for pl in out["players"]) # nobody flagged hero
def test_hero_hand_still_attributed(poker):
out = poker.normalize_structured({
"hero_involved": True, "hero_pos": "BTN", "hero_cards": ["As", "Ks"],
"players": [{"pos": "BTN"}]})
assert out["hero_pos"] == "BTN"
hero = next(pl for pl in out["players"] if pl.get("pos") == "BTN")
assert hero.get("hero") and hero["cards"] == ["As", "Ks"]
def test_card_normalization(poker):
out = poker.normalize_structured(_full_hand())
assert out["hero_cards"] == ["Ah", "Kh"] # lowercased input -> canonical