PolicyEngine / PolicyEngine/policyengine-scorecard

OBR policy costings (mode 2): Policy Measures Database + EFO 3.17 → PE-UK static counterparts

Open
#54 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
0
Forks
0
Avg merge
6d 12h
Merged PRs (30d)
32

Description

Max's steer (2026-08-16): center PE model development — including PolicyEngine Macro — on the Scorecard. Use it to compute PE counterparts to OBR's published scores first, before adding machinery nothing else uses. This issue is the static half; the macro half is the companion issue linked below.

The population

The 8/2 harvest staged the full OBR Policy Measures Database (~/scorecard-harvest/uk_obr/; access recipe and staging decisions in its NOTES.md): 24,304 rows = every measure × tax head × FY, Budget 1970 → Autumn Budget 2025, certified costings, positive_gain_to_exchequer verbatim; plus EFO March 2026 Table 3.17 (95 rows): OBR's current re-estimated yields of the personal-tax measures (PA/HRT freezes, additional-rate cut, NICs thresholds) — each a one-line policyengine-uk reform.

None of it is in the DB. #48/#51 cover mode 1 (levels/baseline moments; OBR enters as 259 EFO welfare rows). This lane is mode 2 (#4): reform deltas — OBR's certified costing of a measure vs PE-UK's static costing of the same measure.

Precedent to extend, not reinvent

sources/campaign-20260802/uk/obr_measures.jsonl — 10 rows (SB2024 HICBC, employee NICs 2p/4p): reversal legs on the certified 2026 world, with annotations naming the axes — OBR = announcement-baseline vintage, behavioural-adjusted, FY accrual; PE = certified world, static, CY. Those axes are the assumptions-registry entries (#10) and the explained-share material.

Design

  • Measure → reform registry (e.g. data/uk/obr_measure_reforms.yaml): per measure — PMD row key, fiscal event, verbatim OBR description, PE reform spec (parametric dict + start FY), computability ∈ {expressible, partial (annotate what's missing), not_expressible (why)}, construction (reversal-on-certified-world, or forward from the announcement baseline when the baseline registry (#13) has it), notes. Human-readable provenance on every row; the registry is itself a Scorecard artifact.
  • Compute: policyengine.py (latest) managed sims on the certified populace-uk bundle, one reform per measure, per FY in the OBR window; emit GBP aggregates by head where PE can split (income tax / NICs / benefits) so head-level and total rows both join. Every pe_value traces to a saved per-run artifact.
  • Stage under the campaign ingest contract (results/uk/staged/*.jsonl: external_claim_match descriptor, engine_version, full bundle id, status/construction/run_id/annotations). DB ingest of the PMD claims themselves rides #48's vocabulary (gbp, fy, basis) once it merges — stage first, ingest second, exactly as the US campaign did.
  • Compare descriptively: ratio bins, never pass/fail; benchmark_class = different_model (HMRC/HMT costing models) unless assumption-matched; baseline mismatch surfaced per #13; behavioural vs static named on every row.

First families (in order)

  1. EFO Mar 2026 3.17 — 95 rows, current re-estimates, cleanest joins.
  2. PMD 2023–2025 events, income tax + NICs + welfare heads (~1,000 rows before computability filtering): AS2023/SB2024 NICs cuts, HICBC, PA/HRT freeze extensions, AB2024 employer NICs, AB2025 measures, two-child limit (joins the pentagon).
  3. Backfill earlier events as the registry grows.

Gate

Sol-reviewed PR(s), org-side branch (private repo — fork PRs don't run Actions). Descriptive register throughout (#9): no "replication rate", no wins.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with sources/campaign-20260802/uk/obr_measures.jsonl and the staged harvest's NOTES.md to understand the existing precedent and data. Read policyengine.py and the proposed data/uk/obr_measure_reforms.yaml structure, then trace how results/uk/staged/*.jsonl feeds ingestion. Done means the first EFO 3.17 family is computed with saved run artifacts, provenance, and descriptive comparisons under the stated campaign contract.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
data-engineering, databases
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.