From 51ce8b2054a35bc24d30d8ab737b545aa26a46a1 Mon Sep 17 00:00:00 2001 From: hoshino-love0102 Date: Fri, 16 Oct 2026 21:16:27 +0900 Subject: [PATCH] fix: exclude mislabeled braided photo from medium cut recommendations --- docs/recommendation-photo-length.md | 2 ++ .../V34__exclude_mislabeled_braided_reference.sql | 7 +++++++ .../recommendation/RecommendationApiIntegrationTest.java | 4 ++++ 3 files changed, 13 insertions(+) create mode 100644 src/main/resources/db/migration/V34__exclude_mislabeled_braided_reference.sql diff --git a/docs/recommendation-photo-length.md b/docs/recommendation-photo-length.md index 7042ecf..163ca62 100644 --- a/docs/recommendation-photo-length.md +++ b/docs/recommendation-photo-length.md @@ -34,3 +34,5 @@ docker exec heddy-v2-app java -Djava.awt.headless=true -Xmx256m \ Spring 서버나 마이그레이션을 새로 실행하지 않는다. DB 읽기 전용 트랜잭션, 기존 S3 내부 읽기, 실제 배포된 resolver/scorer만 사용한다. 최대 100개 활성 계정을 검사하며 계정 해시, 입력·적용 길이, 분석 상태와 추천 이름/점수만 출력한다. 사진·연락처·기록 원문·키를 출력하거나 추천/프로필을 저장하지 않는다. V33은 실제 SYSTEM 썸네일을 검수해 확인된 길이 오분류를 교정하고 그룹/묶은머리/불명확한 옛 사진 7개를 추천에서 제외한다. 사용자 기록이나 파일은 삭제하지 않는다. + +V34는 배포 후 실제 상위 추천 썸네일 대조에서 발견한 `미디엄 스타일 32`를 비활성화한다. 사진은 땋은 머리인데 미디엄 CUT 및 선호 메타데이터로 추천되고 있어 해당 메타데이터를 검증할 수 없다. 기존 파일/기록은 보존한다. diff --git a/src/main/resources/db/migration/V34__exclude_mislabeled_braided_reference.sql b/src/main/resources/db/migration/V34__exclude_mislabeled_braided_reference.sql new file mode 100644 index 0000000..54f1486 --- /dev/null +++ b/src/main/resources/db/migration/V34__exclude_mislabeled_braided_reference.sql @@ -0,0 +1,7 @@ +-- Production top-three image audit: this seeded image shows braids, not the advertised medium CUT. +-- Its length, service and preference metadata cannot be justified from the thumbnail. Keep history/files. +UPDATE hairstyle_assets a +SET active = false, updated_at = now() +FROM files f +WHERE f.file_id = a.thumbnail_file_id AND f.owner_type = 'SYSTEM' + AND a.style_name = '미디엄 스타일 32' AND a.category = 'MEDIUM'; diff --git a/src/test/java/com/heddy/adapter/in/web/recommendation/RecommendationApiIntegrationTest.java b/src/test/java/com/heddy/adapter/in/web/recommendation/RecommendationApiIntegrationTest.java index 31c0a19..20113ee 100644 --- a/src/test/java/com/heddy/adapter/in/web/recommendation/RecommendationApiIntegrationTest.java +++ b/src/test/java/com/heddy/adapter/in/web/recommendation/RecommendationApiIntegrationTest.java @@ -277,10 +277,13 @@ void auditedCatalogMigrationRemovesImpossibleLengthsAndAmbiguousReferences() { insertStyle("94000000-0000-4000-8000-000000000004", "클래식 보브", "BOB", "NONE", 1, false); insertStyle("94000000-0000-4000-8000-000000000005", "컬리 스타일 08", "CURLY", "NONE", 1, false); insertStyle("94000000-0000-4000-8000-000000000006", "숏 스타일 05", "SHORT", "NONE", 1, false); + insertStyle("94000000-0000-4000-8000-000000000007", "미디엄 스타일 32", "MEDIUM", "NONE", 1, false); jdbcTemplate.update("UPDATE hairstyle_recommendation_profiles SET compatible_hair_lengths = '[\"SHORT\",\"BELOW_CHIN\",\"BELOW_SHOULDER\"]'::jsonb"); jdbcTemplate.execute((org.springframework.jdbc.core.ConnectionCallback) connection -> { org.springframework.jdbc.datasource.init.ScriptUtils.executeSqlScript(connection, new org.springframework.core.io.ClassPathResource("db/migration/V33__correct_audited_short_catalog.sql")); + org.springframework.jdbc.datasource.init.ScriptUtils.executeSqlScript(connection, + new org.springframework.core.io.ClassPathResource("db/migration/V34__exclude_mislabeled_braided_reference.sql")); return null; }); assertThat(jdbcTemplate.queryForObject("SELECT minimum_hair_length FROM hairstyle_recommendation_profiles WHERE hairstyle_id = '94000000-0000-4000-8000-000000000004'", String.class)) @@ -290,6 +293,7 @@ void auditedCatalogMigrationRemovesImpossibleLengthsAndAmbiguousReferences() { assertThat(jdbcTemplate.queryForObject("SELECT minimum_hair_length FROM hairstyle_recommendation_profiles WHERE hairstyle_id = '94000000-0000-4000-8000-000000000005'", String.class)) .isEqualTo("BELOW_SHOULDER"); assertThat(jdbcTemplate.queryForObject("SELECT active FROM hairstyle_assets WHERE hairstyle_id = '94000000-0000-4000-8000-000000000006'", Boolean.class)).isFalse(); + assertThat(jdbcTemplate.queryForObject("SELECT active FROM hairstyle_assets WHERE hairstyle_id = '94000000-0000-4000-8000-000000000007'", Boolean.class)).isFalse(); } @Test