# Sheet Rescue 24 — Demo QA Report

## Scope and provenance

This report covers a fully synthetic purchase-ledger demo. No customer data, third-party personal data, copyrighted source document, account, message, or payment was used. The visual source is `source-ledger.svg`; `source-ground-truth.csv` is its machine-readable verification sidecar. The intentionally flawed extraction is `messy.csv`, and the reviewed output is `cleaned.csv`.

## Reconciliation summary

| Check | Result |
|---|---:|
| Rows visible in source image | 48 |
| Rows in source verification sidecar | 48 |
| Rows in messy extraction | 48 |
| Unique source records | 46 |
| Rows in cleaned output | 46 |
| Duplicate rows removed | 2 |
| Visual source rows cross-checked | 48 / 48 |
| Cleaned rows exactly matched to source | 46 / 46 |

The two removed rows are duplicate second occurrences of `TX-011` (source row 12) and `TX-032` (source row 34). The first source occurrence is retained, and `cleaned.csv` preserves that source row in its `source_row` column.

## Blank cells

Blank counts cover business fields only (`record_id`, `date`, `vendor`, `description`, `amount`, `currency`, `reference`); verification metadata is excluded.

- Visual/source truth: **3** intentional blanks — references for `TX-007`, `TX-022`, and `TX-041`.
- Messy extraction: **5** blanks — the 3 true blank references plus source row 9 `description` and source row 24 `currency`, both lost during simulated extraction.
- Cleaned output: **3** blanks — only the 3 true source blanks remain. Nothing was invented for them.
- Source rows 9 and 24 were restored by visual-source comparison.

## Unreadable cells and source comparison

| Messy CSV location | Messy value | Visual source value | Cleaned value | Result |
|---|---|---|---|---|
| Source row 17, `amount` (`TX-016`) | `[UNREADABLE]` | `64.25 USD` | `64.25`, `USD` | Resolved from source |
| Source row 29, `reference` (`TX-028`) | `[UNREADABLE]` | `REF-260928` | `REF-260928` | Resolved from source |

No unreadable value was guessed. Both were resolved against a legible cell in `source-ledger.svg`. In a real job, a cell that remains unreadable after source review would be flagged for the buyer rather than silently filled.

## Normalization rules applied

1. Dates are normalized to ISO `YYYY-MM-DD`, from five source styles including `MM/DD/YYYY`, `DD-MM-YYYY`, `YYYY.MM.DD`, abbreviated month names, and `YYYY/MM/DD`.
2. Currency is normalized to ISO codes `USD` or `KRW`; symbols and prefixes/suffixes are removed from the amount.
3. USD amounts use two decimal places. KRW amounts use whole won with no thousands separator.
4. Leading and trailing whitespace is removed from text. The demo contains 20 affected cells.
5. OCR confusions (`O/0`, `l/1`, `S/5`) are corrected only when the visual source confirms the value. Nine deliberately corrupted OCR cells were checked.
6. Two extraction-created blanks are restored from the visual source; three true source blanks remain blank.
7. Duplicate detection uses the canonical `record_id`; the first visual occurrence is retained and its source row is recorded.
8. Vendor and description spelling/capitalization follow the visual source. No enrichment or inference beyond source comparison is performed.

## Reproduce and verify without a browser

From the workspace root:

```sh
python3 artifacts/spreadsheet-offer/generate_demo.py
python3 artifacts/spreadsheet-offer/validate_demo.py --write-result validation-result.txt
```

Or, from `artifacts/spreadsheet-offer/`:

```sh
python3 generate_demo.py
python3 validate_demo.py --write-result validation-result.txt
```

The validator uses only the Python standard library. It parses all 48 SVG table rows, compares them with the sidecar, compares all 46 cleaned rows with first-occurrence source truth, checks counts and formats, and exits nonzero on any mismatch.

## Recorded execution

`validation-result.txt` contains the saved result from an actual run. Recorded status: **PASS**.

Key recorded metrics:

```text
source_image_rows=48
source_truth_rows=48
messy_rows=48
unique_records=46
cleaned_rows=46
duplicates_removed=2
source_blank_cells=3
messy_blank_cells=5
cleaned_blank_cells=3
unreadable_cells_cross_checked=2
extraction_blanks_cross_checked=2
ocr_defects_cross_checked=9
whitespace_cells_normalized=20
visual_source_rows_cross_checked=48
cleaned_rows_exactly_matched_to_source=46
```

SHA-256 values for the four data artifacts are also recorded in `validation-result.txt` so a later run can identify changed outputs.
