Skip to content

fix(scripts): the last three close sites, and stop the test pollution I shipped - #190

Merged
Cipher208 merged 1 commit into
masterfrom
fix/last-three-close-sites
Nov 3, 2026
Merged

Cipher208 merged 1 commit into
masterfrom
fix/last-three-close-sites

Conversation

@Cipher208

Copy link
Copy Markdown
Owner

Что

Последние три скрипта того же класса, что #189, — у каждого свой дефект:

файл что было что стало
scripts/sync_skills.py close после sync_external → raise пропускал закрытие (замер: close не вызван, процесс убит на 20 с) finally + лог сбоя закрытия
scripts/verify_autohooks.py close только на успехе, в функции с os._exit → исключение висело до 45-секундного faulthandler _run_checks() + finally перед os._exit; выход за <1 с
scripts/backfill_memory_kind.py finally был, но contextlib.suppress глотал сбой закрытия except Exception: logger.warning(..., exc_info=True)

os._exit в verify_autohooks оставлен и стоит вне try/finally — внутри finally никогда бы не выполнился. Код возврата на успехе не изменился (26/26, exit 0).

Регрессия, которую я внесла в #189 — здесь же исправлена

pytest tests/test_scripts на 2cffe18: 7 failed / 166 passed. На b5060fe: 162 passed. Полный suite это скрывал порядком.

Причина: test_close_all_on_failure.py патчит shared.write_dispatch.get_write_dispatch, а core.memory (у него from shared.write_dispatch import get_write_dispatch на уровне модуля) впервые импортируется внутри патченного окна — и навсегда связывает заглушку. Дальше test_mirror_identity.py падает на её собственном RuntimeError: boom.

monkeypatch восстанавливал shared.write_dispatch, но не копию в core.memory. Затронуто было четыре модуля: core.episodic, core.memory, core.session, core.session_quality.

Лечение — autouse-фикстура: снимает реальную функцию на setup и на teardown перебиндивает её во всех загруженных модулях. Это лечит механизм, а не три конкретных случая: любой модуль, импортированный в окне, чинится.

Тесты не ослаблены

Откат любого из трёх фиксов роняет свой тест — проверено для всех трёх:

откат результат
sync_skills.py 1 failed (- close / + fail)
backfill_memory_kind.py 1 failed (нет warning)
verify_autohooks.py 2 failed (нет close; subprocess висит до 20 с)

Проверка

  • 2853 passed (полный suite);
  • pytest tests/test_scripts — 177 passed в обоих порядках файлов и на двух сидах pytest-randomly;
  • ruff check чисто, ruff format 754 файла, mypy 63 = baseline;
  • blind verifier: дефектов нет, «Are the three scripts fixed, and is the test pollution gone without weakening the tests? — YES».

Остаточный риск, записанный честно

Фикстура живёт в test_close_all_on_failure.py, поэтому защищает только этот модуль. Тест в другом месте с тем же паттерном (патч + ленивый импорт) снова протечёт; репозиторный tests/conftest.py защитил бы весь suite. Сейчас такого теста нет.

… I shipped

Three scripts still had the #189 class, each in a different shape:

  - `sync_skills.py::sync_one` closed AFTER `sync_external`, so a raise there
    skipped the close entirely (measured at 2cffe18: close never called, the
    process hung and was killed at 20 s);
  - `verify_autohooks.py` closed on the success path only, in the same function
    that ends in `os._exit`. An exception therefore hung until the 45 s
    faulthandler guard fired, and the exit code came from the guard rather than
    from the real failure. The checks moved into `_run_checks()` and `main()`
    now closes in a `finally` before `os._exit` — which stays where it is, on
    purpose, and outside the `try`: inside it, `finally` would never run;
  - `backfill_memory_kind.py` already had `finally`; its defect was a silent
    `contextlib.suppress(Exception)` around the close, which made a genuinely
    broken shutdown indistinguishable from a clean one.

All three now log a failed close (`logger.warning(..., exc_info=True)`) instead
of swallowing it, matching #189.

Separately, this fixes a regression #189 put on master. `test_close_all_on_failure.py`
patched `shared.write_dispatch.get_write_dispatch`, and `core.memory` — which does
`from shared.write_dispatch import get_write_dispatch` at module level — was first
imported lazily INSIDE that patched window. It bound the stub permanently, so
`test_mirror_identity.py` later failed with the stub's own `RuntimeError: boom`:
`pytest tests/test_scripts` read 7 failed on 2cffe18 against 162 passed on
b5060fe. The full suite hid it behind test ordering.

An autouse fixture now snapshots the real function and rebinds it in every loaded
module at teardown. It fixes the mechanism rather than the three instances: any
module imported inside the window is repaired, not just `core.memory`. The tests
are not weakened — reverting any one of the three script fixes still fails its
test, checked for all three.
@coderabbitai

coderabbitai Bot commented Nov 3, 2026

Copy link
Copy Markdown

Important

  • Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

CodeRabbit Verify

  • Run CodeRabbit Verify to test the changes in this pull request.

@github-actions github-actions Bot added the fix label Nov 3, 2026
@Cipher208
Cipher208 merged commit 7b88d04 into master Nov 3, 2026
19 checks passed
@Cipher208
Cipher208 deleted the fix/last-three-close-sites branch November 3, 2026 21:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant