Repository navigation
Conversation
The Scottish Parliament's rate resolutions set, as taxable income above the personal allowance: - 2018-19 (S5M-10397): a 41% higher rate from £31,580, where the file held 40% from £31,500 until 2021-22; - 2019-20 (S5M-15879) and 2020-21 (S5M-21090): limits of £2,049, £12,444 and £30,930, then £2,085, £12,658 and £30,930, where the file repeated the 2018-19 limits; - 2021-22 (S5M-24225): starter and basic rate limits of £2,097 and £12,726, where the file held the 2024-25 limits of £2,306 and £13,991. The 2017-18, 2022-23 and 2023-24 values already matched S5M-03912, S6M-03019 and S6M-07853. Each dated value now names its motion and paragraph, and the references list every resolution from 2017-18. Fixes #2783 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- scottish_rate_resolutions.yaml: 29 cases worked by hand from S5M-10397, S5M-15879, S5M-21090 and S5M-24225, with a taxpayer in each band, one at each corrected limit and the issue's £50,000 of pay in 2018-19 (£9,184). - test_scottish_income_tax_rates.py: compares every limit and rate from 2017-18 to 2026-27 with the resolutions restated in the test, on the model year and across each tax year in the statutory tree; checks the limits plus the personal allowance against gov.scot's tables; and, on hand-built Scottish taxpayers, checks with Hypothesis that income tax on pay equals the resolution's bands and never falls as pay rises. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Married Scottish couples in 2018-19, 2019-20 and 2020-21: an earner at the intermediate rate limit can receive the allowance, one pound above it cannot, and pay of £14,000 with savings of £29,500 can. Twin couples who make no election check the tax at each rate, worked by hand from S5M-10397, S5M-15879, S5M-21090 and ITA 2007 ss. 12, 12A, 12B, 55B. The header now cites s. 23 for applying the limits after the allowance. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The whole-year test now reads the scale on 6 April, on every date its YAML gives within the tax year, and on 5 April, so a change and its reversal inside one year fail it. A new test checks that no rate or limit takes effect before 6 April 2017, the start of S5M-03912's tax year. The Hypothesis reference rounds the tapered allowance up to a whole pound (ITA 2007 s. 35(3)), so it now draws odd pay above £100,000 too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The header now names the Scottish Parliament, quotes the motions' "income", cites ITA 2007 s. 23 for applying the limits after the personal allowance, and keeps the £150,000 and £125,140 tops apart from the gov.scot allowance gloss. The changelog names Parliament's resolutions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The rates, limits and dates now match every resolution from S5M-03912 for 2017-18, which the rate tests and the 2017-18 tax band and Marriage Allowance cases check. The model holds no separate 2016-17 Scottish rates. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The YAML notes now say which sections set the transferable amount and give the tax reduction, and the first-date docstring states only what the scale holds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The YAML headers and two test docstrings now name who acts: Parliament charges the rates, s. 35(1) sets the allowance and gov.scot adds it to each limit. Comments and docstrings only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LwQq6GUMZ7gG6HM75shUVi
…t top limit Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LwQq6GUMZ7gG6HM75shUVi
…omments The gov.scot tables, ITA 2007 s. 23 and s. 35 no longer act in the comments of rates.yaml and scottish_rate_resolutions.yaml, and the test's resolutions comment no longer describes how the data was produced. Comments only: the YAML data and the Python AST are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main now gives the Marriage Allowance as a Step 6 tax reduction, so the five claiming cases also check the reduction and the earner's income tax against the hand-worked law, and the comment no longer describes the old subtraction from income. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
juaristi22
left a comment
There was a problem hiding this comment.
Review status: COMPLETE at e70a40a555686fe2053d3ff0e8b8b5bb891df5a6. No findings or material evidence gaps. Approval is deferred while the exact-head hosted test checks finish.
The independent policy review matched all ten agreed Scottish rate resolutions for 2017–18 through 2026–27, including the changed historical rates/limits in S5M-10397, S5M-15879, S5M-21090, S5M-24225. It checked the limits after Personal Allowance, whole-tax-year commencement, model fiscal sampling, the newly claimed 2017 coverage, and Marriage Allowance boundary premises. The actual queued Axiom packet #541 is dispatch-ready and remains open with pe-parity; queued parity is not executed parity.
Validation under the locked Core 3.34.9: 128 tests passed (88 YAML, 40 Python), including the 41 new policy cases, 47 directly affected Marriage Allowance cases, and the full Scottish Python module. Six native household controls passed through final income tax and household net income. For 2018–19 Scotland, £45,000 pay gives £7,134 tax; adding £5,000 dividends, £5,000 savings or £10,000 property income gives £8,109, £8,764 or £11,234 respectively. North East and Wales controls give £6,630. One repository test invocation; no dependency installation, private/survey data or population run.
The review validated 42 official source/extract pairs (29 reused, 13 newly captured), checked 17 runtime pins and all 194 cached released-Core package files, and preserved 261 immutable technical evidence members before removing the disposable snapshot normally. The author's 930-unit comparison was not counted as an independent review execution.
The full code/source review is complete. I will recheck CI at this same head without repeating it and approve only after the applicable required checks pass and publication guards remain unchanged.
Aggregate impact on certified data: passBase Checks: 0 broken by this change, 1 failing on both sides, 0 fixed. Moves flagged for review: 0 (thresholds in Notes
Moves flagged for reviewNone. Spending by benefit and service
Caseloads
Household net income by decileNo household's net income changes in any year. No change in any year: receipts by tax head; government balance, each component counted once; model totals; household income totals; population; poverty rates; people in poverty; inequality; mean household net income in each side's own deciles; standard reform costings (change in gov_balance); standard reforms: change in each reform's target. Checks failing on both base and head (1)
Counted-once checkThe check raised each of 92 components by £1 per unit in 2026-27 and read every head of its totals household by household: its own head must rise by exactly £1, no other tax head may move, no other benefit may rise, and the model's own total must move by what its heads moved. A response that is not finite breaks every rule. The check measures a head that breaks a rule twice more: once holding every other head at its baseline value, and once holding every other head at its value after the first £1 while the component rises again. The head fails where either measurement still shows the response. The check cannot hold a head at a value that is not finite. In each unit where another head is not finite after the first £1, it holds that head at its baseline value, and the second measurement judges no household the unit belongs to. There a head fails wherever it first broke a rule, or wherever the check could not confirm whether its response contains the component. 0 failed and the check skipped 0.
Provenance
Dataset: Receipts by tax head: head levels
Spending by benefit and service: head levels
Caseloads: head levels
Government balance, each component counted once: head levels
Model totals: head levels
Household income totals: head levels
Population: head levels
Poverty rates: head levels
People in poverty: head levels
Inequality: head levels
Mean household net income in each side's own deciles: head levels
Standard reform costings (change in gov_balance): head levels
Standard reforms: change in each reform's target: head levels
|
test_matches_origin_main_on_unchanged_households compares 23 households with values computed on main at 9dd44e1, which used 2018-19's Scottish starter and basic rate limits (2,000 and 12,150) in 2019-20. At S5M-15879's 2,049 and 12,444, the snapshot's three Scottish taxpayers pay 0.49, 0.49 and 3.43 less tax. Their applicable income rises by those amounts, and their awards fall by 20% of each. Set those three rows to the new values and rewrite the notes beside them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
juaristi22
left a comment
There was a problem hiding this comment.
Approve at c1d55699d962994f54fef4ccb9fb436d11b47e3a. The incremental review is COMPLETE, with the stale 2019 Council Tax Reduction test expectations resolved and no open findings or material evidence gaps.
The new commit updates six expected values for three Scottish households and explains their arithmetic. Formulas, parameters, scenarios, assertions and tolerances are unchanged. The independent source review confirms the £0.49/£3.43 tax effects and the resulting 20% CTR taper, with the existing rounding tolerance retained. All 7 affected tests passed at this head (37.81s pytest; 43.06s bounded invocation), using the locked Core 3.34.9. The prior 128 test passes and six household checks are retained for unchanged behavior, without rerunning them.
The changed RuleSpec #541 packet updates only the commit references; its source values and companion cases are unchanged, and it remains queued rather than executed. The review validated 45 original/extract pairs (42 retained plus the current packet and provided CI evidence). The author's private-data/grid results are not new independently executed results from this review.
All 21 latest exact-head CI contexts passed in the captured results. Head, description, human activity, source guards and applicable required checks are refreshed again before this approval.
Fixes #2783
Reproducer: policyengine_uk/tests/test_scottish_income_tax_rates.py::test_scottish_rates_and_limits_match_each_resolution, policyengine_uk/tests/policy/baseline/finance/tax/income_tax/scottish_rate_resolutions.yaml
axiom: TheAxiomFoundation/rulespec-uk#541 queued
What and why
Each year the Scottish Parliament sets the Scottish rates and limits for one tax year by a Scottish rate resolution (Scotland Act 1998 s. 80C(1) and (3)). PolicyEngine applied different rates or limits in four tax years:
PolicyEngine applied 40% through 2020-21, reused the 2018-19 limits in 2019-20 and 2020-21, and applied the 2024-25 starter and basic rate limits (S6M-12252) in 2021-22. The 2017-18 (S5M-03912), 2022-23 (S6M-03019) and 2023-24 (S6M-07853) values already matched, and so did 2024-25 to 2026-27.
We cite Parliament's motion and paragraph beside each rate and limit from 2017-18 to 2026-27, and list every resolution from 2017-18 in the references. We left the personal allowance, the rest-of-UK rates, the uprating metadata, the announced freeze through 2028-29 and every formula as they were, and moved Scottish income tax's verified start year in
programs.yamlfrom 2019 to 2017. Overmain, this pull request changes six files:rates.yaml,programs.yaml,changelog.d/2783.fixed.md,scottish_rate_resolutions.yaml,test_scottish_income_tax_rates.pyandtest_council_tax_reduction_pensioner_children_tariff_properties.py.Limits of income after the allowance
In the 2017-18 to 2023-24 motions, Parliament charges each rate on "income" up to a limit. It sets those limits on income after the personal allowance: the taxpayer deducts the allowance at Step 3 and works out the tax at each rate at Step 4 (ITA 2007 s. 23). From 2024-25 Parliament says so in the motions, where s. 11A charges this income "above the personal allowance". We kept the limits in that form in
rates.yaml, as before.The Scottish Government adds the standard personal allowance to each limit in its table for each year (gov.scot), and its figures agree with the limits in every year from 2017-18 to 2026-27. The allowance falls by £1 for every £2 of income above £100,000 (s. 35(2)), so none remains at the £150,000 and £125,140 tops, and there the Scottish Government's figure equals the limit. For example:
test_scottish_limits_plus_personal_allowance_match_gov_scot_tableschecks this for every year against the model's personal allowance.Model years
convert_to_fiscal_year_parameters(policyengine_uk/utils/parameters.py) gives each year label the value in force on 30 April, so a value dated 6 April reaches that year's label: 2019-04-06 sets model year 2019 (2019-20). The tests read the model year. They also read the statutory tree on 6 April, on every daterates.yamlgives within the tax year and on the following 5 April, and they check that no rate or limit takes effect before 6 April 2017.Readers
Twelve files read this scale:
earned_income_tax,property_income_tax,tax_band,meets_marriage_allowance_income_conditions,marriage_allowance_appropriate_percentage,uc_income_tax(policyengine_uk/utils/uc_income_tax.py),uc_minimum_income_floor_income_tax,private_pension_contributions_tax,carers_allowance_earnings,esa_exempt_work_earnings,pension_credit_self_employment_deductionsand the working-age Council Tax Reduction earnings rule (council_tax_reduction/working_age/_earnings.py). They read brackets by position, andfirst_extended_scottish_threshold(policyengine_uk/utils/income_tax.py) andtax_bandtell the schedules apart by their number of limits. We kept the order of the brackets and the number in force in each year (three in 2017-18, five from 2018-19 to 2023-24, six from 2024-25), so each reader still finds each band where it was. For example,marriage_allowance_appropriate_percentageand the Council Tax Reduction earnings rule both read the Scottish basic rate from the scale's second bracket, which holds 20% in every year.What moves
We compared this branch at
c1d55699d962994f54fef4ccb9fb436d11b47e3awithmainat3c51e6c00f2e27bcb25f135bdf7dab66472253effor 2015 to 2030, using 930 hand-built units. We built 465 single adults and 465 married couples with a spouse earning £5,000, across Scotland, the North East and Wales. Each adult earns one of 31 pay amounts from £0 to £160,000, with pay alone or with £5,000 of dividends, £5,000 or £29,500 of savings, or £10,000 of property income.income_taxandhousehold_net_incomemove only in Scotland, and only in 2018 (138 of 930 units), 2019 (268), 2020 (268) and 2021 (252). Nothing moves in 2015-2017 or 2022-2030, or outside Scotland.On pay alone, for a single adult:
Parliament charges a Scottish taxpayer's savings and dividends at the rest-of-UK rates (ITA 2007 ss. 11D(6) and 13(5)), and
savings_income_taxanddividend_income_taxmove in no unit, single or couple, in any year.earned_income_taxmoves (130, 260, 260 and 240 units in 2018 to 2021), and so doesproperty_income_tax(30, 46, 50 and 22), since property income bears the Scottish rates. In 2018-19 a single adult with £45,000 of pay pays £0.50 more on the pay (£7,133.50 to £7,134.00), and £5,000 of dividends or savings on top still costs £975 or £1,630. With £10,000 of property income instead, the tax on the property income rises from £4,000 to £4,100, and their income tax by £100.50, from £11,133.50 to £11,234.00.tax_bandmoves for Scottish taxpayers between an old and a new limit: 2 units in 2018, 30 in 2019, 32 in 2020 and 8 in 2021.The Marriage Allowance changes in 19 couple-year observations across 10 of the couples. In 2018-19 the earner with £43,430 of pay (£31,580 after the allowance) now receives the £1,190 transfer, since their last pounds stay at the intermediate rate. In 2019-20 and 2020-21 the same nine earners lose the £1,250 transfer: with £30,931 to £31,500 after the allowance (pay of £43,431, £43,662 or £44,000, alone or with £5,000 of dividends or savings), their last pounds now bear the 41% higher rate, which s. 55B(2)(b) doesn't list.
We used no survey data, so the run gives no aggregate. CI's Aggregate impact report (run 42748132964) covers 2025-26 to 2031-32, after the years this pull request corrects. It compares
mainat3c51e6c00fwitha0a09bcb3b, CI's merge of c1d5569 into thatmain, with a full microsimulation for each side and year onenhanced_frs_2024_25.h5(policyengine-uk-data 1.58.1). It flags no move and finds no change in any household's net income, tax receipt or poverty rate. The change breaks none of its checks, and one check fails on both sides.Council Tax Reduction follows net income. Of the households that
test_matches_origin_main_on_unchanged_householdscompares withmain, three Scottish taxpayers pay £0.49, £0.49 and £3.43 less tax in 2019-20. Their applicable income rises by the same amounts, and their awards fall by 20% of each, from £1,380.24, £889.22 and £461.48 to £1,380.14, £889.13 and £460.79. We moved those three rows of the test's table frommain's values to these, and wrote the arithmetic beside them.Marriage Allowance
On
main,tax_bandbands a Scottish taxpayer's non-savings income on the Scottish limits and their savings and dividends on the rest-of-UK limits, and keeps income at a limit in the band below (#2828).meets_marriage_allowance_income_conditionsapplies the rate conditions of ITA 2007 s. 55B(2)(b) and (ba) to income directly: it tests non-savings income against the limit where the Scottish higher rate starts, and savings and dividends against the rest-of-UK basic rate limit.marriage_allowance_tax_reductiongives the earner a reduction of the transferred amount at the Scottish basic rate, 20%, at Step 6 of s. 23 (s. 55A(2), s. 55B(1) and (3)).The couple cases in
scottish_rate_resolutions.yamlcover 2018-19, 2019-20 and 2020-21. An earner at the limit, and one with pay and savings, can receive the allowance, and one £1 above the limit cannot. Twin couples who make no election pay tax at the rates Parliament set. For the five claiming couples, the cases check the transfer, the reduction and the earner's income tax against the law, and the differential gives the same totals, with no tax on the spouse:Invariants
For every input:
test_scottish_income_tax_rates.pytests 1 to 3 on every year, and 4 and 5 with Hypothesis on hand-built Scottish taxpayers: 4 examples of 48 people with any whole-pound pay up to £320,000, each read in all ten years. The differential above checks 6.Test plan
scottish_rate_resolutions.yaml, 41 cases worked by hand. 29 cover pay alone, from S5M-10397, S5M-15879, S5M-21090 and S5M-24225 with each year's personal allowance, among them the issue's £50,000 of pay in 2018-19 (£9,184.00;maingives £9,133.50). 12 cover married couples, from those motions and ITA 2007 ss. 10, 12, 12A, 12B, 35, 55A and 55B.ruff format --check .,ruff check .andruff check --select F811,F821 policyengine_uk(0.17.2) pass atc1d55699d;git diff --checkagainstmainreports nothing.changelog.d/2783.fixed.md.We ran these locally at
c1d55699d962994f54fef4ccb9fb436d11b47e3a, without survey data and with policyengine-core 3.34.1:scottish_rate_resolutions.yamlscottish_rates.yamlmeets_marriage_allowance_income_conditions.yamlmarriage_allowance_tax_reduction.yamlpolicyengine_uk/tests/policy/reforms/cps/marriage_tax_reforms.yamltest_scottish_income_tax_rates.py, with its Hypothesis testtest_tax_band_scottish_properties.pytest_marriage_allowance_tax_reduction_properties.pytest_council_tax_reduction_pensioner_children_tariff_properties.pyCI at c1d5569 (
pull_requestrun 42748133106, with the locked policyengine-core 3.34.9): Python shards 1 to 8 pass 13,213 tests (61 skipped, 2 xfailed), andTest / YAMLpasses 6,473. The Python shards run the tests that need survey data on the pinnedenhanced_frs_2024_25.h5(policyengine-uk-data 1.58.1).On
main(3c51e6c00), with this branch's Scottish rate tests copied in,scottish_rate_resolutions.yamlgives 30 failures and 11 passes.test_scottish_income_tax_rates.pygives 13 failures and 27 passes: the 2018 to 2021 rows of the table, whole-year and gov.scot tests fail, and so does the Hypothesis test. The cases that pass sit where the two schedules agree, such as £1,000 of taxable income at 19% or £30,000 of pay in 2018-19, or where the old limits give the same answer, as for the couples with pay of £14,000 and savings of £29,500. With this branch'stest_council_tax_reduction_pensioner_children_tariff_properties.pycopied in instead,mainfails the 2019 case oftest_matches_origin_main_on_unchanged_householdson the three Scottish rows' six values, and passes 2024 and 2026.The new tests reject each of 64 scratch mutations of
rates.yaml, none of them committed. At9f2863f45, whoserates.yamland Python test differ from this branch's only in comments, a harness copied the tree, applied each mutation, and ran the table, whole-year, gov.scot and first-date tests, 34 in all, which pass on the unmutated copy. Each of these mutations failed at least one of them:The July 2019 limit and rate failed
test_each_resolution_holds_for_its_whole_tax_year[2019], the 1 April 2017 start and the 2016 copy failedtest_scottish_rates_take_effect_on_6_april_2017, and the 1 April moves for 2018-19 to 2022-23 failed the previous year's whole-year test.Merge notes
For each of the 54 open pull requests,
git merge-tree --write-tree --name-onlygives the same result from this branch's head (c1d55699d) as frommainat3c51e6c00: 35 merge cleanly, and the 19 that conflict withmainconflict in the same files. This branch adds no conflict.🤖 Generated with Claude Code