From f0b788c082850a063bdc4d9e2feee3edb1e78287 Mon Sep 17 00:00:00 2001 From: wooh Date: Sat, 1 Aug 2026 04:03:36 +0900 Subject: [PATCH] =?UTF-8?q?[Fix]=20FABRICATED=20=EC=B6=A9=EB=8F=8C=20?= =?UTF-8?q?=EA=B7=BC=EA=B1=B0=20=EA=B2=80=EC=A6=9D=20=EB=B2=94=EC=9C=84=20?= =?UTF-8?q?=EC=99=84=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 모순, 불일치 등 명시적인 충돌 표현을 유효한 FABRICATED 근거로 인정 - 팀 프로젝트와 개인 프로젝트 또는 단독 수행 주장의 의미상 대조 검증 추가 - 단순 프로젝트 언급과 역할 혼재 표현은 충돌 근거에서 계속 제외 - 운영 환경에서 제거됐던 FABRICATED reason 회귀 테스트 추가 --- .../sanitization/AnalysisSanitizationRules.java | 14 ++++++++++++-- .../service/core/AnalysisServiceTest.java | 2 +- .../AnalysisSanitizationRulesTest.java | 17 +++++++++++++++++ 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/jobdri/jobdri_api/domain/analysis/service/sanitization/AnalysisSanitizationRules.java b/src/main/java/com/jobdri/jobdri_api/domain/analysis/service/sanitization/AnalysisSanitizationRules.java index e6bea6ea..60c7b24b 100644 --- a/src/main/java/com/jobdri/jobdri_api/domain/analysis/service/sanitization/AnalysisSanitizationRules.java +++ b/src/main/java/com/jobdri/jobdri_api/domain/analysis/service/sanitization/AnalysisSanitizationRules.java @@ -39,7 +39,8 @@ public final class AnalysisSanitizationRules { private static final String[] FABRICATED_DIRECT_CONFLICT_TERMS = { "직접 충돌", "명시적 사실과 충돌", "사실과 충돌", "조건과 충돌", "요건과 충돌", "서로 충돌", "상충", "하지 않았다고", "수행하지 않았다고", "경험이 없다고", - "없다고 밝혔", "실제로 하지 않았" + "없다고 밝혔", "실제로 하지 않았", "모순", "불일치", "일치하지 않", "앞뒤가 맞지", + "다르게 서술" }; private static final Set STOP_WORDS = Set.of( "경험", "역량", "업무", "관련", "가능", "보유", "필수", "우대", "자격", "요건", @@ -181,7 +182,16 @@ public static boolean hasFabricatedDirectConflictReason(String reason) { return true; } } - return false; + return containsTeamAndIndividualProjectConflict(normalized); + } + + private static boolean containsTeamAndIndividualProjectConflict(String normalizedReason) { + boolean teamClaim = normalizedReason.contains(normalize("팀 프로젝트")) + || normalizedReason.contains(normalize("팀으로 진행")); + boolean individualClaim = normalizedReason.contains(normalize("개인 프로젝트")) + || normalizedReason.contains(normalize("혼자 수행")) + || normalizedReason.contains(normalize("혼자 진행")); + return teamClaim && individualClaim; } public static boolean isStructuredQualificationKeyword(String keyword) { diff --git a/src/test/java/com/jobdri/jobdri_api/domain/analysis/service/core/AnalysisServiceTest.java b/src/test/java/com/jobdri/jobdri_api/domain/analysis/service/core/AnalysisServiceTest.java index f35c3e1b..9d089d03 100644 --- a/src/test/java/com/jobdri/jobdri_api/domain/analysis/service/core/AnalysisServiceTest.java +++ b/src/test/java/com/jobdri/jobdri_api/domain/analysis/service/core/AnalysisServiceTest.java @@ -661,7 +661,7 @@ void analyzeKeepsTwoValidQuestionAnalyses() { question.getId(), "두 번째 문장입니다.", "fabricated", - "확인된 사실과 직접 충돌합니다.", + "팀 프로젝트로 진행했으나 개인 프로젝트라고 주장함", null ) ) diff --git a/src/test/java/com/jobdri/jobdri_api/domain/analysis/service/sanitization/AnalysisSanitizationRulesTest.java b/src/test/java/com/jobdri/jobdri_api/domain/analysis/service/sanitization/AnalysisSanitizationRulesTest.java index a46e1dc3..3862f301 100644 --- a/src/test/java/com/jobdri/jobdri_api/domain/analysis/service/sanitization/AnalysisSanitizationRulesTest.java +++ b/src/test/java/com/jobdri/jobdri_api/domain/analysis/service/sanitization/AnalysisSanitizationRulesTest.java @@ -34,6 +34,23 @@ void detectsContradictoryProvenReasonByDefectPhrase() { .isTrue(); } + @Test + @DisplayName("FABRICATED reason은 명시적 충돌 표현과 팀·개인 프로젝트의 대조를 인정한다") + void detectsFabricatedReasonByConflictMeaning() { + assertThat(AnalysisSanitizationRules.hasFabricatedDirectConflictReason( + "팀 프로젝트로 진행했으나 개인 프로젝트라고 주장함" + )).isTrue(); + assertThat(AnalysisSanitizationRules.hasFabricatedDirectConflictReason( + "앞뒤 설명이 불일치합니다." + )).isTrue(); + assertThat(AnalysisSanitizationRules.hasFabricatedDirectConflictReason( + "팀 프로젝트 경험을 설명했습니다." + )).isFalse(); + assertThat(AnalysisSanitizationRules.hasFabricatedDirectConflictReason( + "팀 프로젝트와 개인의 역할이 혼재되어 있습니다." + )).isFalse(); + } + @Test @DisplayName("unsafe improvement를 제거한다") void removesUnsafeImprovement() {