Files
awoooi/apps/api/src/repositories/interfaces.py
OG T f5b19cf108 feat(learning): 實作 Playbook 信心度調整機制 (ADR-030)
- 新增 _promote_playbook: 高評分提升信心度 +0.1
- 新增 _demote_playbook: 低評分降低信心度 -0.15
- 新增 find_by_source_incident: 按 incident_id 查詢 Playbook
- 新增 adjust_confidence: 信心度調整 + 狀態自動轉換
- 新增 Playbook.failure_rate 屬性

自動狀態轉換:
- ai_confidence >= 0.9 + DRAFT → 自動 APPROVED
- ai_confidence < 0.3 + failure_rate > 50% → 自動 DEPRECATED

測試: 13 案例全部通過

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-29 22:10:49 +08:00

374 lines
8.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Repository Interfaces - Protocol 定義
======================================
Phase 16 R3: Repository 層 Protocol 介面
設計原則:
- 使用 Python Protocol 實現 DI
- Service 層只依賴 Protocol不依賴具體實作
- 便於測試 (可注入 Mock Repository)
版本: v1.0
建立: 2026-03-26 (台北時區)
建立者: Claude Code (Phase 16 架構重構)
"""
from typing import Protocol, runtime_checkable
from uuid import UUID
from src.models.approval import ApprovalRequest, ApprovalRequestCreate, ApprovalStatus
from src.models.incident import Incident
from src.models.playbook import (
Playbook,
PlaybookStatus,
SymptomPattern,
)
@runtime_checkable
class IApprovalRepository(Protocol):
"""
Approval Repository Protocol
職責: ApprovalRecord CRUD 操作
實作: ApprovalDBRepository (PostgreSQL)
"""
async def create(self, request: ApprovalRequestCreate) -> ApprovalRequest:
"""建立新的 Approval"""
...
async def get_by_id(self, approval_id: UUID) -> ApprovalRequest | None:
"""根據 ID 取得 Approval"""
...
async def get_pending(self) -> list[ApprovalRequest]:
"""取得所有待審核的 Approval"""
...
async def update_status(
self,
approval_id: UUID,
status: ApprovalStatus,
actor: str | None = None,
) -> ApprovalRequest | None:
"""更新 Approval 狀態"""
...
async def add_signature(
self,
approval_id: UUID,
signer: str,
decision: str,
comment: str | None = None,
) -> ApprovalRequest | None:
"""新增簽核"""
...
@runtime_checkable
class IIncidentRepository(Protocol):
"""
Incident Repository Protocol
職責: IncidentRecord CRUD 操作
實作: IncidentDBRepository (PostgreSQL)
"""
async def create(self, incident: Incident) -> Incident:
"""建立新的 Incident"""
...
async def get_by_id(self, incident_id: str) -> Incident | None:
"""根據 ID 取得 Incident"""
...
async def get_active(self) -> list[Incident]:
"""取得所有活躍的 Incident"""
...
async def update(self, incident: Incident) -> Incident | None:
"""更新 Incident"""
...
async def upsert(self, incident: Incident) -> bool:
"""Upsert Incident (存在則更新,不存在則建立)"""
...
@runtime_checkable
class ITimelineRepository(Protocol):
"""
Timeline Repository Protocol
職責: TimelineEvent CRUD 操作
實作: TimelineDBRepository (PostgreSQL)
"""
async def add_event(
self,
approval_id: UUID,
event_type: str,
actor: str,
details: dict | None = None,
) -> bool:
"""新增 Timeline 事件"""
...
async def get_events(
self,
approval_id: UUID,
limit: int = 100,
) -> list[dict]:
"""取得 Approval 的 Timeline 事件"""
...
async def get_recent_events(
self,
limit: int = 50,
hours: int = 24,
) -> list[dict]:
"""取得最近的 Timeline 事件"""
...
@runtime_checkable
class IMetricsRepository(Protocol):
"""
Metrics Repository Protocol
職責: Metrics 相關 DB 查詢 (AI Success Rate)
實作: MetricsDBRepository (PostgreSQL)
版本: v1.0
建立: 2026-03-26 (台北時區)
建立者: Claude Code (Phase 17 技術債修復)
"""
async def get_ai_success_rate(
self,
hours: int = 24,
) -> tuple[float, int, int]:
"""
計算 AI 提案成功執行率
Args:
hours: 統計時間範圍 (小時)
Returns:
(success_rate_percent, executed_count, total_count)
"""
...
async def get_ai_success_trend(
self,
hours: int = 24,
points: int = 10,
) -> list[float]:
"""
取得 AI 成功率趨勢 (Sparkline 用)
Args:
hours: 統計時間範圍 (小時)
points: 趨勢點數量
Returns:
list[float]: 每小時成功率列表 (由舊到新)
"""
...
@runtime_checkable
class IPlaybookRepository(Protocol):
"""
Playbook Repository Protocol
職責: Playbook CRUD 操作 (PostgreSQL + Redis 雙層)
實作: PlaybookRepository
版本: v1.0
建立: 2026-03-26 (台北時區)
建立者: Claude Code (#7 Playbook 萃取)
"""
async def create(self, playbook: Playbook) -> Playbook:
"""建立新的 Playbook"""
...
async def get_by_id(self, playbook_id: str) -> Playbook | None:
"""根據 ID 取得 Playbook"""
...
async def update(self, playbook: Playbook) -> Playbook | None:
"""更新 Playbook"""
...
async def delete(self, playbook_id: str) -> bool:
"""刪除 Playbook (軟刪除 → DEPRECATED)"""
...
async def list_playbooks(
self,
status: PlaybookStatus | None = None,
tags: list[str] | None = None,
limit: int = 20,
offset: int = 0,
) -> tuple[list[Playbook], int]:
"""
列出 Playbooks
Returns:
(items, total_count)
"""
...
async def find_by_symptoms(
self,
symptoms: SymptomPattern,
top_k: int = 5,
min_similarity: float = 0.5,
) -> list[tuple[Playbook, float]]:
"""
根據症狀模式找相似 Playbook
Returns:
list[(Playbook, similarity_score)]
"""
...
async def update_stats(
self,
playbook_id: str,
success: bool,
) -> bool:
"""更新執行統計"""
...
async def find_by_source_incident(
self,
incident_id: str,
) -> list[Playbook]:
"""
根據來源 Incident ID 找 Playbook
2026-03-30 Claude Code: Learning Service 信心度調整用
尋找 source_incident_ids 包含此 incident_id 的 Playbooks
"""
...
async def adjust_confidence(
self,
playbook_id: str,
delta: float,
reason: str,
) -> Playbook | None:
"""
調整 Playbook 信心度
2026-03-30 Claude Code: Learning Service 信心度調整用
Args:
playbook_id: Playbook ID
delta: 調整量 (+/- 0.0~1.0)
reason: 調整原因 (審計用)
Returns:
更新後的 Playbook或 None (如果不存在)
"""
...
@runtime_checkable
class ILearningRepository(Protocol):
"""
Learning Repository Protocol
職責: 學習數據持久化 (Redis)
實作: LearningRepository
版本: v1.0
建立: 2026-03-29 (台北時區)
建立者: Claude Code (Phase D-G P0 修正)
設計原則:
- Service 層不直接存取 Redis
- 透過 Repository 進行資料存取
- 符合 leWOOOgo 積木化原則
"""
async def record_repair(
self,
anomaly_key: str,
repair_action: str,
success: bool,
root_cause: str | None = None,
fix_description: str | None = None,
execution_time_seconds: float | None = None,
) -> bool:
"""記錄修復結果"""
...
async def get_repair_stats(
self,
anomaly_key: str,
repair_action: str,
) -> dict:
"""取得修復統計 (成功率、執行次數)"""
...
async def get_all_repair_stats(
self,
anomaly_key: str,
) -> dict[str, dict]:
"""取得所有修復動作的統計"""
...
async def get_repair_history(
self,
anomaly_key: str,
repair_action: str,
limit: int = 20,
) -> list[dict]:
"""取得修復歷史記錄"""
...
async def get_learning_summary(
self,
anomaly_key: str,
) -> dict:
"""取得學習摘要"""
...
@runtime_checkable
class IEmbeddingCacheRepository(Protocol):
"""
Embedding Cache Repository Protocol
職責: Playbook 向量快取 (Redis)
實作: EmbeddingCacheRepository
2026-03-27 ogt: 模組化改造 (P1 違規修復)
"""
async def store(
self,
playbook_id: str,
embedding: list[float],
metadata: dict | None = None,
) -> bool:
"""儲存 Playbook 向量"""
...
async def get(self, playbook_id: str) -> list[float] | None:
"""取得 Playbook 向量"""
...
async def get_all(self) -> dict[str, list[float]]:
"""取得所有 Playbook 向量"""
...
async def remove(self, playbook_id: str) -> bool:
"""移除 Playbook 向量"""
...