S9 (a1): slip reader — zero-API OCR

tesseract.js (self-hosted WASM, Apache-2.0) + pure per-book layout
parsers (DK/FD/MGM/Caesars) with per-field confidence and needs_review
honesty — the reader never guesses. POST /api/slips/parse (auth, free
1/day paid 10/day, 4MB cap) + Next proxy. Gated /slip page: upload or
paste, manual-correct UI, per-leg grades through the normal engine
(refusals render honestly), add-all to Parlay Lab, share card. Vision
model upgrade logged post-revenue. 2574 -> 2608 tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Kev
2026-07-11 19:32:17 -04:00
parent aaafc3e0f2
commit 4e49ee0990
18 changed files with 1914 additions and 1 deletions
+17
View File
@@ -131,6 +131,23 @@ this is an aggregate + UI change only.
---
## Slip Reader — vision-model upgrade (POST-REVENUE)
Session 9 (A1 board) shipped the zero-API Slip Reader: tesseract.js OCR
(self-hosted WASM, free) + rigid per-book layout parsers (DK/FD/MGM/Caesars)
with per-field confidence and needs_review honesty. That architecture is
deliberately conservative — it reads clean screenshots of the four big books
and refuses everything else.
The upgrade, when revenue funds it (zero-out-of-pocket rule): a vision model
(Claude-class multimodal) replaces the OCR+layout-parser pair — one call reads
ANY book, any theme, any crop, and returns structured legs with real
confidence. Costs per-call money, so it is gated on paid tiers paying for
themselves. The route contract (`POST /api/slips/parse``{ legs,
needs_review, source: 'user_slip' }`) is the stable interface; only the
extraction engine behind it swaps. Keep the never-guess rule: model output
below confidence threshold still nulls the field.
## Operating invariants (do not regress)
- Three stat_type whitelists stay in sync: `routes/analyze.js`, `routes/scan.js`,
`python/utils/validation.py`.