Skip to content

Declare the Kentucky tuition tax credit eligibility flag as a boolean - #10105

Merged
MaxGhenis merged 1 commit into
mainfrom
ky-tuition-eligible-bool
Oct 12, 2026
Merged

MaxGhenis merged 1 commit into
mainfrom
ky-tuition-eligible-bool

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Defect

ky_tuition_tax_credit_eligible is an eligibility flag. Its label is "Eligible for the Kentucky tuition tax credit", and its formula returns a boolean, filing_status != filing_status.possible_values.SEPARATE. But it was declared value_type = float with unit = USD, so API and app metadata presented it as a dollar amount.

Change

  • value_type = float becomes value_type = bool, and unit = USD is removed. The formula is unchanged. This matches the other Kentucky eligibility flags (ky_ccap_eligible, ky_ktap_eligible, ky_ccap_income_eligible, and so on).
  • changelog.d/ky-tuition-eligible-bool.fixed.md.

Readers

git grep ky_tuition_tax_credit_eligible at the head finds these:

Reader Use
ky_tuition_tax_credit.py:13 defined_for
ky_tuition_tax_credit_potential.py:10 defined_for
ky_tuition_tax_credit_eligible.yaml (2 cases), ky_tuition_tax_credit.yaml (2), ky_non_refundable_credit_order.yaml (1) YAML input or expected output, written as true/false

Nothing does arithmetic on the flag, sums it, or reads it as a number.

policyengine-core builds the defined_for mask as calculate(defined_for, period, map_to=entity) > 0. That holds in the version uv.lock pins (3.32.8, simulations/simulation.py:847) and in the latest tag (3.33.2, line 1722). So True/False give the same mask as 1.0/0.0. Core 3.33's registration check (Variable.check_defined_for_variable) accepts only NUMERIC_VALUE_TYPES = (bool, int, float) as a defined_for target, and bool is in that list. All three variables are TaxUnit-level. The default changes from 0.0 to False, and both are falsy.

Tests

Each file below was run in its own process, in the foreground at nice 0, at head 350c61c. All passed.

File (under tests/policy/baseline/gov/states/ky/tax/income/) Cases
credits/tuition_tax/ky_tuition_tax_credit_eligible.yaml 2 passed
credits/tuition_tax/ky_tuition_tax_credit.yaml 2 passed
credits/ky_non_refundable_credit_order.yaml 1 passed
ky_filing_status.yaml 3 passed
integration.yaml 25 passed
credits/dependent_care_credit/ky_cdcc.yaml 3 passed

No test expectations changed. YAML true/false inputs already matched a bool.

Invariants (stated and executed)

