From 3430579eec2d45edd34b98344e394db3ba597ec6 Mon Sep 17 00:00:00 2001 From: ryanbr Date: Fri, 31 Jul 2026 18:39:34 -0700 Subject: [PATCH 1/2] DeepCapture test: name the set for what it actually asserts (#979) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit testNoSlotDuplicatesAnAlreadyPersistedField checked a set called persistedElsewhere, and told the reader on failure that the key 'already has a durable home'. Two of its seventeen entries do not. motion_wear_quality@63 is the same byte as activity_class under a second name; spo2_candidate_82 is a gated 70-100 view of auxByte82. Neither is persisted in its own right — both are RECOVERABLE from a byte that is, which is equally good grounds for refusing to bank them and is not the same claim. Streams.swift already words it correctly; only the test overstated. It reads as 'SpO2 is being stored', which it is not, and briefly convinced the reporter of exactly that. Behaviour is unchanged — same set, same assertion, same slots. Only the name and the failure message move, plus a comment recording why the distinction is worth keeping. --- .../DeepCaptureChannelsTests.swift | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/Packages/WhoopProtocol/Tests/WhoopProtocolTests/DeepCaptureChannelsTests.swift b/Packages/WhoopProtocol/Tests/WhoopProtocolTests/DeepCaptureChannelsTests.swift index 464482077d..c7a723993c 100644 --- a/Packages/WhoopProtocol/Tests/WhoopProtocolTests/DeepCaptureChannelsTests.swift +++ b/Packages/WhoopProtocol/Tests/WhoopProtocolTests/DeepCaptureChannelsTests.swift @@ -281,17 +281,24 @@ final class DeepCaptureChannelsTests: XCTestCase { XCTAssertNotNil(s.gravity.first?.dynAccel) } - /// Everything with an existing durable home is banked once, not twice. - func testNoSlotDuplicatesAnAlreadyPersistedField() { - let persistedElsewhere: Set = [ + /// Nothing already reachable from a banked field is banked a second time. + /// + /// The name matters (#979). Most of these ARE stored under their own column, but two are not: + /// `motion_wear_quality@63` is the same byte as `activity_class` under a second name, and + /// `spo2_candidate_82` is a gated 70-100 view of `auxByte82`. Neither is persisted in its own + /// right — both are RECOVERABLE from a byte that is, which is equally good grounds for refusing + /// to bank them and not the same claim. The old name asserted each "already has a durable home", + /// which reads as "SpO2 is being stored" and is not true. + func testNoSlotDuplicatesAFieldAlreadyReachable() { + let recoverableFromABankedField: Set = [ "unix", "heart_rate", "rr_intervals", "gravity_x", "gravity_y", "gravity_z", "dynamic_acceleration", "skin_temp_raw", "temp_aux_1_raw", "temp_aux_2_raw", "step_motion_counter", "activity_class", "motion_wear_quality", "sleep_state", "sleep_state_byte", "spo2_candidate_82", "ppg_waveform", ] for slot in V18AuxSlot.allCases { - XCTAssertFalse(persistedElsewhere.contains(slot.decoderKey), - "\(slot.decoderKey) already has a durable home — banking it twice is waste") + XCTAssertFalse(recoverableFromABankedField.contains(slot.decoderKey), + "\(slot.decoderKey) is already reachable from a banked field — banking it twice is waste") } } } From ce7bef52f1f06d8d475a9de14c6eae4c5215bfb5 Mon Sep 17 00:00:00 2001 From: ryanbr Date: Fri, 31 Jul 2026 18:40:30 -0700 Subject: [PATCH 2/2] Rename the Kotlin twin to match DeepCaptureChannelsTest.noSlotDuplicatesAnAlreadyPersistedField carried the same overstated set name and the same failure message. Neither the issue nor the Swift-side pass mentioned it; found by grepping for the old name after renaming the Swift side. Renaming one and not the other would leave the two suites asserting the same contract under different names, which is the kind of drift the parity rule exists to stop. --- .../noop/protocol/DeepCaptureChannelsTest.kt | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/android/app/src/test/java/com/noop/protocol/DeepCaptureChannelsTest.kt b/android/app/src/test/java/com/noop/protocol/DeepCaptureChannelsTest.kt index 767170c32f..8c025d0f15 100644 --- a/android/app/src/test/java/com/noop/protocol/DeepCaptureChannelsTest.kt +++ b/android/app/src/test/java/com/noop/protocol/DeepCaptureChannelsTest.kt @@ -298,9 +298,20 @@ class DeepCaptureChannelsTest { assertNotNull(s.gravity.single().dynAccel) } + /** + * Nothing already reachable from a banked field is banked a second time. + * + * The name matters (#979). Most of these ARE stored under their own column, but two are not: + * `motion_wear_quality@63` is the same byte as `activity_class` under a second name, and + * `spo2_candidate_82` is a gated 70-100 view of `auxByte82`. Neither is persisted in its own + * right — both are RECOVERABLE from a byte that is, which is equally good grounds for refusing to + * bank them and not the same claim. The old name asserted each "already has a durable home", + * which reads as "SpO2 is being stored" and is not true. Twin of the Swift + * `testNoSlotDuplicatesAFieldAlreadyReachable`. + */ @Test - fun noSlotDuplicatesAnAlreadyPersistedField() { - val persistedElsewhere = setOf( + fun noSlotDuplicatesAFieldAlreadyReachable() { + val recoverableFromABankedField = setOf( "unix", "heart_rate", "rr_intervals", "gravity_x", "gravity_y", "gravity_z", "dynamic_acceleration", "skin_temp_raw", "temp_aux_1_raw", "temp_aux_2_raw", "step_motion_counter", "activity_class", "motion_wear_quality", "sleep_state", @@ -308,8 +319,8 @@ class DeepCaptureChannelsTest { ) for (slot in V18AuxSlot.entries) { assertFalse( - "${slot.decoderKey} already has a durable home — banking it twice is waste", - slot.decoderKey in persistedElsewhere, + "${slot.decoderKey} is already reachable from a banked field — banking it twice is waste", + slot.decoderKey in recoverableFromABankedField, ) } }