Until now a tag reached the rules only if its text could be read. A tag that was
there but unreadable was indistinguishable from a missing one, so a missing-tag
claim rested on the reader's failures rather than on the shelf - the false
violation that made an earlier run report 106 of them.
Two measurements shaped the detector:
- The tags are printed ON the rail: a red brick-patterned strip running the width
of the shelf. The rail is therefore findable without reading anything, and it is
where tags must be looked for.
- On the rail, a tag is a run of columns carrying paper (bright, unsaturated)
against the brick. Projecting onto x finds 27 tags on add/image6.jpg where
connected components found 9, because tag text fragments a component at every
printed line.
The pipeline now merges the two views: a tag whose text was read keeps its fields,
a tag that was only seen is reported unreadable with its box. Measured on
add/image6.jpg: unreadable tags 8 -> 17, "no tag" 94 -> 85, and the per-row hints
became specific - "tags detected for 8 of 16 facings in this row".
That last number is also a domain fact worth keeping: this store prints one tag
per product, not per facing, so facings are the wrong denominator for a
missing-tag rule. The coverage bar keeps the rules silent until that is fixed,
which is the honest behaviour in the meantime.
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>