mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
docs: #398 spec revision 2 per SPEC-REVIEW-398-r1
User-Visible: no Issue: #398
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
- Issue: https://github.com/Matysh/houseplan-card/issues/398
|
- Issue: https://github.com/Matysh/houseplan-card/issues/398
|
||||||
- Приоритет: P2, infra/tests; полный трек — класс B (тесты и гейт), меняется
|
- Приоритет: P2, infra/tests; полный трек — класс B (тесты и гейт), меняется
|
||||||
правило, а не продуктовый код
|
правило, а не продуктовый код
|
||||||
- Ревизия: 1 (2026-08-31)
|
- Ревизия: 2 (2026-08-31) — по SPEC-REVIEW-398-r1 (Medium: путь 2 несовместим с AC4)
|
||||||
|
|
||||||
## Сценарий
|
## Сценарий
|
||||||
|
|
||||||
@@ -68,20 +68,23 @@ custom_components.houseplan.coordinate_canonicalization
|
|||||||
статически — тогда гвард обязан отказывать (fail-closed): «не могу доказать,
|
статически — тогда гвард обязан отказывать (fail-closed): «не могу доказать,
|
||||||
что ключ не из `custom_components`» — это отказ, а не пропуск.
|
что ключ не из `custom_components`» — это отказ, а не пропуск.
|
||||||
|
|
||||||
**Что делать с `load_pure`.** Два допустимых исхода, выбор — за реализацией
|
**Что делать с `load_pure` — один путь: снимать за собой.** Ревизия 1
|
||||||
после замера:
|
допускала второй исход (объявить `pure_imports.py` вторым легальным
|
||||||
|
исключением), и ревьюер справедливо показал, что он несовместим с AC4:
|
||||||
|
регистрация тогда остаётся, и требование «после прогона нет лишних ключей»
|
||||||
|
краснеет по построению. Держать в ТЗ путь, ведущий в заведомо красный
|
||||||
|
критерий, нельзя — вариант снят.
|
||||||
|
|
||||||
1. **Снимать за собой.** `load_pure` восстанавливает `sys.modules` к состоянию
|
`load_pure` восстанавливает `sys.modules` к состоянию до вызова (образец —
|
||||||
до вызова (образец — обратимая подмена в `scripts/dump-config-schema.py`
|
обратимая подмена в `scripts/dump-config-schema.py` после #389). Существенная
|
||||||
после #389). Плюс: класс закрыт полностью. Минус: относительные импорты
|
деталь, выясненная замером: снимать только собственное имя **недостаточно**.
|
||||||
внутри загруженного модуля должны успеть отработать до восстановления —
|
Относительные импорты внутри загружаемого модуля подтягивают соседей, и после
|
||||||
проверить, что `exec_module` завершается раньше.
|
загрузки `junction_limits` в `sys.modules` остаются ещё `wall_segment_model` и
|
||||||
2. **Объявить единственным легальным исключением** рядом с conftest, с
|
`coordinate_canonicalization`. Снимать нужно всё, что появилось под префиксом
|
||||||
комментарием, почему именно ему можно, и с тестом, фиксирующим, что список
|
`custom_components` за время `exec_module`, — тогда после вызова остаются ровно
|
||||||
исключений состоит ровно из двух файлов и не растёт.
|
пустышки conftest. Проверено исполнением, включая повторный вызов подряд.
|
||||||
|
|
||||||
Предпочтителен (1): исключение, которое нельзя объяснить в одну строку,
|
Единственное исключение остаётся одно — `tests_backend/conftest.py`.
|
||||||
завтра станет прецедентом.
|
|
||||||
|
|
||||||
## Скоуп / не-скоуп
|
## Скоуп / не-скоуп
|
||||||
|
|
||||||
@@ -114,9 +117,8 @@ custom_components.houseplan.coordinate_canonicalization
|
|||||||
`sys.modules.setdefault(...)`/`update(...)` тоже отклоняются либо приводят к
|
`sys.modules.setdefault(...)`/`update(...)` тоже отклоняются либо приводят к
|
||||||
явному отказу «не могу доказать безопасность». Доказательство: по одному
|
явному отказу «не могу доказать безопасность». Доказательство: по одному
|
||||||
контракту на форму.
|
контракту на форму.
|
||||||
- **AC3**. `tests_backend/conftest.py` остаётся разрешённым, и это единственное
|
- **AC3**. `tests_backend/conftest.py` остаётся разрешённым и остаётся
|
||||||
исключение (либо два файла, если выбран путь 2 — тогда список
|
единственным исключением; список зафиксирован тестом, его рост краснеет.
|
||||||
зафиксирован тестом и его рост краснеет).
|
|
||||||
- **AC4**. После прогона всего `tests_backend/` в `sys.modules` нет ключей
|
- **AC4**. После прогона всего `tests_backend/` в `sys.modules` нет ключей
|
||||||
`custom_components*` сверх тех, что положил conftest. Доказательство:
|
`custom_components*` сверх тех, что положил conftest. Доказательство:
|
||||||
исполняемая проверка, а не чтение исходников.
|
исполняемая проверка, а не чтение исходников.
|
||||||
@@ -134,8 +136,7 @@ custom_components.houseplan.coordinate_canonicalization
|
|||||||
1. Синтетический файл с записью через переменную → гвард краснеет (AC1).
|
1. Синтетический файл с записью через переменную → гвард краснеет (AC1).
|
||||||
2. По контракту на каждую форму из AC2.
|
2. По контракту на каждую форму из AC2.
|
||||||
3. `conftest.py` со своей условной подменой → зелено (AC3).
|
3. `conftest.py` со своей условной подменой → зелено (AC3).
|
||||||
4. Попытка добавить третий файл в список исключений (если выбран путь 2) →
|
4. Попытка добавить второй файл в список исключений → красный.
|
||||||
красный.
|
|
||||||
|
|
||||||
**Backend** (`tests_backend/test_backend_quality.py` или новый файл):
|
**Backend** (`tests_backend/test_backend_quality.py` или новый файл):
|
||||||
|
|
||||||
@@ -155,10 +156,15 @@ custom_components.houseplan.coordinate_canonicalization
|
|||||||
строковых литералах; смягчение: тест-контракты на «похожий, но безопасный»
|
строковых литералах; смягчение: тест-контракты на «похожий, но безопасный»
|
||||||
код (например, `# sys.modules[...]` в комментарии) должны оставаться
|
код (например, `# sys.modules[...]` в комментарии) должны оставаться
|
||||||
зелёными.
|
зелёными.
|
||||||
- **Снятие регистрации ломает относительные импорты.** Если выбран путь (1) и
|
- **Снятие регистрации ломает относительные импорты.** Восстановление слишком
|
||||||
восстановление происходит слишком рано, `from .x import y` внутри модуля
|
рано уронит `from .x import y` внутри модуля. Смягчение: восстановление
|
||||||
упадёт. Смягчение: восстановление строго после `exec_module`, AC5 покрывает
|
строго после `exec_module` (замер: модуль полностью рабочий после очистки),
|
||||||
оба существующих места использования.
|
AC5 покрывает оба существующих места использования.
|
||||||
|
- **Соседи, подтянутые относительными импортами.** Снятие одного лишь
|
||||||
|
собственного имени оставляет `wall_segment_model` и
|
||||||
|
`coordinate_canonicalization` — замер это показал. Смягчение: снимать
|
||||||
|
разницу по префиксу `custom_components`, а не одно имя; AC4 проверяет
|
||||||
|
исполнением итог, а не намерение.
|
||||||
- **Скрытая зависимость от повторного импорта.** Модуль, загруженный дважды,
|
- **Скрытая зависимость от повторного импорта.** Модуль, загруженный дважды,
|
||||||
даёт два объекта классов; тесты, сравнивающие типы, могли на этом молча
|
даёт два объекта классов; тесты, сравнивающие типы, могли на этом молча
|
||||||
держаться. Смягчение: AC5 гоняет весь набор, а не отдельный файл.
|
держаться. Смягчение: AC5 гоняет весь набор, а не отдельный файл.
|
||||||
|
|||||||
Reference in New Issue
Block a user