From 83fca5a585c21f5e784e84a99caba94c151a99a4 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 8 Jul 2026 16:59:55 +0000 Subject: [PATCH 1/2] =?UTF-8?q?board:=20E-OCR-SKIP-GATE-1=20=E2=80=94=20sk?= =?UTF-8?q?ip=20cascade=20ABORTED=20by=20the=20go/no-go=20gate=20(28.3%);?= =?UTF-8?q?=20batching=20is=20the=20converged=20lever?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Claude-Session: https://claude.ai/code/session_016b33swuXE23hKtqxsHu9p1 --- .claude/board/EPIPHANIES.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.claude/board/EPIPHANIES.md b/.claude/board/EPIPHANIES.md index 30c4bd9e..73691db3 100644 --- a/.claude/board/EPIPHANIES.md +++ b/.claude/board/EPIPHANIES.md @@ -1,3 +1,14 @@ +## 2026-07-08 — E-OCR-SKIP-GATE-1 — the go/no-go gate ABORTS the skip cascade with a number (28.3% < 30%): probe-first discipline stops a research swamp before a line of cascade is built +**Status:** FINDING (measured; `tesseract-rs` `skip_fraction` instrument; PR #24) + +**The operator hardening that produced this:** the "Morton-tile-pyramid-CAM-PQ recognizes tokens" idea was correctly RESCOPED — not "replace the LSTM" (segmentation-free CTC + font-invariance are load-bearing) but "AVOID LSTM invocations" via a skip/escalate cascade: cheap coarse descriptor → empty (skip) / trivial-known-token (CAM-PQ fast-path) / ambiguous (ESCALATE to the exact LSTM). CAM-PQ/VSA = a CONFIDENCE GATE, never the OCR engine; the LSTM stays the truth oracle for the hard tail (always-escalate preserves byte-parity). And the iron discipline: **first task is instrumentation ONLY** — measure the skippable fraction before building anything; abort < 30%, proceed >= 60%. + +**The measurement (instrumentation only, recognizes nothing):** `skip_fraction.rs` over the 10 committed pages counts, within each line-band ink span, the pure-blank interior column fraction (the safely-skippable floor for a blank-run gate; preserved under the front-end 2× maxpool so it proxies blank LSTM timesteps; same Otsu+binarize as the real path). **Aggregate 28.3% (6212/21962), per-page 20-39% → ABORT.** On dense typeset text the easy skip is not there; inter-word/inter-glyph gaps alone don't pay for a gate + escalation machinery. + +**The convergence — two independent probes name the SAME lever:** (1) the arithmetic-intensity estimate — eng.lstm forward runs at ~0.1% of AVX-512-VNNI peak, i.e. the int8 GEMM is STARVED by per-tiny-op glue (pack_contig, dispatch, requant), not saturated arithmetic; and (2) this 28.3% skip fraction. Both point to **BATCHING the forward** (width-bucket lines → batch-across-lines-per-timestep so the recurrence holds → fill the tiles → fewer, larger cache-friendly kernel calls → scatter), NOT skipping it and NOT more SIMD. The "AMX-Ferrari bekommt Pixelkrümel mit der Pinzette" diagnosis is confirmed: the kernels are fast, the FEED is tiny/irregular. Batching is the developer-army-replacement — one dense feeder vs Tesseract's thousand hand-tuned micro-heuristics. + +**Transferable:** the probe-first gate is the anti-research-swamp mechanism — a one-hour instrument that says NO with a number is worth more than a month of visionary cascade-building. Corpus caveat: dense text is the skip worst-case; the instrument re-runs on any corpus (sparse forms/tables would score far higher — the cascade's real home). Composes with E-OCR-PARALLEL-1: rayon spreads work across cores (outer), batching fills each core's tiles (inner) — multiplicative, and the measured next lever. Branch `claude/happy-hamilton-0azlw4`. + ## 2026-07-08 — E-OCR-PARALLEL-1 — page-chunk rayon closes the throughput gap losslessly: 3.34× on 4 cores, byte-identical to serial (the operator-pinned topology, not whole-doc lanes / not a global crop pool) **Status:** FINDING (measured; tesseract-rs `ocr-pdf`, determinism-gated; PR forthcoming) From 12b11e2f8242b2754ecd6c149430497b91b3549d Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 8 Jul 2026 17:08:38 +0000 Subject: [PATCH 2/2] =?UTF-8?q?board:=20E-OCR-SKIP-GATE-1=20correction=20?= =?UTF-8?q?=E2=80=94=2030.1%=20MARGINAL=20not=2028.3%=20ABORT=20(codex=20P?= =?UTF-8?q?1=20pad-fidelity);=20conclusion=20preserved?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Claude-Session: https://claude.ai/code/session_016b33swuXE23hKtqxsHu9p1 --- .claude/board/EPIPHANIES.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.claude/board/EPIPHANIES.md b/.claude/board/EPIPHANIES.md index 73691db3..3e8cb36f 100644 --- a/.claude/board/EPIPHANIES.md +++ b/.claude/board/EPIPHANIES.md @@ -1,9 +1,9 @@ -## 2026-07-08 — E-OCR-SKIP-GATE-1 — the go/no-go gate ABORTS the skip cascade with a number (28.3% < 30%): probe-first discipline stops a research swamp before a line of cascade is built +## 2026-07-08 — E-OCR-SKIP-GATE-1 — the go/no-go gate rules the skip cascade MARGINAL with a number (30.1%, far below the 60% proceed bar): probe-first discipline stops a research swamp before a line of cascade is built **Status:** FINDING (measured; `tesseract-rs` `skip_fraction` instrument; PR #24) **The operator hardening that produced this:** the "Morton-tile-pyramid-CAM-PQ recognizes tokens" idea was correctly RESCOPED — not "replace the LSTM" (segmentation-free CTC + font-invariance are load-bearing) but "AVOID LSTM invocations" via a skip/escalate cascade: cheap coarse descriptor → empty (skip) / trivial-known-token (CAM-PQ fast-path) / ambiguous (ESCALATE to the exact LSTM). CAM-PQ/VSA = a CONFIDENCE GATE, never the OCR engine; the LSTM stays the truth oracle for the hard tail (always-escalate preserves byte-parity). And the iron discipline: **first task is instrumentation ONLY** — measure the skippable fraction before building anything; abort < 30%, proceed >= 60%. -**The measurement (instrumentation only, recognizes nothing):** `skip_fraction.rs` over the 10 committed pages counts, within each line-band ink span, the pure-blank interior column fraction (the safely-skippable floor for a blank-run gate; preserved under the front-end 2× maxpool so it proxies blank LSTM timesteps; same Otsu+binarize as the real path). **Aggregate 28.3% (6212/21962), per-page 20-39% → ABORT.** On dense typeset text the easy skip is not there; inter-word/inter-glyph gaps alone don't pay for a gate + escalation machinery. +**The measurement (instrumentation only, recognizes nothing):** `skip_fraction.rs` over the 10 committed pages counts, within each line-band ink span, the pure-blank interior column fraction (the safely-skippable floor for a blank-run gate; preserved under the front-end 2× maxpool so it proxies blank LSTM timesteps; same Otsu+binarize as the real path). **Aggregate 30.1% (6772/22522), per-page ~21-41% → MARGINAL** (30-60%, far below the 60% PROCEED bar). On dense typeset text the easy skip is barely there. (First cut read 28.3% by omitting the recognizer's blank 4px x-padding from the tally — codex P1; counting the ACTUAL fed crop raised it to 30.1% and flipped the LABEL ABORT→MARGINAL. CONCLUSION unchanged: 30% << 60%, cascade still not a clear win, batching stays the lever — reported faithfully.) **The convergence — two independent probes name the SAME lever:** (1) the arithmetic-intensity estimate — eng.lstm forward runs at ~0.1% of AVX-512-VNNI peak, i.e. the int8 GEMM is STARVED by per-tiny-op glue (pack_contig, dispatch, requant), not saturated arithmetic; and (2) this 28.3% skip fraction. Both point to **BATCHING the forward** (width-bucket lines → batch-across-lines-per-timestep so the recurrence holds → fill the tiles → fewer, larger cache-friendly kernel calls → scatter), NOT skipping it and NOT more SIMD. The "AMX-Ferrari bekommt Pixelkrümel mit der Pinzette" diagnosis is confirmed: the kernels are fast, the FEED is tiny/irregular. Batching is the developer-army-replacement — one dense feeder vs Tesseract's thousand hand-tuned micro-heuristics.