Port the remaining consistency guards from cmautobuy's
planExistingMatchedInnerCodeItems into assignExistingBoundItems:
- Reject the whole multi-piece group if any candidate's raw ProductSpec,
sku or variationSku differs from the lowest-ID candidate. Candidates
are matched via NormalizeSpecKey, so raw values can legitimately differ
even when normalized keys agree; auto-assigning across genuinely
different items must be blocked.
- Re-verify each candidate against stallMatches when record.Stall is
non-empty, since the no-SKU fallback path in matchEvidence can hand
back candidates that were never stall-checked.
- Reject candidates with a non-positive or duplicate detail ID.
Added one regression test per guard plus a happy-path test confirming
legitimate multi-piece assignment still succeeds.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NTDbDcwbDw1TSAcE6wfh2F