find_keyo() matched the .keyo filename against general["name"], which is the
bot profile ("profile1"), not the character ("fistman"). No file ever starts
with the profile name, so it silently fell through to files[0] — the
alphabetically first .keyo in Saved Games.
In practice that meant `testbed.py keyo` verified Burr114743261.keyo while the
bot itself read Fistman211469871.keyo (key_detector correctly uses char_name),
reporting 3 unbound keys for a character that isn't being played. Running
--fix would have WRITTEN those binds into the wrong character's file.
Now keys off char_name (falling back to name), and normalises both sides
before prefix-matching, since D2R suffixes the file with an account id
("Fistman211469871.keyo") — the same approach key_detector._find_key_file
already uses.
Also stop falling back to an arbitrary character when char_name is set but
matches nothing: raise with the list of files found instead. Silently
verifying/writing someone else's bindings is worse than failing.
Verified: testbed.py keyo now reports the correct file and
"Controls layer matches params.ini".
Co-Authored-By: Claude Opus 5 <[email protected]>