Repository navigation
Conversation
LocalAreaBreakdownOutput gains constituency_withheld_codes and local_authority_withheld_codes, each list[str] | None defaulting to None: the sorted ONS codes of that level's areas that the run estimated but disclosure control did not publish. An empty list means none were withheld; None means the result does not report them, so results from older executors still validate. The gateway's golden OpenAPI, the entrypoint's OpenAPI test and the gateway README describe the fields. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
UKGeographyDisclosureOutput now keeps, for each level, the codes of the areas the release estimated: those with household weight, which is how policyengine.py's AreaWeights.from_labels builds the release's areas. withheld_codes(level) returns, sorted, the estimated areas that are not published. This covers an area whose relative change alone is withheld, which the release still reports an average for, and the case where withholding cannot resolve the findings and no area is published, which withholds every estimated area. An area with no household weight is neither published nor withheld. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
LocalAreaBreakdownBuilder now fills constituency_withheld_codes and local_authority_withheld_codes from the disclosure output it built the records from: the sorted codes of the areas the release estimated but did not publish, [] when a level withheld none. The builder refuses to build without a disclosure output rather than report the lists as unknown. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
assert_uk_local_area_breakdown now requires each level's withheld codes to be a list of area codes, sorted without repeats, holding no published area. The beta test runs against the executor the deployment just released, which reports them, so a missing list fails it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The contract and gateway change, with its own changelog entry, moved to #976, which deploys first. This entry now describes only the executor filling the two lists and the stricter beta check, and sits beside the local-area breakdown entry so that merging main later does not touch the same text. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
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.
Fixes #968
Merge requirement
Don't merge this until #976 is merged and deployed. #976 makes the contract and the deployed gateway accept
constituency_withheld_codesandlocal_authority_withheld_codes, while no executor sends them. This PR makes the executor send them.The deployment workflow redeploys the executor before the stable gateway (
deploy_gatewayneedsdeploy_executor). If this PR deployed first, the old gateway, whose contract forbids unknown keys, would report every breakdown that completed in between as failed. With #976 deployed first, the gateway already accepts the fields.After #976 merges,
maingets merged into this branch. Its diff then shows only the executor commits: the contract commit762f2c6fis the first commit of both PRs.What changes
Each level of a UK local-area breakdown result (
kind: local_areas) now lists the ONS codes of the areas disclosure control withheld, beside the published records. A client can then tell an area that the run estimated and withheld from one it never estimated, such as an area with no households in the local-area dataset.The executor fills the fields that #976 adds to
LocalAreaBreakdownOutput:constituency_withheld_codeslocal_authority_withheld_codes[]means that no area of that level was withheld.Where the codes come from
The executor computes them as the estimated areas minus the published ones, in
UKGeographyDisclosureOutput.withheld_codes:compute_uk_geography_disclosure_outputalready computes them (_uk_area_household_counts), to withhold the unpublished share cells and to take each area's population. This is the set of areas .py's release estimates:AreaWeights.from_labelsnormalises the codes withnormalise_area_codes, treats blank codes as unassigned and keeps only the areas with positive weight._published_area_changesturns into records, which are the breakdown's records.I didn't read the withheld cells from
UKGeographyDisclosure.release, because they don't match what the result leaves out:_resolved_public_tablereturns None). The release has not marked those cells withheld, and gives no public table to read them from.Release._estimates,Release._manual).The difference is right in each of these cases. The tests check that the published and withheld areas never overlap and together equal the estimated areas.
Commits
762f2c6fAdd optional withheld-area code lists to the local-area breakdown result (contract). This is also Accept optional withheld-area code lists on UK local-area breakdown results #976's first commit, so it leaves this PR's diff oncemainis merged in. Seen failing first: the contract tests and the entrypoint's OpenAPI test.bfb7e81fRecord which estimated UK areas the disclosure output did not publish (executor).UKGeographyDisclosureOutputkeeps each level's estimated codes and gainswithheld_codes(level). Seen failing first, withAttributeError: 'UKGeographyDisclosureOutput' object has no attribute 'withheld_codes': for both levels, the published and withheld areas are disjoint and together equal the estimated ones; the thin, undefined and complementary seats are listed; a seat whose households all have zero weight is in neither; and every estimated area is withheld when the findings cannot be resolved.3a71ed3bReport each level's withheld UK areas in the local-area breakdown result (executor).LocalAreaBreakdownBuilder.buildfills both fields from the disclosure output, and refuses to build without one. Seen failing first: the serialized breakdown heldNoneinstead of['E14000529', 'E14000531']and[], and a missing disclosure output raised nothing.d482efeaCheck the withheld-area lists in the beta local-area breakdown test (apis-integ).assert_uk_local_area_breakdownrequires each level's list, sorted, without repeats and without a published area. Seen failing first: the four new rejection cases (each list missing, an unsorted list, a published code in the list) raised nothing.18d7fc96Describe the withheld-area code lists in the changelog. Documentation only.022deac2Limit the changelog entry to the executor change. Accept optional withheld-area code lists on UK local-area breakdown results #976 has its own entry for the contract and gateway change. This entry sits beside the local-area breakdown entry, so mergingmaindoesn't touch the same text. A trial merge of Accept optional withheld-area code lists on UK local-area breakdown results #976's branch into this one merged cleanly.The stricter beta check
test_calculate_uk_local_area_breakdownnow fails when a breakdown carries no withheld-code lists. The deployment runs it against the executor it has just deployed, at the pinned UK version, so after this PR deploys the lists are present.stage12-deploy.yml(deploy_existing_stack: false) runs the integration tests without redeploying the executor. If one ran after this PR merges but before a full deployment of it had succeeded, the beta check would run against the previous executor and fail.Deployment
Overlap with #919
#919 also edits
macro_output.py(the area records'xandy). Aftermainis merged in, this PR no longer changes that file, so the overlap is #976's.Checks run
test_local_area_breakdown.pyandtest_gateway_models.py;test_openapi.py;test_openapi_golden.pyandtest_local_area_breakdown.py;test_simulation_output_geographic.py,test_simulation_output_uk_local_areas.py,test_simulation_output_impacts.py,test_simulation_api_contracts.py,test_microdata_weight_boundaries.pyandtest_runtime_evaluated_annotations.py;test_calculate.pywithout thebeta_onlytests.make checkpasses: ruff format and lint, and Pyright in every package, with no errors.python scripts/run_quality_guards.pywithGITHUB_BASE_REF=mainpasses every guard.simulation_output_geographic.pyis now 795 lines, under the 800-line limit.The work was done red-green: each behaviour change's tests were written first and seen failing for the expected reason, then the code was written, and both were committed together.
🤖 Generated with Claude Code