| name | policyengine-code-organization |
| description | Code organization patterns for PolicyEngine - variable naming conventions, folder structure, file organization |
PolicyEngine Code Organization
Patterns for organizing PolicyEngine code - naming conventions, folder structure, and file organization.
Using the Variable Prefix
The variable prefix is defined in sources/working_references.md.
Look for this section:
## Official Program Name
**Federal Program**: [Federal program name]
**State's Official Name**: [State's official name]
**Abbreviation**: [Abbreviation]
**Source**: [Legal citation]
**Variable Prefix**: `[state]_[abbreviation]`
Use this prefix for all variable and parameter names.
Variable Naming Patterns
State Programs
az_liheap
ca_calfresh
ny_heap
ma_snap
az_liheap_eligible
az_liheap_income_eligible
az_liheap_benefit_amount
Federal Programs
snap
liheap
wic
snap_eligible
snap_gross_income
liheap_eligible
Standard Variable Components
Use these standard suffixes with your variable prefix:
Eligibility Variables
{prefix}_eligible
{prefix}_income_eligible
{prefix}_resource_eligible
{prefix}_activity_eligible
{prefix}_categorical_eligible
{prefix}_demographic_eligible
{prefix}_immigration_eligible
Calculation Variables
{prefix}
{prefix}_maximum_benefit
{prefix}_countable_income
{prefix}_countable_earned_income
{prefix}_countable_unearned_income
{prefix}_gross_income
Deduction/Disregard Variables
{prefix}_earned_income_disregard
{prefix}_work_expense_deduction
{prefix}_dependent_care_deduction
{prefix}_standard_deduction
Threshold/Limit Variables
{prefix}_income_limit
{prefix}_resource_limit
{prefix}_payment_standard
{prefix}_need_standard
State-Specific Terminology
Use the terminology from sources/working_references.md.
States use different terms for the same concepts:
| Concept | Possible Terms | Example |
|---|
| Benefit amount | Payment Standard, Need Standard, Grant Amount | {prefix}_need_standard |
| Income threshold | Gross Income Limit, GMI, Countable Income Limit | {prefix}_gmi_limit |
| Earnings deduction | Earned Income Disregard, Work Expense Deduction | {prefix}_earned_income_disregard |
Match the exact terms from the documentation.
Folder Organization Principles
Core Principles
- Group logically - Files that relate to the same aspect should be together
- Don't create subfolder for 1 file - If only 1 file for an aspect, keep it at parent level
- Final output at root - The main benefit variable (e.g.,
{prefix}.py) stays at the program folder root
Common Aspects (adapt to your program)
income/ - Income calculations, limits, deductions
eligibility/ - Eligibility checks
resources/ - Asset/resource calculations
deductions/ - Deductions and disregards
Study Existing Implementations
Each program is different. Before organizing, look at similar programs in the codebase:
ls policyengine_us/variables/gov/states/{state}/{agency}/
Folder Structure Patterns
Small Program (~5 files) - Keep Flat
policyengine_us/variables/gov/states/{state}/{agency}/{program}/
├── {prefix}.py # Final benefit (at root)
├── {prefix}_eligible.py
├── {prefix}_income_eligible.py
├── {prefix}_maximum_benefit.py
└── {prefix}_countable_income.py
Medium Program (6-15 files) - Light Organization
policyengine_us/variables/gov/states/{state}/{agency}/{program}/
├── {prefix}.py # Final benefit (at root)
├── eligibility/
│ ├── {prefix}_eligible.py
│ ├── {prefix}_income_eligible.py
│ └── {prefix}_resource_eligible.py
└── income/
├── {prefix}_countable_income.py
└── {prefix}_gross_income.py
Large Program (>15 files) - Full Structure
policyengine_us/variables/gov/states/{state}/{agency}/{program}/
├── {prefix}.py # Final benefit (at root)
├── eligibility/
│ ├── {prefix}_eligible.py
│ ├── {prefix}_income_eligible.py
│ ├── {prefix}_resource_eligible.py
│ └── {prefix}_demographic_eligible.py
├── income/
│ ├── {prefix}_countable_income.py
│ ├── {prefix}_countable_earned_income.py
│ └── {prefix}_gross_income.py
└── deductions/
├── {prefix}_earned_income_disregard.py
└── {prefix}_work_expense_deduction.py
Tests
policyengine_us/tests/policy/baseline/gov/states/{state}/{agency}/{program}/
├── {prefix}.yaml
├── {prefix}_eligible.yaml
├── {prefix}_income_eligible.yaml
└── integration.yaml # Always named integration.yaml
Parameter Folder Organization
Parameter folders follow similar principles to variable folders — group by function.
Keep folders focused on their purpose
Each subfolder should contain parameters that serve the same function. Don't use a folder as a catch-all.
# ❌ BAD — eligibility/ contains rate dimension boundaries that aren't eligibility criteria
ccap/
├── eligibility/
│ ├── income_limit.yaml # ✅ Eligibility
│ ├── child_age_threshold.yaml # ✅ Eligibility
│ ├── center_infant_max_months.yaml # ❌ Rate table age group boundary
│ ├── preschool_max_years.yaml # ❌ Rate table age group boundary
│ └── time_category.yaml # ❌ Authorization concept
└── rates/
# ✅ GOOD — each folder contains parameters that match its purpose
ccap/
├── age_groups/ # Age group boundaries for rate lookups
│ ├── center_infant_max_months.yaml
│ └── preschool_max_years.yaml
├── eligibility/ # Actual eligibility criteria
│ ├── income_limit.yaml
│ └── child_age_threshold.yaml
├── rates/
└── time_category.yaml # At root — doesn't fit neatly in a subfolder
The key question: "Is this parameter an eligibility rule, a rate-table dimension boundary, a benefit calculation input, or something else?" Put it in the folder that matches its function.
Common Mistakes to Avoid
Variable Names
ca_tanf_eligible
ca_calworks_eligible
az_liheap_benefit
az_liheap_eligible_status
az_liheap
az_liheap_eligible
Test File Names
az_liheap_integration.yaml
integration.yaml
test_low_income_family.yaml
az_liheap.yaml
az_liheap_eligible.yaml