Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
17f62ba
Massachusetts Child Care Financial Assistance (CCFA)
Aug 12, 2025
d501122
draft
Aug 13, 2025
57e3f96
add
Aug 14, 2025
cbbf1d5
draft
Aug 14, 2025
936fe80
add formula and tests
Aug 15, 2025
8838eca
more tests
Aug 15, 2025
7a0e3e3
Merge branch 'master' of https://github.com/PolicyEngine/policyengine…
Aug 15, 2025
4a4ffbc
Massachusetts Child Care Financial Assistance (CCFA)
Aug 20, 2025
79ba817
more tests
Aug 20, 2025
2754f2e
Merge branch 'master' of https://github.com/PolicyEngine/policyengine…
Aug 20, 2025
e70232f
minor
hua7450 Aug 21, 2025
1072725
adding tests and formula for age category and tafdc related eligibility
hua7450 Aug 21, 2025
b998d23
Merge branch 'master' of https://github.com/PolicyEngine/policyengine…
hua7450 Aug 21, 2025
ed71c65
Lots of renaming and adjustments
hua7450 Sep 2, 2025
351cb20
format
hua7450 Sep 2, 2025
dd180ac
Merge upstream master into pr/hua7450/6390
hua7450 Sep 2, 2025
fc99151
Restore .claude directory that was accidentally deleted
hua7450 Sep 2, 2025
1138d77
remove ma_child_care_subsidies
hua7450 Sep 2, 2025
c94a72f
add ma_child_care_subsidies
hua7450 Sep 8, 2025
ec360ed
Merge branch 'master' of https://github.com/PolicyEngine/policyengine…
hua7450 Sep 8, 2025
1dedfb8
change year
hua7450 Sep 8, 2025
af482a7
test
hua7450 Sep 8, 2025
b89251b
adjust parameters to avoid 'no field of name 0' error
hua7450 Sep 9, 2025
a27a068
minor
hua7450 Sep 9, 2025
6bca5d1
adjustments
hua7450 Sep 12, 2025
276c17a
Restructure PR review commands into read-only and fix modes
MaxGhenis Oct 5, 2025
5806d0b
Update validation agents with correct vectorization and hard-coded va…
MaxGhenis Oct 5, 2025
929d93b
Make country package purely deterministic - read stochastic variables…
MaxGhenis Oct 5, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 27 additions & 13 deletions .claude/agents/implementation-validator.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,20 @@ Validates government benefit program implementations against quality standards,
## Critical Violations (Automatic Rejection)

### 1. Hard-Coded Numeric Values
Any numeric literal (except 0, 1 for basic operations) must come from parameters:
- Thresholds, limits, amounts
- Percentages, rates, factors
- Dates, months, periods
- Ages, counts, sizes

**Acceptable Hard-Coded Values:**
- **Bootstrapping values**: `if month >= 10:` to determine parameter snapshot
- **Mathematical baselines**: `income_ratio - 1` (100% FPG), `level = 1 + ...` (starts at 1)
- **Structural constants**: `min_(size, 12)` (FPG table limit), `range(1, 13)` (months)
- **Derived from parameter structure**: `num_children - 2` (first, second, then additional)
- **Framework constants**: `MONTHS_IN_YEAR` for period conversions (NOT literal 12)
- **Zero checks**: `max_(0, value)`, `== 0`, `> 0`

**Must Be Parameters:**
- Policy thresholds that could change
- Percentages/rates from regulations
- Program-specific age limits
- Benefit amounts

### 2. Placeholder Implementations
No TODO comments or placeholder returns:
Expand Down Expand Up @@ -77,14 +86,19 @@ Validate that:

### Numeric Literal Detection
```python
# Scan for potential hard-coded values
# Allowed: 0, 1, mathematical operations
# Flagged: Any other numeric literal

# Examples of violations:
if age >= 65: # Flag: 65 should be parameter
benefit * 0.5 # Flag: 0.5 should be parameter
month >= 10 # Flag: 10 should be parameter
# ACCEPTABLE (Don't Flag):
if month >= 10: # ✅ Bootstrapping - determines parameter snapshot
income_ratio - 1 # ✅ Mathematical baseline (100% = 1)
min_(family_size, 12) # ✅ Structural constant (FPG table limit)
num_children - 2 # ✅ Derived from parameter structure
/ MONTHS_IN_YEAR # ✅ Framework constant (NOT / 12)
max_(0, value) # ✅ Zero check

# VIOLATIONS (Flag These):
if age >= 65: # ❌ Program age limit - should be parameter
benefit * 0.5 # ❌ Rate from regulation - should be parameter
if income < 50000: # ❌ Policy threshold - should be parameter
income / 12 # ❌ Literal - should use MONTHS_IN_YEAR
```