For every tax unit:

  • D1 The branch flag equals (main's flag > 0), and main's flag is always 0 or 1.
  • D2 Every downstream output is identical under the two declarations: ky_tuition_tax_credit_potential, ky_tuition_tax_credit, ky_non_refundable_credits, ky_files_separately, ky_income_tax, state_income_tax and household_net_income.
  • D3 The branch flag has dtype bool, with metadata value_type bool and no unit. In the comparison system, the main declaration really is float with currency-USD.

The script builds the branch system and a comparison system that swaps main's declaration back in, verbatim, with replace_variable. Units that supply ky_filing_status and units that compute it run in separate simulations. (When some tax units supply an input, core treats the variable as an input for the whole array, and the rest get the default.) It checks D1 to D3 in two ways:

Run Tax units Result
Exhaustive grid: KY and TN; single or married; head and spouse separated or not; no dependent, or a dependent aged 6 or 18, separated or not; wages 0, 30k or 120k; AOC/LLC inputs (0/0, 2,500/0, 0/2,000, 1,500/1,000); ky_filing_status supplied as Single, Joint or Separate, or computed 2,880: 1,440 KY, 2,160 supplied, 720 computed PASS. 792 eligible, 2,088 ineligible (all 1,440 TN units and 648 KY units); 396 with a positive tuition credit. The 360 computed KY units span every status: Separate 288, Joint 48, Single 24.
Hypothesis: 40 derandomized batches of 1 to 12 units (KY or OH, wages 0 to 400k, AOC 0 to 2,500, LLC 0 to 2,000, dependents aged 3 to 70, status supplied or computed) 236 PASS
Power check: a mutant main declaration with the same metadata and a formula that makes everyone eligible, on 24 KY units with a supplied Separate status 24 Caught (D1 fails)

The computed statuses come from main's role inference and spouse rules, which this PR does not touch. With no roles given, an 18-year-old becomes the inferred spouse. A separated dependent drops a married couple's spouse, which is the defect #9932 fixes.

This check is not in CI: the repo keeps policy cases in YAML and keeps model-building Python tests out of CI. Script, log and power check: ~/reviews/ky-tuition-eligible-bool/differential.py, differential.log, mutation_check.py, mutation.log, all at head 350c61c.

Interaction with #9924

#9924 (open draft) edits the same file: it adds a KRS 141.069(4) reference and rewrites the comment. git merge-tree --write-tree with #9924's head 591b05c is clean in both orders and gives the same tree (34a597526b). The merged file has value_type = bool, no unit, and #9924's reference and comment. The two PRs can merge in either order.

Independent review

GPT-6.1 Sol (Subfleet review, hard tier) reviewed head 350c61c: APPROVE, no findings. It checked:

Its sandbox had only read tools. It read the files and #9924's public diff and worked through the merge by hand, without running git or tests. The test logs and merge-tree results above come from the author's own runs. Review: ~/reviews/ky-tuition-eligible-bool/review-r1.md.

Impact

None on any computed amount: this is a metadata change. The flag's values are unchanged, only its type, and the differential check above shows every downstream Kentucky output is identical.

axiom: n/a: variable metadata only (no policy change)

🤖 Generated with Claude Code

The variable is an eligibility flag whose formula returns
filing_status != SEPARATE, but it was declared value_type = float with
unit = USD, so API and app metadata presented it as a dollar amount.
Its only readers are the defined_for of ky_tuition_tax_credit and
ky_tuition_tax_credit_potential (core masks with > 0, so True/False
behave as 1.0/0.0 did) and YAML inputs; nothing does arithmetic on it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis
MaxGhenis marked this pull request as ready for review October 11, 2026 18:34
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Hand-off to the US + core hub.

  • Head: 350c61c9939a9bd6844e741d8b517afd7d4d150f. Not a draft; marked ready 2026-10-11 18:34Z.
  • Independent review: GPT-6.1 Sol (Subfleet review, hard tier, job 20261011-130605-pe-us-10105-review) gave APPROVE with no findings at this head. Verdict: ~/reviews/ky-tuition-eligible-bool/review-r1.md.
  • Passed locally at this head: the six Kentucky YAML files, each in its own process (36 cases: 2 + 2 + 1 + 3 + 25 + 3). The main-vs-branch differential also passed (2,880 grid units + 236 Hypothesis units, all downstream KY outputs identical), and a mutant check was caught. Logs: ~/reviews/ky-tuition-eligible-bool/.
  • Pending: the full CI run started by the ready-for-review event (PR validation and the test jobs; run 38164374089).
  • Depends on: nothing. Kentucky filing status follows the filer's own marital status #9924 (open draft, head 591b05c) touches the same file, but git merge-tree is clean in both orders, so the PRs can merge in either order. The branch also merges cleanly with main as of 18:33Z.
  • Holds and decisions: none. Metadata only, no change to any computed amount (axiom: n/a).
  • Follow-ups owed: none.

@codecov

codecov Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (909176a) to head (350c61c).
⚠️ Report is 409 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main    #10105   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            4         1    -3     
  Lines           76        10   -66     
  Branches         2         0    -2     
=========================================
- Hits            76        10   -66     
Flag Coverage Δ
unittests 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@MaxGhenis MaxGhenis closed this Oct 11, 2026
@MaxGhenis MaxGhenis reopened this Oct 11, 2026
@MaxGhenis MaxGhenis closed this Oct 11, 2026
@MaxGhenis MaxGhenis reopened this Oct 11, 2026
@MaxGhenis
MaxGhenis merged commit 2a862b0 into main Oct 12, 2026
84 of 94 checks passed
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

US + core hub merge audit, us#10105 at 350c61c993 (squash): declare the Kentucky tuition tax credit eligibility flag as a boolean.

  • Review: independent GPT-6.1 Sol review APPROVE at this head, no findings.
  • 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 reviewer's latest review requests changes;
    • the semantic-overlap guard;
    • head pinned.
  • Impact: none. The change is variable metadata (the value type); no computed amount changes, and the description's differential shows identical results.
  • Axiom: n/a, as the description states (variable metadata only).

@MaxGhenis
MaxGhenis deleted the ky-tuition-eligible-bool branch October 12, 2026 12:10
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