Repository navigation
Lift the tax credit income test for State Pension Credit - #2034
Conversation
TCA 2002 s.7(2) lifts the tax credit income test while the claimant or either joint claimant is entitled to a prescribed benefit, and SI 2002/2008 reg 4(1)(d) prescribes State Pension Credit (from 26 November 2003). The model passported Income Support, income-based JSA and income-related ESA but not Pension Credit. Pension Credit counts working tax credit as income (SPCA 2002 s.15(1)(b)), so reading Pension Credit from the income test is circular. The passport is taken from Pension Credit calculated in a core branch in which the income test is lifted: it holds when Pension Credit stays payable with the passported award counted, and the simulation's own award and Pension Credit then equal the branch's. In years with no tax credit awards Pension Credit is read directly; wtc_entitlement returns before the income test in those years, so there is no cycle. Reg 4(1)(d) covers either credit (SPCA 2002 s.1(3)). The reg 4(1)(a) exception (IS Regs 1987 reg 6(2)-(3), the lone parent run-on) is spent from 25 October 2004, and reg 4(2) (the WTC four-week run-on) has no period in a whole-year award; both are documented, not modelled. Adds gov.dwp.tax_credits.means_test.pension_credit_passport, YAML tests hand-computed from the law, and Hypothesis properties (differential against a passported simulation, consistency, no-harm, request-order independence, and the no-award years). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Random draws passport through Pension Credit often (55 of 236 families in a derandomized sample) but never raise CTC and hit the third row once. The YAML households now run as explicit examples of each property, and a test checks that they reach every case: WTC and CTC raised by the passport, the third row, and a mixed-age couple. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review of #2034 (Subfleet job 20261002-020316-tc-pc-passport-review-r1c): - The two-year-old childcare criteria read tax_credits_applicable_income, which the passport zeroes, so a savings-credit-only family with CTC passed the £16,190 "annual gross income" limit (SI 2014/2147 reg 1(2)) whatever its income. Split out tax_credits_current_year_income (TCA 2002 s.7(4); SI 2002/2006 reg 3); the applicable income is that or nil, and both childcare criteria read the gross figure. - YAML case 6 relied on is_WTC_eligible pooling age and hours across the couple (#2042): the older partner now does the work, with the same figures. - Read the branch's Pension Credit through its population, so a microsimulation returns an unweighted array, and take a branch name in use by no other branch. - Docstring: the rule's premise (Pension Credit never rises with WTC in law), the model-only case its savings credit creates (#1954), and the nil-guarantee boundary. Comment covers reg 4(1)(b). - Tests: a childcare case, a 2018-19 case, a Microsimulation test, a household-net-income-first request order, a childcare property, and income-related ESA drawn only below State Pension age. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The targeted childcare tax credit criteria now read tax_credits_current_year_income (the "annual gross income" of SI 2014/2147 reg 1(2)), so their tests enter that instead of the passported tax_credits_applicable_income. Expectations are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The case "The passport does not bring a family under the childcare gross income limit" ( #2057 (stacked on this) had copied the same input and now enters 🤖 Generated with Claude Code |
- The childcare case's grandchild, aged 2, was born after 6 April 2017, so there is no CTC family element (CTC Regs 2002 reg 7(2)(a)): CTC is £3,455. - The 2025-26 case enters the statutory standard minimum guarantee, £227.10 a week (SPC Regs reg 6(1)(b), SI 2025/295 art. 29(2)(b)); the model's value differs (#1937). Guarantee Credit is £3,469.20. - Docstring: the nil-guarantee boundary applies where no savings credit is payable. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rtner' into tax-credits-pension-credit-passport
#2027 has merged, so this brings the branch up to main. One conflict, resolved mechanically: main (#2172) renamed the step-one component property_income to property_income_after_finance_costs in tax_credits_applicable_income. This branch had moved that income calculation, unchanged, into tax_credits_current_year_income, so the rename now lands there and tax_credits_applicable_income keeps the passport. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#1940, now merged in from main, models the SI 2019/37 art. 4 saving, so a mixed-age couple can get Pension Credit and with it the passport. - YAML: the mixed-age case is now the couple without the saving (and asserts there is none); a new case gives the same couple the saving: Guarantee Credit £4,298.40 and the maximum WTC, £4,935, worked from the law in the comments. - Properties: the pinned YAML households include that couple, and the strategy draws the saving, so mixed-age couples reach the passport in the random examples too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… r4) At age 70 the default six months since the last birthday puts the older partner's birth on 6 April 1954, too late to have reached the qualifying age by 14 May 2019, which the SI 2019/37 saving's history needs. Nine months puts it on 6 January 1954. The paired YAML cases and their pinned Hypothesis families now say so; no expected amount changes. The YAML header now describes the savings interest as it is: at least £300 in each case, between the claimants. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Status at
🤖 Generated with Claude Code |
…redit-passport Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…redit-passport Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
CI run cancelled to free runners (UK hub, 2026-10-11 23:30Z). The PolicyEngine org is at GitHub's limit of 60 concurrent jobs, with about 360 queued. Fleet ops asked the hub to let the Budget-critical #2305 take runners first. This PR's queued run had not started, so I cancelled it. Nothing is wrong with the PR. Please don't re-run it or push just to retrigger CI. The hub re-runs this run itself once #2305 has runners. The record is |
#1925 holds the CTC family element at £545 and sets the 2025-26 standard minimum guarantee to £227.10, so case 6's family element and case 10's minimum guarantee now equal the model's own values. The inputs stay; the comments no longer say the model differs. Case 7's nil family element is still needed (the model pays it for a child born on or after 6 April 2017). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…redit-passport Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fixes #2032
Summary
tax_credits_applicable_incomelifted the tax credit income test for Income Support, income-based JSA and income-related ESA, but not for State Pension Credit, which SI 2002/2008 reg 4(1)(d) also prescribes. This PR adds the Pension Credit passport.Working tax credit is Pension Credit income, so Pension Credit and the passport depend on each other. The passport is decided on the Pension Credit payable with the passported award counted, calculated in a core branch.
The passport makes the tested income nil, and the two-year-old childcare criteria read that tested income. So this PR also splits out
tax_credits_current_year_income, the income before the passport, and the childcare criteria now test that gross figure.This PR was stacked on #2027, which switched the other passports to the claimant's and partner's awards. #2027 and the PRs beneath it (#2013, #2001, #1896) have merged. This branch has since merged main six times, at
e89b8abcf,4857dc75f,97ef6e1af,6d89338ab,ed7b42f95and1d3abecef. Only the first had a conflict, and it was mechanical: main (#2172) renamed the step-one componentproperty_incometoproperty_income_after_finance_costs, and the rename now sits intax_credits_current_year_income, where this PR moved that calculation. #2061 and #2057 are stacked on this PR.Law (fetched verbatim from legislation.gov.uk
/data.xml, 2026-10-02)TCA 2002 s.7(2): "Subsection (1) does not apply in relation to the entitlement of a person or persons to a tax credit for so long as the person, or either of the persons, is entitled to any social security benefit prescribed for the purposes of this subsection in relation to the tax credit."
SI 2002/2008 reg 4:
SPCA 2002 s.1(3): a claimant entitled to state pension credit is entitled "(a) to a guarantee credit ... or (b) to a savings credit ... (or to both ...)".
SPCA 2002 s.15(1): "In this Act “income” means income of any of the following descriptions—", with para (b) "working tax credit".
working_tax_credit.SPCA 2002 s.4(1A), from 15 May 2019: "A claimant is not entitled to state pension credit if he is a member of a couple the other member of which has not attained the qualifying age." SI 2019/37 art. 4 saves it for a mixed-age couple entitled to Pension Credit or Housing Benefit on 14 May 2019, until a day on which they are entitled to neither (art. 4(2)). From 8 June 2024 (SI 2024/604) there is one qualification (art. 4(3)-(4)). A member of such a couple who was issued a migration notice and became entitled to Universal Credit by claiming before the final deadline keeps the saving if they claim Housing Benefit or Pension Credit "within three months beginning with ... the day after their award of universal credit terminates": their days on Universal Credit are then disregarded.
SI 2014/2147 reg 1(2), "eligible child", as at 1 September 2024. The two-year-old offer covers a child whose parent is entitled to:
SI 2025/1261 omitted these limbs from 1 January 2026.
WTC Regs 2002 reg 4(1), Second condition, second variation (a joint claim with no child). "The person" who works must be:
IS Regs 1987 reg 6. As at 6 April 2003, paras (2) and (3) said a lone parent who started remunerative work after 26 weeks on Income Support or income-based JSA "shall not be treated as engaged in remunerative work for the period of 14 days" (the lone parent run-on). SI 2003/1589 reg 2(a)(i) omitted paras (2) and (3) from 25 October 2004.
The questions
Any Pension Credit, or only the guarantee credit? Any. Reg 4(1)(d) names "state pension credit within the meaning of" the Act, and s.1(3) makes that a guarantee credit, a savings credit or both. The passport reads
pension_credit(both credits, after take-up), notguarantee_credit. A test covers a couple on the savings credit alone.Entitled, so claimed. There is no entitlement to a benefit without a claim (SSAA 1992 s.1(1), (4)(ab)).
pension_creditapplieswould_claim_pc, so unclaimed Pension Credit gives no passport, asincome_supportdoes for Income Support.Mixed-age couples. A couple claims tax credits jointly, and reg 4 lifts the test if "either of the persons" is entitled to Pension Credit. So the older partner's Pension Credit passports the couple's whole joint award: CTC for their children, and WTC on either partner's work.
has_mixed_age_couple_pension_credit_saving). Because this PR readspension_credit, a couple who keep Pension Credit under the saving get the passport with no further change. Two YAML cases cover the same couple without the saving (no Pension Credit, so the income test applies) and with it (Guarantee Credit and the maximum WTC).The reg 4(1)(a) exception (IS Regs 1987 reg 6(2)-(3)). No modelling is needed. It excluded Income Support paid only under the 14-day lone parent run-on. Those paragraphs were omitted from 25 October 2004, so no one has been entitled to Income Support "only by virtue of" them since then. That is long before the model's first tax credit year. The model has no Income Support run-on in any case.
Reg 4(2), the WTC four-week run-on. Not modelled. During the reg 7D run-on, which starts when the claimant stops work or drops below the hours condition, the passport does not apply to WTC (CTC stays passported). The model's WTC is a whole-year award on the year's hours, with no run-on period.
working_tax_credit_run_onis a whole-year flag read only by the targeted childcare criteria. Using it to switch the WTC passport off for a whole year would overstate a four-week rule 13-fold. The code comment records this.The dependency cycle, and which state the model picks
Pension Credit counts working tax credit as income (s.15(1)(b)), and the tax credit income test reads Pension Credit (s.7(2)). The law gives no tie-break. Write Wmax for the passported (maximum) WTC award, Wt for the income-tested one, and PC(W) for Pension Credit computed with WTC W. Then:
The table assumes Pension Credit never rises with WTC. That holds in law: the guarantee credit falls by the whole of it (s.2(2)), and WTC is not qualifying income for the savings credit (SPC Regs reg 9(a)).
The model's savings credit counts WTC as qualifying income (#1954), so in the model it can rise 20p per £1 of WTC. That adds a fourth, model-only case: PC(Wt) = 0 < PC(Wmax), where both states are consistent and the model takes the passport. In law Pension Credit is nil either way. Reaching it needs income the model excludes from qualifying income (contributory ESA or JSA) alongside WTC above State Pension age. No 2024 Enhanced FRS family has both Pension Credit and tax credits, so none is affected.
"Entitled" is read as payable. At income exactly equal to the minimum guarantee, where no savings credit is payable, a nil guarantee credit gives no passport; this boundary has measure zero.
The rule is: the passport holds when Pension Credit stays payable with the passported award counted.
pension_credit_with_passported_tax_creditscomputes this in a core branch (tax_credits_pension_credit_passport, suffixed if that name is taken) in whichtax_credits_applicable_incomeis set to 0, and removes the branch afterwards. It reads the branch's Pension Credit through its population, so a microsimulation returns an unweighted array. Main'suc_non_dep_receives_pension_credit(#2119) calculates Pension Credit in a branch of its own,uc_non_dep_pension_credit. The two nest in either order, at most two deep: a nested branch reads its parent branch's input, so it creates no further branch. Review r9 checked this with a probe that logged every branch created. Where the passport holds, the simulation's own WTC, CTC and Pension Credit equal the branch's. So the model never shows a passport alongside nil Pension Credit. The third row is the only case in which Pension Credit is paid without the passport. It needs WTC, since CTC is not Pension Credit income.Side effects of the rule:
freeze_pension_credit. With Pension Credit frozen at its baseline, it no longer responds to WTC. A third-row family can then be passported under the reform, so WTC rises although Pension Credit is held fixed. This is consistent with the freeze, but it is a change to tax credits.Years with no awards. From 2025-26,
gov.dwp.tax_credits.activeis false and every tax credit is nil, so the passported and income-tested states coincide.pension_creditis read directly, with no branch. To keep that free of a cycle,wtc_entitlementreturns nil before reading the income test when tax credits are inactive. Its value is unchanged: it was already nil throughtax_credits. A Pension Credit recipient'stax_credits_applicable_incomeis therefore 0 in those years too. That keeps the variable's meaning the same in every year; no amount changes.Cost. The branch is created only in years with awards (2024-25 and earlier), so runs for 2025-26 onward pay nothing.
In 2024, measured on a copy of the Enhanced FRS (
/usr/bin/time -l, separate processes):household_net_income, thenmarginal_tax_rate200a1cdc4→f2eb82445200a1cdc4→f2eb82445200a1cdc4→f2eb82445household_net_income, thenmarginal_tax_ratee89b8abcf(main) →12c38b592e89b8abcf(main) →12c38b592The extra memory on core 3.32.9 came from deep-copying every cached array into each branch. The labour-supply and marginal-tax-rate branches each create a passport branch of their own. policyengine-core 3.32.12 includes PolicyEngine/policyengine-core#556 (branches share arrays and copy on first read). #2054 has since raised PE-UK's floor to 3.32.12; on 3.32.13 the passport adds 0.03 to 0.04 GB. #2262 has since raised the floor and the lock to 3.32.27. A repeat there (
4857dc75f→7e68de22b) ran with the host's one-minute load average at 74 to 248 and is not comparable with these rows, so it is not reported. The lock is now 3.33.2, and the cost has not been measured again there.Changes
tax_credits_current_year_income(new): the tax credit income before the passport (TCA 2002 s.7(4); SI 2002/2006 reg 3), moved out oftax_credits_applicable_incomeunchanged (with main'sproperty_income_after_finance_costs).tax_credits_applicable_income: that income, or nil while a prescribed benefit lifts the test. It now includes the Pension Credit passport (reg 4(1)(d)), with the reasoning above in a docstring. Comments record why the reg 4(1)(a)-(b) exceptions and reg 4(2) are not modelled.meets_child_tax_credit_criteria_for_targeted_childcare_entitlementandmeets_working_tax_credit_criteria_for_targeted_childcare_entitlementtesttax_credits_current_year_incomeagainst £16,190.wtc_entitlement: returns before the income test when tax credits are inactive (no change in value).gov.dwp.tax_credits.means_test.pension_credit_passport: false from 6 April 2003, true from 26 November 2003. It records the commencement and lets a reform switch the passport off.Invariants (property-tested, Hypothesis)
For any family of one or two adults aged 40-90 (mixed-age couples included, with or without the SI 2019/37 saving) and up to two children, with earnings, hours, State Pension, private pension, savings, WTC and CTC claims, Pension Credit take-up and income-related ESA:
tax_credits_applicable_incomeentered as 0, pays Pension Credit. Otherwise the applicable income equals the value with the parameter switched off.Property 1 checks the branch against the same rule computed outside the formula. So it catches stale or leaked caches, but not a wrong rule; the YAML cases check the rule against the law.
Unit tests:
Microsimulation, results match aSimulation, and the helper returns an unweighted array.Income-related ESA is drawn only below State Pension age.
Tests
YAML: 11 cases in
tests/policy/baseline/gov/dwp/tax_credits_pension_credit_passport.yaml, each computed by hand from the law and that year's rates, with the arithmetic in comments:Four intermediate values are entered at their statutory amounts, with comments. The model still gets three wrong for reasons unrelated to this PR:
The fourth, the 2025-26 standard minimum guarantee of £227.10 a week (case 10), was entered when the model had £221.85 (#1937). #1925, now on main, gives the model £227.10, and holds the family element at £545, so case 6's £545 entry also equals the model's value. Both entries stay, and their comments say so.
In each case the claimants have at least £300 of savings interest between them. That makes the model's tax credit income equal the law's: the law puts State Pension in step one (SI 2002/2006 regs 3, 5(1)(a)), where the interest uses up the £300 disregard, and the model counts State Pension in step two.
On main
1d3abecef, 7 cases fail and 4 pass:tax_credits_applicable_income(no passport);tax_credits_current_year_incomeis new;On the first version of this PR (
28eb7d2d4), the reviewer's probe of case 7's household was eligible, which was wrong.Hypothesis:
test_tax_credits_pension_credit_passport_properties.pyhas 6 tests: 3 properties (20 derandomized examples each), 2 unit tests (tracing and nesting; Microsimulation) and a coverage test.@examples of every property, andtest_yaml_families_reach_every_casechecks they hit each case, including the mixed-age couple with and without the saving.9b36445d0), in CI and locally.At this head (
9b36445d0), CI passes the whole YAML suite (3,169 cases) and the three property files in this area: the passport (6), legacy award readers (12) and means-test income (1). Locally,ruff format --checkis clean (ruff 0.17.0), the targeted YAML for gov/dwp, gov/dfe and finance/benefit passes (1,811 tests), and so do the three property files (19 tests).Enhanced FRS impact
Real
Microsimulationruns on a private copy of the Enhanced FRS 2024-25 (sha256e433e532…), years 2024-2030:1d3abecef, which includes Count only the claimant's and partner's legacy awards in means tests and passports #2027, Date the mixed-age couple Pension Credit exclusion and model the SI 2019/37 saving #1940, Count a loss on one source as nil in Pension Credit income and earnings #2259, Stop counting a benefit unit's claimant or partner as its own child or qualifying young person #2285, Set DWP benefit rates to the announced amounts, not CPI projections #1925 (DWP's announced 2025-26 rates), Move families onto Universal Credit when a legacy benefit they receive closes #2119 (Universal Credit when legacy benefits close) and Require a Pension Credit payment for savings-credit-only receipt #2373 (savings-credit-only receipt needs a payment);9b36445d0, this PR's merge of that main, and the head.Both trees were clean, each in its own environment on the locked policyengine-core 3.33.2. The earlier pairs also gave £0 in every year: base
200a1cdc4against284434ffcandf2eb82445; basefc1ff55d1against49e6a51aa; basee89b8abcfagainst12c38b592; base4857dc75fagainst7e68de22b; base97ef6e1afagainst5bec0bb17; base6d89338abagainstbac104ba8; and baseed7b42f95against890470285. Main has changed since each of them, so their record counts can differ from those below. Tax credits are paid only in 2024 in the model; from 2025 the scheme is inactive.Money: £0 in every year. All 105 arrays were compared: benefits, household totals including
gov_spendingandhbai_household_net_income, and poverty rates. The only arrays that change are:tax_credits_applicable_income, now nil for Pension Credit recipients: 2,178 benefit-unit records in 2024, about 1.71 million weighted, 462 of them on the savings credit alone. It changes in every year, but tax credits are nil from 2025, so no amount moves.targeted_childcare_entitlement_eligiblechanges for nobody.Why no amount changes in 2024.
The H5 inputs and per-record arrays stay private; the summaries above are aggregates.
Axiom
axiom: TheAxiomFoundation/rulespec-uk#419 queued
TCA 2002 s.7 and SI 2002/2008 reg 4 are not in the corpus (checked axiom-corpus
origin/main2c86dc9af: TCA s.8 and SI 2002/2008 regs 7 and 9 are, as discovery entries), so the encoder path is blocked. rulespec-uk encodes SPCA 2002 ss.1-3 and SPC Regs reg 15, but s.1 defers Pension Credit entitlement. #419 holds the verbatim law, the required outputs, a pasteablereview_findingand eight companion tests. Tests 1-6 come from this PR's YAML; tests 7-8 (commencement dates and the reg 4(2) run-on) are law-only. It is linked from #416, whose tax credit item now defers to it.The childcare change reads SI 2014/2147 reg 1(2)'s tax credit limbs on gross, pre-passport income. TheAxiomFoundation/rulespec-uk#400, which queues that regulation's Universal Credit route, is extended in a comment with:
Related and follow-ups
pension_credit(YAML case 9).Reproducer
Both cases fail on main
1d3abecef, where Pension Credit does not lift the income test, and pass at this head:Reproducer:
policyengine_uk/tests/policy/baseline/gov/dwp/tax_credits_pension_credit_passport.yaml::Guarantee Credit lifts the income test, with the maximum WTC counted as its income,policyengine_uk/tests/policy/baseline/gov/dwp/tax_credits_pension_credit_passport.yaml::Savings Credit alone lifts the income test for Child Tax Credit🤖 Generated with Claude Code