Two defects in one seam, both found by an adversarial reviewer reading the
diff of the previous commit -- neither has a test that could have caught it,
and both are silent.
1. That commit moved set_nav_active BELOW set_hmove. The first arrow key of a
session sets both in one model call, so hmoveChanged fired while
nav_active was still false and no shelf consumed the pulse. nav_active is
CONTEXT a handler reads, not something consumers have a handler on; hmove
is the third consumer-facing field, alongside index and activate_seq. The
ordering comment undercounted them. Fixed.
2. The deeper one, which predates that commit: hmove is cleared only by a
consumer calling takeHmove(). If nobody consumed the last pulse -- no shelf
focused, the ring not live, a skipped shelf -- the model still holds it, so
the next Right writes 1 over 1 and cxx-qt's generated setter is
CHANGE-GATED: it returns without emitting. The key is then dead until the
user happens to press the other direction. hmove's value is not its
meaning; the edge is. nav_left/nav_right now force the property to 0 first,
so there is a real 0 -> +/-1 transition every time regardless of what the
consumers did.
Verified by effect, not by reading the diff: four consecutive Rights on a
Discover shelf move the cursor four cards
(scratchpad/kiosk/s-02-four-rights.png).
cc