Alice never has a hardcoded counter-table — she has a small belief graph of (counter, counters, opponent) facts each with a valence in [0,1]. To decide what to play, she walks the graph, finds every triple whose object matches what Bob just did, and picks the highest-valence one. Edit the valences, watch Alice's choices flip. The decision is a graph query — nothing more.
What did Bob just do?
pick_counter(beliefs, opponent_kind) — a single scan of iter_spo_triples filtering predicate == 'counters' AND object == opponent_kind, keeping the max-valence subject. No special case for any matchup; no hidden if/else. Edit a valence and the next pick changes the next instant.
examples/cognition_dojo_f_v0.py verbatim — pick_counter over (counter, counters, opponent) triples in the fighter's belief graph. Decision IS a graph query: change the triples, change the policy. Lab 12 lets the outcomes edit those valences; lab 13 adds a model of what Bob will do next.