feat(trust): ADR-088 Trust Score 持久化 — L4 自動放行核心
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 10m40s
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 10m40s
TrustScoreManager 從記憶體升級為 PostgreSQL 持久化,
Pod 重啟後信任分數不再歸零,AI 能真正累積到 L4 自動放行門檻。
變更:
- migrations/adr088_trust_score_persistence.sql: trust_records 表
- db/models.py: TrustRecordDB ORM model
- repositories/interfaces.py: ITrustRepository Protocol
- repositories/trust_repository.py: PG upsert ON CONFLICT DO UPDATE
- services/trust_engine.py: bulk_load() 啟動 warm-up
- services/learning_service.py: _persist_trust() + 2 call sites
- main.py: 啟動時 load_all() → bulk_load()
流程: 批准 5 次 → score=5 寫入 DB → Pod 重啟 → warm-up 讀回
→ evaluate_adjusted_risk MEDIUM→LOW → 自動執行
2026-04-17 ogt + Claude Sonnet 4.6(亞太): ADR-088
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -362,6 +362,46 @@ class TrustScoreManager:
|
||||
record.score = 0
|
||||
logger.warning("[TrustEngine] All trust scores reset!")
|
||||
|
||||
def bulk_load(self, records: list[dict]) -> int:
|
||||
"""
|
||||
從 DB 批量載入 trust records 到記憶體(啟動 warm-up 用)。
|
||||
|
||||
ADR-088: Pod 重啟後從 PostgreSQL 恢復信任分數,
|
||||
確保 AI 不會因重啟而失憶歸零。
|
||||
|
||||
Args:
|
||||
records: list[dict] — 每筆含 action_pattern, score,
|
||||
total_approvals, total_rejections,
|
||||
last_approval_by, last_approval_at,
|
||||
last_rejection_by, last_rejection_at
|
||||
|
||||
Returns:
|
||||
int: 載入筆數
|
||||
|
||||
2026-04-17 ogt + Claude Sonnet 4.6(亞太): ADR-088
|
||||
"""
|
||||
loaded = 0
|
||||
for r in records:
|
||||
pattern = r.get("action_pattern")
|
||||
if not pattern:
|
||||
continue
|
||||
record = TrustRecord(
|
||||
action_pattern=pattern,
|
||||
score=r.get("score", 0),
|
||||
total_approvals=r.get("total_approvals", 0),
|
||||
total_rejections=r.get("total_rejections", 0),
|
||||
last_approval_by=r.get("last_approval_by"),
|
||||
last_approval_at=r.get("last_approval_at"),
|
||||
last_rejection_by=r.get("last_rejection_by"),
|
||||
last_rejection_at=r.get("last_rejection_at"),
|
||||
)
|
||||
self._records[pattern] = record
|
||||
loaded += 1
|
||||
|
||||
if loaded:
|
||||
logger.info(f"[TrustEngine] Warm-up: loaded {loaded} trust records from DB")
|
||||
return loaded
|
||||
|
||||
|
||||
# ==================== Pattern Matching Utilities ====================
|
||||
|
||||
|
||||
Reference in New Issue
Block a user