Skip to content

Date the NY Drive Clean rebate change July 1, 2021 and reject impossible parameter dates - #9935

Merged
MaxGhenis merged 4 commits into
mainfrom
ny-drive-clean-effective-date
Oct 11, 2026
Merged

MaxGhenis merged 4 commits into
mainfrom
ny-drive-clean-effective-date

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Summary

gov.states.ny.nyserda.drive_clean.amount dated two of its July 2021 amount changes 2021-06-31, which is not a day. Core compares instants as strings, and INSTANT_PATTERN accepts day 31 in any month, so the date loaded without error. test_parameter_scale_thresholds.py skipped every instant date.fromisoformat could not parse, with a comment naming this one.

The source is the NYSERDA Drive Clean Implementation Manual, "Last Updated: June 30, 2021", §4, page 8. It gives one table for "Eligible Vehicles Purchased On or Before June 30, 2021" and another for those "Purchased After June 30, 2021", so the new amounts start on July 1, 2021. The same provision's other two changes were dated 2021-06-30, one day early: the 20–39 mile amount ($1,100 → $500) and the MSRP cap for the flat rebate ($60,000 → $42,000). All four now start on 2021-07-01.

Range (miles) On or before 2021-06-30 From 2021-07-01
< 20 $500 $500
20–39 $1,100 $500
40–119 $1,700 $1,000
120–199 $2,000 $1,000
≥ 200 $2,000 $2,000
MSRP cap for the flat $500 $60,000 $42,000

