fix(p0.4): Playbook 學習鏈三道修復 — partial index + race防護 + 手動路徑接線
ADR-092 P0.4 Playbook EWMA 學習閉環的 DB / Repository / Service 三層修補。
DB 層 (db-expert-fix by Engineer-B):
- ApprovalRecord.matched_playbook_id 移除 index=True,改 __table_args__ partial index
(WHERE matched_playbook_id IS NOT NULL) — 多數列 NULL,full index 浪費空間
- adr092_p1_learning_chain_rollback.sql: 純 ROLLBACK SQL(DBA 手動執行)
Repository 層:
- playbook_repository.py: SELECT FOR UPDATE 防 lost update
避免並發 EWMA 更新覆蓋彼此
Service 層 (P0.4 修復):
- proposal_service.py: 手動審核路徑補 _try_playbook_match_id 呼叫
decision_manager auto_execute 路徑已有此邏輯(行 2035),
此處補手動路徑缺口,使 matched_playbook_id 可寫入 DB → EWMA 才能演化
測試:
- test_playbook_repository_race_condition.py: 3 cases SELECT FOR UPDATE 防 race
正確阻擋並發 EWMA 更新(pass)
Note: migration SQL 待 DBA 手動執行(feedback_dev_prod_separation.md),
不執行 alembic upgrade(statu 文件禁忌條款)。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -22,6 +22,7 @@ from sqlalchemy import (
|
||||
Integer,
|
||||
String,
|
||||
Text,
|
||||
text,
|
||||
)
|
||||
from sqlalchemy import (
|
||||
Enum as SQLEnum,
|
||||
@@ -170,10 +171,11 @@ class ApprovalRecord(Base):
|
||||
|
||||
# B2 fix 2026-04-24 ogt + Claude Sonnet 4.6: Playbook 學習閉環斷鏈修復
|
||||
# 原欄位缺失 → 人工審核後 matched_playbook_id 永遠 NULL → EWMA 無法更新
|
||||
# 2026-04-25 db-expert-fix by Claude Engineer-B: 移除 index=True 避免自動生成 full index
|
||||
# Partial index 改在 __table_args__ 宣告(WHERE matched_playbook_id IS NOT NULL)
|
||||
matched_playbook_id: Mapped[str | None] = mapped_column(
|
||||
String(36),
|
||||
nullable=True,
|
||||
index=True,
|
||||
comment="匹配的 Playbook ID,學習服務用以更新 EWMA trust score",
|
||||
)
|
||||
|
||||
@@ -203,7 +205,13 @@ class ApprovalRecord(Base):
|
||||
Index("ix_approval_created_at", "created_at"),
|
||||
Index("ix_approval_requested_by", "requested_by"),
|
||||
Index("ix_approval_fingerprint", "fingerprint"), # 戰略 B: 指紋查詢優化
|
||||
Index("ix_approval_matched_playbook", "matched_playbook_id"), # B2 fix
|
||||
# 2026-04-25 db-expert-fix by Claude Engineer-B: 改為 partial index,只索引非 NULL 值
|
||||
# 原 full index 與 index=True 三重宣告衝突已修復(一個來源真相:此處)
|
||||
Index(
|
||||
"ix_approval_matched_playbook",
|
||||
"matched_playbook_id",
|
||||
postgresql_where=text("matched_playbook_id IS NOT NULL"),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user