Repository navigation
Conversation
…-up input The microsimulation pays the dividend to every Alaska resident: 756,512 people for 2027, against 618,863 applications Alaska paid for 2025. AS 43.23.005(a)(5) limits the dividend to citizens, lawful permanent residents, refugees and asylees, so an eligibility variable now applies that test. The statute's other tests (an application, residence during all of the prior year, absences, felony bars) have no PolicyEngine inputs, and Core forbids formula-time draws. A boolean input that defaults to true, like the other programs' take-up flags, lets microdata or a user say Alaska did not pay a person. Household calculations keep paying each eligible resident. Energy relief shares the gate because Alaska pays it as part of the dividend. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Draw any state in the Hypothesis properties, so invariant 4 (nobody outside Alaska gets paid) holds for more than Washington. Point the validation doc at microcosm#1551 and say why is_incarcerated does not feed the dividend. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The eligibility variable's documentation now matches the validation doc: the model has no input for conviction-based incarceration during the qualifying year, even though is_incarcerated exists. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
State v. Andrade and 15 AAC 23.154 read "lawfully admitted for permanent residence" as legal presence plus the ability to intend to remain, so the parameter comment, docs and variable documentation now say that and give the reason each excluded status stays out. OAH 25-3180-PFD covers fixed-term parole. A child born during the dividend year cannot qualify, but age 0 does not show that: Populace's age is ASEC A_AGE, measured as of a February to April survey date, so most records aged 0 were born the year before. The tests now draw ages and pin that a resident aged 0 stays paid unless an input says otherwise. Add YAML cases for an undocumented child and for a supplied zero dividend that leaves energy relief in place. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
15 AAC 23.154(e) tests status on the application date, alongside the qualifying year that OAH 25-3180-PFD applies. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #10763 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 1 4 +3
Lines 37 49 +12
=========================================
+ Hits 37 49 +12
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
The dividend docs and the eligibility variable's documentation said why a person "is incarcerated" and that a child "was born" in a year. They now say that `is_incarcerated` records no conviction, and they give children's birth dates instead. No formula, parameter or test changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The children-under-one section now says how a record's survey date maps to the dividend year. If each record keeps its own survey date, 92% to 96% of the people aged 0 in Populace's 2024 Alaska records have birth dates in 2022 or 2023 and can qualify under AS 43.23.005(c); if every survey fell in the dividend year, 71% to 87% could. `birth_year` would put all of them in the dividend year. The section also says that a child born during the qualifying year qualifies only through an eligible parent, which the model does not check, and the TPS bullet says that Andrade did not address TPS. The eligibility variable's documentation adds the parent test to the list of tests the take-up input covers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Handing this PR to the US + core hub. Only CI remains.
|
Text only. The Alaska Supreme Court held Andrade, the Department of Revenue applies its reading in 15 AAC 23.154(a), an alien's qualifying year starts under 15 AAC 23.154(c), a person coded DACA holds no status under 8 U.S.C. 1101 to 1189, and PolicyEngine calculates both payments. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
I'm taking this PR back from the US + core hub for a text-only commit, |
The administrative law judge upheld the Division's denial in OAH No. 25-3180-PFD; the decision itself denied nothing, so the docs and the parameter comment now say who acted. Test names and docstrings take PolicyEngine or Alaska as subject where a document stood in before. Text only: no formula, parameter value or test expectation changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The parameter comment and the validation doc now name the Permanent Fund Dividend Division at first mention. The property tests' docstring says they catch a changed status list only in a year they test, and Case 5's name covers the codes PolicyEngine leaves unmapped for other reasons. Text only: no formula, parameter value or test expectation changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The docstring said the tests catch a changed status list "in a year they test", where "they" could read as the person editing. It now says "in a year these tests cover". Docstring only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Follows #10692.
What and why
PolicyEngine pays the Alaska Permanent Fund Dividend and energy relief to everyone who lives in Alaska: by our estimate, 756,512 people for 2027, about 19% more than Alaska pays. Under AS 43.23.005, Alaska pays only people who apply and pass the statute's residence, presence, immigration status and Selective Service tests, and under (d) it denies the dividend to some people with felony or repeat convictions.
This PR:
ak_permanent_fund_dividend_eligible, which applies the immigration status test in AS 43.23.005(a)(5), the one test PolicyEngine can resolve from its inputs;takes_up_ak_permanent_fund_dividend_if_eligible, a default-true input for the statute's other tests and for anyone who doesn't apply;ak_permanent_fund_dividendandak_energy_reliefon both, because Alaska pays energy relief as part of the dividend (sec. 13, ch. 34, SLA 2026).A household calculation still pays a resident unless an input says otherwise: an unset status counts as citizen, and an unset flag counts as true.
The status test closes 9% of the gap by itself. In PolicyEngine/microcosm#1551, we specify a Microcosm stage that sets the flag and takes reported dividends out of
miscellaneous_income(PolicyEngine/microcosm#1443). To show what such a flag does to totals and poverty, we set a prototype flag and picked its draw cutoff so the eligible people it flags match Alaska's 2024 count on the file's released weights.Who Alaska pays
The PFD Division reports these counts in its summary of dividend applications and payments:
In its 2024 annual report, the Division counts 659,422 applications for 2024, from 494,717 adults and 164,705 children. As of December 31, it lists 627,030 as eligible, 23,629 as denied with no appeal, 8,317 in review and 446 in appeal. Those counts differ from the summary table's, and we compare the model with the table's paid counts.
Where each piece belongs
The status test belongs here. The Legislature names the statuses in AS 43.23.005(a)(5), and the model already has
immigration_status. In State v. Andrade, 23 P.3d 58 (Alaska 2001), the Alaska Supreme Court read "lawfully admitted for permanent residence" as legal presence plus the ability to intend to remain, rather than the federal definition. In 15 AAC 23.154(a), the Department of Revenue applies that reading to a status under 8 U.S.C. 1101 to 1189 that allows domicile. We give the reason for each status indocs/validation/alaska-pfd.md. Populace's Alaska records hold 714,298 citizens, 15,852 permanent residents, 9,894 undocumented people and almost no DACA recipients, so these totals don't move however we read the other codes. The Census Bureau asks about citizenship in the ASEC, and Microcosm imputes the non-citizen labels, so the status test's count inherits that imputation's error.The model can't apply the birth-date test from age. A child born during the dividend year can't qualify: the child fails (a)(3), and under (c) only children born in the two calendar years before it qualify. The Division takes applications for a child "born on or before December 31st of the qualifying year." But for a child under one,
agedoesn't say which calendar year the birth fell in. Populace'sageequals ASECA_AGEon all 2,444 Alaska records. The Census Bureau conducts the ASEC in February, March and April, records age as of the survey date, and asks about income in the year before, which Populace records assource_year. Of Alaska's 6,337 people aged 0 for 2024, all of whom pass the status test, 74% come from the 2023 survey, 26% from 2024's and 0.3% from 2025's. So the share who can qualify for 2024 turns on how a record's survey date maps to the dividend year:birth_year's formula (the year minusage) puts every birth in the dividend yearWe assume births spread evenly over the year before the survey. The ranges run from mid-February to mid-April interviews, and for the counts we assume mid-March. The first dating depends on the release weights, which give the 2025 survey 0.3% of the age-0 weight but 25% of all Alaska weight. If the age-0 weight spread over surveys like all Alaska weight, 68% (65% to 70%) could qualify. Either way, if the model gated at age 1, it would remove 6,337 people, mostly children who can qualify, so this PR leaves age out. Set the take-up input to false for a child born during the dividend year.
Who applies and passes the other tests belongs in the data.
policyengine_core.commons.formulas.randomraises "Formula-time randomness is not allowed", so a formula can't draw take-up. PolicyEngine models take-up of other programs the same way, with default-true inputs such astakes_up_snap_if_eligibleandtakes_up_medicaid_if_eligiblethat Microcosm sets.is_incarceratedrecords no conviction and doesn't tie to the qualifying year, and Populace doesn't set it.OI_VAL, which the model doesn't read. Microcosm puts ASECOI_VALinmiscellaneous_income, apart from the alimony and strike benefit codes, so reported dividends overlap the simulated dividend today.This PR couples to Microcosm's next engine bump.
assert_take_up_contract_currentfails when the engine carries atakes_up_*variable thatus/take_up_contract.jsonomits, andtest_checked_in_table_matches_installed_enginefails when the table lists a variable the engine lacks. The bundle's take-up spec has to cover the engine too:_take_up_program_bindingsrequires exactlyUS_TAKE_UP_PROGRAM_COUNT(17) programs inus/spec/take_up.yaml, andassert_engine_abi_lock_currentraises "take_up/programs: mapping is not total over the fresh engine ABI" when the engine's take-up variables differ from the bundle's. Microcosm locks policyengine-us 2.2.1, and draft PolicyEngine/microcosm#1365, which moves the lock to 2.60.4, addstakes_up_medicare_part_d_if_eligibleas the 18th program. So whoever first bumps Microcosm's engine past a release containing this PR has to add, in the same PR, a contract row and a 19th program for the new flag, a count of 19 and a regeneratedus/engine_abi.lock.json. We spell out each change in PolicyEngine/microcosm#1551.Impact
We ran
Microsimulationfor every recipient count, dollar total and poverty rate, on the Alaska households of the default dataset:populace_us_2024.h5atpopulace-us-2024-spm-20260909(sha2566496cc43...), 826 households and 2,444 person records at their own weights. The match-rule and weight diagnostics read the file's inputs directly. This PR changes only Alaska's formulas, so all its effects fall on these records. Main's 2027 dividend total, $756,512,330.77, equals the figure from #10692's full-file run.origin/mainat 30d03c3.miscellaneous_income.Recipients
For 2026, we estimated Alaska's count by dividing the Legislature's $127,340,800 estimate by the $200 energy relief. The prototype matches 2024 because we set its cutoff there. The model keeps the same flags in later years and uprates the weights: each seed's 2025 and 2026 counts equal its 2024 count times main's uprating ratios (1.00928 and 1.01649). Those rows compare national population uprating with Alaska's counts, so they don't test the draw rule.
2027
2026
Limits
Invariants
These hold for every modeled year, every mix of people in a household and every age, unless an input overrides the eligibility variable or a payment:
Test plan
ak_permanent_fund_dividend.yamlcases 15 to 25,ak_energy_relief.yamlcases 13 to 18, andak_permanent_fund_dividend_eligible.yamlcases 1 to 7. All 50 cases in the folder pass.policyengine_us/tests/test_ak_permanent_fund_dividend_receipt.py: every combination of status, take-up and six representative ages in Alaska and Washington for 2015, 2022, 2026 and 2027, plus drawn years, states, ages and household mixes. The file restates the statute's four statuses, so it fails if someone changes the parameter's statuses in a year it tests without changing the file. YAML can't draw household mixes or exhaust that product. Each of eleven mutations fails the new file or the YAML folder: droppingASYLEE, addingTPS, ignoring take-up in the dividend or in energy relief, restoring the residence-only gate on either payment, removing the state gate from eligibility, waiving the status test or the take-up input for children, tying energy relief to a paid dividend, and failing a person aged 0.PAROLED_ONE_YEARdoesn't say a parole runs indefinitely.TPSandDEPORTATION_WITHHELD(8 U.S.C. 1231(b)(3)) fall outside 8 U.S.C. 1101 to 1189, and a person codedDACAholds no status under those sections. A person codedUNDOCUMENTEDlacks the legal presence the court required in Andrade.CUBAN_HAITIAN_ENTRANTandCONDITIONAL_ENTRANTdon't say whether the person may adopt the United States as their domicile.ruff formatandruff checkon the whole repository, asmake formatruns themchangelog.d/Test cost
At 059bf7c, CI run 42622268857 ran the new file on Python shard 5, in the shard planner's
remaining-1process. Its seven tests took 14.9 s there. That process ran 76 files (2,323 tests) in 20:40 of wall time, and GNU time measured its peak resident set at 6.45 GiB; the Makefile gives the runner 16 GB. Locally on macOS the file takes 10 s, or 35 s of wall time including its import of the model, and peaks at a 1.5 GB footprint. It builds no extra model and loads no dataset; each case reuses the shared system throughSimulation(situation=...).Scripts for the figures
build_state_subset.pywrites the Alaska records.run_scenarios.pyruns main and this branch.seed_flag.pysets the prototype flag,sweep.pyruns it across seeds, andmatch_rule_check.py,weights_check.py,age_check.py,age_dating_check.py,parent_check.pyandstage_time_emulation.pyproduce the diagnostics.axiom: TheAxiomFoundation/rulespec-us#2140 queued
TheAxiomFoundation/rulespec-us#2066 covers the amounts.
🤖 Generated with Claude Code