Root cause: _DEDUP_HOUSE_NO_RE требовал trailing \b после захваченной
цифры/литеры. Кириллическая буква и цифра — оба \w, между ними нет
word-boundary, поэтому когда avito приклеивает название станции метро
прямо к номеру дома без пробела («2Чкаловская11-15 мин. пешком»), матч
цифры «2» целиком отменялся, и .search() уезжал вправо до дистанции
«11-15» (где дефис даёт настоящую границу), ошибочно принимая «15» за
номер дома.
Фикс: убрали trailing \b (незачем — \d+ уже жадный), сузили суффикс-
литеру условием "это последний word-символ токена" через (?!\w) — не
просто "не кириллическая буква", а вообще ЛЮБОЙ word-символ (буква ИЛИ
цифра). Первая версия фикса ((?![а-яё]), из первоначального дизайна)
ловила метро-кейс, но ломала 4 существующих теста: avito-формат «6к1»
(литера корпуса приклеена к цифре без пробела) стал давать house="6к",
расходясь с эквивалентным domklik-форматом «6 к1» → "6" — guard_house
видел «6к» != «6» и блокировал законный cross-source merge. (?!\w)
устраняет и метро-баг, и эту регрессию разом: «6к1» теперь тоже даёт "6".
guard_house/union() не тронуты — чистая extraction-фикс, guard уже
корректно обрабатывает equal-or-missing house_no.
9 новых тестов (глухие метро-имена: обычное/дефисное/короткое; пин
letter-suffix/corpus-slash; partial-capture для глухого corpus-letter;
limitation-пин для двух склеенных числовых прогонов; 2 e2e merge/no-merge)
+ обновлены 2 существующих pinned-ожидания под улучшенное поведение "6к1".