fix(L.2g-S2b): turn/sidestep axes checked BEFORE overlay classification in RemoteMotionSink

The first S2b cut classified turn/sidestep dispatches (Modifier-class
0x65xxxxxx) into the generic overlay router before the axis checks ran —
turns never reached the cycle pick OR the ObservedOmega seed. S2 smoke
symptoms: turn-in-place showed no animation (orientation snapping only)
and running-in-circles had no client-side rotation between UPs.
Log evidence: 30 [TURN_WIRE] events, zero turn [SETCYCLE]s
(launch-s2-smoke.log).

Harness gap noted: the conformance suite stops at the funnel->sink
boundary; extending golden coverage through the sink (SETCYCLE-level
fixtures) is scheduled with the R-phase rewrite.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-07-02 19:19:46 +02:00
parent 67506ce988
commit 4bfcd2735e

View file

@ -61,6 +61,18 @@ internal sealed class RemoteMotionSink : IInterpretedMotionSink
return; return;
} }
// Turn/sidestep FIRST: they are Modifier-class (0x65xxxxxx), so the
// generic overlay classification below would swallow them — that
// exact ordering bug shipped in the first S2b cut and killed
// turn-in-place animation + the ObservedOmega seed (S2 smoke,
// 2026-07-02: 30 [TURN_WIRE] events, zero turn SetCycles). They are
// cycle-axis candidates for the single-cycle pick, not overlays.
uint low = motion & 0xFFu;
bool isTurn = low is 0x0D or 0x0E && (motion & 0xFF000000u) == 0x65000000u;
bool isSidestep = low is 0x0F or 0x10 && (motion & 0xFF000000u) == 0x65000000u;
if (!isTurn && !isSidestep)
{
var route = AnimationCommandRouter.Classify(motion); var route = AnimationCommandRouter.Classify(motion);
if (route is AnimationCommandRouteKind.Action if (route is AnimationCommandRouteKind.Action
or AnimationCommandRouteKind.Modifier or AnimationCommandRouteKind.Modifier
@ -74,10 +86,7 @@ internal sealed class RemoteMotionSink : IInterpretedMotionSink
_sequencer, _style, motion, speed <= 0f ? 1f : speed); _sequencer, _style, motion, speed <= 0f ? 1f : speed);
return; return;
} }
}
uint low = motion & 0xFFu;
bool isTurn = low is 0x0D or 0x0E && (motion & 0xFF000000u) == 0x65000000u;
bool isSidestep = low is 0x0F or 0x10 && (motion & 0xFF000000u) == 0x65000000u;
if (isTurn) if (isTurn)
{ {