Skip to content

Formula-owned export must supersede eCPS parity matching (drop formula-owned vars even when eCPS stores them) #25

@MaxGhenis

Description

@MaxGhenis

Decision

When the no-formula rule (formula_owned_export) and the eCPS-parity rule (parity) conflict, no-formula wins. A variable that PolicyEngine computes via formula must never be persisted as an input — even if enhanced CPS persists it.

Why

eCPS itself stores formula-derived values it shouldn't. Example: traditional_ira_contributions (and the other contribution variables) should follow from the *_desired inputs plus the statutory caps, computed by the engine — not be frozen as a stored column. eCPS storing the computed contribution is an eCPS bug. If populace matches eCPS (the parity gate requires populace to populate every layer eCPS populates), it inherits that bug and masks the engine's cap logic.

So the gates must be ordered: a formula-owned variable is dropped regardless of eCPS, and parity must exempt formula-owned variables from its "populate what eCPS populates" requirement (the engine computes them, so a "gap" there is correct, not a regression).

Scope / changes

  1. parity_gate (or its runner) must treat formula-owned variables as exempt — not a parity gap when populace omits a formula-owned layer eCPS happens to store.
  2. The formula-owned drop list (Certified populace-us persists 18 formula-owned variables eCPS doesn't (formula_owned_export gate never wired into the build) #24) expands from 18 → 22: the 4 currently marked "parity-consistent because eCPS also stores them" are in scope under this precedence and should also be dropped/recomputed:
    • traditional_ira_contributions (← *_desired + statutory caps)
    • self_employed_pension_contribution_ald
    • spm_unit_capped_work_childcare_expenses
    • (person_id is a structural ID — keep via the structural_columns allow-list, not dropped)
  3. The canonical "formula-owned" set is the oracle for both gates: has an engine formula ⇒ not persisted (minus a documented structural allow-list).

Follow-ups (separate, lower priority)

  • File the eCPS-side bug upstream in policyengine-us-data (eCPS shouldn't persist traditional_ira_contributions etc. either) — but populace should not wait on that; the precedence rule makes populace correct independently.

Related: #24 (formula-owned over-export — this expands its drop list), PolicyEngine/populace-benchmarks#1 (parity gate — this adds the exemption).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions