Skip to main content

Donation Receipt Generator rules: resolution of the 2026-09-25 adversarial reviews

  • Editor: Claude Fable 5.1 (rules editor; did not author any of the three reviews)
  • Date: 2026-09-25
  • Reviews resolved:
    • donation-receipts-2026-09-25-opus.md: 13 findings (C-1, M-1, M-2, m-1..m-10)
    • donation-receipts-2026-09-25-fable.md: 20 findings (R-01..R-20)
    • donation-receipts-2026-09-25-codex.md: 13 findings (DR-001..DR-013)
  • Files rewritten: sources/donation-receipts/rules.yaml (38 rules: 28 computed, 7 refer, 3 product; canonical schema; shared fixtures; 47 fields), test-cases.yaml (73 cases: CA 20 computed / 9 refer / 11 invalid; US 18 / 5 / 10), receipt-templates.md, open-questions.md. New: validate.py (spec checker, not app code).

Totals: 45 FIXED · 0 REJECTED · 1 REFER (46 findings).

Primary sources opened in this pass (24 WebFetch + Chrome + local PDF extraction)​

SourceURLWhat it established
Income Tax Regulations s.3501 (current to 2026-09-03)https://laws-lois.justice.gc.ca/eng/regulations/C.R.C.,_c._945/section-3501.htmlVerbatim chapeau, (1)(i), (2), (3), (3.1), (4), (5), (6). (3.1) = "another recipient of the gift" only.
CRA — Computer-generated receipts (2020-02-24)https://www.canada.ca/en/revenue-agency/services/charities-giving/charities/operating-a-registered-charity/issuing-receipts/computer-generated-receipts.htmlEvery signature/read-only/encryption sentence is "should"; "copies of email-issued receipts must be retained"; non-erasable media, off-site copies.
CRA — Books and records (2025-09-08)https://www.canada.ca/en/revenue-agency/services/charities-giving/charities/operating-a-registered-charity/books-records.htmlTwo years / six years / Canadian address / electronically readable / backup copy — verbatim for the retention notice.
CRA — Correcting or replacing receipts (2017-06-22)https://www.canada.ca/en/revenue-agency/services/charities-giving/charities/operating-a-registered-charity/issuing-receipts/correcting-replacing-official-donation-receipts.htmlFull page: "lost or contained incorrect information"; replacement contents; unsent receipts "keep both copies ... cancelled".
CRA — Split receipting (2018-05-22)https://www.canada.ca/en/revenue-agency/services/charities-giving/charities/operating-a-registered-charity/issuing-receipts/split-receipting.html"not more than $75 or 10% ... whichever is less"; "does not have to subtract"; mug + pen example; near-cash exclusion; 80% rule.
CRA — Sample official donation receipts (2021-12-01)https://www.canada.ca/en/revenue-agency/services/charities-giving/charities/sample-official-donation-receipts.html"Only the following organizations have registration numbers..."; field labels; title; "more than 80% of the cash gift, you cannot issue". Correct URL (the /issuing-receipts/ one is a 404).
CRA — What you need to know to issue a receipt (2018-11-02)https://www.canada.ca/en/revenue-agency/services/charities-giving/charities/operating-a-registered-charity/issuing-receipts/what-you-need-know-issue-official-donation-receipt.htmlTrue donor / intermediaries; postmark + "keep the stamped envelope"; joint accounts; anonymous box.
CRA — Registered charity vs non-profit (2025-09-02)https://www.canada.ca/en/revenue-agency/services/charities-giving/giving-charity-information-donors/about-registered-charities/what-difference-between-a-registered-charity-a-non-profit-organization.htmlNPO: "Cannot issue official donation receipts"; "No registration number".
CRA — Find another type of qualified donee (2025-10-24)https://www.canada.ca/en/revenue-agency/services/charities-giving/list-charities/list-charities-other-qualified-donees.html"Only Canadian registered charities and other qualified donees can issue official donation receipts..."; search-tool URL.
CRA List of charities — basic + advanced search (Chrome; JS-rendered; version 2026-07-31)https://apps.cra-arc.gc.ca/ebci/hacc/srch/pub/dsplyBscSrch?request_locale=en · https://apps.cra-arc.gc.ca/ebci/hacc/srch/pub/dsplyAdvncdSrch?request_locale=enPublic can "confirm whether a Canadian charity ... is registered, revoked, annulled, penalized, or suspended". BN/Registration number = "Business number, 9 digits" + "BN Program Account Type, 2 letters" + "bn Program Account Number, 4 digits".
CRA — When should a charity issue a receipt (Chrome)https://www.canada.ca/en/revenue-agency/services/charities-giving/charities/operating-a-registered-charity/issuing-receipts/when-should-a-charity-issue-a-receipt.htmlFebruary 28 suggestion; cumulative receipts for cash; separate receipt per non-cash gift — verbatim.
ITA s.188.1 (current to 2026-09-03)https://laws-lois.justice.gc.ca/eng/acts/I-3.3/section-188.1.html(7) 5%, (8) 10%, (9) 125% penalties — verbatim (was HYPOTHESIS in R-02).
Income Tax Folio S7-F1-C1 (2020-10-09)https://www.canada.ca/en/revenue-agency/services/tax/technical-information/income-tax/income-tax-folios-index/series-7-charities-non-profit-organizations/series/income-tax-folio-s7-f1-c1-split-receipting-deemed-fair-market-value.html¶1.5, 1.9, 1.12, 1.13 quoted; singular "the gift"; no aggregation guidance.
26 U.S.C. §170https://www.law.cornell.edu/uscode/text/26/170(f)(8)(A)-(C), (f)(12)(C) 30 days, (f)(17).
26 CFR §1.170A-13(f)https://www.law.cornell.edu/cfr/text/26/1.170A-13(f)(1), (f)(2) structure (goods other than IRB + IRB statement), (f)(3), (f)(8)(i) — summary, not verbatim.
IRS — Written acknowledgments (28-Jun-2026)https://www.irs.gov/charities-non-profits/charitable-organizations/charitable-contributions-written-acknowledgmentsContents list; no form and no signature requirement stated.
IRS Pub 526 (2025; Feb 5, 2026 build) — PDF text extractedhttps://www.irs.gov/pub/irs-pdf/p526.pdf"your contribution is the amount of the payment that is more than the value of the goods and services"; "lists each contribution and the date of each contribution"; "earlier of" timing.
IRS Pub 1771 (Rev. 11-2023) — PDF text extractedhttps://www.irs.gov/pub/irs-pdf/p1771.pdf"There are no IRS forms ... Letters, postcards, or computer-generated forms ... are acceptable"; no signature sentence anywhere; token exception three conditions; $75 membership + $20 poster; "no donative element"; January 31.
IRS IR-2025-08 (Jan. 10, 2025)https://www.irs.gov/newsroom/irs-announces-jan-27-start-to-2025-tax-filing-season-agency-continues-historic-improvements-to-expand-enhance-tools-and-filing-options-to-help-taxpayers"the nation's 2025 tax season will start on Monday, Jan. 27, 2025" (late-January filing warning).
404 / unreachableCRA general BN page; T4033 (no format text); T4063; CRA search "Search tips" (HTTP 500); CRA receipt checklistNo prose page stating "RR"; structure taken from the search tool instead.

