diff --git a/scripts/reboot-recovery/tests/test_momo_source_arrival_gate.py b/scripts/reboot-recovery/tests/test_momo_source_arrival_gate.py new file mode 100644 index 000000000..d8c59fe6b --- /dev/null +++ b/scripts/reboot-recovery/tests/test_momo_source_arrival_gate.py @@ -0,0 +1,89 @@ +from __future__ import annotations + +import importlib.util +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[3] +SCRIPT = ROOT / "scripts" / "reboot-recovery" / "momo-source-arrival-gate.py" + + +def load_module(): + spec = importlib.util.spec_from_file_location("momo_source_arrival_gate", SCRIPT) + assert spec and spec.loader + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +BASE_PREFLIGHT = """ +HOST ollama +MOMO_HEALTH_CODE 200 +MOMO_PUBLIC_HEALTH_CODE 200 +MOMO_APP_HEALTH healthy +SCHEDULER_RUNNING true +SCHEDULER_HEALTH healthy +DRIVE_ARCHIVE_LATEST_MODIFIED 2026-06-25T04:21:47.000Z +DRIVE_GLOBAL_LATEST_MODIFIED 2026-06-25T04:21:47.000Z +DRIVE_FAILED_COUNT 0 +DB_MONTHLY_SYNC 15383|15383|2026-06-01|2026-06-24|2026-06-01|2026-06-24 +DB_LATEST_DAILY_IMPORT_JOB 57|completed|即時業績_當日.xlsx|2026-06-25T13:16:47.359958|2026-06-25T13:18:02.964985|15383|15383|0 +IMPORT_CONFIG 當日業績匯入|即時業績_當日 +MOMO_DRIVE_TOKEN_SOURCE_PREFLIGHT PASS=20 WARN=3 BLOCKED=2 HOST=ollama@192.168.0.188 FRESHNESS_MAX_DAYS=2 +""" + + +def classify(extra_lines: str): + module = load_module() + return module.classify(module.parse_preflight(BASE_PREFLIGHT + extra_lines)) + + +def assert_no_write_authorization(result): + assert result["runtime_write_authorized"] is False + assert result["db_write_authorized"] is False + assert result["drive_move_authorized"] is False + assert result["manual_import_authorized"] is False + assert result["secret_value_collection_allowed"] is False + + +def test_source_absent_fail_closed(): + result = classify( + """ +DRIVE_INTAKE_COUNT 0 +DB_DAILY_FRESHNESS 3|2026-06-24 +""" + ) + + assert result["status"] == "blocked_source_absent_fail_closed" + assert result["exit_code"] == 2 + assert result["safe_import_preflight_allowed"] is False + assert_no_write_authorization(result) + + +def test_source_arrived_allows_only_safe_import_preflight(): + result = classify( + """ +DRIVE_INTAKE_COUNT 1 +DB_DAILY_FRESHNESS 3|2026-06-24 +""" + ) + + assert result["status"] == "source_arrived_ready_for_safe_import_preflight" + assert result["exit_code"] == 0 + assert result["safe_import_preflight_allowed"] is True + assert_no_write_authorization(result) + + +def test_freshness_green_requires_cold_start_recheck(): + result = classify( + """ +DRIVE_INTAKE_COUNT 0 +DB_DAILY_FRESHNESS 1|2026-06-26 +""" + ) + + assert result["status"] == "freshness_already_green_recheck_cold_start" + assert result["next_step"] == "rerun_post_reboot_readiness_summary_with_same_evidence_chain" + assert result["exit_code"] == 0 + assert result["safe_import_preflight_allowed"] is False + assert_no_write_authorization(result)