"""Strict client reply quality gate regressions.""" from __future__ import annotations import unittest from .services import guardrail class ClientReplyQualityGateTest(unittest.TestCase): def test_blocks_self_harm_means_detail(self) -> None: """자해 수단·방법 상세는 차단(1.1 확장 — DBT 자해 페르소나 대비).""" samples = [ "커터로 했어요. 그게 제일 쉬워서요.", "면도날을 항상 가지고 다녀요.", "어젯밤에도 손목 긋고 잠들었어요.", ] for sample in samples: with self.subTest(sample=sample): result = guardrail.sanitize_client_reply(sample, ideation_stage=3, turn_seq=4) self.assertTrue(result.needs_regeneration) self.assertTrue(any(r.startswith("means_info:") for r in result.reasons)) def test_allows_boundary_setting_language(self) -> None: """'선을 긋다'(경계 설정) 같은 정상 상담 표현은 차단하지 않는다.""" result = guardrail.sanitize_client_reply( "이제는 엄마랑 선을 긋고 제 생활을 지키고 싶어요.", ideation_stage=1, turn_seq=4, ) self.assertFalse(result.needs_regeneration) def test_blocks_role_meta_speech_variants(self) -> None: samples = [ "내담자 역할로 응답하겠습니다. 엄마가 가보라고 해서요.", "AI로서 답변드리면 저는 우울한 학생입니다.", "상담자 입장에서 보면 제 핵심신념은 무가치감입니다.", "제 핵심신념은 저는 쓸모없다는 것입니다.", ] for sample in samples: with self.subTest(sample=sample): result = guardrail.sanitize_client_reply(sample, ideation_stage=1, turn_seq=2) self.assertTrue(result.needs_regeneration) self.assertIn("role_meta", result.reasons) def test_blocks_repeated_greeting_after_opening_turn_only_when_greeting_starts_reply(self) -> None: blocked = guardrail.sanitize_client_reply( "안녕하세요. 처음 뵙겠습니다. 저는 서연이에요.", ideation_stage=1, turn_seq=3, ) first_turn = guardrail.sanitize_client_reply( "안녕하세요. 엄마가 가보라고 해서 왔어요.", ideation_stage=1, turn_seq=1, ) quoted = guardrail.sanitize_client_reply( "방금 선생님이 안녕하세요라고 말해서 더 어색했어요.", ideation_stage=1, turn_seq=3, ) self.assertTrue(blocked.needs_regeneration) self.assertIn("repeat_greeting_after_opening", blocked.reasons) self.assertFalse(first_turn.needs_regeneration) self.assertFalse(quoted.needs_regeneration) def test_blocks_near_duplicate_previous_client_reply_but_allows_short_overlap(self) -> None: previous = "몰라요. 엄마가 그냥 가보라고 해서 왔어요." duplicate = guardrail.sanitize_client_reply( "몰라요. 엄마가 그냥 가보라고 해서 왔어요.", ideation_stage=1, previous_client_reply=previous, ) near_duplicate = guardrail.sanitize_client_reply( "엄마가 그냥 가보라고 해서 왔어요. 몰라요.", ideation_stage=1, previous_client_reply=previous, ) allowed = guardrail.sanitize_client_reply( "엄마가 가보라고 한 건 맞는데, 지금은 좀 짜증나요.", ideation_stage=1, previous_client_reply=previous, ) self.assertTrue(duplicate.needs_regeneration) self.assertIn("duplicate_client_reply", duplicate.reasons) self.assertTrue(near_duplicate.needs_regeneration) self.assertIn("duplicate_client_reply", near_duplicate.reasons) self.assertFalse(allowed.needs_regeneration) if __name__ == "__main__": unittest.main()