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:
+21
-2
@@ -662,8 +662,9 @@ Schema:
|
||||
{
|
||||
"game": "NLH" | "PLO" | ...,
|
||||
"stakes": "<e.g. 1/3, or null>",
|
||||
"hero_pos": "<UTG|UTG1|MP|LJ|HJ|CO|BTN|SB|BB, hero's position>",
|
||||
"hero_cards": ["As","Ax", ...], // rank+suit (s/h/d/c); 'x' suit if unknown e.g. "Ax"; "x" for a fully unknown card
|
||||
"hero_involved": true | false, // is the narrator actually IN this hand? (see HERO rule)
|
||||
"hero_pos": "<UTG|UTG1|MP|LJ|HJ|CO|BTN|SB|BB, hero's position — null if hero not involved>",
|
||||
"hero_cards": ["As","Ax", ...], // hero's cards; [] / null if hero not involved. rank+suit (s/h/d/c); 'x' suit if unknown e.g. "Ax"; "x" for a fully unknown card
|
||||
"players": [ // every player mentioned, incl. hero
|
||||
{"pos": "<position>", "stack": <number|null>, "name": <string|null>, "cards": [".."]|null}
|
||||
],
|
||||
@@ -676,6 +677,17 @@ Schema:
|
||||
"result": {"pot": <number|null>, "hero_net": <number|null>, "summary": "<one line>"}
|
||||
}
|
||||
|
||||
HERO — who the hand belongs to. The narrator writes as "I/me/my". Set \
|
||||
hero_involved=true and fill hero_pos + hero_cards ONLY if he was actually dealt in and \
|
||||
playing THIS hand. If he's describing a hand he WATCHED between other players — he wasn't \
|
||||
in it (e.g. "two guys got it in", "the neck-tattoo reg stacked the whale", it's all names/\
|
||||
seats with no I/me/my holding cards) — set hero_involved=false, hero_pos=null, hero_cards=null, \
|
||||
and just record those players in players[] and their action. NEVER attribute another player's \
|
||||
cards, position, or result to the hero. When hero isn't involved, result.hero_net=null (a pot \
|
||||
he wasn't in didn't win or lose him anything). Example: "the lag in the CO stacked off KK vs \
|
||||
the nit's AA" -> hero_involved=false, hero_pos=null, hero_cards=null, players=[{pos:CO,cards:\
|
||||
["Kx","Kx"]},{pos:?,cards:["Ax","Ax"]}].
|
||||
|
||||
Rules: infer positions and street order sensibly. Amounts are plain numbers (no $). \
|
||||
NEVER invent suits or cards. A card is rank+suit where suit is one of s/h/d/c; if the suit \
|
||||
wasn't stated, use 'x' for the suit (e.g. "Ax","Kx","4x"); if a whole card wasn't stated, \
|
||||
@@ -792,6 +804,13 @@ def normalize_structured(parsed: dict) -> dict:
|
||||
return parsed
|
||||
p = dict(parsed)
|
||||
p["schema_version"] = HAND_SCHEMA_VERSION
|
||||
# Observed hand (Brian watched it, wasn't in it): never pin cards/position/result
|
||||
# to the hero. Explicit false is the signal; a null hero_pos is treated the same.
|
||||
if p.get("hero_involved") is False:
|
||||
p["hero_pos"] = None
|
||||
p["hero_cards"] = []
|
||||
if isinstance(p.get("result"), dict):
|
||||
p["result"] = {**p["result"], "hero_net": None}
|
||||
p["hero_cards"] = [_norm_card(c) for c in (p.get("hero_cards") or [])]
|
||||
p["board"] = [_norm_card(c) for c in (p.get("board") or [])]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user