Repository navigation
Date the NY Drive Clean rebate change July 1, 2021 and reject impossible parameter dates - #9935
Merged
Merged
Conversation
…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>
Contributor
Author
|
Reopened by the US + core hub to start a fresh CI run at the same head. The previous run failed on |
Contributor
Author
|
US + core hub merge audit, us#9935 at
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
gov.states.ny.nyserda.drive_clean.amountdated two of its July 2021 amount changes2021-06-31, which is not a day. Core compares instants as strings, andINSTANT_PATTERNaccepts day 31 in any month, so the date loaded without error.test_parameter_scale_thresholds.pyskipped every instantdate.fromisoformatcould 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 on2021-07-01.Guard
test_parameter_scale_thresholds.pyis gone. The comparison with Core's public scale lookup now skips only the documented0000-01-01"since the beginning of time" sentinel, which that lookup cannot parse (seetests/code_health/test_uprating_placement.py). The duplicate-threshold scan itself still checks every instant string, including the sentinel.test_parameter_instants_are_calendar_dates: every instant of every loaded parameter must be a realYYYY-MM-DDday, with0000-01-01the 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").tests/test_ny_drive_clean_rebate_schedule.pychecks 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 asyear:2021-06-01andyear:2021-07-01, now covered here. In the specified interpreter, Core 3.32.15 rejects cachingyear:2021-06-30because 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.amount.yamlandflat_rebate/msrp_threshold.yamlwith 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.test_ny_drive_clean_rebate_schedule.pyfour passed, 474.38 seconds full elapsed time and 830,832,640 bytes peak RSS.test_parameter_scale_thresholds.py12 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.dump_frameinfaulthandler_threadas 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
remaininggroup (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 -lcould not report peak memory for the original YAML attempt because the sandbox deniedsysctl kern.clockrate; later runs use a diagnostic-only startup hook withresource.getrusageand periodic stack snapshots. No CI runner or concurrency changes.Invariants
YYYY-MM-DDGregorian date, except exactly0000-01-01. Hypothesis usescalendar.monthrangeas an independent day-count oracle, generates valid dates and noncanonical forms, and checks that no other year-zero instant is exempt.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
6b80a8e447against this PR's head1480bbf54c, for 2025 and 2026. The runs went one at a time under the shared heavy-job lock. Sums are weighted.ny_drive_clean_rebatestate_income_taxincome_taxhousehold_net_incomehousehold_benefitsNo 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:
>=where the manual says MSRP "over" the cap;rate_unit/threshold_unitlabels are swapped, and the MSRP cap's unit ismiles.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.yamllists it underus-ny-manualswithcoverage_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