Agent Lab Vol 3 #02 starts with the thing that is wrong with it. There is no public corpus of personal bank statements, there cannot be one, and no honest way to make one out of somebody else's life. So the whole year here is invented: 530 transactions across 3 accounts and 27 merchant profiles, each carrying a declared true category and a declared answer to "is this spending". The page says so in its first card, above every number.
It also names the dose of real-world mess, counted rather than hand-waved: 11 pre-authorisation holds each posting as a pending/settled triple, 7 refunds with one straddling a rename on purpose, 36 self-transfer debits worth ₹7,43,491.12, and 3 merchants whose string changes format mid-year. A real export has more of all four, so on real data every categoriser here gets worse and the structural checks get more valuable. And rules reads 1.0000 only because its rule list and the answer key were written from the same declaration. That is not a measurement, and every informative comparison on the page is between the wrong engines.
rows = read(statement) exact. It is a CSV.
category = engine(row) confidently wrong, nothing in the file checks it
spending = row not in transfers silently double-counts, everything reconciles
pattern = share(spending) the only line that answers the question
Run all 100 configurations - 5 categorisers x 5 transfer policies x 4 netting rules - and the reconciliation total is identical in every one (₹16,80,080.65) while "what did I spend" comes back 20 different ways spanning 3.66x, from ₹3,70,851.16 to ₹13,56,589.53. A total that is right for every implementation that sums the column is evidence about nothing else.
The control makes the point twice. reconciled is one cosmetic line on top of an engine that passes 5 of 6 self-checks: the sweep takes it to 6 of 6 by moving 179 assignments worth ₹11.2 lakh and changing the correctness of exactly zero of them. And a word list for transfers, with NEFT on it, deletes the whole year's rent - ₹3,36,000 straight off the spend.
The result I did not set out to get
I built this to show that fixing the categoriser is the expensive half. On the total it is worth ₹0.00.
| fix | spend total | pattern error |
|---|---|---|
| nothing (the control) | ₹13,56,589.53 | 26.1pp |
| transfers only | ₹9,06,589.53 | 17.4pp |
| categoriser only | ₹9,36,589.53 | 7.1pp |
| both | ₹9,06,589.53 | 8.1pp |
"Fix both" is bit-identical to "fix transfers only", to the paisa, because a category is a label on a row the total already contains. Read the same two fixes on the pattern and the ranking reverses: the categoriser leaves 7.1pp against the transfer fix's 17.4pp, 2.4x better. There is no single number that combines them, which is the whole argument for keeping the total and the pattern apart.
Three nulls came with it. Floats drift 4.5e-08 paise over the year and the slogan does not reproduce - what they break is the equality, not the number. The two rounding rules agree everywhere while 55 of 100 share vectors still miss 100.00. And by-count and by-rupee accuracy differ by 30 points without ever reordering the engines.
Twelfth reversal in twelve projects. Repo: https://github.com/dev48v/money-map - PUBLIC, MIT, standard library only, 52 pytest, no key and no network. 55 in-page assertions and 132 in the verifier: https://dev48.infy.uk/agentlab/vol3-02-money-map.html
12 of 15 projects now have a page: https://dev48.infy.uk/agentlab.php
Top comments (0)