Guard

  • The parse-failure skip in test_parameter_scale_thresholds.py is gone. The comparison with Core's public scale lookup now skips only the documented 0000-01-01 "since the beginning of time" sentinel, which that lookup cannot parse (see tests/code_health/test_uprating_placement.py). The duplicate-threshold scan itself still checks every instant string, including the sentinel.
  • New test_parameter_instants_are_calendar_dates: every instant of every loaded parameter must be a real YYYY-MM-DD day, with 0000-01-01 the only exception. A unit case checks that it accepts 2024-02-29 and the sentinel, and rejects 2021-06-31, 2025-02-29 and 2025-04-31, as well as partial or compact forms ("2021", "2021-06", "20210630", "2021-W26-3").
  • New tests/test_ny_drive_clean_rebate_schedule.py checks the schedule and the MSRP cap at 2021-06-30 and 2021-07-01. Calendar-year periods read parameters on January 1. Rolling-year YAML periods can exercise first-of-month starts such as year:2021-06-01 and year:2021-07-01, now covered here. In the specified interpreter, Core 3.32.15 rejects caching year:2021-06-30 because its string form loses the day (see the storage guard and Core #526); the attempted June 30 YAML cases failed before entering the rebate formula. The Python tests therefore retain exact June 30/July 1 public parameter lookups and randomized schedule invariants.

Review round 2

Corrected the blanket claim that YAML cannot exercise mid-year starts. Reproducing the reviewer's exact June 30 YAML scenario instead exposed Core 3.32.15's explicit mid-month cache rejection; the preserved run has three cache errors and 16 passing cases. Added supported June 1/July 1 formula coverage of the old/new schedules and retained exact June 30/July 1 parameter regressions. Added Hypothesis properties for real calendar dates, the sole year-zero sentinel, noncanonical date rejection, the July 1 schedule transition, and January 1 schedule stability. No policy formula or parameter value changes in this round. The independent review's two P2 landing gates were the hub's: the Axiom line and measured impact, both now below.

Tests (fail before, pass after)

The specified interpreter uses Core 3.32.15, Python 3.13.9, pytest 9.1.1, and Hypothesis 6.168.5. All runs are single-file, foreground, and sequential. The pass-after tree is committed at 1480bbf54c81e676dfe22dea7e8e1fd375589a8e.

  • Original-parameter replay: on the verified PR tree, replaced only amount.yaml and flat_rebate/msrp_threshold.yaml with their merge-base (6b80a8e4476d4c49900060ab58e0ac2cf96815c0) versions. The attempted June 30/July 1 YAML file collected 19 cases: 16 passed; three June 30 cases failed at Core's cache guard before the rebate formula. Full elapsed time was 1,328.94 seconds; this is runtime evidence against the reviewer's June 30 YAML claim, not a rebate-output regression.
  • Isolated public-parameter/date-guard replay against that same original subtree: three failed, two passed. Failures expose both June 31 keys, June 30's $500 instead of $1,100 20-mile amount, and $42,000 instead of $60,000 MSRP cap. This evidence loads the actual YAML through Core and extracts the actual guard helpers via AST; it does not initialize the full country model or modify cache behavior. The two parameter files were then restored from the verified PR head before pass-after runs.
  • The same isolated checks with the corrected PR parameters: five passed (18.58 seconds of pytest runtime). Full country-model pass-after runs: test_ny_drive_clean_rebate_schedule.py four passed, 474.38 seconds full elapsed time and 830,832,640 bytes peak RSS. test_parameter_scale_thresholds.py 12 passed, 383.13 seconds full elapsed time and 827,277,312 bytes peak RSS. The supported June 1/July 1 YAML file 19 passed (108.02 seconds of pytest runtime, 1,155.48 seconds full elapsed time, exit 0). Total: 35 tracked tests passed, plus the five isolated regression checks.
  • A diagnostic-only YAML attempt exited 139 before collection after 1,084.45 seconds. Its macOS crash report identifies dump_frame in faulthandler_thread as the faulting stack; the periodic traceback hook was removed for the successful retry. No peak RSS was captured for that clean YAML run. This was a diagnostic process crash, not a rebate assertion failure.

The added Python checks reuse the existing read-only country system; no repeated full model setup was added within either file. They stay in the existing Rest remaining group (repository CI estimate: 239 seconds for that group in run 37198184683); the YAML cases stay in the NY state suite. These local elapsed-time and memory measurements are separate from Linux CI timing. A successful pre-round full-file timing is unavailable: the reviewer interrupted the original schedule run during loading. The head measurements therefore do not establish a measured test-overhead delta. macOS /usr/bin/time -l could not report peak memory for the original YAML attempt because the sandbox denied sysctl kern.clockrate; later runs use a diagnostic-only startup hook with resource.getrusage and periodic stack snapshots. No CI runner or concurrency changes.

Invariants

  • Every loaded parameter instant, including scale bracket children, must be a real canonical YYYY-MM-DD Gregorian date, except exactly 0000-01-01. Hypothesis uses calendar.monthrange as an independent day-count oracle, generates valid dates and noncanonical forms, and checks that no other year-zero instant is exempt.
  • The documented Drive Clean schedule and MSRP cap switch together on July 1, 2021: dates through June 30 retain the old values; dates from July 1 use the new values. Hypothesis samples dates on both sides, with explicit boundary examples, against the manual's tables.
  • January 1 lookups retain the old schedule through 2021 and the new schedule from 2022. A generated-year property checks this calendar-year invariant; it is analytical/unit evidence, not a microsimulation measurement.

Methodology

Retain the existing annual period-start convention; the alternative is modeling the actual purchase date, which this PR does not introduce. The manual resolves the effective date unambiguously as July 1. Relative to main, June 30 parameter lookups change to the pre-July amounts/cap; January 1 and supported first-of-month formula calculations retain their existing values. Current Core prevents executing June 30 rolling-year calculations, so this PR does not bypass its cache guard. The pre-existing 119-mile threshold and exact-cap comparison remain disclosed follow-ups below.

Hub microsimulation impact (current head)

A real microsimulation on the default dataset, main at the merge base 6b80a8e447 against this PR's head 1480bbf54c, for 2025 and 2026. The runs went one at a time under the shared heavy-job lock. Sums are weighted.

Output 2025 change 2026 change 2025 records changed (weighted) 2026 records changed (weighted)
ny_drive_clean_rebate +0 +0 0 (0) 0 (0)
state_income_tax +0 +0 0 (0) 0 (0)
income_tax +0 +0 0 (0) 0 (0)
household_net_income +0 +0 0 (0) 0 (0)
household_benefits +0 +0 0 (0) 0 (0)

No record changes in either year, measured at the exact head against its merge base.

Comparison files are in fixes/9935-impact/ on the hub host.

Impact

Analytically, the changed instants fall between June 30 and July 1, so calendar-year calculations read the same values on January 1 before and after the PR. The hub's measured run above confirms it: no record changes in 2025 or 2026. The June 30 schedule lookup changes the 20-mile amount from $500 to $1,100 and restores the MSRP cap from $42,000 to $60,000. By the manual's table and the retained formula, those corrected values imply $1,100 for a 20-mile/$30,000 vehicle and $2,000 for a 200-mile/$50,000 vehicle; these are source-based expectations, not executed mid-month simulation results, because current Core rejects that period. On July 1 both vehicles receive $500 in the supported formula tests.

Follow-ups split out

Checking the manual turned up three more mismatches in this program, left for a separate PR:

  • the "120–199 miles" bracket's threshold is 119, so a 119-mile vehicle got $2,000 before July 2021 instead of $1,700;
  • the flat rebate uses >= where the manual says MSRP "over" the cap;
  • the rate_unit / threshold_unit labels are swapped, and the MSRP cap's unit is miles.

Parity issue for the NYSERDA Drive Clean Rebate Program Implementation Manual §4 (pe-parity; dispatch-ready):

axiom: TheAxiomFoundation/rulespec-us#1639 queued

The signed encoder is blocked: the manual is not yet in axiom-corpus (manifests/policyengine-source-coverage.yaml lists it under us-ny-manuals with coverage_status: not_started), and the issue records that blocker.

Independent review: review-r1 requested changes; the YAML coverage/documentation finding is addressed in round 2. Round 2 found no code defect; the hub then supplied the Axiom line and the measured impact.

🤖 Generated with Claude Code

MaxGhenis and others added 4 commits October 6, 2026 16:52
…dates

The NYSERDA Drive Clean Implementation Manual (last updated June 30,
2021, section 4) gives one rebate table for vehicles purchased on or
before June 30, 2021 and another for vehicles purchased after it. The
parameters dated two of the new amounts 2021-06-31, which is not a day,
and the other new amount and the $42,000 MSRP cap 2021-06-30, one day
early. All four now start on 2021-07-01.

Core compares instants as strings and its INSTANT_PATTERN accepts day 31
in any month, so the impossible date loaded without error, and the
duplicate-threshold test skipped it by name. That exception is gone: a
new test requires every parameter instant to be a calendar date, with
the documented 0000-01-01 sentinel as the only exception.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review note: the old check in this file skipped every instant that
date.fromisoformat could not parse (a comment named the Drive Clean
dates), rather than skipping those dates by name as the previous commit
message said. The new check's YYYY-MM-DD pattern now has direct cases:
"2021" and "2021-06" (which core's INSTANT_PATTERN accepts) and
"20210630" and "2021-W26-3" (which date.fromisoformat accepts).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Reopened by the US + core hub to start a fresh CI run at the same head. The previous run failed on test_spm_system.py, which broke on every pull request when policyengine-core 3.33.1 was released; #10069 fixed it on main at 20:42Z on 2026-10-10. Nothing in this pull request changed.

@MaxGhenis
MaxGhenis merged commit a844fc1 into main Oct 11, 2026
51 of 52 checks passed
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

US + core hub merge audit, us#9935 at 1480bbf54c81e676dfe22dea7e8e1fd375589a8e (squash): Date the NY Drive Clean rebate change July 1, 2021 and reject impossible parameter dates.

  • Review: independent GPT-6.1 Sol review approves this exact head, with no findings and no methodology choice (reviews-gen/us-9935/review-r4.md). Round 2 found no code defect (hand recomputation matches NYSERDA's manual); rounds 2-3 asked only for the hub gates, which the hub supplied.
  • Impact: a hub microsimulation on the default dataset for 2025 and 2026, merge base 6b80a8e447 against this head: no record changes in either year (the corrected dates fall between June 30 and July 1; calendar-year runs read January 1 values). See the body's "Hub microsimulation impact (current head)" section.
  • Gates checked live at merge:
    • gh pr checks exits 0;
    • the latest Pull request run at the head concluded success;
    • MERGEABLE, not a draft, no CHANGES_REQUESTED;
    • the semantic-overlap guard;
    • head pinned.
  • Axiom: rulespec-us#1639 queued (OPEN, pe-parity, checked live 2026-10-11).
  • Follow-ups (in the body): the 119-mile bracket threshold, the >= MSRP comparison, swapped unit labels.
  • --admin: used only because a required approving review is the sole block.

@MaxGhenis
MaxGhenis deleted the ny-drive-clean-effective-date branch October 11, 2026 12:34
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.

1 participant