強化 EA JSON fallback 與 EDM cache 自癒
Some checks failed
CD Pipeline / deploy (push) Has been cancelled

This commit is contained in:
OoO
2026-05-21 18:58:52 +08:00
committed by AiderHeal Bot
parent 31f88898c2
commit 5a5f268358
9 changed files with 288 additions and 22 deletions

View File

@@ -316,6 +316,31 @@ def test_promo_dashboard_shared_cache_ignores_other_versions(tmp_path, monkeypat
assert edm_routes._load_shared_promo_dashboard_cache(cache_key) is None
def test_promo_dashboard_shared_cache_discards_corrupt_payload(tmp_path, monkeypatch):
from routes import edm_routes
shared_cache = tmp_path / "promo_dashboard_cache.pkl"
shared_cache.write_bytes(b"\x96not-a-pickle")
monkeypatch.setattr(edm_routes, "_PROMO_SHARED_CACHE_FILE", shared_cache)
assert edm_routes._load_shared_promo_dashboard_cache(("edm",)) is None
assert not shared_cache.exists()
def test_promo_dashboard_shared_cache_write_recovers_from_corrupt_payload(tmp_path, monkeypatch):
from routes import edm_routes
shared_cache = tmp_path / "promo_dashboard_cache.pkl"
shared_cache.write_bytes(b"\x96not-a-pickle")
cache_key = ("edm", "default", "desc", "", "bucket", (1, "ts", 1))
data = {"items_in_batch": [{"sku": "SKU-1"}]}
monkeypatch.setattr(edm_routes, "_PROMO_SHARED_CACHE_FILE", shared_cache)
edm_routes._write_shared_promo_dashboard_cache(cache_key, data)
assert edm_routes._load_shared_promo_dashboard_cache(cache_key) == data
def test_sales_analysis_preview_context_cache_avoids_reloading_options(tmp_path, monkeypatch):
from routes import sales_routes

View File

@@ -0,0 +1,99 @@
import asyncio
def test_elephant_orchestrator_extracts_fenced_json_object():
from services.elephant_alpha_orchestrator import ElephantAlphaOrchestrator
payload = ElephantAlphaOrchestrator._extract_json_object(
"""```json
{"priority":"high","confidence":0.91}
```"""
)
assert payload == {"priority": "high", "confidence": 0.91}
def test_elephant_orchestrator_extracts_json_object_from_prefaced_text():
from services.elephant_alpha_orchestrator import ElephantAlphaOrchestrator
payload = ElephantAlphaOrchestrator._extract_json_object(
'先做分析:\n{"priority":"medium","agents_required":["hermes"]}\n以上。'
)
assert payload["priority"] == "medium"
assert payload["agents_required"] == ["hermes"]
def test_elephant_orchestrator_fallback_uses_concrete_evidence_without_plan():
from services.elephant_alpha_orchestrator import ElephantAlphaOrchestrator
orchestrator = ElephantAlphaOrchestrator()
decision = orchestrator._fallback_decision(
{
"trigger_type": "market_opportunity",
"conditions": {
"_prefetched_hermes_threats": [
"[SKU-1] 測試商品MOMO $1,200 vs PChome $990每件價差 NT$ 210"
]
},
},
reason="測試解析失敗",
)
assert decision.priority == "high"
assert decision.confidence == 0.74
assert decision.execution_plan == []
assert "1 筆 DB/Hermes 價格比對實證" in decision.reasoning
assert "自動調價" in decision.reasoning
def test_elephant_orchestrator_fallback_without_evidence_has_no_openclaw_action():
from services.elephant_alpha_orchestrator import ElephantAlphaOrchestrator
orchestrator = ElephantAlphaOrchestrator()
decision = orchestrator._fallback_decision(
{"trigger_type": "market_opportunity", "conditions": {}},
reason="測試解析失敗",
)
assert decision.confidence == 0.6
assert decision.execution_plan == []
assert decision.agents_required == ["elephant_alpha"]
assert "沒有可稽核的 DB/Hermes 實證" in decision.reasoning
def test_elephant_orchestrator_uses_evidence_fallback_on_non_json_response(monkeypatch):
from services.elephant_service import ElephantResponse
from services.elephant_alpha_orchestrator import ElephantAlphaOrchestrator
class FakeElephant:
def generate(self, **_kwargs):
return ElephantResponse(
success=True,
content="\n我無法輸出 JSON但建議先處理。",
model="fake-model",
)
async def _noop_log(*_args, **_kwargs):
raise AssertionError("parse fallback should not log an LLM decision")
orchestrator = ElephantAlphaOrchestrator()
orchestrator.elephant = FakeElephant()
monkeypatch.setattr(orchestrator, "_get_recent_performance_metrics", lambda: {})
monkeypatch.setattr(orchestrator, "_get_agent_status", lambda: {})
monkeypatch.setattr(orchestrator, "_get_system_load", lambda: "normal")
monkeypatch.setattr(orchestrator, "_get_pending_actions_count", lambda: 0)
monkeypatch.setattr(orchestrator, "_log_decision", _noop_log)
decision = asyncio.run(orchestrator.analyze_and_coordinate({
"trigger_type": "price_drop_alert",
"conditions": {
"_prefetched_hermes_threats": [
"[SKU-9] 實證商品MOMO $1,000 vs PChome $800每件價差 NT$ 200"
]
},
}))
assert decision.priority == "high"
assert decision.execution_plan == []
assert "1 筆 DB/Hermes 價格比對實證" in decision.reasoning

View File

@@ -531,6 +531,38 @@ def test_marketplace_matcher_promotes_nivea_dry_lotion_with_long_shared_anchor()
assert "shared_identity_anchor_nivea_dry_lotion" in diagnostics.reasons
def test_marketplace_matcher_promotes_curel_body_lotion_with_brand_alias():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【Curel 珂潤】潤浸保濕清爽身體乳液 220ml",
"珂潤 Curel 潤浸保濕清爽身體乳液220ml",
momo_price=399,
competitor_price=399,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert "brand_match" in diagnostics.tags
assert "shared_identity_anchor" in diagnostics.reasons
def test_marketplace_matcher_promotes_karadium_pearl_shadow_stick_anchor():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【KARADIUM】閃亮珍珠眼影棒 1.4g",
"karadium 閃亮珍珠眼影棒 1.4g",
momo_price=259,
competitor_price=259,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert "brand_match" in diagnostics.tags
assert "shared_identity_anchor" in diagnostics.reasons
def test_marketplace_matcher_rejects_refill_core_vs_case_only_pack():
from services.marketplace_product_matcher import score_marketplace_match