Skip to content

feat(clergy): file the housing allowance excess, ministerial SE earnings and Form 4361 boxes from sourced W-2 rows - #173

Merged
a7ul merged 1 commit into
filedcom:mainfrom
bhailey55-alt:clergy-source-backed
Oct 31, 2026
Merged

a7ul merged 1 commit into
filedcom:mainfrom
bhailey55-alt:clergy-source-backed

Conversation

@bhailey55-alt

Copy link
Copy Markdown
Contributor

Problem

#56 replaced the clergy node with a stub that throws for every entry: its
input named no W-2, employer, minister or advance designation, so it could not
tell an allowance already left out of W-2 box 1 from taxable excess, or check
Form 4361. A minister's return cannot be prepared at all today.

Evidence model

One strict row per church W-2 (forms/f1040/nodes/inputs/income/wages/clergy),
patterned on f2106:

  • minister: owner (taxpayer | spouse), name, SSN, credential
    (ordained, commissioned or licensed), ordained_commissioned_or_licensed_confirmed: true,
    ministerial_services_confirmed: true, credential_reference.
  • employer: church name, EIN, w2_reference (the entered W-2's
    source_document_reference); ministerial_wages equals that W-2's box 1.
  • housing_allowance (optional): included_in_w2_box1; designation
    (amount, designated_on no later than effective_from, both by the end of
    the year, designation_reference); paid (amount, record,
    paid_after_designation_confirmed: true); actual_housing_expenses (amount,
    record); fair_rental_value (furnished plus utilities, confirmation, record);
    not_more_than_reasonable_pay_confirmed: true.
  • parsonage (fair rental value plus utilities, record,
    not_more_than_reasonable_pay_confirmed: true),
    unreimbursed_ministerial_expenses (amount, not_reimbursed_confirmed: true,
    record), form4361 (approved: false, or true with approved_on and
    approval_reference), tax_year.

Reasonable pay is attested, not computed. Pub 517 (2025) limits the rental
allowance exclusion to an amount that "isn't more than reasonable pay for your
services" and says of a parsonage that "the exclusion can't be more than the
reasonable pay for your services". The engine cannot judge that, so both
objects require not_more_than_reasonable_pay_confirmed: true, in the same
literal-attestation pattern as the other confirmations.

The start node passes the general filer identity and entered W-2s as context
fields, as it already passes owner_identity, filing_status and
owner_birth_dates to other input nodes. The node fails closed unless each
row matches the return's taxpayer or joint spouse and exactly one W-2 with the
same SSN, EIN, employer name, reference and box 1, no statutory-employee box
and no box 3 or box 5 wages (a minister's earnings are not covered under FICA:
Pub 517, Table 1), and unless all rows for one minister agree on Form 4361
approval. The minister's name is compared after ignoring case, periods,
commas, extra spaces, leading titles (Rev., Reverend, Pastor, Dr., Fr.) and
trailing suffixes (Jr., Sr., II, III, IV); every other word must match the
return's first, optional middle initial and last name. Doing this in the node
gives a calculation diagnostic for a mismatched W-2 and validates the owner
(taxpayer or spouse) before any Schedule SE row is created. At export,
domains/income/wages/clergy/clergy_source.ts reconciles the retained rows
again against the retained general and W-2 sources, the finalized Schedule SE
rows and Schedule 2, as form2106_staged.ts does for Form 2106. If you would
rather keep reconciliation export-only, as Form 2106 does, say so and I will
move it.

