def test_aider_heal_allowed_file_pattern_accepts_nested_service_modules(): from services import aider_heal_executor as svc assert svc.ALLOWED_FILE_PATTERN.match("services/market_intel/phase.py") assert svc.ALLOWED_FILE_PATTERN.match("routes/market_intel_mcp_run_routes.py") assert svc.ALLOWED_FILE_PATTERN.match("database/ai_models.py") assert not svc.ALLOWED_FILE_PATTERN.match("tests/test_market_intel_skeleton.py") assert not svc.ALLOWED_FILE_PATTERN.match("config.py") def test_aider_heal_rejects_disallowed_file_before_ssh(monkeypatch): from services import aider_heal_executor as svc messages = [] def fail_if_called(*_args, **_kwargs): raise AssertionError("SSH preflight should not run for disallowed files") monkeypatch.setattr(svc, "_ssh_exec", fail_if_called) monkeypatch.setattr(svc, "_notify_telegram", messages.append) result = svc.execute_code_fix( error_type="code_review_security", error_message="疑似硬編碼敏感字串", target_file="tests/test_market_intel_skeleton.py", ) assert result["success"] is False assert result["commit_sha"] is None assert result["reverted"] is False assert "不在 ADR-020 自動修復白名單" in result["message"] assert messages assert "已略過自動修復" in messages[0] def test_aider_heal_health_accepts_current_healthy_status(monkeypatch): from services import aider_heal_executor as svc monkeypatch.setattr(svc, "_http_get_json", lambda _url: {"status": "healthy"}) assert svc._wait_for_health( "https://mo.wooo.work/health", timeout_seconds=1, interval_seconds=0, ) is True