Repository navigation
Description
Summary
The Swift and Kotlin chargeDrivers twins round an exact negative half-tie contribution differently. For the same default-path input, the user-facing HRV driver reports deltaPoints = -1 on Swift and deltaPoints = 0 on Kotlin.
The headline Charge score is unchanged. The mismatch is in its driver attribution and can also affect exact row ordering when magnitudes tie.
Found by the Recovery charge-drivers differential rollout at base fd48e88872f70be232353429a63543febfa52052.
Minimal reproduction
Invoke the real seven-argument/default-arg8 path with:
{
"hrv": 29.99117725828923,
"rhr": 60.0,
"hrvBaseline": {
"baseline": 30.0,
"spread": 0.55,
"nValid": 14,
"nightsSinceUpdate": 0,
"status": "trusted"
}
}For the HRV marginal, full - neutralised is exactly -0.5 as a Double (0xbfe0000000000000).
Native observed behavior
All row fields except deltaPoints are identical:
| Platform | deltaPoints |
value | baseline | verdict |
|---|---|---|---|---|
| Swift | -1 |
30 ms |
30 ms baseline |
below baseline, limiting recovery |
| Kotlin | 0 |
30 ms |
30 ms baseline |
below baseline, limiting recovery |
Cause
The production helpers use different tie rules:
- Swift:
Int((full - neutralised).rounded()), which rounds this tie away from zero. - Kotlin:
(full - neutralised).roundToInt(), which rounds this tie toward positive infinity.
Duplicate search
This is related to, but not duplicated by:
- [P2] Recovery trace rounds negative half-ties differently on Swift and Kotlin #38, which was limited to the two-decimal engineer-facing Recovery trace and is closed after its focused fix/regression fixture.
- [P2] Recovery trace rounding diverges for signed zero and large finite values #47, which covers signed zero and huge finite inputs in the trace rounding helper.
No open or closed issue was found for chargeDrivers, RecoveryDrivers, or deltaPoints negative-half-tie behavior.
Impact and severity
P2. The Charge score itself is unchanged, but its user-visible explanation is platform-dependent by one point and exact magnitude-based ordering can diverge.
Acceptance criteria
- Define one cross-platform integer rounding rule for charge-driver marginal points.
- Emit identical
deltaPointsfor positive and negative half-ties, including this exact-0.5reproduction. - Preserve ordinary non-tie contributions and the headline Charge score.
- Preserve exact ordered output across platforms when rounded magnitudes tie.
- Add mirrored unit tests plus an exact native differential fixture covering the true default-arg8 path.
No production fix is included in the rollout that discovered this issue.
Activity
bhelm commentedon Aug 19, 2026
Resolved and differentially verified.