Join the three evidence sources that were kept apart, and extract the useful
result: each source independently decides what belongs in code and what belongs
to the model, and every serious bug we have found broke one of those rules.
* Game mechanism -> arithmetic and rules belong in CODE
* Internal state -> anything directly readable or writable belongs in CODE
* TypeSafe -> judgements go to the MODEL, in the primitive matching the
answer's shape
* never blocked in boss fights -> game mechanism (arithmetic left to the model)
* card quality asked as a Noul -> primitives (a spectrum forced into yes/no)
* indices read from the wrong array -> internal state
The counter-example is kept too: the Score we tried for fight-level planning was
unusable, so the rule is "match the primitive to the shape, and verify" rather
than "use Score more".
Also records the ordered plan (measurement first, then re-run, then primitives,
then deck composition), the continual-learning design, and why it is blocked:
with 0 wins in 37 runs the reward has no gradient, so training would fit the bug
rather than the game.
Read the vendor documentation against what the bot actually does, and separate
what is measured from what is merely by construction.
Adopt structured criteria where disambiguation costs us -- measured on card
play, the structured shape picked the same card 6/6 with margin 0.425 -> 0.473,
so it is a small effect worth having at irreversible decisions, not a blanket
rewrite.
What the measurements KILLED, recorded so it is not retried:
* A fight-level plan asked as a Score was unusable on 4 of 6 combat states,
confidence as low as 0.01. Fight-level planning stays in code.
* "A bigger margin means a better play" is not supported: the same question
repeated on the same state returned 0.04 -> 0.24 and 0.36 -> 0.02. We have
no optimal-action label, so a higher margin is evidence of noise, not skill.
Also records three correctness fixes that are independent of any model question:
enemy block counted twice in the lethal search, the executor ignoring player
statuses, and `relic_select` asking `good_relicN` while reading `relicN`.
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.
DESIGN.md covers the three-layer architecture (facts in code, Jev for
tactics, gated escalation for macro). research/ documents the engine and
mod surface, the Jev classifier's measured behavior, the STS2MCP HTTP
interface, state shapes, failure modes, decision architecture, and a
run log of the first four sessions.