diff --git a/.claude/board/EPIPHANIES.md b/.claude/board/EPIPHANIES.md index c22743c3..6f51cafb 100644 --- a/.claude/board/EPIPHANIES.md +++ b/.claude/board/EPIPHANIES.md @@ -1,3 +1,12 @@ +## 2026-07-07 — E-OCR-LINEFEED-1 — the typographic line feeding lands: `LSTMRecognizeWord`'s band transcoded, position invariance PROVEN — 3F₂'s boundary #2 is closed +**Status:** FINDING (falsifier green on the roomy stacked fixture; `tesseract-ocr`, tested) + +**The transcode** (tesseract-rs `4eb73f9`): `recognize_page_makerow` now feeds each row exactly as `Tesseract::LSTMRecognizeWord` does (`linerec.cpp:239-246`) — the row's ink bounding box EXTENDED (never shrunk) to `[baseline + descdrop, baseline + xheight + ascrise]`, baseline evaluated at the box x-midpoint from the wave-2 parallel fit (straight case `m·x + parallel_c`), then `GetRectImage`'s `kImagePadding = 4` pad on ALL sides + clip to the image (`imagedata.h:39`), cropping x AND y. This replaces the raw `[min_y, max_y]` expand_rows band — E-OCR-LINEFINDER-1's documented boundary #2. Semantics note: in LSTM mode the real pipeline recognizes a whole TEXTLINE per `LSTMRecognizeWord` call (the row's words are merged first), so feeding the row box IS the real feeding — no per-word segmentation gap here. + +**The falsifier (position invariance):** identical ink at different page positions must produce pixel-identical crops → identical text. First run on the legacy tight fixture FAILED the equality — and the debug bands showed exactly why: both rows carry IDENTICAL typographic parameters (xh 24.33 / asc 12.17 / desc −12.17, identical extensions relative to baseline), but the 24×88 layout clips the padded band at the image TOP for row A and the BOTTOM for row B (57 vs 45 tall) — which is *faithful* `GetRectImage` edge clipping, not a transcode defect. On a roomy re-layout (32 px margins / 64 px gap, same tile) both rows crop to 32×58 and recognize to IDENTICAL text. The E2E anchor asserts the equality (`stacked_page_finds_two_deterministic_rows`, roomy fixtures only). + +**Transferable lesson:** a position-invariance falsifier needs a fixture whose typographic band + padding CLEARS the image edges — edge-tight fixtures test the clip path instead (worth keeping, separately). Generator banked (`tesseract-rs/.claude/harvest/oracles/gen_page_fixture.py`, tile embedded verbatim; its tight-layout arm byte-reproduces the original 24×88 fixture). Remaining documented approximations in the page path: blob source (island-in-hole, E-OCR-LINEFINDER-1 boundary #1) + straight-baseline (`row->base_line()` consults the quadratic spline where one exists). Gates: 79/79 lib tests, clippy both feature sets, `qLLiy,,` regression intact. Next: P6 golden corpus. Plan `tesseract-rs/.claude/plans/pdf-to-text-ocr-v1.md`. Branch `claude/happy-hamilton-0azlw4`. + ## 2026-07-07 — E-OCR-LINEFINDER-1 — 3F₂ COMPLETE: the REAL makerow line finder replaces the projection approximation — CC pixel counts (no outline tracer needed) + filter_noise_blobs byte-parity 14/14 + the full composition wired **Status:** FINDING (leaves byte-parity proven; composition functional with two DOCUMENTED boundaries; `tesseract-ocr`, tested)