add run logging and smart state polling - #13
Conversation
- Add mcp/run_logger.py: lightweight JSONL logger that records every tool call and AI decision to logs/run_<timestamp>.jsonl - Add _get_smart() to server.py: polls up to 8s during enemy turns until the state is actionable (Play Phase: True, combat ended, or non-combat state), reducing wasted tool calls and token consumption - Add log_agent_decision MCP tool: lets the AI log reasoning before key decisions for post-run analysis - Add logs/ to .gitignore Closes Gennadiyev#10 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Thanks for the PR. I'm manually reviewing this one and it looks very promising. Recently, another STS2 player reminded me about the existence of an Regarding the logging, while I still agree that actions should be properly logged, explicitly declaring a tool for this seems to be beyond the scope of STS2MCP. API Hooks are neat and definitely nice-to-have. |
I have no idea that "instant mode" is a thing😂, I will look into it and see if any improvements can be made with that also I'll see if the log can be improved with better readbility |
ok i see so there's a hidden game speed setting called "Instant"that can be unlocked through mod? yeah if it actually works i think it will definitely be better than the smart polling way. I'll test it our later and see how it goes. Also I agree with you that logging should be put on the agent.md instead of directly injected inside the MCP |
Adds JSONL run logging, smart state polling during enemy turns, and a log_agent_decision tool for recording AI reasoning. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Haha I was also told by another friend of mine about the instant mode xD Glad it helped, and hope you enjoy the new version here <3 |
Builds on commit 25b6fd2 (Phase 0/A/C). Continues the "code > NL for hard rules" principle by encoding 4 more catastrophic rules as action-time validators, adds a strategic-level pre-fight assessment tool, and trims the auto-loaded prompt by ~25% (from ~55KB to ~41.5KB). Phase E — 4 new validators in mcp/validators.py: * V5 BLOCK: 昏眩 (Daze) + self-damage card → refuse. Daze limits play to 1 card/turn, so self-damage strictly dominates death (Run Gennadiyev#10 case). * V6 WARN: 纸伤难愈 (Paper Cuts) enemy + projected unblocked > 0 → must 100% block (every unblocked HP is permanent max-HP loss). Run Gennadiyev#11. * V7 WARN: 缠结 (Entangled) + attack card without sufficient block planned → defensive turn warning. Run Gennadiyev#7 was a death-by-缠结. * V8 WARN: buff potion (力量/敏捷药水) used after attacks already played this turn → too late for full multiplier. Wired into use_potion via a per-turn _attacks_played_this_turn counter that resets on round change. All four wired into combat_play_card / combat_batch (per-step) / combat_end_turn / use_potion preflight; bypassable with force=True. Telemetry extended in game_logger.py to count V5-V8 triggers. Phase F — Pre-fight Kill Math tool: * New mcp/kill_math.py module with DPS estimator (hand+draw pile attack cards, Strength scaling, vuln/weak modifiers, energy ceiling), survival estimator (HP / (incoming - block_per_turn)), verdict logic. * New combat_kill_math() MCP tool returns structured assessment: GO (gap >= +2) / MARGINAL (-2..+2) / NO_GO (<= -3) plus damage, turns-to-kill, recommendations, warnings (Ritual etc.). * sts2-combat-strategy.instructions.md updated: "T1 of every elite/boss call combat_kill_math() and branch by verdict" — addresses Run Gennadiyev#13's "知道≠使用" failure mode at the strategic level. Phase G — Skill file trim (~25% reduction in auto-loaded prompt): * sts2-play-game: 125→90 lines (drop dup batch-safety, compress narration examples, consolidate validators/Kill Math/state polling sections) * sts2-combat-strategy: 210→187 (move Boss/elite details to bestiary; consolidate Act 3 enemy classes into single table) * sts2-deck-building: 108→73 (move detailed S/A/B card lists to card-atlas.md; condense archetypes into single comparison table) * sts2-learnings: 114→91 (trim enemy quick-ref to "key reminders" only; flatten synergy index by character) * docs/bestiary.md: absorbed Boss strategy details + new Run Gennadiyev#11/Gennadiyev#12/Gennadiyev#13 enemies (Insatiable, Waterfall Giant, Ceremonial Beast, Fabricator, Scroll of Biting, Ritual Sculptor, Act 2 Bowlbug/Tunneler/Exoskeleton). Telemetry: per-run summary.md now shows V5/V6/V7/V8 trigger counts. Verification: * All Python files parse + import OK; 68 MCP tools registered (was 67). * V5 + V1 + V4 all fire correctly when low-HP self-damage played under Daze. * Kill Math correctly returns NO_GO for weak deck vs Ceremonial Beast. * Telemetry detection regex matches all 8 validator codes + batch abort. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Summary
Addresses #10. Adds two features:
mcp/run_logger.py) — records every tool call and AI decision tologs/run_<timestamp>.jsonlfor post-run analysisand model comparison
_get_smart()) — waits up to 8s during enemy turns for an actionable state, reducing wasted tool calls and tokenconsumption
log_agent_decisiontool — lets the AI record reasoning before key decisionsAll changes are additive — no modifications to existing tool signatures or the C# mod.
Details
Run logging
Every
_getand_postcall is logged to a JSONL file with timestamp, action name, args, and result preview. A newlog_agent_decisionMCP tool lets the AI explicitly record reasoning (e.g., "Combat turn 3: enemy intends Attack 11, playing Defend + Strike because...").
Smart polling
get_game_statenow uses_get_smart()which detectsPlay Phase: Falsein combat states and polls (1s intervals, up to 8s) until thestate is actionable. This saved ~40% of redundant state calls in testing with both Claude and local models.
Test plan
logs/directory is created with JSONL fileget_game_statewaits during enemy turns and returns on player turnCloses Feature: Add run logging and smart state polling for combat turns #10