Calculation and routing

  • Excludable allowance = smallest of designated, paid, used and fair rental
    value (IRC §107(2)). The excess goes to f1040 and agi_aggregator
    line1h_other_earned (Pub 517: "Include this amount in the total on Form
    1040 or 1040-SR, line 1h. On the dotted line next to line 1h, enter 'Excess
    allowance'"). A parsonage needs no income adjustment (§107(1)).
  • Without Form 4361: wages + whole allowance paid + parsonage value − expenses
    in full (Pub 517, "Figuring Net Earnings", "Allowable deductions" and
    "Expenses Allocable to Tax-Free Income"; i1040sse 2025, Ministers) go to
    schedule_se.ministerial_sources, one owned, referenced row per W-2; a bare
    amount is not taken (the existing "unsourced ministerial loss" test still
    passes). Schedule SE adds them to line 2, per spouse on a joint return
    (kind: "ministerial" owner rows), and a loss reduces other line 2 earnings
    (i1040sse, More Than One Business). With an approved Form 4361,
    unreimbursed expenses are ignored rather than rejected.
  • QBI, Form 7206 and Schedule 1-A receive no SE deduction from ministerial
    earnings, which are pay for services, not a trade or business. When
    ministerial earnings sit beside Schedule C, Schedule F or partnership
    earnings, schedule_se sends those consumers the line 13 figured on the
    business earnings alone (businessLine13, and business in the owned
    branch). That split is provisional and reachable only in tests, because
    export refuses every such return (below). The part an exportable route needs
    is narrower: with ministerial earnings only, nothing reaches QBI or
    Schedule 1-A, and Form 7206 sees no SE deduction (test "sourced ministerial
    earnings alone are Schedule SE line 2"). Dropping the split would send a
    pastor's ministerial SE deduction to QBI on that route, so it stays, marked
    provisional in the code.
  • An allowance inside W-2 box 1 fails closed and asks for a W-2c: there is no
    IRS-instructed way to subtract it from reported wages, and the engine has no
    negative line 8z route.

Filing

Item MeF (TY2025) PDF (2025 AcroForm)
Line 1h excess OtherEarnedIncomeAmt → WagesNotShownSchedule, OtherWagesNotShownTxt EXCESS ALLOWANCE type "EXCESS ALLOWANCE" (f1_54)
Schedule SE line 2 NetNonFarmProfitLossAmt includes ministerial earnings f1_5
Line 2 explanation, only when expenses are subtracted (i1040sse 2025, Ministers: "subtract on line 2 the allowable expenses ... and attach an explanation"; Pub 517, "Allowable deductions") AllowableSEExpenseExplnStmt, referenced from the IRS1040ScheduleSE root page after Schedule SE
Schedule SE line A (4361 + $400 other SE) ExemptForm4361Ind, first element after SSN c1_1
Schedule 2 line 4 box 1 (4361, no other SE income) ExemptForm4361Ind Line4_ReadOrder.c1_3
Form 1040 line 27b ClergyMemberInd, between EarnedIncomeCreditAmt and DoNotClaimEICInd c2_12

clergy leaves the attachment-coverage blocklist only for rows that parse,
reconcile to their context and keep the allowance out of box 1.

Still fail-closed (named errors)

  • Allowance in W-2 box 1; W-2 mismatch or FICA wages on the church W-2;
    missing evidence, including the reasonable-pay attestation; rows for one
    minister disagreeing on Form 4361; spouse minister on a non-joint return;
    wrong-year row.
  • Ministerial earnings beside any Schedule C, Schedule F or partnership SE
    earnings on the return, including a spouse's.
    The joint Schedule SE
    already keeps each spouse's earnings on their own schedule (tested at the
    node, export-guard and end-to-end levels), but the export guards that replay
    the owner Schedule SE sources for Form 8995 (joint owner), Form 8995-A,
    Schedule 1-A and Form 7206 would see the ministerial rows as businesses and
    are not ministerial-aware. A pastor whose spouse has a Schedule C is
    therefore still refused.
  • Form 4361 with other SE earnings under $400, or with no other SE income
    beside another person's Schedule SE, such as a spouse's. The 2025 Schedule
    SE instructions say to check box 1 "if you had no other income subject to SE
    tax"; whether a joint return checks it beside the other spouse's SE tax was
    not confirmed.
  • Any EIC, and ACTC beside ministerial SE earnings: the clergy earned-income
    rules (EIC worksheet, Schedule 8812) are not modeled.
  • A Schedule C marked clergy_schedule_c (fees and honoraria).
  • Line 1h mixed with another line 1h source.
  • TY2026 PDF Schedule 2 Form 4361 box (draft widget not mapped).

Planned follow-up

I plan a follow-up PR for the most common blocks above, which share the same plumbing:

  • Ministerial Schedule C: fees for weddings, funerals, guest preaching and conferences, and itinerant ministers paid only on 1099s. SE treatment follows the minister's Form 4361 status; the income-tax Deason allocation of Schedule C expenses applies; QBI treatment is settled explicitly.
  • Ministry earnings alongside other SE income: the minister's own non-ministerial Schedule C, a Schedule F farm, partnership SE income, or a spouse's SE income. Each Schedule SE already computes; the follow-up teaches the QBI (8995/8995-A), Schedule 1-A and Form 7206 routes to treat ministerial earnings correctly, and settles the joint-return Schedule 2 line 4 presentation for a Form 4361 minister whose spouse owes SE tax.

Keeping it separate should make this PR easier to review.

Known limitations, not blocked

  • Form 2441, IRA and SEP compensation and Form 7206 are computed without the
    clergy earned-income rules: ministerial SE earnings are not added to their
    earned income or compensation. ministerial_sources reach only
    schedule_se, which passes Form 7206 the business earnings alone; Form 2441
    and the IRA/SEP limits never see them. How far that departs from the clergy
    rules has not been worked out.

TY2026

Same shared nodes and builders, year from ctx.taxYear. Tested: calculation,
MeF build and local business rules for the excess/Schedule SE/explanation
return and the Form 4361 return; Form 1040 and Schedule SE PDF projections on
the 2026 drafts. Not verified: element names against the 2026v1.0 XSD.

Tests

  • clergy/index.test.ts (19): every evidence path fails when missing,
    including the reasonable-pay attestation on the allowance and the parsonage;
    the designation date rule; each §107(2) limit; spending above the
    designation; box-1 refusal; parsonage; full-allowance SE base; expenses to a
    loss; 4361 (expenses ignored); two churches; Form 4361 disagreement across
    one minister's W-2s (spouses may differ); names with titles and suffixes;
    each W-2 mismatch; owner/spouse/year checks.
  • schedule_se/index.test.ts (+5): ministerial-only line 2, loss against
    Schedule C, no QBI reduction, repeated reference, joint spouse instance.
  • clergy_source.test.ts (8): export facts, explanation only with expenses,
    refusals (drift, EIC/ACTC, clergy Schedule C, route support), and both
    spouse cases refused with per-spouse Schedule SE amounts checked.
  • e2e/income/clergy/clergy_source_route.test.ts (12, plus 1 XSD test that
    skips without irs/): executeReturn → MeF XML, business rules and PDF
    projections for each route above, the explanation statement and its PDF page
    only when expenses are subtracted, both spouse refusals, and TY2026.
  • PDF field tests (+3).

Synthetic regression: single, church W-2 50,000, allowance designated and paid
24,000, used 20,000, fair rental value 22,000: line 1h 4,000; Schedule SE line
2 74,000, line 12 10,456; AGI 48,772 (base: clergy node threw). Fixture names
are synthetic ("Alex Example", "Example Community Church").

Verified

  • Full suite under Bun 1.4.4, every test file run separately, main 3add1ba vs
    this branch: 11,446 → 11,490 passing (+44, all in the files above),
    1,534 → 1,534 failing (the identical set), 303 → 304 skipped. No test that
    passes on main fails or disappears here. The failures come from the
    authoring environment: no network to irs.gov for fixtures that download IRS
    PDFs, and irs/ not installed.
  • On a networked macOS machine (Bun 1.4.4, IRS PDFs downloaded, irs/ not
    installed): bun run verify:changed 3add1ba7 passed. test:unit --changed
    ok; test:forms --changed 5,510 form tests, 30 failing, 0 outside
    forms-failure-baseline.json; check:mef 374 sample returns, 373 ready to
    file, 0 problems; check:cli 18 returns, 0 problems; bench 87 failing
    (base 87). check:ty2026 0 problems. The patch also applies cleanly to
    current main (25884d9).
  • The 137 TY2025 benchmark inputs run through executeReturn give identical
    pending output and diagnostics on main and here.
  • check:structure, check:cases, check:oracle, check:sandbox and
    check:irs pass; oxlint reports 0 errors and the same 238 warnings as
    main, none in the changed files.
  • Per-file TypeScript semantic diagnostics: 0 errors in all 30 changed .ts
    files. Whole-program tsc --project tsconfig.json ran out of heap at 8 GB on
    the authoring machine (not compared against main there); the type check in
    verify:changed's unit gate passed.
  • MeF names, order and attributes against public copies of the 2025v5.2
    schemas
    (Final Release, February 19, 2026): IRS1040ScheduleSE.xsd
    (ExemptForm4361Ind first after SSN; only the root carries
    referenceDocumentId/referenceDocumentName, fixed to
    AllowableSEExpenseExplanationStatement; NetNonFarmProfitLossAmt has no
    attributes), IRS1040.xsd (ClergyMemberInd between
    EarnedIncomeCreditAmt and DoNotClaimEICInd; OtherEarnedIncomeAmt
    references WagesNotShownSchedule) and IRS1040Schedule2.xsd
    (ExemptForm4361Ind after AdditionalTaxAmt).
  • Pub 517 (2025) quotes re-checked on irs.gov for this revision (rental
    allowances and parsonage reasonable pay, Allowable deductions, Excess rental
    allowance, Required statement); a reviewer also checked the 2025 edition.
    The 2025 Schedule SE instructions' Form 4361 text was checked directly.

Not verified, and why

  • The output has not been validated against 2025v5.4 or 2026v1.0. Please
    run the skipped test "E2E clergy returns validate against the TY2025 MeF
    XSD" (forms/f1040/e2e/income/clergy/clergy_source_route.test.ts) with your
    team copy of irs/; it covers the excess/Schedule SE return, both Form 4361
    presentations and the explanation statement.
  • No public TY2025 copy of ReturnData1040.xsd, WagesNotShownSchedule.xsd
    or AllowableSEExpenseExplanationStatement.xsd was found.
    AllowableSEExpenseExplnStmt is placed after PostponementCropInsDsstrStmt
    as in the TY2018 ReturnData1040.xsd (maxOccurs 2 there). The TY2018
    WagesNotShownSchedule required WagesLiteralCd, whose list included
    EXCESS ALLOWANCE; the IRS TY2025 stylesheet shows a choice of
    WagesLiteralCd or OtherWagesNotShownTxt, so the free-text element is
    used. If the 2025 list still has EXCESS ALLOWANCE, switching to the code is
    a one-line change in foreign_employer_wages.ts.
  • Business rules: the repository's rules, generated from
    1040_Business_Rules_2025v3.0.csv, have 8 SSE rules, all implemented, and
    none requires a Schedule C or K-1 when Schedule SE line 2 is nonzero; the
    e2e returns pass them. Later rule releases were not available here and could
    conflict, for example a rule tying a nonzero line 2 to Schedule C or K-1.
  • bun run test:unit / whole-program tsc: the environment has 4 GB and the
    whole program does not fit; see the per-file check above.
  • check:mef, check:ty2026, check:cli, bench: their fixtures fetch IRS
    PDFs, which this environment cannot reach.
  • Filled PDF pages were not rendered. Checkbox names come from published
    TY2025 AcroForm field listings (Schedule SE c1_1, Schedule 2
    Line4_ReadOrder[0].c1_3, Form 1040 c2_12); the explanation page is
    tested only for being appended.
  • ATS.

Review notes

  • The export guard is not cached per export: like assertOwnedScheduleSE and
    form2106_staged, it recomputes in each builder, and a cache keyed on the
    mutable pending object could hide in-place drift.

References

…ngs and Form 4361 boxes from sourced W-2 rows
@a7ul
a7ul merged commit 8f724d4 into filedcom:main Oct 31, 2026
1 check passed
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.

2 participants