fix(auto-repair): preserve exact playbook candidates
All checks were successful
Code Review / ai-code-review (push) Successful in 10s
CD Pipeline / tests (push) Successful in 5m46s
CD Pipeline / build-and-deploy (push) Successful in 4m6s
CD Pipeline / post-deploy-checks (push) Successful in 1m28s

This commit is contained in:
Your Name
2026-05-13 23:37:59 +08:00
parent 5161a9dfd6
commit a0a0731cd6
3 changed files with 138 additions and 21 deletions

View File

@@ -25,6 +25,7 @@ from src.models.playbook import (
RiskLevel,
SymptomPattern,
)
from src.services.playbook_rag import PlaybookMatch
from src.services.playbook_service import PlaybookService
from src.utils.timezone import now_taipei
@@ -282,6 +283,92 @@ class TestPlaybookService:
# Should be empty or have very low similarity
assert len(recommendations) == 0 or recommendations[0].similarity_score < 0.4
@pytest.mark.asyncio
async def test_get_recommendations_prioritizes_exact_alert(self, service, mock_repo):
"""Exact alert matches should win over fuzzy service matches."""
exact_alert = create_test_playbook(
playbook_id="PB-EXACT-ALERT",
success_count=0,
failure_count=0,
)
exact_alert.symptom_pattern.alert_names = ["AwoooPT16E"]
exact_alert.symptom_pattern.affected_services = ["different-service"]
competing_service = create_test_playbook(
playbook_id="PB-FUZZY-SERVICE",
success_count=20,
failure_count=0,
)
competing_service.symptom_pattern.alert_names = ["SentryDown"]
competing_service.symptom_pattern.affected_services = [
"awoooi-auto-repair-canary-livefire"
]
await mock_repo.create(exact_alert)
await mock_repo.create(competing_service)
symptoms = SymptomPattern(
alert_names=["AwoooPT16E"],
affected_services=["awoooi-auto-repair-canary-livefire"],
severity_range=["P2"],
)
recommendations = await service.get_recommendations(
symptoms,
top_k=1,
use_rag=False,
)
assert recommendations[0].playbook.playbook_id == "PB-EXACT-ALERT"
@pytest.mark.asyncio
async def test_get_recommendations_preserves_jaccard_candidates(
self,
service,
mock_repo,
):
"""RAG hybrid top-k must not drop exact Jaccard candidates."""
exact_alert = create_test_playbook(
playbook_id="PB-EXACT-JACCARD",
success_count=0,
failure_count=0,
)
exact_alert.symptom_pattern.alert_names = ["AwoooPT16F"]
exact_alert.symptom_pattern.affected_services = ["different-service"]
competing_vector = create_test_playbook(
playbook_id="PB-VECTOR-ONLY",
success_count=20,
failure_count=0,
)
competing_vector.symptom_pattern.alert_names = ["SentryDown"]
competing_vector.symptom_pattern.affected_services = [
"awoooi-auto-repair-canary-livefire"
]
await mock_repo.create(exact_alert)
await mock_repo.create(competing_vector)
class FakeRagService:
async def hybrid_search(self, **_kwargs):
return [
PlaybookMatch(
playbook_id="PB-VECTOR-ONLY",
similarity_score=0.99,
match_type="vector",
)
]
async def fake_rag_service():
return FakeRagService()
service._get_rag_service = fake_rag_service
symptoms = SymptomPattern(
alert_names=["AwoooPT16F"],
affected_services=["awoooi-auto-repair-canary-livefire"],
severity_range=["P2"],
)
recommendations = await service.get_recommendations(symptoms, top_k=1)
assert recommendations[0].playbook.playbook_id == "PB-EXACT-JACCARD"
@pytest.mark.asyncio
async def test_approve_playbook(self, service, mock_repo):
"""Test approving a draft playbook"""