feat: C5 FR-9 预警处置时效升级(RISK-007,P0)
- 仓储:新增 list_pending_alerts_all / update_alert_escalation(统一读改写 payload, 升级标记独占写入,status/handler_* 列不碰;_parse_alert 补 created_at/handled_at 字符串→datetime 解析,兼容 sqlite 原生 DDL) - escalation_service.scan_and_escalate:扫描判级(普通 4h/24h、AML 1h/4h 短通道)、 幂等闸门(仅升不降)、先持久化再推送、按 (customer_id,level) 降噪合并一次推送、 通知链累积(L1 含 risk_manager / L2 含 compliance)、逐单+任务级审计 - scripts/cron/escalation_scan.py:15min 定时扫描壳(sys.path 引导 + new_trace + JSON 摘要) - 对话线 query_overdue_alerts Tool + 注册表 + 意图词(置于 alert_query 之前)+ summarize 分支 - C5 前置:seed STAFF-31001/31002(risk_manager) + deps 矩阵放行 + chat.py 显式 deny + risk.py 台账全量只读分支;JWT 手册 §5.3/§5.4/§6.1 增补 risk_manager - 测试:conftest 回拨 fixture + test_escalation_service(9) + risk_api/manager(5) + chat deny(1) + chat_tools overdue(2);全量 470 绿(453+17)
This commit is contained in:
@@ -607,3 +607,44 @@ def test_summarize_tool_rejection_not_authz_wording():
|
||||
record = {"tool_name": "query_holdings", "status": "blocked", "error_code": "TOOL_BAD_PARAM"}
|
||||
text = tool_service.summarize(record)
|
||||
assert "无权访问" not in text and "TOOL_BAD_PARAM" in text
|
||||
|
||||
|
||||
# ---------- C5 · FR-9 query_overdue_alerts Tool(直接调函数;需真实 RiskRepository) ----------
|
||||
|
||||
|
||||
def test_query_overdue_alerts_filters_by_hours(sqlite_engine, backdated_alert):
|
||||
from app.repository.risk_repository import RiskRepository
|
||||
from app.service.risk.chat_tools import query_overdue_alerts
|
||||
|
||||
backdated_alert("ALT-OV-1", "C1", hours_ago=5) # 超 4h → 命中
|
||||
backdated_alert("ALT-OV-2", "C1", hours_ago=2) # 未达 4h → 不命中
|
||||
repo = RiskRepository(engine=sqlite_engine)
|
||||
|
||||
# 缺省 hours = settings.risk_escalation_l1_hours(4)→ 仅 1 张
|
||||
data = query_overdue_alerts(None, core_ro=None, risk_repo=repo)
|
||||
assert data["overdue_count"] == 1
|
||||
assert data["items"][0]["alert_id"] == "ALT-OV-1"
|
||||
assert data["items"][0]["overdue_hours"] >= 4
|
||||
|
||||
# 显式 hours=1 → 两张都超期
|
||||
data2 = query_overdue_alerts(None, core_ro=None, risk_repo=repo, hours=1)
|
||||
assert data2["overdue_count"] == 2
|
||||
|
||||
# 按超期时长降序
|
||||
assert data2["items"][0]["overdue_hours"] >= data2["items"][1]["overdue_hours"]
|
||||
|
||||
|
||||
def test_query_overdue_alerts_intent_match_and_summarize(sqlite_engine, backdated_alert):
|
||||
"""意图词命中 query_overdue_alerts(置于 alert_query 之前)+ summarize 摘要。"""
|
||||
from app.repository.risk_repository import RiskRepository
|
||||
from app.service.risk.chat_tools import query_overdue_alerts
|
||||
|
||||
backdated_alert("ALT-OV-3", "C1", hours_ago=6)
|
||||
repo = RiskRepository(engine=sqlite_engine)
|
||||
data = query_overdue_alerts(None, core_ro=None, risk_repo=repo, hours=1)
|
||||
assert tool_service.match_intent("risk", "这些预警超时多久没处理了") == "query_overdue_alerts"
|
||||
|
||||
record = {"tool_name": "query_overdue_alerts", "status": "success", "data": data}
|
||||
text = tool_service.summarize(record)
|
||||
assert "超期预警" in text
|
||||
assert "ALT-OV-3" in text
|
||||
|
||||
Reference in New Issue
Block a user