fix: state pension respects recorded amount for new-SP cohort#60
Open
vahid-ahmadi wants to merge 1 commit into
Open
fix: state pension respects recorded amount for new-SP cohort#60vahid-ahmadi wants to merge 1 commit into
vahid-ahmadi wants to merge 1 commit into
Conversation
Mirrors the existing old-SP scaling pattern for the new-SP cohort: - If `person.state_pension > 0`: pass through, scaled by `(new_state_pension_weekly / baseline_new_sp_weekly)` for reform correctness - Else: fall back to `new_state_pension_weekly × 52` Previously the new-SP branch always returned the full parameter rate × 52, ignoring any recorded amount. This over-stated SP for partial- year claimants and broke parity for the pensioner_couple synthetic scenario in PR #53's parity harness (£946 diff). Implementation: - Plumb `baseline_new_sp_weekly` through `Simulation`, `calculate_benunit`, `calculate_state_pension`, and `person_state_pension`, parallel to the existing `baseline_old_sp_weekly` field - 3 new Rust unit tests (recorded-amount preserved, fallback to param when no record, recorded amount scales under reform) Parity-harness impact (synthetic pensioner_couple scenario): state_pension rust=23,000 py=23,000 diff=£0 (was £946) household_net_income diff=£-41 (was £905) Stacked on #58. Closes #59 (filed today as a follow-up to PR #53). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2097c87 to
974dc21
Compare
89b4655 to
10c89d3
Compare
Contributor
Author
|
Rebased onto Now sits directly on |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #59. The state-pension calculation was ignoring the recorded
person.state_pensionamount for anyone in the new-SP cohort (post-2016 SP claimants — currently anyone aged 66–74 in fiscal year 2025/26). It always returned the fullnew_state_pension_weekly × 52, over-stating SP for partial-year / partial-record claimants and breaking parity with the Python engine on every synthetic pensioner.Surface from the parity harness
PR #53's parity harness directly surfaced this — the
pensioner_couplesynthetic scenario was £946 off:Two pensioners with
state_pension: 11_500each → input total £23,000. Rust ignored those values and returned2 × £230.25 × 52 = £23,946.After this fix:
The £946 state-pension gap is gone. Net-income diff drops from £905 to £41 (the residual is the same base divergence visible in every scenario).
Fix
Mirror the existing old-SP scaling pattern. If
person.state_pension > 0, pass through the recorded amount scaled by(new_state_pension_weekly / baseline_new_sp_weekly)for reform correctness; else fall back tonew_state_pension_weekly × 52.This requires plumbing
baseline_new_sp_weeklythroughSimulation,calculate_benunit,calculate_state_pension, andperson_state_pension, parallel to the existingbaseline_old_sp_weekly.Why both
baseline_old_sp_weeklyandbaseline_new_sp_weekly?A reform that changes the new-SP rate should scale recorded amounts proportionally — someone with a £11,500 baseline SP should still pay/receive the right share when the rate moves. Passing
baseline_new_sp_weeklyseparately from the (potentially reformed)params.state_pension.new_state_pension_weeklyletsperson_state_pensioncompute the ratio correctly.What's included
person_state_pensionandcalculate_state_pensionupdated to take a secondbaseline_new_sp_weeklyargument (same shape asbaseline_old_sp_weekly)Simulation::newandSimulation::new_with_baseline_spupdated to capture and storebaseline_new_sp_weeklymain.rs/simulation.rs, 4 inlabour_supply.rs)changelog.d/fixed/Verified locally
cargo test: 165 passing (162 + 3 new)pytest interfaces/python/tests: 87 passingpython -m policyengine_uk_compiled.yaml_tests tests/policy: 29/29param_state_pension_new_weeklytest still passes (it usesstate_pension = 0, hitting the fallback branch unchanged)Stacking
vahid/state-pension-recorded←vahid/council-tax-spd(#58) ←vahid/dla-aa-from-flags(#57) ←vahid/pip-from-flags(#56) ←vahid/lbtt-ltt(#55) ←vahid/yaml-test-harness(#54) ←vahid/parity-harness(#53) ←vahid/from-situation(#52). Eight-deep stack.Test plan
pensioner_couplestate_pension matches Python (£23,000 = £23,000)new_state_pension_weeklyfrom £230.25 to £250 scales recorded amounts proportionally (£11,500 → £12,484.80)🤖 Generated with Claude Code