feat: Decide mode — a tie-breaker that settles choices instead of listing options

Brian's bottleneck is committing, not generating options, so a pros/cons dump makes
it worse. Decide mode's card: get the real decision crisp, weigh it against what HE
values + past regrets (pull running_stats/recent_sessions for poker/money calls),
MAKE the call with the one or two reasons that tip it, pressure-test it once, and
stand behind it — no "it's up to you." Read-only lookups, no live logging.

Sixth mode (Talk/Poker/Build/Explore/Study/Decide); added to UI selectors, labels,
badge-cycle. Suite 96 green, ruff clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-24 16:21:03 +00:00
parent 03aceec6fa
commit 17ab95dc98
3 changed files with 33 additions and 4 deletions
+23 -1
View File
@@ -59,6 +59,9 @@ _TALK_TOOLS = _BASE + _LOOKUPS + ("start_session",)
# Study = poker review away from the table: read-only lookups + equity, no live logging. # Study = poker review away from the table: read-only lookups + equity, no live logging.
_STUDY_TOOLS = _BASE + _LOOKUPS + ("analyze_spot",) _STUDY_TOOLS = _BASE + _LOOKUPS + ("analyze_spot",)
# Decide = help him settle a choice; read-only lookups for bankroll/variance context.
_DECIDE_TOOLS = _BASE + _LOOKUPS
_CASH_CARD = """You are copiloting Brian's LIVE cash game right now — you're at the table with him, \ _CASH_CARD = """You are copiloting Brian's LIVE cash game right now — you're at the table with him, \
a session is (or should be) open. You move between two registers depending on what he's doing: a session is (or should be) open. You move between two registers depending on what he's doing:
@@ -151,6 +154,24 @@ Connect it to his actual tendencies and known leaks when you can (his profile, p
genuinely close and explain what tips it. This is the slow, careful counterpart to live Poker mode.""" genuinely close and explain what tips it. This is the slow, careful counterpart to live Poker mode."""
_DECIDE_CARD = """You're in DECIDE mode — Brian is indecisive and needs help SETTLING a \
choice, not generating more options. Be the tie-breaker who knows him. His bottleneck is \
committing, so a pros/cons dump makes it WORSE — don't do that.
• GET THE REAL DECISION CRISP. What's actually being chosen, the genuine constraints, the \
deadline. Cut the noise to the one or two things that actually decide it.
• WEIGH IT AGAINST HIM. Use what you know about him — his values, what he genuinely enjoys, \
how he's felt about similar calls before, his energy/schedule, his bankroll and how he's \
running if money's involved (pull running_stats / recent_sessions when it's a poker call). \
The point is HIS satisfaction and regret, not a generic optimum.
• MAKE THE CALL. Give a clear recommendation and the one or two reasons that genuinely tip \
it. Commit — don't hedge, don't hand the indecision back with "it's up to you."
• PRESSURE-TEST YOUR OWN CALL ONCE: the strongest reason you might be wrong, and the one \
thing that would flip it. Then hold your recommendation unless he pushes back with something real.
Warm but firm — he asked you to help him stop spinning. Decide, and stand behind it."""
TALK = Mode( TALK = Mode(
key="conversation", key="conversation",
label="Talk", label="Talk",
@@ -168,8 +189,9 @@ CASH = Mode(
BUILD = Mode(key="build", label="Build", card=_BUILD_CARD, tools=_BASE) BUILD = Mode(key="build", label="Build", card=_BUILD_CARD, tools=_BASE)
EXPLORE = Mode(key="explore", label="Explore", card=_EXPLORE_CARD, tools=_BASE) EXPLORE = Mode(key="explore", label="Explore", card=_EXPLORE_CARD, tools=_BASE)
STUDY = Mode(key="study", label="Study", card=_STUDY_CARD, tools=_STUDY_TOOLS) STUDY = Mode(key="study", label="Study", card=_STUDY_CARD, tools=_STUDY_TOOLS)
DECIDE = Mode(key="decide", label="Decide", card=_DECIDE_CARD, tools=_DECIDE_TOOLS)
MODES: dict[str, Mode] = {m.key: m for m in (TALK, CASH, BUILD, EXPLORE, STUDY)} MODES: dict[str, Mode] = {m.key: m for m in (TALK, CASH, BUILD, EXPLORE, STUDY, DECIDE)}
DEFAULT = TALK.key DEFAULT = TALK.key
+5 -2
View File
@@ -30,6 +30,7 @@
<option value="build">🛠 Build</option> <option value="build">🛠 Build</option>
<option value="explore">🔭 Explore</option> <option value="explore">🔭 Explore</option>
<option value="study">📐 Study</option> <option value="study">📐 Study</option>
<option value="decide">⚖️ Decide</option>
</select> </select>
</div> </div>
@@ -73,6 +74,7 @@
<option value="build">🛠 Build</option> <option value="build">🛠 Build</option>
<option value="explore">🔭 Explore</option> <option value="explore">🔭 Explore</option>
<option value="study">📐 Study</option> <option value="study">📐 Study</option>
<option value="decide">⚖️ Decide</option>
</select> </select>
<button id="settingsBtn" style="margin-left: auto;">⚙ Settings</button> <button id="settingsBtn" style="margin-left: auto;">⚙ Settings</button>
<div id="theme-toggle"> <div id="theme-toggle">
@@ -613,8 +615,9 @@
// ----- Conversation modes (Talk / Poker / Build / Explore / Study) ----- // ----- Conversation modes (Talk / Poker / Build / Explore / Study) -----
const MODE_LABELS = { conversation: "💬 Talk", poker_cash: "♠ Poker", const MODE_LABELS = { conversation: "💬 Talk", poker_cash: "♠ Poker",
build: "🛠 Build", explore: "🔭 Explore", study: "📐 Study" }; build: "🛠 Build", explore: "🔭 Explore", study: "📐 Study",
const MODE_ORDER = ["conversation", "poker_cash", "build", "explore", "study"]; decide: "⚖️ Decide" };
const MODE_ORDER = ["conversation", "poker_cash", "build", "explore", "study", "decide"];
// Reflect a mode value across the controls + header accent (no network call). // Reflect a mode value across the controls + header accent (no network call).
function applyMode(value) { function applyMode(value) {
+5 -1
View File
@@ -50,7 +50,11 @@ def test_every_mode_tool_exists(lyra):
def test_work_modes_present_and_gated(lyra): def test_work_modes_present_and_gated(lyra):
_, _, modes, tools = lyra _, _, modes, tools = lyra
# the full set Brian chose # the full set Brian chose
assert set(modes.MODES) == {"conversation", "poker_cash", "build", "explore", "study"} assert set(modes.MODES) == {"conversation", "poker_cash", "build", "explore", "study", "decide"}
# Decide = read-only lookups for context, no live logging; has a real card
decide = _names(tools.specs(modes.DECIDE.tools))
assert {"running_stats", "recent_sessions"} <= decide and "log_hand" not in decide
assert modes.DECIDE.card
# Build/Explore are conversational: base agency tools only, no live poker logging # Build/Explore are conversational: base agency tools only, no live poker logging
for key in ("build", "explore"): for key in ("build", "explore"):
names = _names(tools.specs(modes.get(key).tools)) names = _names(tools.specs(modes.get(key).tools))