### Parameter Organization Check
Expand Down
131 changes: 110 additions & 21 deletions .claude/agents/policy-domain-validator.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,27 +61,73 @@ existing_patterns = [

### 3. Hard-Coded Value Detection

**Patterns to Flag:**
```python
# Numeric literals that should be parameters
suspicious_patterns = [
r'\b0\.\d+\b', # Decimals like 0.5, 0.33
r'\b\d{2,}\b', # Numbers >= 10 (except common like 12 for months)
r'return \d+', # Direct numeric returns
r'= \d+\.?\d*[^)]', # Numeric assignments not in function calls
r'\* \d+\.?\d*', # Multiplication by literals
r'/ \d+\.?\d*', # Division by literals (except 12 for monthly)
]

# Exceptions (OK to have literals)
ok_literals = [
'range(', 'np.array([', 'np.zeros(', 'np.ones(',
'== 0', '> 0', '< 0', '>= 0', '<= 0', # Zero comparisons
'== 1', '== 2', # Small integer comparisons
'/ 12', # Monthly conversion
'* 12', # Annual conversion
]
```
**Acceptable Hard-Coded Values (Don't Flag):**

1. **Bootstrapping values** - values needed to access parameters:
```python
if month >= 10: # ✅ OK - needed to determine which FPG snapshot to use
instant_str = f"{year}-10-01"
```

2. **Mathematical baselines** - representing 100%, starting at 1, etc:
```python
income_ratio - 1 # ✅ OK - means "income above 100% FPG"
fee_level = 1 + ... # ✅ OK - fee levels start at 1
```

3. **Structural constants** from external systems:
```python
min_(size, 12) # ✅ OK - FPG tables only go to 12 people
range(1, 13) # ✅ OK - 12 months in a year
```

4. **Derived from parameter structure**:
```python
num_children - 2 # ✅ OK - reflects parameter structure (first, second, additional)
```

5. **Period conversions** (use framework constants):
```python
/ MONTHS_IN_YEAR # ✅ CORRECT - use framework constant
* MONTHS_IN_YEAR # ✅ CORRECT - use framework constant
/ 12 # ❌ HARD-CODED - use MONTHS_IN_YEAR instead
* 12 # ❌ HARD-CODED - use MONTHS_IN_YEAR instead
```
Note: MONTHS_IN_YEAR is imported from model_api

6. **Comparisons and zero-checks**:
```python
== 0, > 0, >= 1, == 1, == 2 # ✅ OK
max_(0, value) # ✅ OK - prevent negative
```

**Problematic Hard-Coded Values (DO Flag):**

1. **Policy-specific thresholds** that could change:
```python
if income < 50000: # ❌ Should be parameter
```

2. **Percentages/rates** from regulations:
```python
benefit = income * 0.65 # ❌ Should be parameter
```

3. **Age limits** specific to programs:
```python
if age < 18: # ❌ Should be parameter (unless universal definition)
```

4. **Benefit amounts**:
```python
return 1000 # ❌ Should be parameter
```

**When in Doubt:**
- If the value appears in regulations → parameter
- If the value could differ across states → parameter
- If it's a mathematical constant or structural limit → OK to hard-code
- If it's needed to bootstrap parameter access → OK to hard-code

### 4. Reference Validation

Expand Down Expand Up @@ -169,6 +215,49 @@ child_age = p.child_age_limit
elderly_age = p.elderly_age_limit
```

### 9. Vectorization Rules

**IMPORTANT: `if` statements are context-dependent**

`if` statements are **FINE** for scalar values:
- ✅ Period attributes: `if period.start.month >= 10:`
- ✅ Parameter values: `if parameters(period).threshold > 0:`
- ✅ Scalar calculations: `if year >= 2024:`

`if` statements are **PROBLEMATIC** for vectorized arrays:
- ❌ Person/household data: `if income > 1000:` (use `where(income > 1000, ...)`)
- ❌ Array checks: `if income.any():` (prevents vectorization)
- ❌ Conditional on arrays: `if eligible:` where `eligible` is an array

**Correct Pattern:**
```python
# BAD - if on vectorized data
def formula(person, period, parameters):
income = person("income", period)
if income > 10000: # ❌ income is an array!
return 100
else:
return 0

# GOOD - where() for vectorized data
def formula(person, period, parameters):
income = person("income", period)
return where(income > 10000, 100, 0) # ✅

# ALSO GOOD - if on scalar period data
def formula(person, period, parameters):
month = period.start.month # scalar value
if month >= 10: # ✅ month is a scalar!
param = parameters(f"{year}-10-01")
else:
param = parameters(f"{year-1}-10-01")
```

**When Validating:**
- Don't flag `if` statements on `period.start.*`, `year`, `month`, or parameter values
- DO flag `if` statements on person/household/entity calculations
- Look for context: is the value being tested a scalar or an array?

## Validation Process

1. **Scan all changed files** in the PR
Expand Down
Loading