Repository navigation
ESI employer premium contributions as a first-class, validated resource component #454
Copy link
Copy link
Open
Labels
tier:standardSpec'd build/assembly with acceptance tests; suitable for Opus/GPT-class agentsSpec'd build/assembly with acceptance tests; suitable for Opus/GPT-class agents
Description
Motivation
Employer-sponsored insurance premium contributions are the largest health subsidy absent from Populace's resource surface. Dense builds impute employer_sponsored_insurance_premiums (~$1.13T at f0af251, right scale against KFF EHBS employer-share benchmarks), but:
- The column dies in sparse exports (Sparse-57k export drops 94 no-formula input columns from the dense parent (tips, overtime, disability flags, ESI premiums, rent, QBI basis) #361 inventories it among the 94 dropped inputs) and was never stored in the retired us-data lineage — the IARIW OBBBA paper (PolicyEngine/obbba-paper) found it computes $0 on eCPS 1.73.0 and had to document ESI as a levels-omission in its resource measure.
- No calibration target or validation gate anchors it. A CBO-comparable household-resources measure counts employer premium contributions as income; without an external anchor the imputation can drift silently.
- ESI status gates real policy interactions: an affordable-ESI offer blocks marketplace PTC eligibility, and ESI/Medicaid churn matters for coverage analyses. A live, validated ESI input makes those model pathways meaningful rather than degenerate.
Proposed work
- Carry
employer_sponsored_insurance_premiums(and the ESI offer/coverage flags it pairs with) through every release class — wire into the Sparse national-only release never persists input columns for tips/overtime/auto-loan/education/retirement-contribution/casualty/misc bases (absent-from-H5, engine defaults to 0) #340/Sparse-57k export drops 94 no-formula input columns from the dense parent (tips, overtime, disability flags, ESI premiums, rent, QBI basis) #361 input-coverage gate so sparse exports fail without it. - Add a Ledger fact + calibration or validation target for aggregate employer premium contributions (NHEA sponsor-of-funds employer share, or KFF EHBS average premiums × employer share × covered lives; state-level if a defensible source exists).
- Release gate: aggregate within a stated tolerance of the external anchor, plus a nonzero-mass check.
- Document the resource-concept role: ESI belongs in the CBO-style "income including health benefits" surface alongside Medicaid/CHIP/PTC.
Acceptance
A release's stored ESI premiums aggregate within tolerance of the documented external anchor on both dense and sparse artifacts, with the gate red if the column is absent or zero-mass.
Consumer
PolicyEngine/obbba-paper (IARIW 2026): methods currently disclose "employer contributions to health premiums, which CBO's income measure also counts, are absent from this file" — this issue is the permanent fix.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
tier:standardSpec'd build/assembly with acceptance tests; suitable for Opus/GPT-class agentsSpec'd build/assembly with acceptance tests; suitable for Opus/GPT-class agents
Activity
MaxGhenis commentedon Jul 19, 2026
Claiming: ESI employer-premium anchor sourcing (NHEA sponsor-of-funds / NIPA 7.8 class) underway together with the #451 quartet facts; export carry-through + gate wiring rides the same Build N branch. — populace owner session
MaxGhenis commentedon Jul 19, 2026
ESI anchor sourcing complete (values read from fetched official tables today):
cms.gov/files/zip/nhe-tables.zip)apps.bea.gov/national/Release/XLS/Survey/Section7All_xls.xlsx, published 2025-09-26)Concept flag before the gate lands: the dense f0af251 imputation (
$1.13T) exceeds BOTH employer-share anchors ($0.98–1.05T) and sits well under total premiums ($1.43T). First step of the gate work is pinning which conceptemployer_sponsored_insurance_premiumsencodes in policyengine-us — if employer-share, the imputation is ~8–15% hot against 2024 anchors; if total-premium, it is ~21% cold. Tolerance and anchor choice follow from that determination, not the other way around.MaxGhenis commentedon Jul 20, 2026
Concept check resolved (read from the released engine, policyengine-us 1.764.6):
employer_sponsored_insurance_premiumsis documented as "Annual employer-paid health insurance premiums. CBO treats this as part of household market income" — employer share, person-level, uprated by the CBO employment-income series. So the anchor is the employer-contribution class, and the concept-matched candidates are:Implication: the dense f0af251 imputation (~$1.13T) is ~8% above the broadest 2024 employer-share anchor, not between concepts as previously hypothesized — the validation gate should target NHEA Table 24 with a stated tolerance, and the imputation likely needs a modest trim when the gate first binds. Receipts for both anchors are on #451.
Add CMS NHEA Table 24 ESI employer-contribution anchor package
Quartet anchor facts: SE-health deduction, W-2 tips alignment, NHE Ta…
MaxGhenis commentedon Jul 21, 2026
Two facts pinned while sequencing this against Build N, one of which descopes it from the N release:
1. Concept pinned (anchor selection unblocked).
employer_sponsored_insurance_premiumsin policyengine-us is a person-grain input documented as "Annual employer-paid health insurance premiums. CBO treats this as part of household market income" — the employer share, not the total premium. So NIPA 7.8 employer contributions for group health insurance ($1,002.9B CY2024) and the NHEA sponsor-of-funds employer share ($1,047.0B CY2024 class) are two estimates of the same concept (~4% apart), and the gate anchor should be one of them with the other as a cross-check — not a total-premium series. The banked ledger fact drafts from 7/19 can proceed on that basis.2. The column has no live producer in the current lineage — this cannot be a "carry-through" fix. The declared
meps_esi_premiumsstage (MEPS-IC priors over ASEC policyholder fields, per the archived eCPS derivation at 42ed5d45) is a recorded parity known-gap with hard evidence: the retired derivation requiresNOW_OWNGRP,NOW_HIPAID, andNOW_GRPFTYP, and all three sha-recorded 2022–2024 ASEC h5 inputs omit them (onlyPHIP_VALsurvives;has_esi/NOW_GRPare recorded as semantically invalid substitutes). The ~$1.13T dense figure in this issue's motivation came from a pre-hermetic lineage that still had those fields. Today's builds — including Build N — produce nothing for this column, which is exactly what the obbba-paper methods disclosure already says.So the deliverable splits: Build N ships with the documented known-gap unchanged (no regression — the gap predates it), and this issue becomes the source-restoration decision: (a) re-pull ASEC vintages carrying the NOW_* trio into the sha-pinned inputs and run the archived derivation, or (b) design a PHIP_VAL+MEPS-priors derivation that doesn't need the trio. (a) preserves the fenced method; (b) is new methodology needing its own validation. That's a scoping call for the data-inputs lane, not a release-window patch.
Add BEA NIPA Table 7.8 line 17: employer contributions for private gr…
Add BEA NIPA Table 7.8 line 17: employer contributions for private gr…
Rework the ESI premium stage after independent review (#454)
Re-pin three test counts for the single-output ESI stage (#454)
Run the ESI premium stage in the stacked pool (#454)
Document the stacked pool's ESI premium stage and anchor (#454)
Transfer the ESI employer premium onto the ACS local lane's ACS spine (…
Grade the ESI employer premium at staging, finalize and package in th…
14 remaining items
Answer the first review of the ESI pool anchor (#454)
Answer the second review of the ESI pool anchor (#454)
Merge origin/main into esi-employer-premiums-454 (#454)
Name NHE, not BEA, as the receipts' cross-check in the experiment REA…
Merge origin/main into esi-employer-premiums-454 (#454)
Rerun the registry comparison after the merge and record its compiler…
Merge pull request #1189 from PolicyEngine/esi-employer-premiums-454
MaxGhenis commentedon Oct 24, 2026
The code for the employer premium landed in #1189 (merge
1eb0b1b4, 2026-10-24). This issue stays open until a release carries the column and the anchor gate has run on real dense and sparse artifacts; that release is queued for Max.What now exists
meps_esi_premiumsstage (us_runtime/esi_premiums.py). It runs in the US base build before the PUF support clone and writesemployer_sponsored_insurance_premiums.NOW_OWNGRP,NOW_HIPAID,NOW_GRPFTYP,NOW_GRPFTYP2,PEMLRandNOEMPare restored by exactPERIDNUMjoin from the sha-pinned Census person files for every pinned income year (2022 to 2025), through the Read the ASEC at-interview coverage recodes the 2022/2023 inputs lack from the pinned Census archives (#720) #991 mechanism. Each year's code set and universe relations are checked, and the stage refuses a frame that breaks them.us_esi_premiums_signal_gateis red when the column is absent, zero-mass, non-finite, negative, outside its universe, not a common multiple of its MEPS-IC cell, when PUF clones disagree, or when a raw ASEC coverage column is missing.us_esi_premiums_anchor_gateis red when the weighted total over the anchor's universe is more than 5% from BEA B4923C. The release tool runs the signal gate on the base frame and on the calibrated export for both the dense and the sparse default, and writesesi_premiums.jsonas required release evidence. The input isrequiredin the release input-coverage manifest, with a neutralization probe.tools/build_us_meps_ic_esi_cells.py --checkrebuilds the cell table from the PDFs.Method, and what the independent reviews changed
Each current policyholder (
NOW_OWNGRP == 1) is priced from the MEPS-IC cell for their plan tier, firm size and State (census division for governments).NOW_HIPAID == 1gives the full premium,3gives zero, and2gives the premium minus the contribution of an employee who pays one (MEPS-IC's average contribution includes enrollees who pay nothing, so it is divided by one minus the published no-contribution share).The first draft scaled employed policyholders to BEA on the reading that BEA's series is active-worker only. The first review showed that is wrong: BEA's State Personal Income methodology (December 2025, paragraphs 3.18 and 3.19) says its estimates cover active and retired employees, as NHE's do. So the stage now prices every policyholder, employed or not, scales that universe to the anchor, and writes the column for employed policyholders only. Retiree and COBRA dollars are priced and left out of the column, not loaded onto workers.
With both national totals retiree-inclusive, the anchor was a methodology choice. Max ruled d1317 on 2026-10-11: BEA NIPA 7.8 line 17 (B4923C), $977.034B for 2024 (revised from $1,002.9B on 2026-09-30). Under BEA, the private part of the column matches MEPS-IC's own active-employee total within half a percent; under NHE it was 6.7% above. The US Chronicle feed is re-pinned to carry the B4923C facts (PolicyEngine/chronicle#331), and the release tool refuses a feed whose values differ from the stage's.
Measured on the pinned pools (target year 2024, before calibration)
By plan tier on the default pool: family $366.9B, employee-plus-one $184.9B, single $312.1B. By sector: private $665.6B, State and local $162.7B, federal $35.6B. Receipts are in
experiments/us-esi-454/receipts/.The mean is about $11.7k per covered worker, against the roughly $15k CRFB had in mind. Across all 79.69M employed policyholders, including the 5.72M whose employer pays nothing, it is $10,840. Under the readings not taken, NHE over every policyholder gives $925.7B ($12,515), and loading BEA onto workers only gives $977.0B ($13,209).
What is not done
pre_tax_health_insurance_premiumsis not produced. PolicyEngine-US treats it as disjoint from the other premium inputs (Document disjoint health premium inputs and correct consumer treatment policyengine-us#10046), so a producer must move those dollars out of the reported premium on an engine that includes that change. It is a separate, sequenced follow-up.Merge pull request #1379 from PolicyEngine/esi-454-registry-receipt-s…
Merge origin/main into esi-premiums-pool-operator (#454)
Transfer the ESI employer premium onto the ACS local lane's ACS spine (…
Grade the ESI employer premium at staging, finalize and package in th…
Document the ACS local lane's ESI employer premium (#454)
Keep the ACS local lane's ESI code and tests anchor-agnostic (#454)
Fit the ACS local lane's ESI anchor to the pool kernel's wage-evidenc…