Mechanical check (sources/donation-receipts/validate.py)​

$ python validate.py
rules: 38 ({'computed': 28, 'refer': 7, 'product': 3}); fields: 47; test cases: 73 {'CA': {'computed': 20, 'refer': 9, 'invalid': 11}, 'US': {'computed': 18, 'refer': 5, 'invalid': 10}}
RESULT: PASS (0 problem(s))

$ python validate.py --selftest # positive control: one expectation deliberately corrupted
FAIL CA-TC-01
- eligible_amount: got 10000 expected 9999
RESULT: FAIL (1 problem(s))

What it proves: both YAML files parse; every base fixture, rule id, satisfies id and F-* id resolves; every case is deep-merged onto the shared fixture and recomputed in integer cents from the rules' formulas (A <= 7500 and 10A <= G; 5A > 4G; P − FMV >= 25000; P > 7500), including refusal messages and log rows; every document-generating case has every required field non-blank; and the checker fails when an expectation is wrong.

Resolutions: Opus review​

FindingResolutionWhat changed / whySource
C-1 (critical) — US-09 "safe path (b)" omits two of three token conditionsFIXEDPath (b) deleted. US-09 lists all three conditions (fundraising campaign; donor told the deductible amount; dollar test — test 2 on COST), states the tool cannot check (1)-(2), and offers only "re-enter as goods provided". goods_status: token_item → refer (US-TC-15); the re-entered gift is US-TC-29 ($92 ceiling, disclosure).Pub 1771 p.4 (PDF text)
M-1 (major) — $250 test on NET contribution; US-TC-18 wrong; Q12 answerableFIXEDUS-01 formula cwa_required = (P − FMV) >= 25000, Pub 526 quoted verbatim. US-TC-18: cwa_required: false, disclosure still true. US-TC-21 added ($350/$100 → net $250 → CWA); US-TC-33 ($349.99/$100 → $249.99 → no CWA). Q12 closed.Pub 526 (2025) "Contributions of $250 or More"
M-2 (major) — CA-TC-19 cannot discriminate; float formulasFIXEDHeader + CA-09/CA-10 formulas rewritten as integer-cent comparisons with no division. CA-TC-24 added: G=333.35, A=33.34 → not nominal → $300.01 (a half-up-rounded cap gives $333.35). CA-TC-19 kept, relabelled non-discriminating.CRA Split receipting
m-1 — Q5 lost receipts answeredFIXEDCA-12 excerpt now quotes "issued a receipt that was lost or contained incorrect information"; Q5 RESOLVED.CRA Correcting/replacing
m-2 — Q2 partly answeredFIXEDCA-09 quotes "does not have to subtract these advantages" and the mug + pen example; Q2 labelled PRODUCT ASSUMPTION for the $0.00 printing convention.CRA Split receipting
m-3 — no gate for non-individual donorsFIXEDdonor.kind ∈ {individual, organization}; organization requires legal name + address only; CA-TC-33. Header scope widened.Reg. 3501(1)(g) "in the case of an individual"
m-4 — (3.1)/(1.1) never distinguishedFIXEDCA-11 rule text and excerpt say (3.1) is for "another recipient of the gift" and is not an e-signature route.Reg. 3501(3.1) verbatim
m-5 — disclosure overstates the deductionFIXEDUS-06 text and F-US-13: "The amount you may deduct for this payment is limited to $[P − FMV]." (deductible_ceiling in schema).Pub 1771 p.7 "may not exceed $60"
m-6 — US-07 attribution; Pub 526 stronger supportFIXEDUS-02 and US-07 quote Pub 526 "lists each contribution and the date of each contribution" and "If the acknowledgment doesn't show the date..."; s.170(f)(17) described as the donor-side condition; Q15 RESOLVED.Pub 526 (2025)
m-7 — refer table misroutes US gift cardsFIXEDRefer table US column → US-12(d): "redeemable for cash = monetary (Pub 1771); otherwise property — accountant". US-10 note added.Pub 1771 p.2
m-8 — mixed IRB + goods unhandled (unverified)FIXED (via R-17's alternative, not "refer")Fourth goods_status value provided_plus_intangible_religious prints the goods line AND the IRB statement (US-02(7), US-TC-24). Reg. 1.170A-13(f)(2) fetched as a summary only → confidence medium, open-questions item 16 asks for verbatim verification before go-live. "Contradictory" error removed.Reg. 1.170A-13(f)(2) (summary); Pub 1771 p.5 poster example
m-9 — ambiguous refusal text; grammarFIXEDCA-10 message: "The advantage ($81.00) is more than 80% of the $100.00 gift (80% of $100.00 = $80.00)." (computed by the validator, CA-TC-08/21). Goods descriptions carry their own article ("a harvest dinner").CRA sample receipts
m-10 — unverified itemsREFER (partly closed)Verified this pass: CA-01 title (sample page lists it); Feb 28 tip (page read in Chrome); Q8 labelled product assumption with folio quotes. Still open: ITA s.248(30)–(32) verbatim (Q1); current-year token figures (Q10).CRA sample receipts; CRA When should a charity issue a receipt; Folio S7-F1-C1

Resolutions: Fable review​

FindingResolutionWhat changed / whySource
R-01 (critical) — typed name is not a signature; no "read-only" claimFIXEDCA-11 rewritten: Reg. 3501(2)/(3)/(3.1) verbatim; CRA guidance quoted as "should"; signer name + title required (F-CA-23, CA-TC-30); banner "Not valid until signed by an authorized person" (F-CA-24) on screen, on the download control and on the PDF; "keep a copy of the SIGNED receipt" instruction; all "flattened / read-only" claims deleted (CA-01 note). US: Pub 1771 quoted — no form, no signature requirement; F-US-15 optional.Reg. 3501; CRA computer-generated receipts; Pub 1771 p.3
R-02 (critical) — no registered-charity gateFIXEDNew CA-00: attestation "Our church is a registered charity with the CRA." (F-CA-27); regex ^[0-9]{9}RR[0-9]{4}$ hard-validated against the CRA search tool's documented structure, with the List of charities link; s.188.1(7)-(9) penalties now verbatim (no longer HYPOTHESIS). Unchecked → CA-20 thank-you letter only (no title, no registration number). US mirror: US-00 s.170(c) attestation (F-US-19, US-TC-31). Tests CA-TC-28, CA-TC-29.CRA advanced search; sample receipts; charity-vs-NPO page; ITA s.188.1
R-03 (critical) — serial consumption undefinedFIXEDCA-03 defines Preview (watermark, nothing consumed) and Issue (treasurer enters next starting serial from their log; batch uniqueness asserted; issued-receipts CSV log F-CA-26; post-issue message). Tests CA-TC-26 (duplicate → invalid), CA-TC-27 (replacement replaces itself → invalid), CA-TC-31 (preview), CA-TC-32 (batch of three). Browser-local reminder → Phase 2 note (Q19), not a rule.CRA Correcting/replacing ("keep both copies ... cancelled"); Reg. 3501(1)(c), (4), (5)
R-04 (high) — retention notice incompleteFIXEDCA-14 / F-CA-22 notice uses the CRA's own sentences: electronic file, signed copy, Canadian address, backup, two years / six years. retention_notice_contains asserted in CA-TC-01.CRA Books and records; computer-generated receipts
R-05 (high) — contemporaneous warning fires too lateFIXEDUS-08: test is when the donor OBTAINS it; three-tier message (≤ Jan 31 / Feb 1–Apr 15 / Apr 16–Oct 15 / after Oct 15) computed from today; late-January filing cited to IR-2025-08. Tests US-TC-17 (extension_only), US-TC-25 (Feb → late_for_early_filers), US-TC-26 (too_late).§170(f)(8)(C); Pub 526; Pub 1771; IR-2025-08
R-06 (high) — issue-date override permits backdatingFIXEDCA-04 and US-08/US-14: date_issued = clock.today, displayed, not editable; date_issued in inputs is rejected (CA-TC-37, US-TC-30). ">= last gift date" phrasing removed; kept as an assertion.Reg. 3501(1)(f)
R-07 (medium) — donor address demands Canadian partsFIXEDCA-06: one free-text address ≥ 10 characters, any country; CA-TC-34 (Florida address issued).Reg. 3501(1)(g)
R-08 (medium) — corporate donors blockedFIXEDAs m-3: donor.kind, CA-TC-33; true-donor rule quoted.Reg. 3501(1)(g); CRA true donor
R-09 (medium) — double receipting via intermediaryFIXEDCA-15(f) + gift-row flag via_receipting_intermediary → refer (CA-TC-35). Platform mechanics labelled HYPOTHESIS in help text.CRA "customers are the true donors"
R-10 (medium) — Q5 already answeredFIXEDAs m-1.CRA Correcting/replacing
R-11 (medium) — foreign currencyFIXEDNew CA-19 (refer): currency fixed to CAD, "CAD"/"USD" labels on every amount, refer text; CA-TC-36. Conversion practice labelled HYPOTHESIS (confidence low; Q9 open).Reg. 3501(1)(h) (basis only)
R-12 (medium) — FMV == P contradictionFIXEDUS-04 and US-14: 0 < FMV < P; US-TC-20 expects invalid; validator recomputes it.Pub 1771 p.7 "no donative element"
R-13 (medium) — mailed gifts: envelope, which date to printFIXEDCA-05 formula date_of_donation = postmark_date if received_by_mail else date_received; printed date = date of donation; tip "Keep the postmarked envelope with your records." CA-TC-16 asserts per_gift_dates_printed: [2026-11-15, 2026-12-30].CRA What you need to know
R-14 (low) — label driftFIXED"Place issued", "Name and website of the Canada Revenue Agency"; nominal wording "too minimal to affect the amount of the gift (CRA nominal threshold)" — "de minimis" removed.CRA sample receipts; Split receipting
R-15 (low) — 80% error textFIXEDAs m-9.—
R-16 (low) — 30-day rule verifiedFIXEDUS-11 quotes §170(f)(12)(C); tool says "within 30 days"; Q13 half-closed.26 U.S.C. §170(f)(12)(C)
R-17 (low) — goods plus IRBFIXEDFourth enum value (see m-8), US-TC-24.Reg. 1.170A-13(f)(2); Pub 1771
R-18 (low) — input schema inconsistencyFIXEDCanonical schema: block in rules.yaml; every test uses base: + the schema's names only (amount_of_gift, advantage.amount, advantage.is_cash_or_near_cash, good_faith_estimate, receipt_year, clock.today).—
R-19 (low) — provided with FMV 0FIXEDUS-14(3) rejects; US-TC-23.—
R-20 (low) — donor name not statutoryFIXEDF-US-04 satisfies US-16 (product rule) with the note; US-14 note.§170(f)(8)(B)

Resolutions: Codex review​

FindingResolutionWhat changed / whySource
DR-001 (critical) — FMV <= P vs rejection of FMV == PFIXED0 < FMV < P everywhere (US-04, US-14, US-15, schema constraint); US-TC-20 recomputed as invalid.Pub 1771 p.7
DR-002 (major) — CA fixtures omit signer and gated fieldsFIXEDfixtures.ca_valid (charity, registration number, signer, serial, donor, clock); every CA case is base: ca_valid + overrides; validator audits every required field on every document-generating case.—
DR-003 (major) — US fixtures omit org, donor, issue dateFIXEDfixtures.us_valid; same audit.—
DR-004 (major) — no canonical schema; aliased namesFIXEDschema.ca_input/ca_output/us_input/us_output + money_convention; templates use the same names.—
DR-005 (major) — empty satisfiesFIXEDNew product rules US-16 (layout/delivery) and US-13 (signature optional); F-US-02/03/05/15/16 map to them; validator fails on any empty satisfies.Pub 1771 p.3
DR-006 (major) — no batch serial uniqueness / duplicate testFIXEDCA-03 formula asserts distinct serials; CA-16(8); CA-TC-26.Reg. 3501(1)(c)
DR-007 (major) — goods_status required only ≥ $250FIXEDUS-02/US-14: required for EVERY gift; US-TC-27 ($100 gift, status missing → invalid).§170(f)(8)(B)(ii)
DR-008 (major) — signer has no field ids / validationFIXEDF-CA-23 (name + title, both non-blank), F-CA-18 (line), F-CA-24 (banner); CA-TC-30.Reg. 3501(1)(i), (2)
DR-009 (major) — tax year, gift date, description/GFE, issue date can be blankFIXEDSchema required/required_when; US-14(5)-(7); tests US-TC-28 (tax year), US-TC-32 (date outside year), US-TC-23 (GFE), CA-TC-38/39/40; validator's required-field audit.—
DR-010 (minor) — no exact-10% caseFIXEDCA-TC-22 (G=500, A=50 → nominal) and CA-TC-23 (A=50.01 → $449.99).CRA Split receipting
DR-011 (minor) — $0 gifts untestedFIXEDCA-TC-25 and US-TC-22.—
DR-012 (minor) — cents test not discriminatingFIXEDCA-TC-24 (G=333.35, A=33.34 → $300.01).—
DR-013 (minor) — Q8 and Q12 unresolvedFIXEDQ12 RESOLVED (Pub 526, net). Q8 closed as a labelled PRODUCT ASSUMPTION (folio and Reg. 3501(1)(h.1) speak of "the gift"; no aggregation guidance exists; per-gift is the conservative reading).Pub 526; Folio S7-F1-C1

Still open / needs the founder​

  • Founder decisions encoded as defaults (review wording): the not-registered thank-you letter (CA-20); the nominal-advantage printing convention (CA-09); per-gift nominal threshold on cumulative receipts (CA-18); the mixed goods + intangible-religious-benefits enum (US-02(7)); CAD-only with refer for other currencies (CA-19).
  • Unverified primary text: ITA s.248(30)–(32) verbatim (Q1); Reg. 1.170A-13(f)(2) verbatim (Q16); current-year token figures (Q10); s.6714 verbatim; CRA foreign-currency guidance (Q9); a canada.ca prose page stating "RR" (structure verified from the CRA search tool; RR confirmed only by the sample receipt image and List entries).
  • Implementation choice, no rule impact: whether to add owner-password PDF encryption in addition to the signing workflow.

Final-pass resolutions (2026-09-25, after the final Fable verification and the Codex final findings)​

Editor: Claude Fable 5.1. Inputs: donation-receipts-2026-09-25-final-fable.md (PASS, 9 nits) and Codex's final findings DR-004 / DR-014 / DR-015 / DR-016 / DR-017. Files changed: rules.yaml, test-cases.yaml, receipt-templates.md, open-questions.md, validate.py; new requirements.txt. No app code.

Codex final findings​

FindingResolutionWhat changed
DR-004 — tests used undeclared output aliases (per_gift_eligible, per_gift_dates_printed, per_gift_deductible_ceiling)FIXEDEvery per-gift expectation is now the schema's per_gift list of rows (CA: date_printed, amount_of_gift, advantage_raw, advantage_effective, eligible_amount, nominal; US: date_received, amount, good_faith_estimate, net_contribution, deductible_ceiling, cwa_required, disclosure_required) in CA-TC-16/20 and US-TC-05/06/07/08/18/21/24/29/33. Output keys are now a CLOSED SET: schema.ca_output / us_output gained the keys the tests legitimately used (title, sentence_printed, donor_name_printed, gifts_included, gifts_excluded, log_row_count, message_after_issue, timing_message, tips, goods_lines), test-only matchers are declared in schema.output_matchers (tips_contain, message_after_issue_contains), and note_to_treasurer moved out of expected_output to the case level. Inputs are closed too: refer_description and donor_is_issuer declared; the seven refer cases renamed description → refer_description. validate.py FAILS on any undeclared output key, any undeclared input key, and on any key its own engines emit that the schema lacks. Money keys and per-row money columns are read from the schema types, not hard-coded.
DR-015 — blankness of ALL required fields before parsingFIXEDca_required_blank() / us_required_blank() run right after the forbidden-input check and before any refer gate, date.fromisoformat or Decimal: mode, receipt_type, clock.today, charity/signer/donor fields (per attestation branch; skipped for an anonymous donor, whose refer decides), serial_start / replaces_serial_number / receipt_year (conditional), every gift's date_received, postmark_date when received_by_mail, amount, advantage description when amount > 0 (US: goods_status, description and GFE when goods provided). CA-16(4) and US-14(5) rewritten to say so, with the gate ORDER in each formula. New tests: CA-TC-41 (clock blank → CA-04), CA-TC-42 (mailed gift without postmark → CA-16), CA-TC-43 (date_received blank), US-TC-34 (clock blank → US-14), US-TC-35 (date_received blank).
DR-016 — template placeholdersFIXEDreceipt-templates.md rewritten: every placeholder is a canonical schema path ({charity.name}, {donor.first_name} {donor.middle_initial} {donor.last_name}, {amount_of_gift}, {amount_of_advantage}, {eligible_amount}, {replaces_serial_number}, {donor_name_printed}, {per_gift[i].amount}, {per_gift[i].good_faith_estimate}, {per_gift[i].deductible_ceiling}, {goods_lines[i]}, {gifts_excluded[i].reason} ...); {first}, {G}, {A_eff}, {original}, {donor name}, ${amount}, ${P}, ${GFE} are gone. Each placeholder line carries its F-id and rule id, including the thank-you letter (F-CA-28/02/03/14; the closing is tagged as NOT F-CA-23) and the US signer line (F-US-15, US-13). validate.py parses the file: 45 distinct placeholders, all resolve; every F-* id and rule id mentioned must exist.
DR-017 — G=$50 boundary pairFIXEDCA-TC-44: A=$5.00 → nominal, eligible $50.00, advantage $0.00. CA-TC-45: A=$5.01 → not nominal, eligible $44.99. CA-09 notes list the pair.
DR-014 — PyYAML missingFIXEDvalidate.py prints PyYAML is not installed. Run: pip install pyyaml (or: pip install -r requirements.txt) and exits 2; requirements.txt (pyyaml>=6.0) sits beside it.

Fable's nine nits​

#NitResolution
1US goods line drifted (template vs rule/tests)FIXED — one pattern everywhere, the longer form: "In exchange for your contribution of {amount} on {date_received}, we gave you {goods_description} with an estimated fair market value of {good_faith_estimate}." Output is goods_lines (one per gift with goods; the old single-goods_line engine returned nothing for two such gifts). US-04, F-US-11, template §2(b), US-TC-05/06/08/24 aligned; US-TC-36 (two gifts with goods → two lines) added. Recorded as open-questions item 24.
2Thank-you letter printed the signer although F-CA-23 is "absent"FIXED — closing is "With gratitude, {charity.name}"; signer inputs are not required and never printed on the CA-20 path (a blank signer cannot render ", "). CA-20 rule/formula and open-questions item 20 updated.
3§0 "official never appears" contradicted the letter titleFIXED — §0 now says the words never appear on that path "except inside the two negations" (title and mandatory sentence); CA-20 says the same.
4CA-18 "not receiptable" row neither templated nor testedFIXED (product decision) — a gift failing CA-10 on a cumulative receipt is EXCLUDED: not printed, not in the totals; the treasurer sees an on-screen notice per excluded gift (gifts_excluded rows + tips), wording in the template §1a; if every gift fails → refer CA-10. Tests CA-TC-46 (one excluded, totals over the other two) and CA-TC-47 (all excluded → refer). Labelled PRODUCT ASSUMPTION in CA-18 notes and open-questions item 8.
5Validator skipped the 8 None-message refer cases; fields_present/absent not computedFIXED — the eight messages now live in rules.yaml as refer_messages on CA-15, CA-17, CA-19, US-09, US-10, US-11, US-12 (12 entries); the engines return them and the validator compares every message exactly (a None from the engine is a mismatch, not a skip). fields_present is COMPUTED for every document (CA: 19 base ids + individual/initial/joint/replacement/cumulative/preview/issue conditionals; US: 10 base ids + address/EIN/statement/goods/IRB/disclosure/signer conditionals) and checked: expected-present must be a subset, expected-absent must be disjoint.
6Banner still said "Not valid until signed" after signingFIXED — "Valid only when signed by an authorized person" in CA-11 (rule + formula), F-CA-24, schema note, template (banner + download caption), CA-TC-01, validator, open-questions item 3. Grep for the old wording across the five files: 0 hits.
7"M." vs "A"FIXED — the initial prints as entered, no period added: template {donor.middle_initial}, F-CA-10 note, schema note on donor_name_printed; "Ruth A Vanderberg" everywhere.
8Serial fallback only in the validatorFIXED — CA-03 rule text and formula document the no-trailing-digits fallback ("B" → "B-1", "B-2"); template §1 note; open-questions item 19; test CA-TC-48.
9CA-03 cited Q17FIXED — CA-03 notes cite open-questions Q19; item 19 states that CA-03 references it.

Mechanical evidence​

$ python validate.py
rules: 38 ({'computed': 28, 'refer': 7, 'product': 3}); fields: 47; refer messages: 12; template placeholders: 45; test cases: 84 {'CA': {'computed': 24, 'refer': 10, 'invalid': 14}, 'US': {'computed': 19, 'refer': 5, 'invalid': 12}}
RESULT: PASS (0 problem(s)) exit 0

$ python validate.py --selftest # corrupts one expectation AND adds one undeclared output key
FAIL CA-TC-01
- eligible_amount: got 10000 expected 9999
FAIL CA-TC-02
- undeclared output key 'per_gift_eligible' in expected_output (schema.ca_output)
RESULT: FAIL (2 problem(s)) exit 1

$ # DR-004 positive control on the REAL file: `per_gift_eligible: [...]` injected into CA-TC-20
FAIL CA-TC-20
- undeclared output key 'per_gift_eligible' in expected_output (schema.ca_output)
RESULT: FAIL (1 problem(s)) exit 1
$ # injected line removed; sha256 of test-cases.yaml identical before and after; validate.py PASS again

Case count 73 → 84 (CA 40 → 48, US 33 → 36). Nothing in this pass changes a threshold, a formula result, or a printed legal element other than the banner wording (nit 6) and the goods-line pattern (nit 1).

Codex re-check resolutions (orchestrator, 2026-09-25)​

The Codex re-check confirmed DR-004 and DR-017 PASS, and all 43 computed cases recompute in integer cents with zero mismatches. Two items remained:

  • DR-015: FIXED. expand_generated() no longer parses gifts_generated.start before the engine's blank-field audit. A blank or malformed start passes through unparsed as one gift, so ca_eval/us_eval report it through their ordered required-field checks. Positive control, using Codex's exact probe (CA-TC-02 with a blank clock.today plus a malformed start): it previously raised a ValueError, and now returns invalid CA-04 "The device date is missing…".
  • DR-016: FIXED. 15 layout lines are now tagged with a field id and rule id. validate.py REQUIRES every placeholder line inside the printed layouts to carry both. Positive control: removing one tag fails with "TEMPLATE line 124: placeholder without field id + rule id tag"; restored, it passes.

The validator passes on 84 cases, and --selftest fails as it should. Status: donation-receipt rules CLEARED for build.