fix(governance): cast dispatch status filter
All checks were successful
Code Review / ai-code-review (push) Successful in 10s
CD Pipeline / tests (push) Successful in 1m25s
CD Pipeline / build-and-deploy (push) Successful in 3m46s
CD Pipeline / post-deploy-checks (push) Successful in 1m16s

This commit is contained in:
Your Name
2026-05-14 18:39:03 +08:00
parent 5ef9240583
commit 6220f52266
4 changed files with 7 additions and 4 deletions

View File

@@ -275,14 +275,14 @@ async def _query_dispatch_table(
NULL::text AS operator_note
FROM governance_remediation_dispatch d
JOIN ai_governance_events e ON e.id = d.governance_event_id
WHERE d.dispatch_status = :dispatch_status
WHERE d.dispatch_status = CAST(:dispatch_status AS governance_dispatch_status)
ORDER BY d.dispatched_at DESC
""")
count_sql = text("""
SELECT count(*) AS cnt
FROM governance_remediation_dispatch
WHERE dispatch_status = :dispatch_status
WHERE dispatch_status = CAST(:dispatch_status AS governance_dispatch_status)
""")
async with get_db_context() as db:

View File

@@ -288,6 +288,7 @@ class TestQueueEndpoint:
assert "d.dispatched_at AS created_at" in source
assert "ORDER BY d.dispatched_at DESC" in source
assert "NULL::text AS operator_note" in source
assert "CAST(:dispatch_status AS governance_dispatch_status)" in source
assert "d.created_at" not in source
assert "d.operator_note" not in source

View File

@@ -5,11 +5,13 @@
**根因**
- `governance/events`production `ai_governance_events.details.remediation` 已有 dict 形態,例如 `{"items": [...]}`read model `GovernanceEvent.remediation` 期待字串Pydantic validation 造成 500。
- `governance/queue`:查詢仍讀 `governance_remediation_dispatch.created_at` / `operator_note`,但 production migration schema 實際是 `dispatched_at` / `created_by`,沒有 `created_at` / `operator_note`
- `governance/queue`:第二層 production 差異是 `dispatch_status` 為 PostgreSQL enumSQLAlchemy 參數被送成 varchar未明確 cast 時 Postgres 會拒絕 enum = varchar 比較,導致真表被誤判成 `table_pending=true`
**修正**
- `governance_query_service._extract_remediation()``details.remediation` 的 string / dict / list 正規化成短字串,避免歷史治理事件破壞 response schema。
- `_to_governance_event()` 對非 dict details 做 read-side guard。
- `_query_dispatch_table()` 對齊 production schema`d.dispatched_at AS created_at``NULL::text AS operator_note` 相容現有前端 DTO不改 DB schema。
- `_query_dispatch_table()``dispatch_status` 明確 `CAST(:dispatch_status AS governance_dispatch_status)`,避免 enum/varchar 比較錯誤。
- 補測 `test_ai_governance_endpoints.py`,覆蓋 dict remediation normalization 與 queue 查詢欄位相容性。
**本地驗證**

View File

@@ -2119,8 +2119,8 @@ Phase 6 完成後
**T17b Governance API 紅燈修復2026-05-14 台北)**
- 觸發T17A 前端工作鏈路已能顯示治理卡點,但 live smoke 發現 `governance/events` 500、`governance/queue``table_pending=true`,會讓 Operator Console 無法可信呈現治理告警是否被 dispatch、跳過、修復或卡人工。
- 根因:`ai_governance_events.details.remediation` 在 production 已有 dict/list 形態read model 仍只收字串;`governance_remediation_dispatch` production schema 使用 `dispatched_at`,查詢卻讀不存在的 `created_at` / `operator_note`
- 修正read-side normalization 將 remediation string/dict/list 正規化成短字串queue query 改用 `d.dispatched_at AS created_at``NULL::text AS operator_note` 相容既有 DTO不改 DB schema。
- 根因:`ai_governance_events.details.remediation` 在 production 已有 dict/list 形態read model 仍只收字串;`governance_remediation_dispatch` production schema 使用 `dispatched_at`,查詢卻讀不存在的 `created_at` / `operator_note`;第二層差異是 `dispatch_status` 為 PostgreSQL enum未明確 cast 時會被 asyncpg 以 varchar 參數送入
- 修正read-side normalization 將 remediation string/dict/list 正規化成短字串queue query 改用 `d.dispatched_at AS created_at``NULL::text AS operator_note` 相容既有 DTO並以 `CAST(:dispatch_status AS governance_dispatch_status)` 對齊 enum不改 DB schema。
- 驗證:`py_compile` pass`pytest tests/test_ai_governance_endpoints.py tests/test_governance_remediation_dispatch.py -q` 53 passedruff F/E9 passdiff check pass。
- 目前進度更新Alertmanager 低風險自動修復主線約 96%;完整 AI 自動化管理產品化約 75%。T17B 推版後,下一段收斂 governance dispatcher skipped reason / leader-dedupe / SLO emitter。