From 235c55fd6fa4ec772e721372af7b86e45bc058a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Sun, 19 Jul 2026 15:01:25 +0300 Subject: [PATCH] =?UTF-8?q?fix(finder):=20=D1=80=D0=B5=D0=B0=D0=BB=D1=8C?= =?UTF-8?q?=D0=BD=D1=8B=D0=B9=20=D1=82=D0=B5=D0=BB=D0=B5=D1=84=D0=BE=D0=BD?= =?UTF-8?q?=20=D0=B4=D0=B8=D1=80=D0=B5=D0=BA=D1=82=D0=BE=D1=80=D0=B0=20?= =?UTF-8?q?=D1=83=D0=B1=D1=80=D0=B0=D0=BD=20=D0=B8=D0=B7=20=D1=82=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D0=BE=D0=B2=20=D1=81=D0=BB=D1=83=D0=B6=D0=B1=D1=8B?= =?UTF-8?q?=20=D0=BF=D0=BE=D0=B8=D1=81=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Утренняя чистка ПДн искала только в app/ и docs/ и пропустила моя/sales-finder — папка скрыта от обычного поиска, номер оставался живым в трёх тестах (26 раз). Заменён на фиктивный 79990000001, все 321 тест зелёные. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/observer/STATUS.md | 8 +-- моя/sales-finder/tests/test_phonecheck.py | 62 +++++++++++------------ моя/sales-finder/tests/test_render.py | 2 +- моя/sales-finder/tests/test_ui.py | 4 +- 4 files changed, 38 insertions(+), 38 deletions(-) diff --git a/docs/observer/STATUS.md b/docs/observer/STATUS.md index f65d080d..dbf55049 100644 --- a/docs/observer/STATUS.md +++ b/docs/observer/STATUS.md @@ -1,6 +1,6 @@ # Brain Status (auto-generated) -Last updated: 2026-07-19T08:53:58.508Z +Last updated: 2026-07-19T09:11:02.760Z | Контролёр | Состояние | Детали | |---|---|---| @@ -112,9 +112,9 @@ Episodes since last run: 542 / threshold: 10 | PID | Имя | CPU-время | Возраст | |---|---|---|---| -| 3540 | MsMpEng | 5.14ч | NaNч | -| 10836 | Code | 2.88ч | NaNч | -| 1312 | svchost | 1.11ч | 0.0ч | +| 3540 | MsMpEng | 5.22ч | NaNч | +| 10836 | Code | 2.95ч | NaNч | +| 1312 | svchost | 1.13ч | 0.0ч | ⚠️ Проверь, не «осиротевшие» ли это процессы от завершённых Claude-сессий. diff --git a/моя/sales-finder/tests/test_phonecheck.py b/моя/sales-finder/tests/test_phonecheck.py index 69c7011b..839abb57 100644 --- a/моя/sales-finder/tests/test_phonecheck.py +++ b/моя/sales-finder/tests/test_phonecheck.py @@ -11,7 +11,7 @@ def test_normalize_11_digits_with_7(): assert pc.normalize_phone("79139884603") == ("79139884603", "") def test_normalize_10_digits_mobile(): - assert pc.normalize_phone("9990000009") == ("79990000009", "") + assert pc.normalize_phone("9990000001") == ("79990000001", "") def test_normalize_10_digits_landline(): assert pc.normalize_phone("3812361211") == ("73812361211", "") @@ -50,24 +50,24 @@ def test_prepare_drops_tail_fragments(): assert [g["phone"] for g in got] == ["79059223914"] def test_prepare_keeps_order_and_notes(): - got = pc.prepare_phones(["9990000009", "3812361211"], city="Омск") - assert [g["phone"] for g in got] == ["79990000009", "73812361211"] + got = pc.prepare_phones(["9990000001", "3812361211"], city="Омск") + assert [g["phone"] for g in got] == ["79990000001", "73812361211"] assert all(g["note"] == "" for g in got) def test_prepare_real_screenshot_case(): - raws = ["9990000009", "9139884603", "3812361211", "89139884603", + raws = ["9990000001", "9139884603", "3812361211", "89139884603", "89059223914", "9223914", "3812302920", "3812606679"] got = pc.prepare_phones(raws, city="Омск") # 9139884603 выброшен как хвост 89139884603 (остаётся ВТОРОЕ вхождение), # 9223914 — хвост 89059223914 assert [g["phone"] for g in got] == [ - "79990000009", "73812361211", "79139884603", + "79990000001", "73812361211", "79139884603", "79059223914", "73812302920", "73812606679"] # --- parse_clean_response / clean_phone: ДаДата «Стандартизация телефона» --- -CLEAN_MOBILE = [{"source": "+79990000009", "type": "Мобильный", "phone": "+7 999 000-00-09", +CLEAN_MOBILE = [{"source": "+79990000001", "type": "Мобильный", "phone": "+7 999 000-00-01", "provider": "ПАО \"МТС\"", "city": None, "region": "Омская", "qc": 0}] CLEAN_LANDLINE = [{"source": "+73812361211", "type": "Стационарный", "phone": "+7 3812 36-12-11", @@ -99,15 +99,15 @@ def test_clean_phone_uses_cache(tmp_path): calls.append(url) return CLEAN_MOBILE keys = ("api", "secret") - a = pc.clean_phone("+79990000009", keys, fetch=fake_fetch, cache_dir=str(tmp_path)) - b = pc.clean_phone("+79990000009", keys, fetch=fake_fetch, cache_dir=str(tmp_path)) + a = pc.clean_phone("+79990000001", keys, fetch=fake_fetch, cache_dir=str(tmp_path)) + b = pc.clean_phone("+79990000001", keys, fetch=fake_fetch, cache_dir=str(tmp_path)) assert a["kind"] == b["kind"] == "mobile" assert len(calls) == 1 # второй раз — из кэша, денег не тратим def test_clean_phone_network_error_is_unknown(tmp_path): def boom(url, headers, body): raise IOError("сеть упала") - got = pc.clean_phone("+79990000009", ("a", "s"), fetch=boom, cache_dir=str(tmp_path)) + got = pc.clean_phone("+79990000001", ("a", "s"), fetch=boom, cache_dir=str(tmp_path)) assert got["kind"] == "unknown" CLEAN_VIRTUAL = [{"source": "+79001112233", "type": "Виртуальный", "phone": "+7 900 111-22-33", @@ -140,8 +140,8 @@ def test_clean_phone_does_not_cache_service_error(tmp_path): def fake_fetch(url, headers, body): calls.append(url) return responses[len(calls) - 1] - a = pc.clean_phone("+79990000009", ("a", "s"), fetch=fake_fetch, cache_dir=str(tmp_path)) - b = pc.clean_phone("+79990000009", ("a", "s"), fetch=fake_fetch, cache_dir=str(tmp_path)) + a = pc.clean_phone("+79990000001", ("a", "s"), fetch=fake_fetch, cache_dir=str(tmp_path)) + b = pc.clean_phone("+79990000001", ("a", "s"), fetch=fake_fetch, cache_dir=str(tmp_path)) assert a["kind"] == "unknown" and b["kind"] == "mobile" assert len(calls) == 2 # сбой сервиса не закэшировался — со второй попытки добрали @@ -179,7 +179,7 @@ def test_hlr_alive_send_then_poll(tmp_path): def fake_fetch(url, params): calls.append(url) return seq[len(calls) - 1] - v = pc.hlr_alive("+79990000009", ("login", "psw"), + v = pc.hlr_alive("+79990000001", ("login", "psw"), fetch=fake_fetch, cache_dir=str(tmp_path), pause=0) assert v == "alive" assert calls[0].endswith("send.php") and calls[1].endswith("status.php") @@ -199,7 +199,7 @@ def test_hlr_alive_cached_no_second_charge(tmp_path): def test_hlr_alive_timeout_is_unknown_and_not_cached(tmp_path): def fake_fetch(url, params): return {"id": 77, "cnt": 1} if url.endswith("send.php") else {"status": 0, "err": 0} - v = pc.hlr_alive("+79990000009", ("l", "p"), fetch=fake_fetch, + v = pc.hlr_alive("+79990000001", ("l", "p"), fetch=fake_fetch, cache_dir=str(tmp_path), tries=2, pause=0) assert v == "unknown" assert not list(tmp_path.iterdir()) # unknown не кэшируем @@ -207,7 +207,7 @@ def test_hlr_alive_timeout_is_unknown_and_not_cached(tmp_path): def test_hlr_alive_network_error_is_unknown(tmp_path): def boom(url, params): raise IOError() - assert pc.hlr_alive("+79990000009", ("l", "p"), fetch=boom, + assert pc.hlr_alive("+79990000001", ("l", "p"), fetch=boom, cache_dir=str(tmp_path)) == "unknown" def test_parse_hlr_string_fields(): @@ -229,12 +229,12 @@ def test_hlr_alive_id_zero_is_valid(tmp_path): def fake_fetch(url, params): calls.append(url) return seq[len(calls) - 1] - v = pc.hlr_alive("+79990000009", ("l", "p"), fetch=fake_fetch, + v = pc.hlr_alive("+79990000001", ("l", "p"), fetch=fake_fetch, cache_dir=str(tmp_path), pause=0) assert v == "alive" # id=0 — успешная оплаченная отправка, опрашиваем статус def test_hlr_alive_no_id_is_unknown(tmp_path): - v = pc.hlr_alive("+79990000009", ("l", "p"), + v = pc.hlr_alive("+79990000001", ("l", "p"), fetch=lambda url, params: {"cnt": 1}, cache_dir=str(tmp_path), pause=0) assert v == "unknown" @@ -253,11 +253,11 @@ def _hlr_stub(phone, creds, **kw): def test_check_full_happy_path(): checked, warn = pc.check_contact_phones( - ["9990000009", "9139884603", "3812361211"], "Омск", + ["9990000001", "9139884603", "3812361211"], "Омск", ("api", "secret"), ("login", "psw"), clean=_clean_stub, hlr=_hlr_stub) assert warn is None by = {c["phone"]: c for c in checked} - assert by["79990000009"]["kind"] == "mobile" and by["79990000009"]["alive"] == "alive" + assert by["79990000001"]["kind"] == "mobile" and by["79990000001"]["alive"] == "alive" assert by["79139884603"]["alive"] == "dead" assert by["73812361211"]["kind"] == "landline" and by["73812361211"]["alive"] is None @@ -271,7 +271,7 @@ def test_check_no_dadata_keys_still_normalizes(): def test_check_no_smsc_creds_types_only(): checked, warn = pc.check_contact_phones( - ["9990000009"], "Омск", ("api", "secret"), None, + ["9990000001"], "Омск", ("api", "secret"), None, clean=_clean_stub, hlr=_hlr_stub) assert checked[0]["kind"] == "mobile" and checked[0]["alive"] is None assert "smsc.txt" in warn @@ -281,51 +281,51 @@ def test_check_hlr_only_for_mobiles(): def hlr_spy(phone, creds, **kw): calls.append(phone) return "alive" - pc.check_contact_phones(["9990000009", "3812361211"], "Омск", + pc.check_contact_phones(["9990000001", "3812361211"], "Омск", ("a", "s"), ("l", "p"), clean=_clean_stub, hlr=hlr_spy) - assert calls == ["79990000009"] # городской HLR-ом не проверяем (деньги) + assert calls == ["79990000001"] # городской HLR-ом не проверяем (деньги) def test_sort_mobiles_first_gone_last(): checked = [ {"phone": "73812361211", "kind": "landline", "alive": None}, {"phone": "79139884603", "kind": "mobile", "alive": "dead"}, - {"phone": "79990000009", "kind": "mobile", "alive": "alive"}, + {"phone": "79990000001", "kind": "mobile", "alive": "alive"}, {"phone": "79000000000", "kind": "mobile", "alive": "gone"}, ] got = [c["phone"] for c in pc.sort_for_display(checked)] - assert got == ["79990000009", "79139884603", "73812361211", "79000000000"] + assert got == ["79990000001", "79139884603", "73812361211", "79000000000"] def test_check_junk_not_hlr_checked_and_one_raise_does_not_kill_batch(): # мусорный номер не гоняем через HLR (деньги), а упавший clean не роняет остальные calls = [] def clean_stub(phone, keys, **kw): - if phone == "79990000009": + if phone == "79990000001": raise IOError("сервис лёг") return {"kind": "junk", "provider": "", "city": "", "qc": 2} def hlr_spy(phone, creds, **kw): calls.append(phone) return "alive" checked, warn = pc.check_contact_phones( - ["9990000009", "9139884603"], "Омск", ("a", "s"), ("l", "p"), + ["9990000001", "9139884603"], "Омск", ("a", "s"), ("l", "p"), clean=clean_stub, hlr=hlr_spy) - assert [c["phone"] for c in checked] == ["79990000009", "79139884603"] + assert [c["phone"] for c in checked] == ["79990000001", "79139884603"] assert checked[0]["kind"] == "unknown" # упавший clean → номер без пометки assert checked[1]["kind"] == "junk" assert calls == [] # ни junk, ни unknown в HLR не ушли def test_check_both_warnings_joined(): - _, warn = pc.check_contact_phones(["9990000009"], "Омск", None, None, + _, warn = pc.check_contact_phones(["9990000001"], "Омск", None, None, clean=_clean_stub, hlr=_hlr_stub) assert "dadata_clean_keys.txt" in warn and "smsc.txt" in warn and "; " in warn def test_check_unrecognized_raws_reported_not_lost(): checked, warn = pc.check_contact_phones( - ["9990000009", "12345"], "Омск", None, None, + ["9990000001", "12345"], "Омск", None, None, clean=_clean_stub, hlr=_hlr_stub) - assert [c["phone"] for c in checked] == ["79990000009"] + assert [c["phone"] for c in checked] == ["79990000001"] assert "не распознаны и скрыты: 12345" in warn @@ -342,9 +342,9 @@ def test_sort_junk_ranks_above_gone(): # --- label / is_dead: одна строка для показа --- def test_label_mobile_alive(): - c = {"phone": "79990000009", "kind": "mobile", "provider": "МТС", + c = {"phone": "79990000001", "kind": "mobile", "provider": "МТС", "city": "", "alive": "alive", "note": ""} - assert pc.label(c) == "79990000009 · МТС" + assert pc.label(c) == "79990000001 · МТС" def test_label_landline(): c = {"phone": "73812361211", "kind": "landline", "provider": "Ростелеком", diff --git a/моя/sales-finder/tests/test_render.py b/моя/sales-finder/tests/test_render.py index 26d367e3..c5da0893 100644 --- a/моя/sales-finder/tests/test_render.py +++ b/моя/sales-finder/tests/test_render.py @@ -29,7 +29,7 @@ def test_to_rows_has_contact_columns(): def test_to_rows_uses_checked_phone_labels(): from salesfinder.phonecheck import label as pc_label - alive = {"phone": "79990000009", "kind": "mobile", "provider": "МТС", + alive = {"phone": "79990000001", "kind": "mobile", "provider": "МТС", "city": "", "alive": "alive", "note": ""} dead = {"phone": "79139884603", "kind": "mobile", "provider": "Билайн", "city": "", "alive": "dead", "note": ""} diff --git a/моя/sales-finder/tests/test_ui.py b/моя/sales-finder/tests/test_ui.py index 9d5b66ba..88eb94ed 100644 --- a/моя/sales-finder/tests/test_ui.py +++ b/моя/sales-finder/tests/test_ui.py @@ -398,7 +398,7 @@ def test_results_shows_collected_contacts(): def test_results_shows_checked_phones_dead_struck_through(): - alive = {"phone": "79990000009", "kind": "mobile", "provider": "МТС", + alive = {"phone": "79990000001", "kind": "mobile", "provider": "МТС", "city": "", "alive": "alive", "note": ""} offline = {"phone": "79139884603", "kind": "mobile", "provider": "Билайн", "city": "", "alive": "dead", "note": ""} @@ -411,7 +411,7 @@ def test_results_shows_checked_phones_dead_struck_through(): "evidence": [], "hotness": 90}]} html = ui.results_html(run) assert "79000000000 · не существует" in html - assert "79990000009 · МТС" in html + assert "79990000001 · МТС" in html assert "79139884603 · Билайн" in html assert "79139884603" not in html assert "отключён" not in html