docs(research): 프론트 지도 리서치 배치 5건 재검증 자산 (#801 #802 #803 #806 #894)#1053
Merged
Conversation
기존 이슈 코멘트의 findings를 baseline으로 삼아 현재 dev 트리(07-22) 앵커를 재검증하고, close = merged 불변식을 충족할 내구 자산으로 캡처한다. - #801 search country/locale 계약: CONFIRMED (D-BACKEND 확정). country_of_origin 접근 경로 이원화 + posts search의 Orval 우회 신규 발견. - #802 9무드 SSOT: 데이터 9/9 일치 CONFIRMED, messages drift는 PR #912로 해소(OVERTURNED). 남은 비준 블로커는 vault 문서 자체의 버전 라벨 모순뿐. - #803 Style DNA write 경로: 전제 금지 유지. persona/mood 이중 의존 규명, persona-only 유저는 기존 배치로 치유 불가(소급 onboarding_pick 필요). primary_mood 404는 latent(웹 호출부 없음)로 전복. - #806 VTON Vertex 토큰: 원 질문 moot — web 서버리스 라우트가 #988로 삭제, 기본 엔진 gpt-image-2는 GCP 미사용. 공개 레포엔 요약 스텁만(본문 vault). - #894 계측 truth map: Meta Pixel 부재 전복(PR #1046, PageView 한정·동의 게이트 없음). UTM/click-id 캡처·가입 이벤트 emit은 여전히 0. 조사 전용 — 소스 코드 변경 없음. 라이브 시스템 조회 없음(prod 크레덴셜 미보유). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This was referenced Jul 22, 2026
별도 리뷰 레인의 반증 결과를 반영한다(self-approve 회피). - #802 결론3·R2: "T10 가드가 CI에서 재발을 차단한다"는 거짓 — .github/workflows 전체에서 vitest를 도는 워크플로가 없고(bun run 호출은 doc-frontmatter, schema-drift 2건뿐) pre-push도 lint/prettier/tsc만 돈다. "수동 실행 가드"로 정정하고 CI 배선을 후속으로 명시. 가드 파일 docblock의 자기서술을 검증 없이 옮긴 것이 원인. - #806 stub: "비기본 엔진을 '명시적으로' 선택했을 때"는 코드가 반증 — factory.py의 (VTON_ENGINE or "vertex")는 빈 값 주입 시 명시적 선택 없이 Vertex로 폴백한다. vault 원문에 없던 한정어를 공개 요약에 덧붙여 안전 범위를 좁혀 말한 것이라 제거하고, 배포 환경 점검이 형식이 아님을 명시. - #802 후속 참조: vault PR decoded-docs#18 머지 시 vault 라인 앵커 +4행 이동 고지. - 교정: market.ts 앵커 1-27→1-30, snapshot.json 1-15→1-14, "두 축"→"세 축", "나머지 4개"→"3개", 서피스 카운트 표현. - front-matter 5문서 정규화(doc/essence/owner 추가, status=final 통일). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
리뷰 레인이 트리 이동을 잡았다. 작성 20분 뒤 PR #985가 머지(b48a770, 2026-07-22T10:01:18Z)되어 #894의 핵심 결론 일부가 dev에서 무효가 됐다. - #894: superseded 배너 추가. 현재 dev에 attribution.ts(UTM 5필드+fbclid/gclid first-touch), meta-pixel-events.ts(표준 이벤트 레이어), first-core-action.ts가 있고 trackAnonEvent 프로덕션 호출부가 4곳이다. 결론 3·4와 §1의 UTM· trackAnonEvent·표준 이벤트 행, §2의 #985 상태, §6 해당 행이 뒤집혔다. b48a7701은 dev 전용이라 "main ⊇ dev" 전제도 해당 행에서 깨졌다. 스냅샷 본문은 지우지 않고 기준 커밋을 명시해 보존한다. - #803: users.style_dna writer가 둘이 아니라 셋 — update_style_dna (service.rs:80, PATCH /me/style-dna, 무검증 전체 교체)가 누락됐다. onboarding_pick 없이 primary_mood를 세울 수 있어 "재-온보딩 전까지 영원히"는 과장. #799 복구 설계에서 소급 onboarding_pick 잡이 유일 선택지가 아님을 명시. - #803 G1 상태코드 400 → 422 (error.rs:81-84에서 UNPROCESSABLE_ENTITY 매핑). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
21에이전트 교차 감사(공개 아티팩트 ↔ 정본 문서 정합·인용 무결성·완결성) 반영. - 전 문서 검증 기준 커밋 고정(origin/dev=a3d5702b). 브랜치명만으론 머지 후 앵커 복원이 불가하고, 이 배치 자신이 2주 만의 앵커 이동을 보여준다. - #801 시제 정정: #796·#799는 2026-07-09 CLOSED. 이 문서는 미결 결정의 입력이 아니라 확정된 D-BACKEND의 사후 확인이며, 4단 목록은 실행 목록으로 읽어야 한다. - #801 신규: entity_id filterable은 이미 색인 문서에 있고(batch/entity_reindex.rs:66) ENTITIES_FILTERABLE 등재만 빠짐 → 설정 1줄+재색인. country(스키마+적재 포함 4단계)와 티어를 같이 매기면 값싼 언블록이 비싼 항목 뒤에 줄 선다. - #803: FE 앵커 한정 드리프트 고지(#985 머지, 서버측 결론 불변) · §5-3을 "피드 개인화 신호 없음"에서 "DNA 재랭킹이 무증상 no-op"으로 정정 (feed/service.rs blend_with_dna의 `_ => base`, 로그·플래그 없음. 단 손실 크기는 feed_dna_mix 미확인이라 '피드가 죽는다'는 과장) · 권고2를 2a(응답 플래그, 저비용)/2b(picker 풀 제한, BE 계약=티어 대상)로 분리하고 GET /posts?mood=가 대체재가 아닌 이유 명시. - #894: front-matter status=superseded·essence=partial · §6 item6은 전제만 참 (soft_wall_hit은 loginRequiredStore.ts:36에서 발화) · signup_complete emit 0은 dev에서도 유효 · 앵커 nit 2건. - vault 링크는 decoded-docs#18 머지 전까지 main에서 404 → 브랜치 참조 hedge. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
두 문서가 참조하는 vault 자산이 decoded-docs main에 올라갔다(PR #18 머지, 2026-07-22T12:04Z). '머지 전까지 브랜치 참조' 임시 문구를 제거한다. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
cocoyoon
added a commit
that referenced
this pull request
Jul 24, 2026
…1064) * docs(research): 프론트 지도 리서치 배치 5건 재검증 자산 (#801 #802 #803 #806 #894) (#1053) * docs(research): 프론트 지도 리서치 배치 5건 재검증 자산 (#801 #802 #803 #806 #894) 기존 이슈 코멘트의 findings를 baseline으로 삼아 현재 dev 트리(07-22) 앵커를 재검증하고, close = merged 불변식을 충족할 내구 자산으로 캡처한다. - #801 search country/locale 계약: CONFIRMED (D-BACKEND 확정). country_of_origin 접근 경로 이원화 + posts search의 Orval 우회 신규 발견. - #802 9무드 SSOT: 데이터 9/9 일치 CONFIRMED, messages drift는 PR #912로 해소(OVERTURNED). 남은 비준 블로커는 vault 문서 자체의 버전 라벨 모순뿐. - #803 Style DNA write 경로: 전제 금지 유지. persona/mood 이중 의존 규명, persona-only 유저는 기존 배치로 치유 불가(소급 onboarding_pick 필요). primary_mood 404는 latent(웹 호출부 없음)로 전복. - #806 VTON Vertex 토큰: 원 질문 moot — web 서버리스 라우트가 #988로 삭제, 기본 엔진 gpt-image-2는 GCP 미사용. 공개 레포엔 요약 스텁만(본문 vault). - #894 계측 truth map: Meta Pixel 부재 전복(PR #1046, PageView 한정·동의 게이트 없음). UTM/click-id 캡처·가입 이벤트 emit은 여전히 0. 조사 전용 — 소스 코드 변경 없음. 라이브 시스템 조회 없음(prod 크레덴셜 미보유). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(research): 적대적 리뷰 반영 — 거짓 주장 2건 정정 + 앵커/카운트 교정 별도 리뷰 레인의 반증 결과를 반영한다(self-approve 회피). - #802 결론3·R2: "T10 가드가 CI에서 재발을 차단한다"는 거짓 — .github/workflows 전체에서 vitest를 도는 워크플로가 없고(bun run 호출은 doc-frontmatter, schema-drift 2건뿐) pre-push도 lint/prettier/tsc만 돈다. "수동 실행 가드"로 정정하고 CI 배선을 후속으로 명시. 가드 파일 docblock의 자기서술을 검증 없이 옮긴 것이 원인. - #806 stub: "비기본 엔진을 '명시적으로' 선택했을 때"는 코드가 반증 — factory.py의 (VTON_ENGINE or "vertex")는 빈 값 주입 시 명시적 선택 없이 Vertex로 폴백한다. vault 원문에 없던 한정어를 공개 요약에 덧붙여 안전 범위를 좁혀 말한 것이라 제거하고, 배포 환경 점검이 형식이 아님을 명시. - #802 후속 참조: vault PR decoded-docs#18 머지 시 vault 라인 앵커 +4행 이동 고지. - 교정: market.ts 앵커 1-27→1-30, snapshot.json 1-15→1-14, "두 축"→"세 축", "나머지 4개"→"3개", 서피스 카운트 표현. - front-matter 5문서 정규화(doc/essence/owner 추가, status=final 통일). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(research): #985 머지로 뒤집힌 #894 결론에 superseded 배너 + #803 writer 3번째 보완 리뷰 레인이 트리 이동을 잡았다. 작성 20분 뒤 PR #985가 머지(b48a770, 2026-07-22T10:01:18Z)되어 #894의 핵심 결론 일부가 dev에서 무효가 됐다. - #894: superseded 배너 추가. 현재 dev에 attribution.ts(UTM 5필드+fbclid/gclid first-touch), meta-pixel-events.ts(표준 이벤트 레이어), first-core-action.ts가 있고 trackAnonEvent 프로덕션 호출부가 4곳이다. 결론 3·4와 §1의 UTM· trackAnonEvent·표준 이벤트 행, §2의 #985 상태, §6 해당 행이 뒤집혔다. b48a7701은 dev 전용이라 "main ⊇ dev" 전제도 해당 행에서 깨졌다. 스냅샷 본문은 지우지 않고 기준 커밋을 명시해 보존한다. - #803: users.style_dna writer가 둘이 아니라 셋 — update_style_dna (service.rs:80, PATCH /me/style-dna, 무검증 전체 교체)가 누락됐다. onboarding_pick 없이 primary_mood를 세울 수 있어 "재-온보딩 전까지 영원히"는 과장. #799 복구 설계에서 소급 onboarding_pick 잡이 유일 선택지가 아님을 명시. - #803 G1 상태코드 400 → 422 (error.rs:81-84에서 UNPROCESSABLE_ENTITY 매핑). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(research): 교차 감사 반영 — 기준 커밋 고정 + 시제·비용등급 정정 21에이전트 교차 감사(공개 아티팩트 ↔ 정본 문서 정합·인용 무결성·완결성) 반영. - 전 문서 검증 기준 커밋 고정(origin/dev=a3d5702b). 브랜치명만으론 머지 후 앵커 복원이 불가하고, 이 배치 자신이 2주 만의 앵커 이동을 보여준다. - #801 시제 정정: #796·#799는 2026-07-09 CLOSED. 이 문서는 미결 결정의 입력이 아니라 확정된 D-BACKEND의 사후 확인이며, 4단 목록은 실행 목록으로 읽어야 한다. - #801 신규: entity_id filterable은 이미 색인 문서에 있고(batch/entity_reindex.rs:66) ENTITIES_FILTERABLE 등재만 빠짐 → 설정 1줄+재색인. country(스키마+적재 포함 4단계)와 티어를 같이 매기면 값싼 언블록이 비싼 항목 뒤에 줄 선다. - #803: FE 앵커 한정 드리프트 고지(#985 머지, 서버측 결론 불변) · §5-3을 "피드 개인화 신호 없음"에서 "DNA 재랭킹이 무증상 no-op"으로 정정 (feed/service.rs blend_with_dna의 `_ => base`, 로그·플래그 없음. 단 손실 크기는 feed_dna_mix 미확인이라 '피드가 죽는다'는 과장) · 권고2를 2a(응답 플래그, 저비용)/2b(picker 풀 제한, BE 계약=티어 대상)로 분리하고 GET /posts?mood=가 대체재가 아닌 이유 명시. - #894: front-matter status=superseded·essence=partial · §6 item6은 전제만 참 (soft_wall_hit은 loginRequiredStore.ts:36에서 발화) · signup_complete emit 0은 dev에서도 유효 · 앵커 nit 2건. - vault 링크는 decoded-docs#18 머지 전까지 main에서 404 → 브랜치 참조 hedge. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(research): vault 링크 hedge 제거 — decoded-docs#18 머지로 main 도달 두 문서가 참조하는 vault 자산이 decoded-docs main에 올라갔다(PR #18 머지, 2026-07-22T12:04Z). '머지 전까지 브랜치 참조' 임시 문구를 제거한다. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(plans): auto-extract PR #1053 body [skip ci] * feat: 앵커축 facet 승격 v1 — color/style_tags 큐레이터·Explore·홈 연결 thestylearchivist류 "[아이템/컬러/스타일] × 컬렉션" 탐색을 재현하기 위해, cody_analysis(color_palette/items[].color)와 posts.style_tags 자유텍스트를 color_mappings/style_tag_mappings(결정론적 매핑, style_mood_mappings 패턴 재사용)로 canonical 값으로 정규화하고 posts.canonical_colors/canonical_styles 에 materialize했다. 세 표면이 이 값을 공유: - 큐레이터 챗(editorial_story_chat search_posts) — colors/styles 배열 overlap 필터, members/query 없이 단독 소싱 가능 - Explore — 가짜 canned-query 스타일 칩을 진짜 Meilisearch facet 필터로 교체 - 홈 — "How to Style Red/Black/Navy" 앵커 레일 추가(seasonal 레일과 동형) Materialization은 search_reindex 배치(daily 04:00 + boot)에서 전체 active post에 대해 계산 — verify/update_post 경로는 건드리지 않음(해당 DTO들이 cody_analysis/style_tags를 바꾸지 않아 재계산이 무의미하다고 판단, 배치가 유일한 신뢰 가능한 백필 경로). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * feat(web): Explore 필터 바를 칩 스크롤러 → Style/Color 드롭다운으로 교체 색은 "읽는" 축이 아니라 "보는" 축이라 텍스트 칩(FilterChipRow)으로는 안 맞는다고 판단 — Style은 SortDropdown과 동형인 native <select>로, Color는 실제 스와치를 그리는 커스텀 팝오버(ColorDropdown)로 분리해 Style/Color/Sort가 한 톤의 필터 바 패밀리로 읽히게 했다. - ColorDropdown: canonical_colors 13개 스와치 팝오버. 다크모드에서 검정 스와치가 카드 배경에 묻히는 문제 발견 → border 대신 ring(+dark 변형)으로 경계를 항상 보이게 수정 (Playwright 스크린샷으로 확인) - StyleDropdown: FilterChipRow/FilterChip 대체(둘 다 삭제, 재사용처 없음) - 스타일/컬러 필터 선택 시 mode가 "search"로 전환되며 필터 바 자체가 통째로 사라지는 버그 발견 → 필터 바를 mode 분기 바깥으로 이동해 두 모드 모두에서 항상 보이도록 수정 - Playwright로 로컬 dev 서버 구동해 스와치 팝오버·필터 조합(Street+Red 동시 적용)·필터 바 지속 렌더를 스크린샷으로 확인 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(web): Explore 필터 바 — "Style"/"Color" 라벨 정렬 + 포커스 링 톤 통일 닫힌 상태에서 스타일 드롭다운이 "All"로 표시돼 옆의 "Color"와 짝이 안 맞고 무슨 필터인지 모호했음(raf 피드백, 스크린샷) — "All" 옵션의 표시 텍스트만 "Style"로 바꿔 ColorDropdown과 대칭 페어("Style ▾"/"Color ▾") 로 읽히게 함. 내부 StyleTag 타입·"All" sentinel·로직은 그대로(옵션의 표시 텍스트만 분리, value는 안 바뀜 — 회귀 없음). 같은 화면에서 기본 브라우저 파란 포커스 링이 앱 톤과 안 맞는 것도 같이 확인돼 Style/Color/Sort 세 트리거 모두 --ring 토큰 기반 focus-visible 링으로 통일. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * feat(editorial_discovery): color-story 앵글 타입 추가 — canonical_colors 기반 Discovery 자동 앵글 추천이 여태 raw style_tags 빈도만 근거로 삼고 앵커축 facet v1(canonical_colors/canonical_styles)은 전혀 안 쓰고 있었음(raf 질문 으로 확인). style-archetype/item-anchor 옆에 3번째 유형 color-story 추가 — #thestylearchivist 류 "How to style X"를 하드코딩 홈 레일이 아니라 에이전트가 실데이터 색상 분포로 직접 제안하게 함. - DiscoveryInput.color_frequency + PostSummary.canonical_colors 추가 - repository.py: posts 쿼리에 canonical_colors 추가, color_freq 집계 (style_tag_freq는 원본 세밀 태그 그대로 유지 — 창의성 근거 그대로 둠) - prompts.py: color-story 유형 설명 + 근거 데이터 섹션 추가 - AngleRecommendation.angle_type Literal에 "color-story" 추가 - supabase-assets 마이그레이션: editorial_recommendations.angle_type CHECK 제약에 'color-story' 추가 (cloud-only 프로젝트 — supabase db push 는 별도로 필요, 이 세션에서 직접 push 안 함) - admin 스토리 페이지 AngleTypeBadge에 컬러 타입 배지 추가 로컬 operation DB(posts) 대상 dry-run으로 color_frequency 집계 로직 검증 (top-80 트렌딩 포스트 기준 실데이터 분포 확인) + Pydantic 모델/프롬프트 빌더 렌더링 검증. assets DB는 cloud-only라 전체 파이프라인 e2e는 미검증. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(api-server): 앵커축 컬러 facet 오분류 수정 — importance/prominence 필터링 raf 리뷰(red color-story 앵글 검토 중 발견) — canonical_colors가 아이템 importance 구분 없이 모든 아이템 색 + 전체 룩 팔레트 전부를 합쳐서 만들어짐. 그 결과 액세서리 하나만 red인 룩, 심지어 아이템 레벨엔 red가 전혀 없고 전체 팔레트 5번째 항목에만 잡힌 룩까지 "red 룩"으로 분류됨(4개 중 3개가 실제로는 red 아닌 오분류 확인). - items[].color: importance == "high" 인 아이템만 카운트 (mid/low 액세서리· 액센트 제외) - style.color_palette: prominence 순 상위 2개만 (cody 프롬프트가 이미 시각적 두드러짐 순으로 정렬해서 줌 — 하위권은 배경/조명 등 비전 노이즈일 가능성) 실데이터로 재검증: 로컬 330개 포스트 재인덱싱 후 red 태그 포스트가 top-80 기준 14 → 3(진짜만)으로 정확해짐. 유닛테스트 4개 추가(실제 오분류 케이스 재현 포함), 8개 전부 통과. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(ai-server): editorial story 카피 생성에 컬러 그라운딩 가드레일 추가 raf 리뷰로 발견 — "Summer Ease" 슬라이드 캡션이 "a bold pair of red shorts" 라고 썼는데 실제 하의는 black. 원인: 두 카피 생성 경로(자동 compose / 챗 add_look_slide) 다 전체 룩 레벨 canonical_colors 만 LLM 에 주고 개별 아이템 색은 전혀 안 줌 — 컬러 스토리 앵글의 "red" 테마가 룩 전체에 어울리는 아이템(가방 하나)에서 왔는지 특정 못 하니 아무 아이템에나 갖다 붙일 수 있었음. - editorial_story/prompts.py: "COLOR GROUNDING" 룰 신설 — 아이템 자체의 name 에 그 색상/패턴 단어가 실제로 있을 때만 색 단정 허용, 아니면 실루엣/소재로 대체. 예시 문구도 색상 임의 언급하던 것 순화. - editorial_story_chat/agent.py: 챗 에이전트 시스템 프롬프트에 동일 룰. - editorial_story_chat/tools.py: search_posts 후보 요약의 컬러/스타일 facet 라벨을 "전체 룩 기준"으로 명시(개별 아이템 색과 혼동 방지). per-item cody_analysis.items[].color 를 실제로 두 파이프라인에 plumbing 하는 건 별도 작업(solution↔cody item 간 직접 조인이 없어 더 큰 작업) — 이번엔 프롬프트 레벨 가드레일로 우선 차단. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * feat(editorial_discovery): 계절성 반영 — current_season() 자동 계산 + season_frequency raf 지적 — 여름에 "니트웨어" item-anchor 앵글이 나온 게 문제. 근본 원인은 마이닝이 계절 신호를 전혀 안 봄. 하드코딩("지금은 여름이다" 프롬프트 텍스트)은 계절 바뀔 때마다 사람이 고쳐야 해서 기각하고, 호출 시점 실제 날짜에서 매번 계산하는 방식으로 감. - prompts.py: current_season(now=None) 헬퍼 — KST 기준 월→계절 매핑, cody Stage-1 의 season 보캐뷸러리(spring/summer/fall/winter)와 동일. 테스트 위해 now 주입 가능. - repository.py: cody_analysis.style.season 을 posts 쿼리에 추가, canonical colors 와 같은 패턴으로 season_frequency 집계. - models.py: PostSummary.season, DiscoveryInput.season_frequency 추가. - prompts.py: "계절성(모든 유형 공통 적용)" 섹션 신설 — item-anchor 는 명백한 비계절 아이템 회피/감점, style/color-story 는 계절 맞는 포스트 우선, 데이터 불확실하면 강제 배제 안 함. 실제 Gemini 호출로 검증(blue color-story 생성) — rationale 에 "summer 시즌과 겹치는 포스트들이 많아 계절성을 고려" 라고 직접 언급, season_frequency 를 실제로 참조해 판단하는 것 확인. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * feat(ai-server): 카피 톤 완화, 뉴진스 그룹 제외, 후보 번호 매기기 raf 피드백 3건 반영: 1. topic_title/deck 이 "충실한 번역만, 재창작 금지" 제약 때문에 한글 앵글 원문(구체적이고 캐치한)에 비해 영문 카피가 밋밋했음(예: "The Temperature of Red"). 개념 충실성(같은 색/아이템/인물, 새 컨셉 금지)은 유지하되 표현은 매거진 에디터처럼 자유롭게 다시 쓰도록 완화. COLOR GROUNDING(사실 관계)은 그대로 분리 유지 — 톤 자유 ≠ 사실 날조 허용. 2. Discovery 마이닝(services/editorial_discovery/repository.py) + 챗 search_posts(editorial_story_chat/tools.py) 양쪽에 그룹 제외 필터 추가 (_EXCLUDED_GROUP_PATTERNS = ["%newjeans%"], product 결정). 실제 로컬 DB로 두 쿼리 다 라이브 검증(뉴진스 0건, 다른 그룹 영향 없음). 3. search_posts 후보 목록에 1-based 번호 추가, 챗 에이전트가 post_id 대신 번호로 후보를 지칭하도록 시스템 프롬프트에 명시 — 프론트의 이미지 카드 번호와 대응(다음 커밋). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * feat(web): 스토리 챗에 search_posts 후보 이미지 카드 렌더링 raf 피드백 — 후보가 raw UUID 텍스트로만 나와서 뭘 골라야 할지 알 수 없었음. 조사해보니 구조화 데이터(data.candidates, 이미지 URL 포함)는 이미 서버가 생성·저장·응답까지 다 하고 있는데, 프론트 타입(ChatMessage.tool_result)이 data 필드를 아예 선언 안 해서 죽은 채로 버려지고 있었음 — 렌더링만 없었음. - useEditorialStoryChat.ts: SearchPostCandidate(Item) 타입 추가, tool_result.data.candidates 타입 선언. - StoryChatPanel.tsx: search_posts 결과일 때 텍스트 대신 번호+썸네일+ 누구/컨텍스트+facet 칩 카드 그리드로 렌더(기존 drafts 페이지의 슬라이드 썸네일과 동일 <img> 패턴). 카드 번호는 candidates 배열 순서 = 챗 에이전트가 참조하는 번호와 동일(직전 커밋의 백엔드 numbering과 대응). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * feat: editorial_stories 에 'publishing' 상태 추가 raf 피드백 — Publish 누르면 실제로는 백그라운드 job(operation DB editorial_story_publish_jobs)이 큐에 들어가 나중에 처리되는데, story.status(assets DB)는 발행 완료/실패 시점까지 계속 'draft' 로 남아서 Publish 버튼이 응답 직후 바로 재활성화되고 화면엔 진행 중 표시가 전혀 없었음. - supabase-assets 마이그레이션: editorial_stories.status CHECK 에 'publishing' 추가. - admin/editorial_stories.rs::publish() — job INSERT(operation) 직후 assets_db 에 status='publishing' UPDATE (두 DB 라 트랜잭션 불가 — best-effort, job 은 이미 성공적으로 큐잉된 뒤라 이 UPDATE 실패해도 발행 자체엔 영향 없음). - ai-server publish_job.py — 잡 종료 시 writeback을 published 외에 failed_terminal → 'failed' 도 반영(기존엔 published 만 반영, 실패 시 story 가 영원히 'publishing' 에 멈춰있었을 것). failed_retryable(자동 재시도 중)은 그대로 'publishing' 유지. - 프론트: AdminStatusBadge 에 publishing variant(파란색), 발행 버튼은 story.status !== "draft" 조건으로 이미 자동 비활성화되던 것에 스피너+ "Publishing…" 라벨 추가, useEditorialStory 폴링(5s)을 publishing 에도 적용해 완료 시 자동 반영. cargo test 전체 통과(기존 무관 실패 5건 제외), typecheck/lint 클린. 마이그레이션은 cloud assets 프로젝트 전용이라 이 커밋엔 파일만 포함 — push 는 별도 확인 후 진행. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * style(web): 기존 prettier 포맷 위반 3건 자동 수정 pre-push 훅을 이번에 처음 로컬에 설치(just hook)하면서 이전엔 아무도 못 걸러낸 기존 포맷 부채가 드러남 — qa-gallery/page.tsx, sitemap.ts, SearchSuggestions.tsx. 전부 로직 변경 없는 순수 들여쓰기/줄바꿈 포맷팅(eslint --fix). typecheck 클린. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * style(web): 기존 prettier 포맷 위반 — qa/ 19개 파일 자동 수정 pre-push 훅(prettier --check) 최초 실행에서 드러난 기존 포맷 부채. 전부 로직 변경 없는 순수 개행/들여쓰기(JSON 스냅샷 포함 — 값 변경 없음, 줄바꿈만). typecheck 클린. qa/matrix.test.ts 의 README 드리프트 가드 실패 1건은 이 커밋과 무관한 기존 실패(수정 전 dev에서도 동일하게 실패 확인). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(api-server): 로컬 pre-push CI 최초 실행에서 드러난 기존 부채 정리 이번 세션에서 pre-push 훅(just hook)을 처음 설치·실행하면서 그동안 로컬 -D warnings clippy / 아키텍처 테스트 / 일부 unit test 가 한 번도 통과된 적 없었다는 게 드러남 — 전부 내가 이번 세션에서 만든 코드와 무관한 기존 파일들. **clippy (-D warnings) 35~42건, 전부 기존 코드** - disallowed_methods(unwrap): serde_json::json! 매크로 전개가 내부적으로 unwrap 을 쓰는 false positive — 프로젝트 기존 컨벤션대로 함수 단위 #[allow(clippy::disallowed_methods)] 부여(home_curation.rs 5개 함수, catalog_gaps.rs, editorial_stories.rs, item_likes/handlers.rs, posts/handlers.rs 4개 함수, posts/service.rs 테스트 모듈 1개 누락분). - manual_contains: catalog_gaps.rs — iter().any() → contains(). - doc_lazy_continuation: editorial_stories.rs 독립 문단 앞 빈 줄 추가. - single_match: item_likes/service.rs — match → if let. - items_after_test_module: item_likes/service.rs — mod diversify_tests 를 taste_centroid/curation_facts 뒤(파일 끝)로 이동. - too_many_arguments(8/7): raw_posts/relocate.rs — raw_public_url/ op_public_url 두 인자를 RelocateBucketUrls 구조체로 묶음(호출부 3곳+ 테스트 6곳 갱신). - empty_line_after_doc_comments: posts/service.rs — list_posts 가 다른 곳으로 옮겨지며 남은 고아 doc 주석 2줄 삭제. **아키텍처 테스트 3건** - domain_dependencies_match_allowed_list: posts↔catalog(complete_the_look → catalog_knn), posts→onboarding(interleave), catalog/catalog_entities →posts(DTO 재사용) — 전부 이미 배포된 기능 코드, 허용 목록만 안 따라감. 리팩터링 대신 실제 참조 목적을 코멘트로 남기고 허용 목록에 반영. - files_should_not_exceed_line_budget: 기존 LINE_BUDGET_ALLOWLIST 패턴을 그대로 확장 — 5개 파일(vton/mod.rs 1604줄 등) 등재. 실제 분리는 별도 리팩터링 과제(회귀 감지는 계속 유효). - all_handlers_registered_in_openapi: complete_the_look 핸들러를 openapi.rs paths 에 등록 누락 — 추가 + openapi.json 재생성. **unit test 2건 — mock 쿼리 순서 버그** - feed/tests.rs: FeedService::trending() 의 실제 DB 호출 순서는 user DNA load → posts(24h) → spots → post_mood_vectors 인데, 테스트 mock 이 posts를 맨 앞에 두고 있어 첫 쿼리부터 어긋나 있었음(뒤 쿼리들이 엉뚱한 shape 의 row 를 디코드하려다 email null 에러로 실패). 실제 호출 순서에 맞게 mock 순서 재배열. cargo fmt/clippy(migration+entity, decoded-api 둘 다 -D warnings)/ cargo test --lib(1304 passed, 0 failed)/cargo deny 전부 클린 확인. cargo tarpaulin 커버리지(40.99% < 65% 요구)는 별도 장기 과제로 남김 — 수천 줄 규모 신규 테스트가 필요해 이 세션 스코프 밖. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(api-server): vton — useless AppError 변환 제거 (clippy) rebase 로 새로 들어온 #1054(vton QA 백엔드 블로커 수정) 커밋에서 upload() 가 이미 AppError 를 반환하는데 불필요하게 .into() 로 재변환 — 클린 clippy -D warnings 유지를 위해 제거. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> --------- Co-authored-by: Kiyori <113906780+thxforall@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: decoded-ci <ci@decodedcorp.com>
cocoyoon
added a commit
that referenced
this pull request
Jul 24, 2026
* docs(research): 프론트 지도 리서치 배치 5건 재검증 자산 (#801 #802 #803 #806 #894) (#1053) * docs(research): 프론트 지도 리서치 배치 5건 재검증 자산 (#801 #802 #803 #806 #894) 기존 이슈 코멘트의 findings를 baseline으로 삼아 현재 dev 트리(07-22) 앵커를 재검증하고, close = merged 불변식을 충족할 내구 자산으로 캡처한다. - #801 search country/locale 계약: CONFIRMED (D-BACKEND 확정). country_of_origin 접근 경로 이원화 + posts search의 Orval 우회 신규 발견. - #802 9무드 SSOT: 데이터 9/9 일치 CONFIRMED, messages drift는 PR #912로 해소(OVERTURNED). 남은 비준 블로커는 vault 문서 자체의 버전 라벨 모순뿐. - #803 Style DNA write 경로: 전제 금지 유지. persona/mood 이중 의존 규명, persona-only 유저는 기존 배치로 치유 불가(소급 onboarding_pick 필요). primary_mood 404는 latent(웹 호출부 없음)로 전복. - #806 VTON Vertex 토큰: 원 질문 moot — web 서버리스 라우트가 #988로 삭제, 기본 엔진 gpt-image-2는 GCP 미사용. 공개 레포엔 요약 스텁만(본문 vault). - #894 계측 truth map: Meta Pixel 부재 전복(PR #1046, PageView 한정·동의 게이트 없음). UTM/click-id 캡처·가입 이벤트 emit은 여전히 0. 조사 전용 — 소스 코드 변경 없음. 라이브 시스템 조회 없음(prod 크레덴셜 미보유). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(research): 적대적 리뷰 반영 — 거짓 주장 2건 정정 + 앵커/카운트 교정 별도 리뷰 레인의 반증 결과를 반영한다(self-approve 회피). - #802 결론3·R2: "T10 가드가 CI에서 재발을 차단한다"는 거짓 — .github/workflows 전체에서 vitest를 도는 워크플로가 없고(bun run 호출은 doc-frontmatter, schema-drift 2건뿐) pre-push도 lint/prettier/tsc만 돈다. "수동 실행 가드"로 정정하고 CI 배선을 후속으로 명시. 가드 파일 docblock의 자기서술을 검증 없이 옮긴 것이 원인. - #806 stub: "비기본 엔진을 '명시적으로' 선택했을 때"는 코드가 반증 — factory.py의 (VTON_ENGINE or "vertex")는 빈 값 주입 시 명시적 선택 없이 Vertex로 폴백한다. vault 원문에 없던 한정어를 공개 요약에 덧붙여 안전 범위를 좁혀 말한 것이라 제거하고, 배포 환경 점검이 형식이 아님을 명시. - #802 후속 참조: vault PR decoded-docs#18 머지 시 vault 라인 앵커 +4행 이동 고지. - 교정: market.ts 앵커 1-27→1-30, snapshot.json 1-15→1-14, "두 축"→"세 축", "나머지 4개"→"3개", 서피스 카운트 표현. - front-matter 5문서 정규화(doc/essence/owner 추가, status=final 통일). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(research): #985 머지로 뒤집힌 #894 결론에 superseded 배너 + #803 writer 3번째 보완 리뷰 레인이 트리 이동을 잡았다. 작성 20분 뒤 PR #985가 머지(b48a770, 2026-07-22T10:01:18Z)되어 #894의 핵심 결론 일부가 dev에서 무효가 됐다. - #894: superseded 배너 추가. 현재 dev에 attribution.ts(UTM 5필드+fbclid/gclid first-touch), meta-pixel-events.ts(표준 이벤트 레이어), first-core-action.ts가 있고 trackAnonEvent 프로덕션 호출부가 4곳이다. 결론 3·4와 §1의 UTM· trackAnonEvent·표준 이벤트 행, §2의 #985 상태, §6 해당 행이 뒤집혔다. b48a7701은 dev 전용이라 "main ⊇ dev" 전제도 해당 행에서 깨졌다. 스냅샷 본문은 지우지 않고 기준 커밋을 명시해 보존한다. - #803: users.style_dna writer가 둘이 아니라 셋 — update_style_dna (service.rs:80, PATCH /me/style-dna, 무검증 전체 교체)가 누락됐다. onboarding_pick 없이 primary_mood를 세울 수 있어 "재-온보딩 전까지 영원히"는 과장. #799 복구 설계에서 소급 onboarding_pick 잡이 유일 선택지가 아님을 명시. - #803 G1 상태코드 400 → 422 (error.rs:81-84에서 UNPROCESSABLE_ENTITY 매핑). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(research): 교차 감사 반영 — 기준 커밋 고정 + 시제·비용등급 정정 21에이전트 교차 감사(공개 아티팩트 ↔ 정본 문서 정합·인용 무결성·완결성) 반영. - 전 문서 검증 기준 커밋 고정(origin/dev=a3d5702b). 브랜치명만으론 머지 후 앵커 복원이 불가하고, 이 배치 자신이 2주 만의 앵커 이동을 보여준다. - #801 시제 정정: #796·#799는 2026-07-09 CLOSED. 이 문서는 미결 결정의 입력이 아니라 확정된 D-BACKEND의 사후 확인이며, 4단 목록은 실행 목록으로 읽어야 한다. - #801 신규: entity_id filterable은 이미 색인 문서에 있고(batch/entity_reindex.rs:66) ENTITIES_FILTERABLE 등재만 빠짐 → 설정 1줄+재색인. country(스키마+적재 포함 4단계)와 티어를 같이 매기면 값싼 언블록이 비싼 항목 뒤에 줄 선다. - #803: FE 앵커 한정 드리프트 고지(#985 머지, 서버측 결론 불변) · §5-3을 "피드 개인화 신호 없음"에서 "DNA 재랭킹이 무증상 no-op"으로 정정 (feed/service.rs blend_with_dna의 `_ => base`, 로그·플래그 없음. 단 손실 크기는 feed_dna_mix 미확인이라 '피드가 죽는다'는 과장) · 권고2를 2a(응답 플래그, 저비용)/2b(picker 풀 제한, BE 계약=티어 대상)로 분리하고 GET /posts?mood=가 대체재가 아닌 이유 명시. - #894: front-matter status=superseded·essence=partial · §6 item6은 전제만 참 (soft_wall_hit은 loginRequiredStore.ts:36에서 발화) · signup_complete emit 0은 dev에서도 유효 · 앵커 nit 2건. - vault 링크는 decoded-docs#18 머지 전까지 main에서 404 → 브랜치 참조 hedge. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(research): vault 링크 hedge 제거 — decoded-docs#18 머지로 main 도달 두 문서가 참조하는 vault 자산이 decoded-docs main에 올라갔다(PR #18 머지, 2026-07-22T12:04Z). '머지 전까지 브랜치 참조' 임시 문구를 제거한다. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(plans): auto-extract PR #1053 body [skip ci] * feat: 앵커축 facet 승격 v1 — color/style_tags 큐레이터·Explore·홈 연결 thestylearchivist류 "[아이템/컬러/스타일] × 컬렉션" 탐색을 재현하기 위해, cody_analysis(color_palette/items[].color)와 posts.style_tags 자유텍스트를 color_mappings/style_tag_mappings(결정론적 매핑, style_mood_mappings 패턴 재사용)로 canonical 값으로 정규화하고 posts.canonical_colors/canonical_styles 에 materialize했다. 세 표면이 이 값을 공유: - 큐레이터 챗(editorial_story_chat search_posts) — colors/styles 배열 overlap 필터, members/query 없이 단독 소싱 가능 - Explore — 가짜 canned-query 스타일 칩을 진짜 Meilisearch facet 필터로 교체 - 홈 — "How to Style Red/Black/Navy" 앵커 레일 추가(seasonal 레일과 동형) Materialization은 search_reindex 배치(daily 04:00 + boot)에서 전체 active post에 대해 계산 — verify/update_post 경로는 건드리지 않음(해당 DTO들이 cody_analysis/style_tags를 바꾸지 않아 재계산이 무의미하다고 판단, 배치가 유일한 신뢰 가능한 백필 경로). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * feat(web): Explore 필터 바를 칩 스크롤러 → Style/Color 드롭다운으로 교체 색은 "읽는" 축이 아니라 "보는" 축이라 텍스트 칩(FilterChipRow)으로는 안 맞는다고 판단 — Style은 SortDropdown과 동형인 native <select>로, Color는 실제 스와치를 그리는 커스텀 팝오버(ColorDropdown)로 분리해 Style/Color/Sort가 한 톤의 필터 바 패밀리로 읽히게 했다. - ColorDropdown: canonical_colors 13개 스와치 팝오버. 다크모드에서 검정 스와치가 카드 배경에 묻히는 문제 발견 → border 대신 ring(+dark 변형)으로 경계를 항상 보이게 수정 (Playwright 스크린샷으로 확인) - StyleDropdown: FilterChipRow/FilterChip 대체(둘 다 삭제, 재사용처 없음) - 스타일/컬러 필터 선택 시 mode가 "search"로 전환되며 필터 바 자체가 통째로 사라지는 버그 발견 → 필터 바를 mode 분기 바깥으로 이동해 두 모드 모두에서 항상 보이도록 수정 - Playwright로 로컬 dev 서버 구동해 스와치 팝오버·필터 조합(Street+Red 동시 적용)·필터 바 지속 렌더를 스크린샷으로 확인 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(web): Explore 필터 바 — "Style"/"Color" 라벨 정렬 + 포커스 링 톤 통일 닫힌 상태에서 스타일 드롭다운이 "All"로 표시돼 옆의 "Color"와 짝이 안 맞고 무슨 필터인지 모호했음(raf 피드백, 스크린샷) — "All" 옵션의 표시 텍스트만 "Style"로 바꿔 ColorDropdown과 대칭 페어("Style ▾"/"Color ▾") 로 읽히게 함. 내부 StyleTag 타입·"All" sentinel·로직은 그대로(옵션의 표시 텍스트만 분리, value는 안 바뀜 — 회귀 없음). 같은 화면에서 기본 브라우저 파란 포커스 링이 앱 톤과 안 맞는 것도 같이 확인돼 Style/Color/Sort 세 트리거 모두 --ring 토큰 기반 focus-visible 링으로 통일. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * feat(editorial_discovery): color-story 앵글 타입 추가 — canonical_colors 기반 Discovery 자동 앵글 추천이 여태 raw style_tags 빈도만 근거로 삼고 앵커축 facet v1(canonical_colors/canonical_styles)은 전혀 안 쓰고 있었음(raf 질문 으로 확인). style-archetype/item-anchor 옆에 3번째 유형 color-story 추가 — #thestylearchivist 류 "How to style X"를 하드코딩 홈 레일이 아니라 에이전트가 실데이터 색상 분포로 직접 제안하게 함. - DiscoveryInput.color_frequency + PostSummary.canonical_colors 추가 - repository.py: posts 쿼리에 canonical_colors 추가, color_freq 집계 (style_tag_freq는 원본 세밀 태그 그대로 유지 — 창의성 근거 그대로 둠) - prompts.py: color-story 유형 설명 + 근거 데이터 섹션 추가 - AngleRecommendation.angle_type Literal에 "color-story" 추가 - supabase-assets 마이그레이션: editorial_recommendations.angle_type CHECK 제약에 'color-story' 추가 (cloud-only 프로젝트 — supabase db push 는 별도로 필요, 이 세션에서 직접 push 안 함) - admin 스토리 페이지 AngleTypeBadge에 컬러 타입 배지 추가 로컬 operation DB(posts) 대상 dry-run으로 color_frequency 집계 로직 검증 (top-80 트렌딩 포스트 기준 실데이터 분포 확인) + Pydantic 모델/프롬프트 빌더 렌더링 검증. assets DB는 cloud-only라 전체 파이프라인 e2e는 미검증. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(api-server): 앵커축 컬러 facet 오분류 수정 — importance/prominence 필터링 raf 리뷰(red color-story 앵글 검토 중 발견) — canonical_colors가 아이템 importance 구분 없이 모든 아이템 색 + 전체 룩 팔레트 전부를 합쳐서 만들어짐. 그 결과 액세서리 하나만 red인 룩, 심지어 아이템 레벨엔 red가 전혀 없고 전체 팔레트 5번째 항목에만 잡힌 룩까지 "red 룩"으로 분류됨(4개 중 3개가 실제로는 red 아닌 오분류 확인). - items[].color: importance == "high" 인 아이템만 카운트 (mid/low 액세서리· 액센트 제외) - style.color_palette: prominence 순 상위 2개만 (cody 프롬프트가 이미 시각적 두드러짐 순으로 정렬해서 줌 — 하위권은 배경/조명 등 비전 노이즈일 가능성) 실데이터로 재검증: 로컬 330개 포스트 재인덱싱 후 red 태그 포스트가 top-80 기준 14 → 3(진짜만)으로 정확해짐. 유닛테스트 4개 추가(실제 오분류 케이스 재현 포함), 8개 전부 통과. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(ai-server): editorial story 카피 생성에 컬러 그라운딩 가드레일 추가 raf 리뷰로 발견 — "Summer Ease" 슬라이드 캡션이 "a bold pair of red shorts" 라고 썼는데 실제 하의는 black. 원인: 두 카피 생성 경로(자동 compose / 챗 add_look_slide) 다 전체 룩 레벨 canonical_colors 만 LLM 에 주고 개별 아이템 색은 전혀 안 줌 — 컬러 스토리 앵글의 "red" 테마가 룩 전체에 어울리는 아이템(가방 하나)에서 왔는지 특정 못 하니 아무 아이템에나 갖다 붙일 수 있었음. - editorial_story/prompts.py: "COLOR GROUNDING" 룰 신설 — 아이템 자체의 name 에 그 색상/패턴 단어가 실제로 있을 때만 색 단정 허용, 아니면 실루엣/소재로 대체. 예시 문구도 색상 임의 언급하던 것 순화. - editorial_story_chat/agent.py: 챗 에이전트 시스템 프롬프트에 동일 룰. - editorial_story_chat/tools.py: search_posts 후보 요약의 컬러/스타일 facet 라벨을 "전체 룩 기준"으로 명시(개별 아이템 색과 혼동 방지). per-item cody_analysis.items[].color 를 실제로 두 파이프라인에 plumbing 하는 건 별도 작업(solution↔cody item 간 직접 조인이 없어 더 큰 작업) — 이번엔 프롬프트 레벨 가드레일로 우선 차단. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * feat(editorial_discovery): 계절성 반영 — current_season() 자동 계산 + season_frequency raf 지적 — 여름에 "니트웨어" item-anchor 앵글이 나온 게 문제. 근본 원인은 마이닝이 계절 신호를 전혀 안 봄. 하드코딩("지금은 여름이다" 프롬프트 텍스트)은 계절 바뀔 때마다 사람이 고쳐야 해서 기각하고, 호출 시점 실제 날짜에서 매번 계산하는 방식으로 감. - prompts.py: current_season(now=None) 헬퍼 — KST 기준 월→계절 매핑, cody Stage-1 의 season 보캐뷸러리(spring/summer/fall/winter)와 동일. 테스트 위해 now 주입 가능. - repository.py: cody_analysis.style.season 을 posts 쿼리에 추가, canonical colors 와 같은 패턴으로 season_frequency 집계. - models.py: PostSummary.season, DiscoveryInput.season_frequency 추가. - prompts.py: "계절성(모든 유형 공통 적용)" 섹션 신설 — item-anchor 는 명백한 비계절 아이템 회피/감점, style/color-story 는 계절 맞는 포스트 우선, 데이터 불확실하면 강제 배제 안 함. 실제 Gemini 호출로 검증(blue color-story 생성) — rationale 에 "summer 시즌과 겹치는 포스트들이 많아 계절성을 고려" 라고 직접 언급, season_frequency 를 실제로 참조해 판단하는 것 확인. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * feat(ai-server): 카피 톤 완화, 뉴진스 그룹 제외, 후보 번호 매기기 raf 피드백 3건 반영: 1. topic_title/deck 이 "충실한 번역만, 재창작 금지" 제약 때문에 한글 앵글 원문(구체적이고 캐치한)에 비해 영문 카피가 밋밋했음(예: "The Temperature of Red"). 개념 충실성(같은 색/아이템/인물, 새 컨셉 금지)은 유지하되 표현은 매거진 에디터처럼 자유롭게 다시 쓰도록 완화. COLOR GROUNDING(사실 관계)은 그대로 분리 유지 — 톤 자유 ≠ 사실 날조 허용. 2. Discovery 마이닝(services/editorial_discovery/repository.py) + 챗 search_posts(editorial_story_chat/tools.py) 양쪽에 그룹 제외 필터 추가 (_EXCLUDED_GROUP_PATTERNS = ["%newjeans%"], product 결정). 실제 로컬 DB로 두 쿼리 다 라이브 검증(뉴진스 0건, 다른 그룹 영향 없음). 3. search_posts 후보 목록에 1-based 번호 추가, 챗 에이전트가 post_id 대신 번호로 후보를 지칭하도록 시스템 프롬프트에 명시 — 프론트의 이미지 카드 번호와 대응(다음 커밋). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * feat(web): 스토리 챗에 search_posts 후보 이미지 카드 렌더링 raf 피드백 — 후보가 raw UUID 텍스트로만 나와서 뭘 골라야 할지 알 수 없었음. 조사해보니 구조화 데이터(data.candidates, 이미지 URL 포함)는 이미 서버가 생성·저장·응답까지 다 하고 있는데, 프론트 타입(ChatMessage.tool_result)이 data 필드를 아예 선언 안 해서 죽은 채로 버려지고 있었음 — 렌더링만 없었음. - useEditorialStoryChat.ts: SearchPostCandidate(Item) 타입 추가, tool_result.data.candidates 타입 선언. - StoryChatPanel.tsx: search_posts 결과일 때 텍스트 대신 번호+썸네일+ 누구/컨텍스트+facet 칩 카드 그리드로 렌더(기존 drafts 페이지의 슬라이드 썸네일과 동일 <img> 패턴). 카드 번호는 candidates 배열 순서 = 챗 에이전트가 참조하는 번호와 동일(직전 커밋의 백엔드 numbering과 대응). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * feat: editorial_stories 에 'publishing' 상태 추가 raf 피드백 — Publish 누르면 실제로는 백그라운드 job(operation DB editorial_story_publish_jobs)이 큐에 들어가 나중에 처리되는데, story.status(assets DB)는 발행 완료/실패 시점까지 계속 'draft' 로 남아서 Publish 버튼이 응답 직후 바로 재활성화되고 화면엔 진행 중 표시가 전혀 없었음. - supabase-assets 마이그레이션: editorial_stories.status CHECK 에 'publishing' 추가. - admin/editorial_stories.rs::publish() — job INSERT(operation) 직후 assets_db 에 status='publishing' UPDATE (두 DB 라 트랜잭션 불가 — best-effort, job 은 이미 성공적으로 큐잉된 뒤라 이 UPDATE 실패해도 발행 자체엔 영향 없음). - ai-server publish_job.py — 잡 종료 시 writeback을 published 외에 failed_terminal → 'failed' 도 반영(기존엔 published 만 반영, 실패 시 story 가 영원히 'publishing' 에 멈춰있었을 것). failed_retryable(자동 재시도 중)은 그대로 'publishing' 유지. - 프론트: AdminStatusBadge 에 publishing variant(파란색), 발행 버튼은 story.status !== "draft" 조건으로 이미 자동 비활성화되던 것에 스피너+ "Publishing…" 라벨 추가, useEditorialStory 폴링(5s)을 publishing 에도 적용해 완료 시 자동 반영. cargo test 전체 통과(기존 무관 실패 5건 제외), typecheck/lint 클린. 마이그레이션은 cloud assets 프로젝트 전용이라 이 커밋엔 파일만 포함 — push 는 별도 확인 후 진행. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * style(web): 기존 prettier 포맷 위반 3건 자동 수정 pre-push 훅을 이번에 처음 로컬에 설치(just hook)하면서 이전엔 아무도 못 걸러낸 기존 포맷 부채가 드러남 — qa-gallery/page.tsx, sitemap.ts, SearchSuggestions.tsx. 전부 로직 변경 없는 순수 들여쓰기/줄바꿈 포맷팅(eslint --fix). typecheck 클린. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * style(web): 기존 prettier 포맷 위반 — qa/ 19개 파일 자동 수정 pre-push 훅(prettier --check) 최초 실행에서 드러난 기존 포맷 부채. 전부 로직 변경 없는 순수 개행/들여쓰기(JSON 스냅샷 포함 — 값 변경 없음, 줄바꿈만). typecheck 클린. qa/matrix.test.ts 의 README 드리프트 가드 실패 1건은 이 커밋과 무관한 기존 실패(수정 전 dev에서도 동일하게 실패 확인). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(api-server): 로컬 pre-push CI 최초 실행에서 드러난 기존 부채 정리 이번 세션에서 pre-push 훅(just hook)을 처음 설치·실행하면서 그동안 로컬 -D warnings clippy / 아키텍처 테스트 / 일부 unit test 가 한 번도 통과된 적 없었다는 게 드러남 — 전부 내가 이번 세션에서 만든 코드와 무관한 기존 파일들. **clippy (-D warnings) 35~42건, 전부 기존 코드** - disallowed_methods(unwrap): serde_json::json! 매크로 전개가 내부적으로 unwrap 을 쓰는 false positive — 프로젝트 기존 컨벤션대로 함수 단위 #[allow(clippy::disallowed_methods)] 부여(home_curation.rs 5개 함수, catalog_gaps.rs, editorial_stories.rs, item_likes/handlers.rs, posts/handlers.rs 4개 함수, posts/service.rs 테스트 모듈 1개 누락분). - manual_contains: catalog_gaps.rs — iter().any() → contains(). - doc_lazy_continuation: editorial_stories.rs 독립 문단 앞 빈 줄 추가. - single_match: item_likes/service.rs — match → if let. - items_after_test_module: item_likes/service.rs — mod diversify_tests 를 taste_centroid/curation_facts 뒤(파일 끝)로 이동. - too_many_arguments(8/7): raw_posts/relocate.rs — raw_public_url/ op_public_url 두 인자를 RelocateBucketUrls 구조체로 묶음(호출부 3곳+ 테스트 6곳 갱신). - empty_line_after_doc_comments: posts/service.rs — list_posts 가 다른 곳으로 옮겨지며 남은 고아 doc 주석 2줄 삭제. **아키텍처 테스트 3건** - domain_dependencies_match_allowed_list: posts↔catalog(complete_the_look → catalog_knn), posts→onboarding(interleave), catalog/catalog_entities →posts(DTO 재사용) — 전부 이미 배포된 기능 코드, 허용 목록만 안 따라감. 리팩터링 대신 실제 참조 목적을 코멘트로 남기고 허용 목록에 반영. - files_should_not_exceed_line_budget: 기존 LINE_BUDGET_ALLOWLIST 패턴을 그대로 확장 — 5개 파일(vton/mod.rs 1604줄 등) 등재. 실제 분리는 별도 리팩터링 과제(회귀 감지는 계속 유효). - all_handlers_registered_in_openapi: complete_the_look 핸들러를 openapi.rs paths 에 등록 누락 — 추가 + openapi.json 재생성. **unit test 2건 — mock 쿼리 순서 버그** - feed/tests.rs: FeedService::trending() 의 실제 DB 호출 순서는 user DNA load → posts(24h) → spots → post_mood_vectors 인데, 테스트 mock 이 posts를 맨 앞에 두고 있어 첫 쿼리부터 어긋나 있었음(뒤 쿼리들이 엉뚱한 shape 의 row 를 디코드하려다 email null 에러로 실패). 실제 호출 순서에 맞게 mock 순서 재배열. cargo fmt/clippy(migration+entity, decoded-api 둘 다 -D warnings)/ cargo test --lib(1304 passed, 0 failed)/cargo deny 전부 클린 확인. cargo tarpaulin 커버리지(40.99% < 65% 요구)는 별도 장기 과제로 남김 — 수천 줄 규모 신규 테스트가 필요해 이 세션 스코프 밖. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(api-server): vton — useless AppError 변환 제거 (clippy) rebase 로 새로 들어온 #1054(vton QA 백엔드 블로커 수정) 커밋에서 upload() 가 이미 AppError 를 반환하는데 불필요하게 .into() 로 재변환 — 클린 clippy -D warnings 유지를 위해 제거. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * chore: backend-release 재트리거 (누락된 push 웹훅 복구) (#1066) PR #1064 머지 시 GitHub push 웹훅이 이 커밋에 대해 전달되지 않아 backend-release.yml(버전 bump+태그)과 deploy-backend.yml(prod 배포) 둘 다 트리거 안 됨(GitHub 쪽 일회성 전달 누락으로 추정, Actions 권한/브랜치 보호/워크플로우 상태 전부 정상 확인됨). deploy-backend 는 workflow_dispatch 로 수동 재실행해 prod 배포 완료. backend-release 는 workflow_dispatch 트리거가 없어 재실행 불가능 — main 에 새 push 를 만들어 재트리거하기 위한 순수 빈 커밋(파일 변경 없음). 스캔 로직이 마지막 backend-v* 태그 이후 전체 커밋을 보므로 PR #1064 의 bump:minor 라벨이 그대로 반영됨. Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com> * docs(plans): auto-extract PR #1066 body [skip ci] --------- Co-authored-by: Kiyori <113906780+thxforall@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: decoded-ci <ci@decodedcorp.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
프론트 지도(#789) 리서치 배치 5건의 재검증 자산을
docs/research/에 캡처한다. 소스 코드 변경 0 · 라이브 시스템 조회 0(prod 크레덴셜 미보유).5건 모두 이미 적대검증을 통과한 findings가 이슈 코멘트에 있었고, 이슈가 열려 있던 이유는 리서치 미완이 아니라
close = merged불변식(자산 미커밋)이었다. 그래서 이번 배치의 실제 작업은 기존 findings를 baseline으로 주입 → 현재 dev 트리(07-22) 앵커 재검증 → drift/전복 기록이다. 결과적으로 5건 중 4건에서 baseline이 뒤집히거나 조건이 바뀌었다.country_of_origin접근 경로 이원화(실컬럼 vsmetadata->>) + posts search가 Orval을 우회해 locale이 와이어에 없음 +RequestMarket이 search 핸들러에 미배선(origin↔market 분기 1차 증거)cody_analysisvs 사전계산post_mood_vectors). persona-only 유저는 기존 배치로 치유 불가 → 소급onboarding_pick방출 잡 필요.primary_mood404는 웹 호출부가 없어 latentgpt-image-2는 GCP 미사용 → 원 블로커 두 축 소멸. 공개 레포엔 요약 스텁만(본문 vault)origin/main에 존재(fbf47d54, #1046) — 단 PageView 한정 · 표준 전환 이벤트 없음 · 동의 게이트 없음. UTM/fbclid캡처와 가입 이벤트 emit은 스냅샷(a3d5702b) 기준 0 — 작성 20분 뒤 #985 머지(b48a7701)로 dev에서만 UTM 캡처·Meta 표준 이벤트가 생겼다(문서 내 SUPERSEDED 배너).main미반영이고signup_complete자체 emit은 dev에서도 0Design Decisions / 주요 설계 결정
NOT-IN-CODE갭으로 명령만 기재, 미실행Test Plan
bash scripts/check-no-machine-paths.sh→ OK (instruction surface 머신 경로 0)bun run scripts/check-doc-frontmatter.ts→ OK (38 docs)git log origin/main -- packages/web/lib/analytics/meta-pixel.tsx→fbf47d54존재 /en.json:312,314="Daily Casual"/"Edgy Chic"= DB 시드 일치git show --stat은docs/research/*.md5개만)머지 선행 의존성
#806스텁과#894문서가 vault 문서를 참조하는데, 그 두 파일은 아직 decoded-docsmain에 없다(브랜치docs/2026-07-22-research-assets에만 존재) → 순서가 바뀌면 공개 레포에 404 링크가 남는다. 문서 안에 임시 hedge 문구는 넣어 두었다.Follow-ups
style-mood-taxonomy.md의 status/H1/tag 3중 모순 정리(~3줄) → 그 후 D-STYLEDNA 비준. supabase↔SeaORM 이중 시드 dedup, vault↔seed 자동 가드 부재(T10 미커버) + T10 자체도 CI 미배선(현재 수동 실행)post_mood_vectors백필은 필요조건이지 충분조건 아님 —style_dna.source_post_ids기반 소급onboarding_pick잡이 백엔드 갭 구축 스코프·순서 (philippe 협업) #799 티어링 결정의 입력b48a7701, 10:01Z) — 단 dev 전용,main미반영이라 prod 계측은 아직 PageView뿐이다(rebase 항목은 소멸). 남은 갭 = dev→main 릴리즈 ·signup_complete·dna_committed자체 emit 0 ·useTrackEvent로그인 게이트 · 동의 배너 부재(제품/법무) ·NEXT_PUBLIC_META_PIXEL_IDprod 주입 여부 미확인packages/web/lib/gcp/auth.ts정리 +VTON_ENGINE빈 문자열 시 Vertex 폴백(잠복) 확인