diff --git a/docs/memory/claude_inventory_validation_20260513.md b/docs/memory/claude_inventory_validation_20260513.md index fcb6f47..98a8397 100644 --- a/docs/memory/claude_inventory_validation_20260513.md +++ b/docs/memory/claude_inventory_validation_20260513.md @@ -30,6 +30,7 @@ - `migrations/031` 權限已是 `644`。 - `app.py` 的 `SYSTEM_VERSION` 已從 `config.py` import,app 內只留版本註解。 - V2 提到的 `app.py` 死 import 與 `scheduler.py import schedule` 已不成立;`app.py` 仍使用 `schedule.run_pending()` 等呼叫。 +- `tests/test_phase3f_cleanup_contracts.py` 已補 guard:V2 點名的舊 app imports 不得回來,且 `app.py` 的 active `schedule` 用法不可被誤刪。 - Cron 盲區清單多數已補 `_notify_scheduler_failure()`;ROI 月報已避開 09:00 改 09:05,AI smoke 已是 09:10。 - V2 指出的 9 個 cron 盲區已補回歸守門:8 個 `run_scheduler.py` wrapper 必須呼叫 `_notify_scheduler_failure()`,`scheduler.py::run_promo_event_task` 必須呼叫 `notify_failure()`。 - 09:00 排程衝突已有回歸守門:`daily_report=09:00`、`roi_monthly_report=09:05`、`ai_smoke_daily_summary=09:10` 必須保持錯開。 @@ -95,3 +96,5 @@ - `b22cbb2` 守住 scheduler 失敗告警覆蓋 - `8026b93` 守住 scheduler 早晨排程錯開 - `eb6886e` 同步 scheduler 排程摘要 +- `b24241f` 守住 migration blocker 修補 +- `6c86839` 守住盤點誤判依賴 diff --git a/tests/test_phase3f_cleanup_contracts.py b/tests/test_phase3f_cleanup_contracts.py index 89fa99a..b879cd3 100644 --- a/tests/test_phase3f_cleanup_contracts.py +++ b/tests/test_phase3f_cleanup_contracts.py @@ -81,6 +81,21 @@ def test_scheduler_does_not_silently_swallow_exceptions(): assert not re.search(r"except(?: Exception)?[^\n]*:\n\s+pass(?:\s|#|$)", scheduler_source) +def test_v2_flagged_imports_are_removed_or_active(): + app_source = (ROOT / "app.py").read_text(encoding="utf-8") + scheduler_source = (ROOT / "scheduler.py").read_text(encoding="utf-8") + + for module_name in ["math", "hashlib", "zipfile", "io", "traceback"]: + assert not re.search(rf"^\s*import\s+{module_name}\b", app_source, re.MULTILINE) + assert "EXCEL_EXPORT_DIR" not in app_source + assert "DATABASE_TYPE" not in app_source + + assert re.search(r"^\s*import\s+schedule\b", app_source, re.MULTILINE) + assert "schedule.run_pending()" in app_source + assert "schedule.every(" in app_source + assert not re.search(r"^\s*import\s+schedule\b", scheduler_source, re.MULTILINE) + + def test_tracked_backup_artifacts_stay_removed(): forbidden_artifacts = [ "app.py.backup_login_required",