Two findings, both from measurement rather than the public guides. 1. The public STS2 meta is not usable as evidence. Deck-size targets disagree by 3x across five sources (12-18 to 25-35), and one tier list names Demon Form, Barricade, Limit Break and Body Slam as STS2 Ironclad cards -- those are Slay the Spire 1 cards, so that page is an STS1 list retitled. Only Offering and Break appear on more than one list. 2. Our own run files are far better evidence, and they contain 1052 labelled decisions. They show the bot is NOT bloating (249 picks from 1087 offers = 23% per card, ~69% per reward), that 81% of runs die in Act 1, and that 43% die to an Act 1 boss with `THE_KIN_BOSS` alone killing 9. The binding constraint is combat defence, not deck composition: those Kin fights ran 5-10 turns and cost 44-80 HP with block cards in hand the whole time. |
||
|---|---|---|
| .. | ||
| 01-game-engine-and-mod-surface.md | ||
| 02-system-one-jev.md | ||
| 03-sts2mcp-interface.md | ||
| 04-state-shapes.md | ||
| 05-failure-modes.md | ||
| 06-decision-architecture.md | ||
| 07-run-log.md | ||
| 08-what-actually-wins.md | ||
| README.md | ||
STS2 Bot — Research Notes
Living notes on reverse-engineering Slay the Spire 2 and driving it with a TypeSafe System One (Jev) decision model.
These documents record what was measured, not what was assumed. Where a claim comes from a live test, the evidence is quoted. Where something is a guess, it says so.
Contents
| # | Document | Covers |
|---|---|---|
| 01 | Game engine and mod surface | Engine, assemblies, the official mod loader, manifest schema |
| 02 | System One / Jev | What Jev is, measured latency and cost, the arithmetic failure |
| 03 | STS2MCP interface | The community mod, version drift, rebuilding from source |
| 04 | State shapes | Every verified JSON shape, per state_type |
| 05 | Failure modes | Every infinite loop found live, with its fix |
| 06 | Decision architecture | The three-layer design and why the split is where it is |
| 07 | Run log | Results per run, with seeds and outcomes |
Architecture summary lives in ../DESIGN.md.
How to add a finding
- Prefer a measurement over an inference. Quote the command and the output.
- Put game facts in 01/03/04, model facts in 02, bugs in 05.
- Record the date and the game build (
v0.107.1today). Both move. - When a finding is later disproved, do not delete it. Mark it superseded and say what replaced it. The wrong turn is often the useful part.
Environment these notes were taken on
| Item | Value |
|---|---|
| Game build | v0.107.1, commit 59260271 |
| Platform | macOS (arm64), Steam |
| Engine | Godot 4.5.1 (.NET), runtime .NET 9.0.7 |
| Mod | STS2MCP, rebuilt from upstream main @ 55e0648 |
| Model | jev-latest resolving to jev-1.13.0 |
Rebuilding the mod
STS2MCP release 0.4.0 is broken on this game build. See
03. To rebuild:
cd ~/sts2-bot/vendor/STS2MCP
nix shell nixpkgs#dotnet-sdk_9 --command bash -c '
dotnet build STS2_MCP.csproj -c Release -o out/STS2_MCP \
-p:STS2GameDir="$HOME/Library/Application Support/Steam/steamapps/common/Slay the Spire 2"'
cp out/STS2_MCP/STS2_MCP.dll \
"$HOME/Library/Application Support/Steam/steamapps/common/Slay the Spire 2/SlayTheSpire2.app/Contents/MacOS/mods/"
Then restart the game. Mods load only at process start.
Testing
Two suites, both offline. Run them before every session.
python3 test_brain.py # 54 assertions — structural / programmatic
python3 test_facts.py # 29 assertions — arithmetic and parsing
test_brain.py is the important one for catching usage bugs. It asserts that
every state_type produces an action legal for that state, that every
action the decision layer can emit is declared somewhere, and that every
fallback respects its own inputs. It needs no model and no running game.
It was added after a session in which four separate infinite loops and three hardcoded fallbacks were found by hand. Most of them would have been caught here.