"""治理审计落库的字段契约(`agent_type` + 治理是否改写过输出)。 **为什么需要这个文件**:治理层(`PlatformGovernance.review`)会**改写对外输出** —— 追加固定免责声明(门禁 F5),命中禁用词时还会把整条回复替换成安全话术。 架构师评审明确要求:"治理层改写了对外输出,事后必须能追溯到是哪个 Agent 触发的。" 所以 `agent.run_completed` 那条审计的 `detail` 里必须带 `agent_type`; 本文件锁住这个契约,避免以后有人"顺手精简"掉它。 """ from app.core.contracts import AgentResult, CoreResult from app.service.agent_persistence_service import _governance_rewrote def _result(text: str, *, transfer_required: bool = False) -> AgentResult: return AgentResult( run_id="r", result=CoreResult(text=text, transfer_required=transfer_required), ) def test_plain_answer_without_disclaimer_counts_as_rewritten() -> None: """客服出口的正文**不带**免责声明(话术由治理层统一注入)。 所以"Agent 产出的纯粹正文"在治理前后的差异就是那句被追加的话术—— 见到治理后的正文(含话术)即说明治理改写过。 """ assert _governance_rewrote( _result( "交易日 15:00 前提交,T+1 日确认份额。\n\n" "本内容仅为投资分析参考,不构成任何直接投资建议。" ) ) is True def test_transfer_required_counts_as_rewritten() -> None: """拦截分支:治理层把回复替换成"该内容需要人工核实"并置 `transfer_required`。""" assert _governance_rewrote( _result("该内容需要人工核实。基金投资存在风险,本系统不代客交易。", transfer_required=True) ) is True def test_untouched_text_is_not_marked_as_rewritten() -> None: """没有任何治理痕迹时不标记(避免"全部记 True"让这个字段失去信息量)。""" assert _governance_rewrote(_result("交易日 15:00 前提交,T+1 日确认份额。")) is False def test_empty_text_does_not_crash() -> None: """空正文(异常路径)不得让审计写入抛异常。""" assert _governance_rewrote(_result("")) is False