feat(prompting): Phase B step 2 — wire the sharded poker prompt into the pipeline
build_messages now shards poker_cash: injects poker_prompts.BASE + exactly ONE fragment chosen by classify(user_msg, roster_handles), replacing the ~100-line _CASH_CARD monolith. Roster handles are fetched fail-safe from the live session so the READ-vs-HAND split is reliable. CASH.card set to "" (monolith kept only as the distillation source, superseded). Other modes' single-card path unchanged. Verified end-to-end: TAG-limp→READ, his-hand→HAND, table-broke→TABLE, tilt→MENTAL, bare-stack→LOG, all with BASE always present. 5 injection/pipeline tests. Full suite 196 green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+16
-4
@@ -17,8 +17,8 @@ from __future__ import annotations
|
|||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
|
|
||||||
from lyra import (
|
from lyra import (
|
||||||
clock, config, llm, logbus, memory, modes, perceive, persona, scouting,
|
clock, config, llm, logbus, memory, modes, perceive, persona, poker, poker_prompts,
|
||||||
self_state, thoughts,
|
scouting, self_state, thoughts,
|
||||||
)
|
)
|
||||||
from lyra.llm import Backend, Message
|
from lyra.llm import Backend, Message
|
||||||
|
|
||||||
@@ -153,8 +153,20 @@ def build_messages(session_id: str, user_msg: str,
|
|||||||
if inner:
|
if inner:
|
||||||
messages.append(inner)
|
messages.append(inner)
|
||||||
|
|
||||||
# Mode card: how to behave *right now*. Talk mode has no card (persona is Talk).
|
# Mode framing: how to behave *right now*. Poker (poker_cash) is SHARDED — a lean
|
||||||
if mode and mode.card:
|
# always-on BASE plus ONE response-shape fragment chosen by classifying this message
|
||||||
|
# (replaces the old ~100-line monolithic card). Roster handles make the READ-vs-HAND
|
||||||
|
# split reliable; fetched fail-safe. Other modes use their single card.
|
||||||
|
if mode and mode.key == "poker_cash":
|
||||||
|
messages.append({"role": "system", "content": poker_prompts.BASE})
|
||||||
|
try:
|
||||||
|
handles = [r["name"] for r in poker.session_roster()]
|
||||||
|
except Exception:
|
||||||
|
handles = []
|
||||||
|
msg_type = poker_prompts.classify(user_msg, handles)
|
||||||
|
messages.append({"role": "system", "content": poker_prompts.fragment_for(msg_type)})
|
||||||
|
logbus.log("info", "poker turn classified", type=msg_type)
|
||||||
|
elif mode and mode.card:
|
||||||
messages.append({"role": "system", "content": mode.card})
|
messages.append({"role": "system", "content": mode.card})
|
||||||
|
|
||||||
# Mode awareness: she can offer to switch when the work clearly shifts (she decides
|
# Mode awareness: she can offer to switch when the work clearly shifts (she decides
|
||||||
|
|||||||
+4
-1
@@ -240,7 +240,10 @@ TALK = Mode(
|
|||||||
CASH = Mode(
|
CASH = Mode(
|
||||||
key="poker_cash",
|
key="poker_cash",
|
||||||
label="Poker",
|
label="Poker",
|
||||||
card=_CASH_CARD,
|
# Poker mode is SHARDED at the pipeline (lyra.poker_prompts: BASE + a per-message
|
||||||
|
# fragment), so no monolithic card here. _CASH_CARD is kept below only as the source
|
||||||
|
# material the fragments were distilled from — superseded, safe to delete later.
|
||||||
|
card="",
|
||||||
tools=_CASH_TOOLS,
|
tools=_CASH_TOOLS,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -75,3 +75,31 @@ def test_mode_menu_note_suppressed_in_poker(mind):
|
|||||||
if m["role"] == "system")
|
if m["role"] == "system")
|
||||||
assert "Your modes:" not in poker # no "offer to switch" note at the table
|
assert "Your modes:" not in poker # no "offer to switch" note at the table
|
||||||
assert "Your modes:" in build # still present in a non-poker mode
|
assert "Your modes:" in build # still present in a non-poker mode
|
||||||
|
|
||||||
|
|
||||||
|
# --- Phase B: sharded poker prompt (BASE + one fragment, no monolith) ---
|
||||||
|
|
||||||
|
def _poker_blob(mind, msg):
|
||||||
|
from lyra import modes
|
||||||
|
return " ".join(m["content"] for m in mind.build_messages("s1", msg, mode=modes.CASH)
|
||||||
|
if m["role"] == "system")
|
||||||
|
|
||||||
|
|
||||||
|
def test_poker_injects_base_plus_the_matching_fragment(mind):
|
||||||
|
blob = _poker_blob(mind, "I flopped a set with 99 on 9h4c2d and bet the turn")
|
||||||
|
assert "LOG FIRST" in blob # BASE is always on in poker
|
||||||
|
assert "MESSAGE TYPE: HAND" in blob # the fragment for THIS message
|
||||||
|
assert "MESSAGE TYPE: STATUS" not in blob # and not the others
|
||||||
|
assert "MESSAGE TYPE: READ" not in blob
|
||||||
|
|
||||||
|
|
||||||
|
def test_poker_fragment_changes_with_message_type(mind):
|
||||||
|
status = _poker_blob(mind, "it's 11:50pm, waiting for a seat")
|
||||||
|
assert "MESSAGE TYPE: STATUS" in status and "MESSAGE TYPE: HAND" not in status
|
||||||
|
|
||||||
|
|
||||||
|
def test_poker_monolith_no_longer_injected(mind):
|
||||||
|
from lyra import modes
|
||||||
|
blob = _poker_blob(mind, "stack 350")
|
||||||
|
assert "You move between two registers" not in blob # the old _CASH_CARD opener is gone
|
||||||
|
assert modes.CASH.card == "" # card sharded out
|
||||||
Reference in New Issue
Block a user