New go/internal/domain/matching package porting three helpers from
scripts/match_payments.py:
- BuildNameVariants: normalized ASCII variants from a member name (nickname
in parens, last/first split, len<3 filtered); variants[0] is always the
full base name — MatchMembers relies on this invariant.
- MatchMembers: auto/review confidence matching with an exact-name
short-circuit pass that prevents nickname substrings (tov) from firing
inside longer surnames (ottova); common-surname filter for review tier.
- FormatDate: nil/empty/""/serial int/float64 (since 1899-12-30, fractional
days supported)/YYYY-MM-DD passthrough/garbage → never errors.
- InferTransactionDetails: composes BuildNameVariants+MatchMembers+
ParseMonthReferences; falls back to sender-only member match and
date-derived month when text carries no signal.
21 table-driven tests; all expected values verified against live Python
on 2026-05-06. go-build, go-test, go-lint all clean.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
SHA-256 dedup hash from sync_fio_to_sheets.py generate_sync_id.
Key subtlety: Python str(float) emits "500.0" for whole-valued floats
and switches to scientific notation at |f|>=1e16 or |f|<1e-4 —
replicated via formatAmount using 'f'/'e' format selection.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>