Skip to content

[P2] Charge drivers round negative half-tie attribution differently across platforms #51

Closed

Description

@bhelm

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:

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 deltaPoints for positive and negative half-ties, including this exact -0.5 reproduction.
  • 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

  1. bhelm commented on Aug 19, 2026

    @bhelm
    OwnerAuthor

    Resolved and differentially verified.

    • The focused production fix is merged in the fork.
    • ChargeDrivers rollout PR Parity: roll out Recovery chargeDrivers/8 #60 adds exact ordered Swift/Kotlin fixtures for this issue.
    • The complete ChargeDrivers slice matched in 14/14 cases; the full pilot matched in 291/291 cases before integration and remained hash-stable after rebasing.
    • Fresh Swift/Kotlin coverage passed, stale output was rejected, and delta/order mutants were detected on both platforms.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions