Type: Test / regression coverage · Parent: #83 · PR that needs this: #84
Why
#83's acceptance criterion #4 asks for a committed macOS-BT DualSense 0x31 fixture + parse/offset-probe test. PR #84 (the accel-as-gyro guard) currently proves its logic only with synthetic _chooseImuOffset rows — there is no real DualSense-over-Bluetooth-on-macOS capture in packages/core/test/fixtures/. The other GOLDEN tests are backed by real captures (GameSir DS4, Sony DS4 v1 BT); the DS5-BT path is the one with the live bug report and no real fixture.
Evidence we already have (from hardware testing #83, on branch claude/issue-83-macos-bt-imu-offset)
Real macOS BT 0x31 at-rest capture, event.data.byteLength = 77 (report-ID byte absent from event.data), baseOffset = 1:
probe bytes (bluetooth 0x31, len=77, baseOffset=1):
41 82 7e 80 79 00 00 01 08 00 00 00 7d 6a bd 25 fc ff f7 ff 00 00 a2 ff 22 1f 67 05 b0 f5 46 1d …
Decoded (int16 LE):
- gyro @16/18/20 =
(-4, -9, 0) → |gyro| ≈ 13 (≈ 0 at rest ✓)
- accel @22/24/26 =
(-94, 7970, 1383) → magnitude ≈ 8090 (≈ 1g, target 8192 ✓; gravity on Y)
- sticks @0..3 =
65,130,126,128 (centered ✓)
So offset 16 is the correct, documented DS5-BT offset on macOS, and there is no report-ID-byte shift on this hardware.
Scope
- Capture a full 77-byte at-rest frame (the console preview is truncated to 32 bytes) — extend the capture wizard or grab via the dump path — and commit it as
packages/core/test/fixtures/sony-dualsense-bt-macos_054c-0ce6.json, mirroring the existing fixture schema + README.md entry.
- Add a GOLDEN test in
packages/core/test/imu-probe.test.js:
- probe over the fixture →
gyroOffset === 16, baseOffset === 1, family sony-ds5
meanAccelMag ≈ 8090 (assert ~1g window) and meanGyroAbs near zero
- assert the neighbours 15/17 score far worse (mirror the existing "wrong offsets score far worse" golden)
- (If feasible) also capture a slow at-rest pitch/roll step so the test can assert gravity tracks the expected accel axis — guards against a future axis-mapping regression (see sibling issue on fusion axis mapping).
Notes / known gap
This fixture exercises the default-kept path (offset correct). The guard's recover-the-shifted-offset path in #84 still has only synthetic coverage, because this hardware does not produce the shift. If a machine/build that does reproduce the shift turns up, capture that too and add it as a second golden — until then, document in the test that the recover path is synthetic-only.
Acceptance
- Committed real macOS-BT DS5
0x31 fixture + README entry.
- Passing golden offset-probe test asserting offset 16 / ~1g accel / ~0 gyro / family sony-ds5.
npm test green in packages/core.
Type: Test / regression coverage · Parent: #83 · PR that needs this: #84
Why
#83's acceptance criterion #4 asks for a committed macOS-BT DualSense
0x31fixture + parse/offset-probe test. PR #84 (the accel-as-gyro guard) currently proves its logic only with synthetic_chooseImuOffsetrows — there is no real DualSense-over-Bluetooth-on-macOS capture inpackages/core/test/fixtures/. The other GOLDEN tests are backed by real captures (GameSir DS4, Sony DS4 v1 BT); the DS5-BT path is the one with the live bug report and no real fixture.Evidence we already have (from hardware testing #83, on branch
claude/issue-83-macos-bt-imu-offset)Real macOS BT
0x31at-rest capture,event.data.byteLength = 77(report-ID byte absent fromevent.data),baseOffset = 1:Decoded (int16 LE):
(-4, -9, 0)→ |gyro| ≈ 13 (≈ 0 at rest ✓)(-94, 7970, 1383)→ magnitude ≈ 8090 (≈ 1g, target 8192 ✓; gravity on Y)65,130,126,128(centered ✓)So offset 16 is the correct, documented DS5-BT offset on macOS, and there is no report-ID-byte shift on this hardware.
Scope
packages/core/test/fixtures/sony-dualsense-bt-macos_054c-0ce6.json, mirroring the existing fixture schema +README.mdentry.packages/core/test/imu-probe.test.js:gyroOffset === 16,baseOffset === 1, familysony-ds5meanAccelMag≈ 8090 (assert ~1g window) andmeanGyroAbsnear zeroNotes / known gap
This fixture exercises the default-kept path (offset correct). The guard's recover-the-shifted-offset path in #84 still has only synthetic coverage, because this hardware does not produce the shift. If a machine/build that does reproduce the shift turns up, capture that too and add it as a second golden — until then, document in the test that the recover path is synthetic-only.
Acceptance
0x31fixture + README entry.npm testgreen inpackages/core.