The crop lane asked the phone for a full-resolution crop of a facing the
frame could not decide. Four defects made that unsafe or useless:
* A capability was half-applied. `crop: true` without a usable
`max_crop_bytes` enabled the lane on the client's say-so, leaving the two
sides believing different limits. A capability is now believed whole or
refused with BAD_MESSAGE, and the limit must be an integer in 1..1048576
(bool is an int in Python and is not a limit).
* A small JPEG could claim enormous dimensions. The header is now read
without decoding and anything over 4 megapixels is refused before the
decode allocates it.
* A request was single-use, so an expired one stranded a facing only the
crop lane could decide. The lane now spends the same max_attempts budget
the frame path spends, refilled on method change and on settled-label
drift, and a phone that never answers still cannot loop.
* A candidate could be asked about from a box the frame path would refuse:
clipped by the frame edge, carried over from an earlier frame, or measured
at a score the tracker does not trust. Both lanes now share one edge gate,
and only a track whose box this frame actually measured is asked about.
Drift and method change also cleared `identity` but left `confirmed = True`,
which permanently blocked both the crop lane and label inheritance for that
track; both now clear it, without which the budget reset was dead code.
Blur and glare are refused as whole-capture faults, while `too_far` is
exempt on purpose: a distant shelf is the one frame a native-resolution crop
exists to decide.