id: 5d69108961b746d092547db72ee31390
parent_id: 566b6cfe43d44e6ab0ebbd2a323230d2
item_type: 1
item_id: b7492324f4d64486ba79ea00e636d2ec
item_updated_time: 1784277603387
title_diff: "[{\"diffs\":[[0,\"r & \"],[-1,\"Scrapers\"],[1,\"Userscript\"],[0,\" Arc\"]],\"start1\":24,\"start2\":24,\"length1\":16,\"length2\":18}]"
body_diff: "[{\"diffs\":[[0,\"r & \"],[-1,\"Scrapers\"],[1,\"Userscript\"],[0,\" Arc\"]],\"start1\":26,\"start2\":26,\"length1\":16,\"length2\":18},{\"diffs\":[[0,\"re\\\n\\\n\"],[-1,\"**Status:** Phase 2 (server core) complete —\"],[1,\"> **Updated\"],[0,\" 2026-0\"],[-1,\"6-15\\\n**Design plan:** `super_marvin/.kilo/plans/live-integration-torn.md`\\\n**Related:** [Vision — Poker AI Testbed & Live Server](joplin://b7bf3a077c064d8493373a3661adc702), [Prototype: Web Traffic Interception](joplin://6794e0bb60ae4da68720868546ddf628), [Browser Extension](joplin://c994139aac9245c79da7923dbe8579b3)\\\n\\\n---\"],[1,\"7-17.** Production: G48 live bot on Torn City poker via TamperMonkey userscript → live_server.\"],[0,\"\\\n\\\n##\"]],\"start1\":51,\"start2\":51,\"length1\":381,\"length2\":120},{\"diffs\":[[0,\"ites\"],[-1,\"/applications. First\"],[1,\". Current production\"],[0,\" tar\"]],\"start1\":219,\"start2\":219,\"length1\":28,\"length2\":28},{\"diffs\":[[0,\"** poker\"],[-1,\"\\\n\"],[1,\" \"],[0,\"page (br\"]],\"start1\":263,\"start2\":263,\"length1\":17,\"length2\":17},{\"diffs\":[[0,\"contains\"],[-1,\"\\\n\"],[1,\" \"],[0,\"site-spe\"]],\"start1\":351,\"start2\":351,\"length1\":17,\"length2\":17},{\"diffs\":[[0,\"am (\"],[-1,\"chosen)\\\n\\\nThe Java JointBot `BotServer` was event-driven (UDP multicast, XML). We modernize to **JSON over\\\nHTTP** but keep the model: t\"],[1,\"HTTP JSON)\\\n\\\nT\"],[0,\"he s\"]],\"start1\":789,\"start2\":789,\"length1\":142,\"length2\":21},{\"diffs\":[[0,\"er-table\"],[-1,\"\\\n\"],[1,\" \"],[0,\"state ma\"]],\"start1\":869,\"start2\":869,\"length1\":17,\"length2\":17},{\"diffs\":[[0,\"on`.\"],[-1,\" (A snapshot-per-decision\\\nmodel was considered and rejected as less robust.)\"],[0,\"\\\n\\\n``\"]],\"start1\":944,\"start2\":944,\"length1\":84,\"length2\":8},{\"diffs\":[[0,\"ile`\"],[-1,\" (format/limit/seats — drives auto-detect)\"],[0,\", `g\"]],\"start1\":1476,\"start2\":1476,\"length1\":50,\"length2\":8},{\"diffs\":[[0,\"op/turn/\"],[-1,\"\\\n\"],[0,\"river), \"]],\"start1\":1511,\"start2\":1511,\"length1\":17,\"length2\":16},{\"diffs\":[[0,\"_action`\"],[-1,\"\\\n\"],[1,\" \"],[0,\"(trigger\"]],\"start1\":1611,\"start2\":1611,\"length1\":17,\"length2\":17},{\"diffs\":[[0,\"decision\"],[1,\", includes `dom_snapshot` field\"],[0,\"), `win`\"]],\"start1\":1630,\"start2\":1630,\"length1\":16,\"length2\":47},{\"diffs\":[[0,\"rings.\\\n\\\n\"],[1,\"## DOM Snapshot Debugging (added 2026-07-17)\\\n\\\n`waiting_for_action` carries `dom_snapshot: Option<String>` — full table HTML for debugging. `player_action` carries `raw_text: Option<String>`. Server stores snapshot on `TableState`, logs to per-hand decision log as `[DOM_SNAPSHOT]`, clears after decision. Gated by `window.__marvinDomDebug` in the userscript.\\\n\\\n\"],[0,\"## Bot a\"]],\"start1\":1739,\"start2\":1739,\"length1\":16,\"length2\":376},{\"diffs\":[[0,\"s; falls\"],[-1,\"\\\n\"],[1,\" \"],[0,\"back to \"]],\"start1\":2241,\"start2\":2241,\"length1\":17,\"length2\":17},{\"diffs\":[[0,\"nced bot\"],[-1,\"\\\n\"],[1,\" \"],[0,\"TOML is \"]],\"start1\":2340,\"start2\":2340,\"length1\":17,\"length2\":17},{\"diffs\":[[0,\"gine\"],[-1,\"; `live_server` instantiates the selected bot per table via\\\n`holdem_core::game::\"],[1,\" via `\"],[0,\"bot_\"]],\"start1\":2379,\"start2\":2379,\"length1\":88,\"length2\":14},{\"diffs\":[[0,\"vin \"],[-1,\"addition\"],[1,\"workspace crate\"],[0,\"s\\\n\\\n`\"]],\"start1\":2428,\"start2\":2428,\"length1\":16,\"length2\":23},{\"diffs\":[[0,\"bleEvent\"],[1,\" (with dom_snapshot, raw_text)\"],[0,\", EventR\"]],\"start1\":2612,\"start2\":2612,\"length1\":16,\"length2\":46},{\"diffs\":[[0,\"Band\"],[-1,\", …\"],[0,\"\\\nliv\"]],\"start1\":2683,\"start2\":2683,\"length1\":11,\"length2\":8},{\"diffs\":[[0,\"_all\"],[-1,\" + read_bot_name\"],[0,\"\\\n  s\"]],\"start1\":2969,\"start2\":2969,\"length1\":24,\"length2\":8},{\"diffs\":[[0,\"cle \"],[-1,\"(decide on waiting_for_action)\"],[1,\"+ DOM snapshot logging\"],[0,\"\\\n  s\"]],\"start1\":3210,\"start2\":3210,\"length1\":38,\"length2\":30},{\"diffs\":[[0,\"y config\"],[1,\" (bind 0.0.0.0:8088)\"],[0,\"\\\nconfigs\"]],\"start1\":3372,\"start2\":3372,\"length1\":16,\"length2\":36},{\"diffs\":[[0,\"ault\"],[1,\" →\"],[0,\" cash_nl\"],[-1,\", sng_gen2, mtt→sng_gen2)\\\n```\\\n\\\n`table_state.rs` is the Rust analogue of JointBot `TableManager`: it accumulates events into\\\nrunning table state (seats, stacks, wagers, board, pot, current_bet, blinds, street, button/sb/bb),\\\ndrives the bot's `HoldemPlayer` lifecycle (game_start_event, hole_cards_dealt, stage_event,\\\naction_event, act, game_over_event), and builds a `GameInfo` on each step.\"],[1,\"_g48_live)\\\n```\"],[0,\"\\\n\\\n##\"]],\"start1\":3455,\"start2\":3455,\"length1\":406,\"length2\":32},{\"diffs\":[[0,\"_server`\"],[1,\" or `./target/release/live_server`\"],[0,\".\\\n\\\n## su\"]],\"start1\":3883,\"start2\":3883,\"length1\":16,\"length2\":50},{\"diffs\":[[0,\"nts` via\"],[-1,\"\\\n\"],[1,\" \"],[0,\"`GM_xmlh\"]],\"start1\":4047,\"start2\":4047,\"length1\":17,\"length2\":17},{\"diffs\":[[0,\"n/` \"],[-1,\"ships a stub `collectEvents()` + `executeAction()`\\\nloop; Phase 3 fills in real Torn DOM scraping. Build: `npm run build` → `torn/dist/torn.user.js`.\\\n\\\n## Verification (Phase 2)\\\n\\\n- 18 unit tests pass (poker_protocol + live_server: bot-selection resolution, session store,\\\n  table-state state machine incl. blinds/pot GameInfo, fold/call via built-in bots).\\\n- End-to-end smoke: posted `table_profile` (cash NL 2-seat) → resolved `cash_nl`; full event stream\\\n  (game_start → deal hole → SB/BB → waiting_for_action) → real engine decision returned inline.\\\n\\\n## Phases\\\n\\\n1. **Phase 1 — Scaffolding** ✅ crates, build pipeline, stubs.\\\n2. **Phase 2 — Server core** ✅ event protocol, bot auto-detect, state machine → engine decisions.\\\n3. **Phase 3 — Torn scraping** — inspect Torn poker DOM/network; implement `collectEvents()` +\\\n   `executeAction()`; live single-table loop.\\\n4. **Phase 4 — Hardening** — GameInfo fidelity tuning vs engine, session/hand lifecycle edge cases,\\\n   reconnect/retry, throttling, hand-history logging, multi-table.\\\n\\\n## Open items / known caveats\\\n\\\n- **GameInfo fidelity:** the server-built `GameInfo` approximates engine state from events. Move\\\n  quality depends on this matching exactly what the engine produces; needs validation against real\\\n  Torn event streams (Phase 3) and possibly unit tests against the engine's\"],[1,\"implements real Torn DOM scraping: `collectEvents()` parses player actions, bets, blinds, community cards from the live table; `executeAction()` clicks the correct buttons. Build: `npm run build` → `torn/dist/torn.user.js`. Current version: v0.1.11.\\\n\\\n### Userscript fixes (2026-07-17)\\\n- Raise regex: `[\\\\d,.]+[kKmM]?` (handles k/M suffix)\\\n- Corrupt blinds false positive fix\\\n- Raise tolerance: 5% (Torn adds ~$50K chip denomination regardless of raise size)\\\n- DOM_DEBUG runtime toggle via `window.__marvinDomDebug`\\\n\\\n## Hand History & Decision Logging\\\n\\\n- Per-hand logs: `/tmp/super_marvin_hands/hands/` — full hand with bot decisions inline\\\n- Decision logs: `/tmp/super_marvin_hands/decisions/` — individual bot decision with game context\\\n- Server log: `/tmp/live_server.log` (RUST_LOG=debug for verbose event/decision logging)\\\n\\\n## Production Status\\\n\\\nAll 4 phases complete. The system is deployed and playing live\"],[0,\" o\"],[-1,\"w\"],[0,\"n \"],[-1,\"`GameInfo` snapshots.\\\n- **`actions_this_hand`** is left empty in the server-built `GameInfo`; the `StrategyBot` derives its\\\n  action history from its own `ActionRecorder` (fed via `action_event`), so this is not blocking, but\\\n  any strategy reading `actions_this_hand` directly would see empty data.\\\n- Server stays site-agnostic; `poker_protocol` stays free of network/runtime deps.\"],[1,\"Torn:\\\n- **Bot**: `cash_nl_g48_live` (G47 preflop + G48 formula postflop)\\\n- **MC samples**: 40K (live config)\\\n- **Key config**: `behind_penalty_weight=0.15`, `narrow_board_hit_boost=3.0`, Harrington-aligned preflop sizing\\\n\"]],\"start1\":4100,\"start2\":4100,\"length1\":1725,\"length2\":1140}]"
metadata_diff: {"new":{},"deleted":[]}
encryption_cipher_text: 
encryption_applied: 0
updated_time: 2026-07-17T08:46:47.665Z
created_time: 2026-07-17T08:46:47.665Z
type_: 13