Docs · Architecture decisions

ADR-007: rounding_compat: pdoc computes CPP in emulated binary64

Who this is for: Engine and API contributors who touch the CPP line or the rounding_compat request field.

When you finish: You know what the pdoc arm changes, why the default keeps decimal arithmetic for the CPP line, and how floats stay out of the money path.

Status: Accepted 2026-10-22. Supersedes the fail-closed clause of ADR-003.

Context

Finding 003 inferred from PDOC's outputs (July 2026 grid, last capture 2026-09-15) that live PDOC, the CRA calculator for T4127 (Payroll Deductions Formulas), computes the period CPP contribution C in IEEE-754 binary64 and rounds half-up from the shortest round-trip decimal. PDOC's code is not public; the rule reproduces every observed CPP line. On an exact decimal half-cent such as 150.00 x 0.0595 = 8.925, binary64 holds 8.924999999999999 and PDOC shows 8.92, one cent below T4127 decimal half-up. That rule explains all 82 CPP-line disagreements in the July 2026 corpus and changes none of the 8,900 CPP lines that already agreed. ADR-003 reserved rounding_compat: pdoc for exactly this case, with the condition that the arm must not ship until the rule is named.

Decision

  1. rounding_compat: pdoc is implemented. It changes one line: the period CPP contribution C, and therefore whatever C feeds (F5, K2, K2P, net pay).
  2. The default stays t4127: decimal arithmetic, half-up, for C. T4127 is the published formula and 8.925 is a half-cent that rounds up. The default arm is T4127 plus two PDOC-matched roundings T4127's text does not specify: the K2/K2P credits and the Ontario surtax lines are rounded separately. Flipping the default is a product decision, recorded as open in the 2026-10-22 audit.
  3. No float enters takehome-core. crates/takehome-core/src/pdoc_compat.rs emulates the three binary64 operations PDOC's outputs imply (decimal to binary conversion, subtraction, multiplication, all round-to-nearest-even) on integer (mantissa, exponent) pairs, then applies the shortest-decimal half-up rule. scripts/float-ban.sh stays clean.
  4. The emulator is judged by hardware floating point, outside the money path: crates/takehome-core/tests/binary64_emulation.rs compares conversions, subtraction and multiplication bit for bit, and the full CPP rule on every gross cent from 0.01 to 20,000.00 at five pay-period exemptions.
  5. EI stays decimal in both arms: binary64 I x 0.0163 breaks two EI lines that exact decimal gets right.
  6. When the CPP annual maximum caps C, both arms use the decimal cap.

Consequences

  • Conformance publishes two rates: default 8905/9002, pdoc 8987/9002.
  • RequestError::RoundingCompatPdocNotImplemented is no longer returned. The variant stays in the enum so clients that match on it still compile.
  • Any change to the CPP formula must keep binary64_emulation and rounding_compat tests green under both arms.

Last reviewed: 2026-10-22 Engine: 0.1.0

Source: docs/ADR-007-pdoc-binary64-cpp.md in the Takehome repository, rendered as written.