← back to Dw Photo Capture
test: fingerprintVendor edge cases + reject OCR-confidence-threshold (cycle 12)
0801a44206116bf6cfa9608b0b6a2622798d1da6 · 2026-06-26 05:34:05 -0700 · Steve Abrams
Brainstorm (qwen3:14b) → triaged 5: rejected 3 as already-done/misconceived (font
smoothing, prefix cache, logo ROTATION — fingerprints are text not pixels), investigated
+ rejected-with-evidence the OCR confidence threshold (Vision returns confidence 1.000
or NO read across all blur/noise tiers — there's no low-confidence band to threshold),
and shipped the safe test-coverage pick.
Added 4 fingerprintVendor guards: empty + <4-char reads → null; punctuation/case
normalized before matching; and the CRITICAL one — a rejected logo (logo_valid=false,
e.g. Versace's mislabeled 'Savannah') is NEVER matched, proving the validation gate keeps
mislabels out of vendor resolution. 32→36 tests, lint clean. $0 (local brainstorm + tests).
Files touched
M OVERNIGHT_LEDGER.mdM test-analyze-ocr.js
Diff
commit 0801a44206116bf6cfa9608b0b6a2622798d1da6
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Fri Jun 26 05:34:05 2026 -0700
test: fingerprintVendor edge cases + reject OCR-confidence-threshold (cycle 12)
Brainstorm (qwen3:14b) → triaged 5: rejected 3 as already-done/misconceived (font
smoothing, prefix cache, logo ROTATION — fingerprints are text not pixels), investigated
+ rejected-with-evidence the OCR confidence threshold (Vision returns confidence 1.000
or NO read across all blur/noise tiers — there's no low-confidence band to threshold),
and shipped the safe test-coverage pick.
Added 4 fingerprintVendor guards: empty + <4-char reads → null; punctuation/case
normalized before matching; and the CRITICAL one — a rejected logo (logo_valid=false,
e.g. Versace's mislabeled 'Savannah') is NEVER matched, proving the validation gate keeps
mislabels out of vendor resolution. 32→36 tests, lint clean. $0 (local brainstorm + tests).
---
OVERNIGHT_LEDGER.md | 6 ++++++
test-analyze-ocr.js | 16 ++++++++++++++++
2 files changed, 22 insertions(+)
diff --git a/OVERNIGHT_LEDGER.md b/OVERNIGHT_LEDGER.md
index 0073f59..024b17f 100644
--- a/OVERNIGHT_LEDGER.md
+++ b/OVERNIGHT_LEDGER.md
@@ -23,6 +23,11 @@ the single highest-value safe one, the officer executes it, and the loop resched
- [x] /code-review pass — NO critical; 3 robustness/security findings fixed (learn cap, fp len-guard, auth colon)
- [x] GATED (drafted to pending-approval): weekly launchd refresh — plist staged
+### Brainstorm pool (cycle 12, qwen3:14b $0) — triaged
+- [reject] Font smoothing (Vision handles low-res) · SKU prefix cache (profiles already in-mem) · logo fingerprint ROTATION (fingerprints are TEXT not pixels; VLM handles rotation)
+- [REJECTED w/ evidence] OCR confidence thresholding: Vision returns confidence 1.000 or NO read across blur+noise tiers — no low-confidence band exists for a threshold to catch. Moot (cycle 12 A/B).
+- [x] Test-coverage: fingerprintVendor edge cases incl. rejected-logo-never-matches (cycle 12)
+
### Brainstorm pool (cycle 10, qwen3:8b $0) — triaged
- [done-already] SKU prefix boost (180 vendor profiles) · early-exit on confident OCR (topStrong fast-lock)
- [ ] UX: surface OCR confidence on the live overlay (topStrong vs tentative) — marginal, no per-token score yet
@@ -48,3 +53,4 @@ the single highest-value safe one, the officer executes it, and the loop resched
- bgIdentify may teach a prefix from an unresolved OCR code (intentional fire-and-forget; vendor must already be real via lexicon/fuzzy; low impact).
| 10 | brainstorm (qwen3:8b $0) → pick #5 (no fork) | harden analyzeOcr ranking contract with 11 adversarial/degraded-input tests (3-char/no-digit/dashed codes, <4 barcode, two-brand order, lowercase brand, dup dedup, two barcodes) | 21→32 tests pass; lint clean; no behavior change (all pre-verified correct) | $0 |
| 11 | investigate→pivot | A/B proved Swift low-light pre-pass MOOT (Vision reads 4-level contrast raw); pivoted to UX: tentative "hold steady · CODE" cue when a non-strong read needs a 2nd frame | OCR reads all contrast tiers raw; inline JS+lint+32 tests green; page 200 | $0 |
+| 12 | brainstorm (qwen3:14b $0) → investigate+pick #5 | A/B proved OCR-confidence-threshold MOOT (Vision = 1.000 or no-read); shipped fingerprintVendor edge tests (empty/short→null, punct-normalized, REJECTED logo never matches) | 32→36 tests pass; lint clean | $0 |
diff --git a/test-analyze-ocr.js b/test-analyze-ocr.js
index 25e7713..feae271 100644
--- a/test-analyze-ocr.js
+++ b/test-analyze-ocr.js
@@ -148,5 +148,21 @@ const bc = (payload, sym = 'Code128') => `BC\t${payload}\t${sym}`;
ok(twoBc.topStrong === true, 'edge: a barcode forces topStrong even with two present');
}
+// ── fingerprintVendor edge cases (cycle 12 brainstorm: harden the tiebreaker contract) ──
+{
+ eq(fingerprintVendor('', 'serif'), null, 'fp edge: empty read → null');
+ eq(fingerprintVendor('ab', 'serif'), null, 'fp edge: <4-char read → null');
+ // punctuation/case is normalized away before matching
+ const k = fingerprintVendor('kravet!!!', 'sans caps');
+ ok(k && k.vendor === 'Kravet', 'fp edge: punctuation/case normalized → resolves');
+ // CRITICAL: a REJECTED logo (logo_valid=false) must never resolve, even though its
+ // stored logo_reads would match — proves the validation gate keeps mislabels out.
+ const rejected = Object.entries(VENDOR_PROFILES).find(([, p]) => p.logo_valid === false && p.logo_reads);
+ if (rejected) {
+ eq(fingerprintVendor(rejected[1].logo_reads, rejected[1].logo_typeface || ''), null,
+ `fp edge: rejected logo (${rejected[0]} reads '${rejected[1].logo_reads}') is never matched`);
+ } else { ok(true, 'fp edge: (no rejected logo in data to assert against)'); }
+}
+
console.log(`\nanalyzeOcr/vendor tests: ${pass} passed, ${fail} failed`);
process.exit(fail ? 1 : 0);
← 8f32cd4 auto-save: 2026-06-26T05:12:44 (1 files) — data/build.json
·
back to Dw Photo Capture
·
test: fuzzyVendor edge guards + disk-full debug note (cycle f050ab3 →