From b4d7106d28c1e10ed83963b34a2e70bbca08d046 Mon Sep 17 00:00:00 2001 From: tngo Date: Mon, 28 Sep 2026 23:27:29 +0900 Subject: [PATCH] docs: record the OCR cache and the two review fixes The pacing paragraph described a defect that no longer exists. Replaced with the measured before/after, and added the two review findings (the missing always-argmax baseline lane, the size-token fill-in) with their test counts. --- .../DECISION.md | 41 ++++++++++++++----- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/recognization/docs/research/2026-09-28-recognition-architecture/DECISION.md b/recognization/docs/research/2026-09-28-recognition-architecture/DECISION.md index 15d9ffd..f555928 100644 --- a/recognization/docs/research/2026-09-28-recognition-architecture/DECISION.md +++ b/recognization/docs/research/2026-09-28-recognition-architecture/DECISION.md @@ -630,16 +630,24 @@ Van's 32/61. So the design does not yet beat Van on both axes at full resolution, and the accept line is provisional: it is tuned on Tier 1 and needs per-input-path calibration on Tier 2. -The live count is pacing-dependent, not a fixed property: a track needs two -attempts before it settles, so a harness that pushes frames faster than the -classifier drains them reports fewer labels. Re-run at four pacings on the same -12-frame clip: 12, 8, 2 and 6 named at full speed, 14 named with 0.1 s between -frames, and 38 named of 30 frames at 0.1 s. Precision stays 100% throughout and -0 unknowns are accepted at every pacing. Coverage is a gate (G1), not a -footnote: 12 of 61 streamed is a regression against Van's 57% until device data -says otherwise, and the likely cause is measurable - OCR runs on every crop at -every attempt, taking a crop from 5 ms to 25 ms and throughput from 789 to 60 -crops/s with 8 workers. +The live count was pacing-dependent, and the cause was measurable: OCR ran on +every crop at every attempt, taking a crop from 5 ms to 25 ms and throughput +from 789 to 60 crops/s with 8 workers. The reading is now cached on the track +and later attempts re-run only the local lane. Measured through the real server +on `add/image6.jpg`: + + saturated pool 15.9 -> 49.4 crops/s (8 workers, 64 crops) + per crop 142 -> 92 ms on a 300x400 crop + 3 s clip, send 19.7 mean labels (15-24, unstable) -> 24.0 (23-25, stable) + 12 s clip, send 48/131 -> 53/131; result pacing 53/134 -> 50/135 + +The 12 s numbers are within run-to-run noise; the short clip is where the +pacing sensitivity lived, and it is now flat across pacings. Precision stays +100% and 0 unknowns are accepted at every pacing. Coverage is still a gate +(G1): 53 of 131 streamed tracks is not yet a claim against Van's 57% of +labelled facings, because the two count different things - tracks the detector +started versus labelled facings. The label-matched comparison is the +evaluator's, above. The shipped default scale now has test coverage. `make_session` builds only `matcher`-backend engines, so `scale == "local"` in `_on_classified` never ran @@ -648,7 +656,18 @@ injects the lanes' evidence into the live path, and `LocalScaleTests` pins the two jobs (a text-only read still labels the track; a text veto blocks a local accept). `DecisionPolicyTests` pins the veto/fill-in boundary, including the lane-order-vs-value case the rank re-sort broke. Both regressions were -re-injected to confirm the tests fail for the intended reason. Suite 251 -> 274. +re-injected to confirm the tests fail for the intended reason. Suite 251 -> 281. + +Two further review findings, both fixed and both measured: + +- The evaluator had no always-argmax lane, so every "vs Van" claim compared + against the *gated* matcher rather than Van's contract. The `van` lane is + that contract; the numbers above use it. +- A crop reading only "400g" scored 0.667 on three SKUs, above `TEXT_ACCEPT`, + so the text lane named a product from a size line. The fill-in job now + requires two non-digit bigrams; the veto is unchanged, so "65%" still + contradicts a local answer. Three tests cover it and all three fail when the + gate is removed. The headline number is reproducible from the repo, not from a scratch script: