# Read-only localization and aggregate validation of real financial source files

Use this reference when asked to locate and analyze current real bank, card, or receipt exports without importing, copying, mutating, or exposing raw financial data.

## Discovery order

1. Bind the code baseline (`HEAD`, branch, initial worktree status).
2. Read the runtime-path ADR/config and derive the approved out-of-repository import roots.
3. Search those roots by extension and profile shape, not only by provider filename. Include hash-named upload/archive directories.
4. Search private/local roots only when permitted by the task.
5. Inspect the documented provider path as the current-source authority when accessible. If provider access is unavailable, label local files by their modification time and do not call them current.
6. Use session history only as secondary evidence for previously observed provider filenames or states; never as proof of current provider contents.

## Strict read-only boundary

- Do not invoke preview paths known to persist sessions or archives, even if named `dry_run`.
- Do not open or query the productive database merely to substitute for missing source files unless the user explicitly includes database analysis in scope.
- Do not download provider files unless explicitly authorized; metadata-only provider scans are preferred for localization.
- Do not create reports, temporary copies, converted files, caches, or extracted workbooks.
- Analyze files with read-only parsers in-process and emit aggregates only.
- Snapshot source `size` and `mtime_ns` before analysis and compare afterward. Re-run `git status --short` at the end.
- If unrelated worktree changes appear during the run, report them as concurrent/unattributed rather than claiming a globally unchanged worktree.

## Provider/profile detection

Classify content by required columns, not by filename:

- VISA/card: `TransactionId`, `CardId`, `Date`, `Amount`, `Currency`, `MerchantName`.
- Migros receipt detail: `Datum`, `Zeit`, `Filiale`, `Transaktionsnummer`, `Artikel`, `Umsatz`.
- Raiffeisen bank: `IBAN`, `Booked At`, `Text`, `Credit/Debit Amount`.
- AKB bank: `Buchung`, `Valuta`, `Buchungstext`, `Belastung`, `Gutschrift`.

Treat one-row hash-named uploads as probes or isolated uploads until content volume and lineage prove they are full real exports.

## Safe structural analysis

Report only:

- masked path/reference;
- file type, byte count, modification timestamp;
- physical rows, logical rows, unique stable IDs;
- parse success/rejection counts;
- date range;
- currency/sign/classification counts;
- aggregate sums explicitly requested by the user;
- duplicate/collision counts;
- pairing counts and aggregate totals.

Never emit raw rows, full account/card references, provider transaction IDs, filenames containing account identifiers, merchant narratives unrelated to an explicitly requested check, or source/file fingerprints.

## CSV and date pitfalls

- Detect delimiter from `;,\t|`, but verify required columns after detection.
- Decode according to observed bytes; profile-declared encoding is not proof that the current path used it.
- For mixed ISO datetimes, use a parser mode that supports mixed formats. A single inferred pandas format can silently turn valid rows into `NaT`.
- Preserve the provider sign as source evidence, but derive household effect from the account role. Never assume card purchases are negative or bank credits are positive without measuring the source.
- Compare physical lines (state explicitly whether the header is included), parsed records, logical bookings, and unique provider IDs separately.

### Malformed multiline bank exports

Some bank CSVs contain both continuation lines and unquoted commas inside descriptions. `csv.DictReader` can silently lose displaced fields when headers contain repeated blank columns. Use this sequence instead:

1. Parse physical records with `csv.reader`, preserving every column.
2. Recognize continuation records only when stable account/date/amount/value-date fields are absent; append their text before fingerprinting.
3. For malformed main records, recover value date, balance, and amount from the right edge, then join the middle columns as the description.
4. Normalize and fingerprint only after reconstruction.
5. If two main records share stable source reference, booking date, amount, and value date, collapse them only when normalized descriptions provide strong identity evidence. Keep legitimate same-day/same-amount purchases when merchant evidence differs.
6. Regression-test the exact physical-line-to-logical-booking boundary and ensure continuation lines create neither bookings nor duplicate candidates.

Always reconcile the provider `Balance` field per stable source reference. Do not confuse a transaction amount (for example an interest credit) with the account balance.

### Account-role sign normalization

- Bank asset debit: negative household cash effect; credit: positive.
- Card liability exports may encode purchases as positive liability increases and payments/refunds as negative liability decreases. Preserve the raw amount internally, but invert it for household income/expense semantics.
- Determine card payment/refund/storno meaning from account role plus transaction text/type before assigning an expense category.
- Pair a bank payment with a card-liability reduction using opposite *economic* legs, not merely opposite raw provider signs.
- An unpaired card repayment remains neutral and must never become income.

## Canonical source-mapping gate

Before any real preview, count distinct stable source references per file. A single export can contain multiple accounts even when the filename suggests one.

- Resolve each reference independently to one canonical account and one budget account role.
- Never map two distinct references to one account merely to satisfy an expected row count.
- A card source requires a liability role; do not create a duplicate cash/portfolio account.
- If a reference has no unique canonical target, or provider balances materially contradict the supplied reference values, stop before productive mapping/deployment and ask for the smallest explicit decision using masked references and aggregate evidence.
- A test-copy-only mapping can diagnose parsers, but it is not evidence that production mapping is valid.

## Receipt grouping and card matching

For Migros-like exports:

1. Group article rows by the complete receipt identity available in the source: date, time, store, register, transaction number.
2. Sum signed line amounts, then document whether matching uses signed or absolute totals.
3. Report article-line count and receipt count separately.
4. Match against card movements using merchant/source evidence, date policy, currency, and amount tolerance.
5. Count unique matches, ambiguous matches, and unmatched receipts separately.
6. Break results down by source period/file when a combined archive can hide that the latest file is stale or partial.

## Reference-value reconciliation

When the user supplies expected counts or totals, produce an explicit evidence table:

- expected value;
- observed local value;
- observed provider value, if accessible;
- status: confirmed / contradicted / unavailable;
- likely boundary difference: stale export, different period, physical vs logical rows, or alternate sign/date policy.

Do not force local data to fit the reference. A mismatch is a useful result.

## Spreadsheet-only evidence

A planning workbook is not automatically a bank export. Before using it as source evidence:

- verify that it carries the provider's expected transaction schema;
- identify header columns structurally;
- aggregate only requested rows by date/amount;
- label workbook findings as secondary/manual evidence when source lineage is absent.

## Completion statement

Always state:

- which roots and provider paths were checked;
- which real files were found, using masked references;
- which sources were absent or inaccessible;
- whether a productive database was accessed;
- whether any provider files were downloaded;
- source-stat comparison result;
- final worktree status and any concurrent changes;
- that no files were created or modified by the analysis.
