Skip to content

Wire the eCPS parity gate: pinned incumbent reference, reason'd exemption register, release-blocking (#313)#316

Merged
MaxGhenis merged 14 commits into
mainfrom
ecps-parity-gate
Jul 5, 2026
Merged

Wire the eCPS parity gate: pinned incumbent reference, reason'd exemption register, release-blocking (#313)#316
MaxGhenis merged 14 commits into
mainfrom
ecps-parity-gate

Conversation

@MaxGhenis

Copy link
Copy Markdown
Contributor

Fixes #313.

What ships

First-run gap census (from the seeded register)

The first comparison against the current base artifacts surfaces ~110 reference-populated layers the candidate does not populate. By family: 42 general input layers (#38 — retirement distributions, occupation descriptors, fine geography, demographic flags; dedicated children recommended), 16 QBI/passthrough qualification layers (probable root cause of #298's −31/−40% QBI base), 15 SPM inputs (#32), 13 take-up flags (#312), 8 wealth/assets (#49), 7 education-credit inputs (#253), 5 hours-worked (#242), 4 capital-gains detail (#274). household_weight is a representation difference (incumbent column vs typed Frame weights), not a gap.

Verification

  • Full workspace suite exit 0 in the CI-mirror env; ruff check clean.
  • Tests: plant-a-layer failure naming the variable (gate-level, test_gates.py), reference integrity (sha matches cached incumbent bytes), register schema (reason + issue required, unique entries, reference-layers-only).
  • Builder test extended for the new gate kwarg.

Provenance

Built by directed agents across three runway-limited sessions with the lead session performing final integration (hygiene-test allowlist, builder-test fakes, suite verification) and PR. Squash-merge recommended (history carries WIP salvage checkpoints). Full working log follows.

PROGRESS — eCPS parity_gate wiring (issue #313)

Branch: ecps-parity-gate (worktree from origin/main @ 7e9a32d)
PR: (not yet opened)

Goal

Wire parity_gate into the US release with a pinned incumbent-eCPS reference
(committed JSON of per-variable nonzero shares + source sha256/vintage) and a
reason'd, issue-linked exemption register. Failure = nonzero exit; GateResult
details land in the release manifest.

Architecture findings (before writing code)

  • parity_gate(candidate_nonzero, reference_nonzero, *, known_gaps=()) in
    packages/populace-build/src/populace/build/gates.py:1347. Two share dicts +
    known_gaps = iterable of NAMES only (no reason mapping). Details:
    reference_populated_layers, gaps, exempted.
  • GateReport.to_manifest() (gates.py:126) already serializes gate details.
  • Declarative gates.json / GatesManifest (country_spec.py) is a
    Belgium-only greenfield construct. BE gates.json policy note explicitly
    says parity/export_surface/target_surface are "deliberately not selected"
    (no incumbent). ALLOWED_GATE_FUNCTIONS (country_spec.py:72) DOES list
    "parity" — so parity is a known gate id, just never selected by any spec.
  • US build (tools/build_us_fiscal_refresh_release.py) does NOT load
    country_spec/GatesManifest at all.
    US gates run as DIRECT function calls
    (e.g. input_mass_parity_gate at lines 3237/3261). => The seam for wiring
    parity into US is the direct call in the release tool, alongside the
    geography-ladder and weights-audit gates. (Chosen seam; rationale recorded.)
  • JSON reference idiom: packages/populace-build/src/populace/build/us/*.json,
    loaded via from importlib.resources import files
    files("populace.build.us").joinpath("X.json").read_text() (see
    us_runtime/fiscal_targets.py:715).

Reference artifact (incumbent eCPS) — PINNED

  • HF: policyengine/policyengine-us-data (repo_type=model), file
    enhanced_cps_2024.h5, revision 21280dca5995e978d706740a8a4b9b7860cfd7b6
    (refs/main at compute time), sha256
    0a6b961ad363a421bde99f2c8e5d8f20370bcba45fd303050537a25bdd805b14
    (verified: HF LFS blob name == content sha256). vintage/period 2024.
  • Native layout is the LEGACY flat variable/2024 HDF5 (244 var keys), NOT the
    USSingleYearDataset entity-table layout Populace publishes — so it cannot be
    loaded with load_us_frame; read each variable array directly.
  • Reference scope: PolicyEngineUSEngine().variables() = 841 engine INPUT vars
    (formula-owned excluded), intersected with eCPS keys, minus 10 schema-
    structural entity-id/membership columns. => 179 present, 158 populated.
  • Candidate measured: policyengine/populace-us populace_us_2024.h5 (sha
    c2065b64…), the small national support frame — populates 51 cols, 48 of them
    reference-populated (parity OK on those).
  • Committed: us/ecps_parity_reference.json (158 shares + source sha/vintage),
    declared in us/country_package.json resources.

FIRST-RUN GAP LIST — 110 honest gaps (SURPRISING: far exceeds the 3 families)

The issue anticipated take-up (#312) + SCF wealth (#49) + SPM (#32). Those
cover only 36 of 110. Mapped the remaining 74 to EXISTING open trackers (no new
issues filed — lead files). Register us/ecps_parity_known_gaps.json, 110
entries, all reason'd + issue-linked. Distribution:
#38 (42) remaining US tax-input & reported-observation & demographic/geo
layers — the explicit catch-all tracker for exactly this residue
#298 (16) QBI / passthrough qualification (*_would_be_qualified, sstb_*,
REIT/PTP/BDC, UBIA, W2-QBI) — QBI base already off vs targets
#32 (15) SPM inputs (housing, child support, workers comp, MOOP/expenses)
#312 (13) take-up flags (takes_up_*, WIC, voluntary-filing)
#49 ( 8) wealth/assets/vehicles (net worth, SCF assets, auto-loan; see #252)
#253 ( 7) education-credit inputs (AOC / tuition)
#274 ( 4) capital-gains detail (collectibles / 1250 / 4952 / inv-interest)
#242 ( 5) hours-worked / labor inputs
NOTE for lead: #38 is doing heavy lifting (42). Its scope ("remaining US input-
layer work … release diagnostics expose reviewed exclusions") legitimately
covers these, but the lead may want dedicated children for: retirement
distributions (401k/403b/sep/keogh/IRA), occupation/labor-status descriptors,
fine geography codes (block/county/tract), and demographic flags. household_weight
is a genuine type-mismatch (incumbent stored a weight column; Populace carries a
typed Frame weight) — flagged under #38 as reported-obs-vs-exclusion.

Steps

  • 1. Pin reference: compute incumbent per-variable nonzero shares ONCE,
    check in JSON with source sha256 + vintage.
  • 2. Wire gate into US release path (direct call seam), fail-loud + manifest.
  • 3. Seed exemption register (checked-in file, reason'd + issue-linked).
  • 4. Tests: plant-a-layer (prove-it-can-find-something), register schema,
    reference-JSON integrity (sha match).

Coordination

Log

  • Set up worktree, read gates.py + country_spec.py, mapped the seam.

MaxGhenis and others added 14 commits July 4, 2026 20:48
Compute per-variable nonzero record shares of the incumbent enhanced-CPS
artifact ONCE and check them in as a frozen reference, plus a reason'd,
issue-linked exemption register seeded from the first parity run. This is
step 1 of wiring parity_gate into the US release (populace#313).

- us/ecps_parity_reference.json: 158 populated input layers of
  hf://policyengine/policyengine-us-data/enhanced_cps_2024.h5
  @ 21280dca (sha256 0a6b961a…805b14, vintage 2024), scoped to engine
  input variables (formula-owned excluded) with entity-id/membership
  structural columns removed. Never recomputed from a moving artifact.
- us/ecps_parity_known_gaps.json: 110 gaps the current small national
  candidate (populace_us_2024.h5) does not populate, each with a reason
  and an existing tracking issue (#312 take-up, #49 wealth, #32 SPM,
  #253 education credits, #298 QBI, #242 hours, #274 capital-gains
  detail, #38 remaining tax-input/reported-observation layers).
- us_runtime/nonzero_shares.py: us_nonzero_shares — the per-record
  nonzero-share evidence the parity gate consumes, matching the
  canonical plan._nonzero_share convention so reference and candidate
  are measured identically.
- Declare both JSONs in us/country_package.json (the loader refuses
  undeclared files).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
us_runtime/parity_reference.py loads the two checked-in facts the parity
gate depends on, with importlib.resources (the fiscal-target idiom) and
loud validation:

- load_ecps_parity_reference -> EcpsParityReference (shares + artifact
  provenance). Refuses an empty share map so a corrupted reference can't
  make the gate vacuously pass.
- load_ecps_parity_known_gaps -> tuple[ParityKnownGap]. Refuses any entry
  missing a reason or issue ref.

Tests cover reference-JSON integrity (including that the recorded sha256
matches the real cached incumbent bytes at the pinned revision — runs, not
skipped, when the artifact is in the HF cache), the register schema (every
entry reason'd + issue-linked), and that the register names only real
reference layers. Re-exported from us_runtime.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Pass the enforced parity variant into the manifest builder so build and
release manifests null the parity block under --allow-ecps-parity-gaps,
and count enforced parity failures in the build_manifest calibration verdict.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nce from the incumbent-string scan

The parity reference must name the incumbent it pins (sha-locked
historical record, not a live dependency); the hygiene test gains a
three-file documented allowlist. Builder-test fakes widened for the
new gate kwarg.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nto ecps-parity-gate

Both-add conflicts resolved keeping all sides: builder-test fakes in stage
order (take-up before parity), both gate kwargs and manifest blocks.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Wire the eCPS parity_gate into the US release with a pinned reference and a reason'd exemption register

1 participant