Repository navigation
UK local surface: band domain, signed small-cell rules, renewals, support flag (#1278) - #1283
Conversation
|
Fine once the two support-floor exclusion reasons drop their support figures (finding 1). The rest are should and nit. @juaristi22, I reviewed the PR at c9bc232 against main at 121fd4d. C1 is correct as far as I can see:
Moving to raw scores to avoid the underflow is the right fix, and the test that compares the softmax with The −9,779 lines are regenerated register content:
Nothing hand-written or still needed is removed. The renewals are real renewals, not just new dates. Each one has a fresh
What I checked
🤖 Generated with Claude Code |
c9bc232 to
4a3b4ed
Compare
|
Thanks @vahid-ahmadi. Rebased onto main at 412f916, which brings #1271 (the policyengine-uk 2.130.1 lock) and #1281 (the QRF tail gate removed). Five files conflicted: the imports in
On your not-checked list: the engine-uk tests, the feed-gated compiles on the 942a1fa feed and the twin licensed spines on the new base (control 412f916, head 4a3b4ed) are running now, with the full engine-free lane. I'll add their results here when they finish. 🤖 Generated with Claude Code |
The SPI housing shell draws council_tax_band from one GB-wide classifier with region as a predictor and no nation mask, so SPI-channel households in England and Scotland could draw band I and Northern Ireland households a band other than the FRS placeholder D. No target counts those rows, and a computed council tax would charge a band missing from a nation's ratio table at the Band D ratio. - uk_runtime.council_tax_constants holds the engine's bands, the placeholder and each nation's bands, with region views derived from the region tier; frs_spine and local_targets import them. - The shell redraws only a band outside its nation's bands, from the classifier's probabilities over those bands with its own identity-keyed uniform. Valid draws never move; the receipt counts redraws by nation; the stage declares the rule council_tax_band_within_its_nation. - A release-blocking spine gate, uk_council_tax_band_domain, checks every household at the transferred boundary. The shared enum_domain_gate takes optional per-partition domains, and the UK binding refuses a declaration that differs from the constant. - The synthetic housing-shell fixture gives Northern Ireland the placeholder band, as the FRS spine does. - Regenerated: source_stages.json, the release input coverage manifest, the H2 spine fixture and the mirrored gate digests; the contract's gate mirrors name the new gate. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
María renewed all six local binding adjudications on 2026-10-14 for three months. Each adjudication records the renewal and the reason the basis still holds; four reasons are re-worded where the basis moved since they were signed: - census_disclosure_control_noise: the cells now reconcile to the nation household controls (#1198). - full_frs_tei_band_unavailable: the HMRC area surface also binds higher rate taxpayer counts, classed by marginal rate, not by a total-income band. - population_universe_private_households: the age cells' vintages (#1198), and the age-universe change that will retire the entry. - uc_unit_vs_household_grain: the area series count all claims, bridged to the paid caseload until PolicyEngine/chronicle#339 lands. The local rowwise test pins the renewed census entry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
_local_contract_covers still keyed the local council-tax rows on the voa.council_tax_stock.by_area. prefix that #929 retired, so the 25 mhclg, welshgov and scotgov by-area rows covered only the LA loss module. They now cover uk-data's la_council_tax source as well, ahead of the re-pin that follows PolicyEngine/policyengine-uk-data#482 and PolicyEngine/policyengine-uk-data#484. Three stale texts are corrected while the register regenerates: the English region concern names the taxbase rows and the nation grain, and the two private-rent concerns describe the calendar-2025 PIPR series in the pinned feed, not a June 2026 snapshot. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The K=25 build's degenerate-surface gate failed on incapacity_benefit_reported, which the national release boundary dropped and the local export kept (#796). 949c2ee made the local export apply UK_RELEASE_EXPORT_DROPPED_COLUMNS, but only the national helper had a test. The new test plants every reviewed column on a synthetic frame and checks that neither the exported tables nor the export descriptor carry them; it fails if the local drop is removed. The next dense build confirms it on licensed data. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The support-floor exclusions promise a support_below_floor flag, which went with the old driver on 2026-09-25 (#796), so consumers of the local file (#1114, #506) could not see which areas are below the floor. - gates.area_support_shortfalls holds the floor rule; area_support_gate and the new area_support_below_floor both use it, so the flag cannot disagree with the gate. A reviewed exclusion passes the gate but leaves the flag set. - The full build's area-support table carries support_below_floor under the floors uk_local_area_support declares (uk_area_support_floors). - The dense assembler writes an area_support block to release_manifest.json: the areas below the floor by grain, as codes only, with the floors. A released file passed the release-blocking support gate, so those are the stood-on reviewed exclusions. The data contract checks the block and that each listed area carries its area_support_exclusion limitation. - The two support-floor exclusions say where the flag is recorded. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The C1 spine build on licensed data refused in spi_housing_shell: for some English households the classifier scores band I so far above A-H that its softmax gives A-H probability exactly zero, so renormalising predict_proba over the nation's bands had nothing to draw from. The redraw now takes a softmax of the raw class scores (decision_function) over the nation's bands: the same conditional distribution, without the underflow. A new test checks that a softmax of class_scores reproduces predict_proba for binary and multiclass classifiers, and another draws rows whose nation's bands rounded to zero. target_compile_modules lists council_tax_constants, which local_targets now imports, so an edit to the bands re-keys the target kernels. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The age-universe change moves every age target to the private-household universe, so a band's target falls by its census communal-establishment share, while the incumbent evaluation keeps gating uk-data's total-resident rows at 25%. The communal receipt now measures that for every local ten-year band and 80 and over, at both local grains, and for the region tier composed from local authorities; Northern Ireland's districts come from NISRA CT0105 over NISRA's mid-2025 population and are marked approximate. Each band reports its median share and the areas at or above 20% and 25%. --communal-only writes the receipt without compiling the surface. The tool's first tests run on synthetic facts. "Aged 2 years and under" now reads as 0-2 rather than 2. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#1278) The small-cell rule's deferrals always join the reconciliation frame. Under a run's own ladder, a deferral whose English area the ladder cannot place now follows the off-surface rule: if the membership binds cells for the area, the run is a narrowed one (a sample or a test ladder), so the deferral is left out and named in the receipt's small_cell_deferrals block; otherwise it refuses. While both rules were unsigned no cell took this path; signing them (next commit) made the toy-ladder graph tests refuse a real constituency's higher rate taxpayer deferral. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
juaristi22 signed both rules in uk/local_small_cell_rule.json on 2026-10-14; they expire on 2027-04-01. Regenerated on the 942a1fa feed, the local references defer the cells the rules name: the 16 council-tax band cells of fewer than 50 dwellings (band G 3, band H 7, band I 6) and the 192 higher rate taxpayer cells HMRC publishes at 5,000 or fewer (155 constituencies, 37 local authorities). Active local references fall from 21,804 to 21,596, and no other status moves. The local scorer's frozen count, the target-surface battery pin, the assembly runbook and the local compile-parity receipt move with them. New tests require every committed rule to be signed, fail 14 days before a rule lapses, and pin the deferred cells. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…CGT script experiments/1278-uk-local-surface-receipts.md reports the first PR's measurements. It gives no counts or weighted figures from the licensed spines: - C1: on twin licensed spines (main, the branch), every band that moved was outside its nation on main; no valid band and no FRS row moved. - C2: the 208 cells the signed rules defer, and the regenerated parity receipt. - C7: the census sizing of the age-universe change. - C8: the script that measures the CGT stage's residual at design weights against its own folded HMRC margins (microcosm#725). Its results are not committed. docs/evidence/uk-local-surface-1278 holds the C1 and C8 scripts. Weighted band totals before and after the fix are not reported, because their difference would isolate the moved households. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The two local-authority support-floor exclusions (Isles of Scilly, City of London) quoted each area's positive-weight rows and effective sample size. They now say only which part of the 50-row / ESS-50 / 50-source floor each area misses. The generator's deferral rationale for the two areas' own cells quoted the same rows; it now says each area misses the floor at every K measured, and the membership is regenerated (the active references are unchanged). Vahid's review, finding 1. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
uk_council_tax_band_domain runs at the spine's transferred boundary, and the full build carries that report forward instead of evaluating it again, so a later step that writes council_tax_band (#1270's band redraw after geography derivation) was checked by nothing. uk_council_tax_band_domain_terminal is the same release-blocking check at the terminal phase; a test pins its parameters to the spine entry's. The release-cut scope owns it, so in the full build a failure stops the build rather than counting as a local export exception. Contract mirrors added and five gate digests re-pinned. Vahid's review, finding 2. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cgt_stage_residual.py pooled groups to 30 distinct source households but wrote weighted gains with no dominance check. Each group that reports gains now also passes two rules on its weighted gains, counted by source household: the largest holds at most half of the group's gains, and what the group holds beyond its two largest is at least 10% of the largest (the p% rule at p = 10). A group that fails pools with its neighbour, and the script refuses if no grouping passes. Vahid's review, finding 3. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…1278) A cell the incumbent carries but a signed small-cell rule defers is fixture-only in the local compile-parity receipt, and it kept the generic taxbase / band-H reason. It now carries its deferral's signed rationale from the membership, which names the rule: the one such cell, Barking and Dagenham band G, names council_tax_band_household_floor. A test pins every such row. Vahid's review, finding 5. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The FRS band map relied on the FRS leaving ctband unset for Northern Ireland, while its comment said every Northern Ireland household takes the placeholder band. frs_council_tax_band now sets D for every Northern Ireland household whatever ctband holds, with a test. On the licensed spine every Northern Ireland household already held D (the transferred band gate passed), so no band moves. Vahid's review, finding 7. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The stage firings council_tax_band:redrawn:<nation> count rows exactly and stay in the spine's stage evidence, which no gate reads. A comment at the source says to band them before any gate detail or report carries them. Vahid's review, finding 6. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#1270 merged first, so this branch regenerates rather than merging the registers by hand. From the 735820c feed main now pins (the consumer artifact rebuilt from PolicyEngine/chronicle at 735820c and checked against its pinned row count and facts digest), the local references, the membership and the local parity receipt are regenerated: 24,269 active local references, main's 24,477 less the same 208 small-cell cells, and 1,796 reviewed exclusions. The scorer's frozen count, the battery pin, the runbook and the receipts move with them. local_binding_adjudications.json keeps the six renewals and #1270's high_value_home_stock_derived_estimate entry; local_targets.py keeps both imports; the parity tool keeps #1270's derived stock rationale beside the small-cell one. The gate digests, the H2 spine fixture and the coverage manifest are regenerated. The C1 receipt now says its twin spines were measured before the rebases, on a shell redraw neither rebase touches. This commit sets the tree to the tested merge of the branch and main; the replayed commits before it resolved conflicts toward the branch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4a3b4ed to
426ac3e
Compare
|
Rebased again after #1270 merged (main at 5792966). This PR landed second, so it regenerates rather than merging the registers by hand:
Twin spines: not rebuilt. My earlier comment said they were running; I stopped them. The C1 receipt was measured on twin licensed spines at main 121fd4d and the branch's C1 commits on that base. Neither rebase touches the shell's redraw, and #1270's band redraw after geography derivation is covered by Tests at 426ac3e: the tested merge of the branch and main passed the targeted suite: 1,150 tests over the gate pins, the contract mirrors, the small-cell rules, the battery bindings, the H2 fixture, the full target graph and the release certification (5 skipped without the feed). 🤖 Generated with Claude Code |
|
Fine once the new C6 test passes on the rebased base (finding 8). All seven round-1 points are dealt with. @juaristi22, I re-reviewed at 426ac3e. It sits directly on main at 5792966 (the #1270 merge). I read both of your replies. Thanks for the per-finding commits. Round-1 points
New
What I checked
When I posted, CI showed lint, engine-uk, integration-uk and wheels passing. Engine-free and engine-us were still running. 🤖 Generated with Claude Code |
describe_uk_export takes solve_year as a required keyword since #1271 (0f0bb869e). The C6 test was written before that and called it without one, so it failed on the rebased base. It now passes solve_year=2025, as the neighbouring export tests do. Vahid's review round 2, finding 8. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks @vahid-ahmadi.
On finding 1's note: agreed. This PR will be squash-merged, so those figures do not enter main's history again. On the local lanes I said I would report: I stopped them, and CI on 0e60dee runs the full engine-free and engine-us jobs. I'll add CI's result to my earlier comment when it finishes. 🤖 Generated with Claude Code |
…1207) The 735820c feed artifact, whose facts and manifest digests are the ones chronicle_feed.json pins, vendors desnz_local_energy_facts.json (declared in country_package.json): the domestic electricity meter counts of 350 Great Britain authorities, the gas meter counts of 347 (the Isles of Scilly, Orkney and Shetland have no gas rows), and four ONS household totals, 701 rows, with the OGL v3.0 licence in the header. desnz_domestic_energy_facts.json and ofgem_price_cap_facts.json take the C1 purpose texts; no value moves. The national references gain the nine BUS01a rows (1,283 to 1,292 active). The local references gain 1,050 DESNZ cells (350 authorities, three rows), 1,040 of them active (24,269 to 25,309): seven are signed deferrals (the support floor's five, Orkney and Shetland's gas-connected cells) and the Isles of Scilly, Orkney and Shetland have no gas kWh row. The compile parity receipts take the new rows as ledger_only (national 691 to 700, local 4,991 to 6,031); no calibration_drift or fixture_only count moves. The reference, deferral, resource and scorer count pins move with them. The coverage manifest and the H2 spine fixture are regenerated here for the whole PR: the rebase onto main after #1283 kept main's regenerated copies in the stage-text and Northern Ireland fare commits, whose source manifest and lcfs_consumption stage contract this PR changes, as the re-vendored purpose text does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
First of two PRs for #1278: the items that are ready before the pre-Budget local build. The November PR (age universe, band H after #1270, support-floor re-sign, representativeness diagnostic) and the follow-ups with outside triggers are listed in the issue. Part of #1278.
What changes
council_tax_bandfrom one GB-wide classifier, so SPI-channel households in England and Scotland could hold band I, and Northern Ireland households a band other than the FRS placeholder D. The shell now redraws only a band outside its nation's bands (England A-H, Wales A-I, Scotland A-H, Northern Ireland D), from a softmax of the classifier's raw class scores over those bands, with its own identity-keyed uniform. Valid draws never move. A new release-blocking spine gate,uk_council_tax_band_domain, checks every household, and a terminal instance,uk_council_tax_band_domain_terminal, checks the frame the release ships (after Place high-value homes where the Land Registry sees them (#1240) #1270's band redraw); the sharedenum_domain_gatetakes optional per-partition domains. The bands live in one module,uk_runtime/council_tax_constants.py.support_below_flooris back in the area-support table. The dense assembler writes anarea_supportblock torelease_manifest.json, with area codes only, and the data contract checks it._local_contract_coverskeys the local council-tax rows on the mhclg, welshgov and scotgov prefixes, so they credit uk-data'sla_council_tax.incapacity_benefit_reportedamong them.tools/uk_target_surface_receipt.py --communal-only.docs/evidence/uk-local-surface-1278/scripts/cgt_stage_residual.pymeasures the CGT stage's residual at design weights against the stage's own folded HMRC margins (microcosm#725). A group pools with its neighbour until it rests on 30 or more distinct source households and its weighted gains pass two dominance rules (the largest source household at most half; the p% rule at p = 10). It has been run on main's spine; its results are not in this PR.experiments/1278-uk-local-surface-receipts.md, with the scripts indocs/evidence/uk-local-surface-1278/.Ruling needed before the November PR
Under one private-household universe, about 21 constituency cells and 5 local-authority cells would sit 25% or more below uk-data's total-resident age rows by construction, and the incumbent evaluation gates those rows at 25% (C7). The November PR needs a ruling on the basis that evaluation compares.
The census facts the November change needs are requested in PolicyEngine/chronicle#358.
Tests
Local runs on the head (426ac3e, rebased onto main with #1270 and the
735820cfeed):ruff check .,ruff format --checkon the changed files,tools/ci_test_plan.py verifyandtools/graph_acceptance_burndown.py --verify: clean;735820c: running; results follow in the PR thread;Review round 1
Vahid's review (all seven findings, each in its own commit): the two support-floor exclusion reasons and the generated deferral rationale drop their per-area support figures; the terminal band gate; the dominance rules in the CGT script; the parity receipt names the small-cell rule on its deferred cells; Northern Ireland FRS households take the placeholder band D whatever
ctbandholds; and a note that the redraw firings are exact counts. The policyengine.py consumer of the support flag is a separate issue.Disclosure
The receipts give no counts or weighted figures from the licensed spines; census and publisher figures appear as published. Weighted band totals before and after the C1 fix are not reported, because their difference would isolate the moved households.
🤖 Generated with Claude Code