PRD.md §2.1-②·§3.1 P0 갭 우선순위 #2. close/formal 2종 관계 티어를 추가하고,
초안 생성 시 상대별 톤을 다르게 낸다.
- core-backend: TwinSettings.RelationshipTier(전역 기본값, 안전 우선 formal
기본), Contact.RelationshipTier(1:1 연락처별 오버라이드, nullable).
persona.go의 resolveRelationshipTier()가 연락처 오버라이드 → 전역 기본값 →
formal 순으로 해석하고, 그룹 대화는 상대가 여럿이라 항상 전역 기본값만 사용.
POST /conversations/:id/draft는 기존에 인증을 요구하지 않던 동작을 깨지
않도록 currentUser(..., false)로 선택적 인증 처리 후 티어를 주입.
- 안전 관련 부수 수정: 그룹 대화에서는 전역 자율성 레벨(L1/L2)과 무관하게
와카뷰 자동 발송을 무조건 차단(단톡 따라잡기는 L0 고정이 맞음).
- ai-service: RELATIONSHIP_TIER_INSTRUCTIONS + system_prompt_for_tier()로
Gemini system_instruction에 관계 톤 지침을 주입. 에스컬레이션/정체성 게이팅
로직은 티어와 무관하게 그대로 유지.
- mobile: 온보딩(말투 샘플 다음 단계)과 자율성 설정 화면에 전역 기본값
SegmentedButton, 연락처 추가/수정 다이얼로그에 _RelationshipTierPicker로
상대별 오버라이드 추가.
- 테스트: core-backend persona_test.go 6개(해석 순서·그룹 예외·비인증
기본값 포함), ai-service 6개(system_prompt_for_tier + draft_reply 경로)
전부 추가, 기존 스위트 모두 통과(go test, pytest 47/47, flutter analyze/test).
실제 Flutter 빌드 + Playwright로 온보딩→연락처 오버라이드→목록 표시까지
전체 라운드트립 시각 검증 완료.
- docs: roadmap.md §2.7-B, deploy-checklist.md N4-C2a~d 완료 처리. 다음
우선순위는 Track C3(스팸/도배 감지 최소 버전).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014YSB5PqF38raTxP5ABgr9m
ai-service:
- escalation_filter/retrieve_style/generation/main(FastAPI)의 ad-hoc
TestClient 검증을 ai-service/tests/ 정식 pytest 스위트로 승격(34개).
Gemini 호출은 mock, retrieve_style은 overlap이 recency를 항상
이긴다는 것(과거 버그 재발 방지)까지 포함
- on_event(deprecated) -> lifespan 컨텍스트 매니저로 교체
core-backend: 자율성 플로우(L0->L1->L2) 통합 테스트를 쓰려면 실제 분기
로직이 있어야 해서, roadmap.md §2.2에서 미결로 남아있던 자율성 엔진
오케스트레이션 최소 버전을 이번에 구현:
- PATCH /users/:id/twin-settings -- 자율성 레벨 변경 (기본값 L0)
- 트윈 발송 시 에스컬레이션 통과 후 레벨 확인: L0는 항상 차단, L1은
approved:true 필요, L2는 화이트리스트 매칭 시 즉시 자동발송·매칭
없으면 L1과 동일하게 승인 필요. 에스컬레이션은 레벨/화이트리스트/
승인 여부와 무관하게 항상 우선(테스트로 확인)
- 화이트리스트 매칭은 v1 최소 구현(전역 키워드 매칭, 상대별 예외는
아직) -- 대화방↔연락처 연결이 모델링되지 않아 보류, README에 명시
온보딩·채팅·설정 수동 QA는 Flutter 클라이언트가 없어 이 환경에서는
보류, roadmap.md에 근거 남김