Reading a statement
The PDF's text is extracted in your browser, with nothing in the PDF executed. Each line that starts with a date and has an amount is a transaction. Whether it is money in or money out is decided in this order: the column it sits under, the change in the running balance, an explicit sign (minus, parentheses, CR or DR), and finally the section heading. A line that none of these settles is left out and counted, so the statement's balance check fails instead of the tool guessing.
Checking the statement against itself
The beginning balance plus every line read must equal the ending balance printed on the statement. Each statement shows whether it adds up.
Grouping records by account
Files for the same account are compared together: same last four digits of the account number, or, for a spreadsheet with no account number, the account whose amounts it shares. Several months of statements for one account are combined into one record.
Matching
Only the dates both records cover are compared. Lines match on the exact amount within seven days, preferring the closest date and the most similar description, with check numbers breaking ties. Batched deposits and split payments of up to five lines are matched next. If one record uses the opposite sign convention, its amounts are flipped and the result says so.
Takes precedence
You choose which record is right when the two disagree. The exported ledger lists every line of that record with its own date, description and amount, and marks each as matched, missing from the other record or different in amount, followed by the lines only the other record has.
Open source
All of this is in recon-core (AGPL-3.0), with tests on synthetic statements.