Commit Graph

111 Commits

Author SHA1 Message Date
Claude a1415f5ce0
운영 대시보드 낡은 메모 정정 + 트윈 발송 차단 사유별 분해 추가
roadmap.md §2.6의 "모니터링 대시보드 UI·지연시간·오류율 아직 없음" 메모가
낡은 기록이었음을 재확인 -- GET /admin/dashboard(HTML)와 /admin/metrics의
생성 지연시간·오류율 계측은 이미 이전 Phase 1 B 커밋에서 구현돼 있었고,
같은 문서 §B 항목과도 모순되고 있었음. [~] -> [x]로 정정하고 실제 배경을
남김.

실제로 오늘 추가한 것: RuntimeMetrics.TwinSendsBlocked를 사유별
(peer_veto/group_conversation/flood_blocked/flood_detected/
escalate_check_error/escalated/autonomy_l0/autonomy_l1_unapproved/
autonomy_l2_no_whitelist_match/autonomy_unknown_level)로 분해하는
TwinSendsBlockedByReason을 추가하고, /admin/metrics에
twin_sends_blocked_by_reason으로 노출(기존 twin_sends_blocked 총합은
유지). 이미 JSON에는 있었지만 화면엔 안 보이던 escalations_by_reason과
새 필드를 /admin/dashboard에 사유별 표로 렌더링.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014YSB5PqF38raTxP5ABgr9m
2026-08-03 07:12:34 +00:00
Cursor Agent 97edabc47d
docs: clear stale Track C undeployed note
Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-08-03 06:41:02 +00:00
Cursor Agent f363e8e773
docs: mark Track C A–F production redeploy done (95422bb)
GitHub+Gitea main synced; msn.iykyka.com web/core/ai rebuilt.

Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-08-03 06:40:39 +00:00
Claude 95422bb012
답장 마감 알림(2.7-F) 구현: 온디바이스 스누즈 저장 + 인앱 배지 + 로컬 알림(부분 검증)
roadmap.md §2.7-F / deploy-checklist.md N4-C6a~c 대응. "이따 답장"을 누르면
대화방별 스누즈 시각을 순수 온디바이스 drift 테이블(ConversationSnoozes)에
저장하고(서버 전송 없음, 다른 사람에게 절대 보이지 않음), chat_screen.dart
앱바에서 빠른 선택(1시간 후/저녁에/내일)으로 걸고 해제할 수 있게 했다. 실제
답장을 보내면 자동으로 스누즈가 풀린다.

로컬 알림은 flutter_local_notifications+timezone을 실제로 붙여
zonedSchedule()/cancel()을 호출하지만, 이 샌드박스에는 실기기·에뮬레이터가
없어 알림이 실제로 울리는지는 검증하지 못했다 — 검증한 건 스케줄러 호출
인자(id/시각/페이로드)가 목(mock) 기준으로 맞는지뿐이다. 그 대신 항상 켜져
있는 인앱 대체 경로로 conversation_list_screen.dart 배지와 chat_screen.dart
배너가 마감 지난 스누즈를 보여주고 바로 해제할 수 있게 했다. 웹 빌드는
플러그인이 웹을 지원하지 않아 no-op 스텁으로 대체.

마감 판정(isSnoozePastDue)과 빠른 선택 시각 계산은 순수 함수로 분리해
고정 시각으로 단위 테스트했고, SnoozeController를 통해 스케줄러를 목으로
바꿔 넣어 호출 인자도 검증했다. 백엔드(core-backend/ai-service) 변경 없음.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014YSB5PqF38raTxP5ABgr9m
2026-08-03 05:55:30 +00:00
Claude f9fba46889
관계 메모 실제 반영(2.7-E) 구현: draftRequest에 RelationshipNote 전달 + 프롬프트 주입
Contact.RelationshipNote는 CRUD는 이미 있었지만 draftRequest에 필드 자체가 없어
ai-service 프롬프트에 전혀 전달되지 않는 저장 전용 스텁이었다. 이번 변경으로 실제
초안 생성에 반영되게 만든다.

- core-backend/aiservice.go: draftRequest에 RelationshipNote string 필드 추가
  (relationship_tier 옆, omitempty, 빈 문자열 = 무영향)
- core-backend/persona.go: resolveRelationshipNote() 추가. 티어/자율성과 달리
  메모는 순전히 개인별이라 전역 기본 메모 개념이 없음 -- 그룹 대화나 매칭되는
  Contact가 없으면 빈 문자열로 귀결. resolveRelationshipTier/resolveAutonomyLevel/
  resolveRelationshipNote 셋이 복붙하던 "1:1 상대 Contact 찾기" 루프를
  findCounterpartContact() 공용 헬퍼로 추출해 중복 제거
- core-backend/main.go: POST /conversations/:id/draft 핸들러가 resolveRelationshipNote
  결과를 draftRequest에 실어 보내도록 연결
- ai-service/app/generation.py: system_prompt_for_tier()가 relationship_note를
  받아 "[관계 메모] {note} -- ..." 문단을 관계 티어 지침과 별도로 추가(빈 값이면
  기존과 동일). draft_reply()도 파라미터 통과만 함 -- 에스컬레이션/정체성 게이팅은
  전혀 영향 없음
- ai-service/app/main.py: DraftRequest에 relationship_note 필드 추가, /draft가
  draft_reply로 그대로 전달
- 테스트: core-backend Go 64개(신규 3개: 메모 전달/빈 값/그룹 스킵) 전부 통과,
  ai-service pytest 52개(신규 5개) 전부 통과, mobile flutter analyze/test 변경 없이
  그대로 6개 통과(이 기능은 새 UI가 필요 없음 -- 필드는 이미 있었음)
- docs/roadmap.md §2.7-E, docs/deploy-checklist.md N4-C5a/b/c 완료 처리 + NOW/
  바로 다음 5개 요약 갱신

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014YSB5PqF38raTxP5ABgr9m
2026-08-03 05:37:33 +00:00
Claude b4a3b4a903
자율성 상대별 예외(2.7-D) 구현: 연락처별 AutonomyLevel 오버라이드 + 발송 게이트 교체
PRD.md §3.1 P0 "자율성 설정(L0~L2) | 전역 기본값 + 상대별 예외 설정" / §4 엣지케이스
대비 미구현 갭 해소. 관계별 페르소나(2.7-B)의 RelationshipTier 오버라이드 패턴을
그대로 미러링:

- core-backend/models.go: Contact.AutonomyLevel *AutonomyLevel 추가(nil = 전역
  기본값), validAutonomyLevel() 검증 헬퍼 추가(twin-settings PATCH의 인라인 검증도
  이 헬퍼로 통일)
- core-backend/autonomy_resolve.go: resolveAutonomyLevel() 신규 — 연락처 오버라이드
  (1:1 전용) → 전역 TwinSettings 기본값 → L0 순으로 해석. L1/L2가 아니라 L0으로
  폴백하는 이유는 이 코드베이스 전반의 안전 우선 기본값과 동일(불확실하면 항상 초안만
  생성, 사람이 직접 발송). 그룹 대화는 RelationshipTier와 동일하게 항상 전역 기본값만
  사용 — main.go의 그룹 대화 무조건 차단과 이중으로 안전
- core-backend/main.go: POST /conversations/:id/messages의 자율성 게이트가
  TwinSettings 전역값만 읽던 걸 resolveAutonomyLevel() 호출로 교체. peer-veto→그룹
  차단→도배 감지→에스컬레이션 순서와 각 하드게이트는 그대로 유지, "level" 계산
  방식만 바뀜
- core-backend/a1_a2_routes.go: createContactRequest/updateContactRequest에
  AutonomyLevel 필드 추가, contactJSON()에 포함, 생성/수정 핸들러가 RelationshipTier와
  동일한 전체 교체(full-replace) 시맨틱으로 처리(PATCH에서 필드 생략 시 nil로 리셋)
- core-backend/autonomy_resolve_test.go: 연락처 오버라이드 우선순위, 전역 기본값
  폴백, 그룹 대화는 오버라이드 무시, 잘못된 값 검증 거부, PATCH 전체 교체 리셋 커버
- mobile: models.dart에 Contact.autonomyLevel(nullable) 추가, api_client.dart
  createContact/updateContact에 선택적 autonomyLevel 파라미터 스레딩,
  contacts_screen.dart에 _AutonomyLevelPicker(_RelationshipTierPicker와 동일 구조)
  추가해 추가/수정 다이얼로그에 배치 + 연락처 목록 서브타이틀에 표시

ai-service는 변경 없음 — 자율성 레벨은 발송 게이트 로직일 뿐 초안 톤에 영향을
주지 않아 ai-service 프롬프트까지 전달될 필요가 없음.

테스트: go test ./... 61개 전부 PASS, flutter analyze/test 클린(기존 무관 info
린트 1건 제외).

docs/roadmap.md §2.7-D, docs/deploy-checklist.md N4-C4a/b/c를 done으로 갱신하고
NOW/바로 다음 5개 요약도 동기화.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014YSB5PqF38raTxP5ABgr9m
2026-08-03 05:30:42 +00:00
Claude 4182eba9a6
docs: PRD 2차 갭 분석 체크리스트 추가 (2.7-D~F / N4-C4~C6)
roadmap.md §2.7-A~C(단톡 따라잡기·관계별 페르소나·스팸 감지) 완료 후 PRD.md 재대조로
발견한 잔여 갭 3건을 체크리스트로 등록. 우선순위: D(자율성 상대별 예외, P0 명시 항목인데
오버라이드 메커니즘 자체가 없음) → E(관계 메모 반영, 필드/UI는 있으나 프롬프트 주입 안 됨) →
F(답장 마감 알림, P1이자 완전 미구현). deploy-checklist.md에도 동일 항목을 N4-C4/C5/C6로
동기화.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014YSB5PqF38raTxP5ABgr9m
2026-08-03 05:23:03 +00:00
Claude a8c7b98922
스팸/도배 감지 최소 버전(2.7-C) 구현: 대화방 단위 자동 응대 일시중단 + 재개
PRD.md §4 엣지케이스가 "안전 관련이라 v1 최소 버전 필요"로 명시한 항목(P0)인데
관련 로직이 0건이었던 마지막 콘텐츠 갭(roadmap.md §2.7-C, deploy-checklist.md
N4-C3a/b)을 채운다. Track C(콘텐츠 갭) A/B/C 전체 완료.

- core-backend/flood_detect.go(신규): floodMessageThreshold=5건 /
  floodWindow=2분 상수 + floodDetected()/floodReason(). 안전을 위해 반드시
  있어야 하는 기술적 최소값이라 명시적으로 placeholder로 남기고 구현했다 —
  roadmap.md §3의 "PoC 결과가 있어야 정할 수 있는 것"(자율성 기본값 등 UX
  기본값)과는 성격이 다름. 카운트는 대화방 내 sender_id != 소유자인 메시지만
  집계(트윈 자동발송·소유자 본인 발송은 소유자 ID로 남으므로 자동 제외).
- core-backend/main.go: POST /conversations/:id/messages 하드게이트에
  peer-veto → 그룹 대화 차단 다음, 에스컬레이션 체크 이전 지점으로 추가 —
  트윈 자동발송 시도가 전부 지나가는 동일한 우회 불가 지점. 이미
  TwinDisabledByFlood가 켜져 있으면 재계산 없이 즉시 차단(중복 로그/쿼리
  방지). 새로 임계치를 넘기면 대화방을 영구 차단하고 EscalationLog 기록 +
  notifyUser 푸시.
- core-backend/models.go: Conversation.TwinDisabledByFlood 필드 추가.
  TwinDisabledByPeer(거부권, 사람의 일방적 선택 — v1엔 되돌리기 API 없음)와
  달리 이건 시스템이 자동으로 취하는 조치라서 AGENTS.md "every automatic
  action needs post-hoc notification + one-tap undo"가 그대로 적용됨 —
  POST /conversations/:id/flood-reset로 되돌릴 수 있게 별도 필드로 분리.
- core-backend/a1_a2_routes.go: GET /conversations 응답에
  twin_disabled_by_flood 추가(twin_disabled_by_peer와 동일한 자리).
- core-backend/flood_detect_test.go(신규): 임계치 경계값(정확히 N건은
  통과, N+1건은 차단), 사람 발송은 게이트 안 걸림, 윈도우 밖 과거 메시지는
  집계 제외, flood-reset으로 재개, 존재하지 않는 대화방 404 — 5개 테스트.
- mobile/lib/models/models.dart, services/api_client.dart: 모델·API
  클라이언트에 twinDisabledByFlood/resetFlood() 추가.
- mobile/lib/screens/conversation_list_screen.dart: 대화 목록에 도배 차단
  배지(거부권과 같은 자리, 다른 아이콘/문구).
- mobile/lib/screens/chat_screen.dart: 채팅방을 열면(목록에서 넘어온 초기
  상태) 또는 발송 시도가 다시 차단되면 배너에 "자동응대 재개" 버튼을 보여줌
  — one-tap undo. 새 알림 메커니즘을 만들지 않고 기존 EscalationLog/
  InboxScreen을 그대로 재사용.
- mobile/test/models_test.dart: twin_disabled_by_flood 파싱 테스트 추가.
- docs/roadmap.md §2.7-C, docs/deploy-checklist.md N4-C3a/b·Track C 요약·
  "바로 다음 5개"를 완료로 갱신.

테스트: go test ./... 51/51, python3 -m pytest tests/ -q 47/47,
flutter analyze 클린 + flutter test 5/5 모두 통과.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014YSB5PqF38raTxP5ABgr9m
2026-08-03 05:12:29 +00:00
Claude 73dfa2c33c
Merge remote-tracking branch 'origin/main'
# Conflicts:
#	docs/deploy-checklist.md
2026-08-03 05:00:58 +00:00
Claude 5733ec4399
관계별 페르소나(2.7-B) 구현: 관계 티어 필드 + 온보딩/연락처 UI + 톤 프롬프트 분기
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
2026-08-03 04:59:34 +00:00
Cursor Agent 9d2e7ec621
docs: mark iMessage theme and C1 production deploy done
Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-08-03 04:32:18 +00:00
Cursor Agent ee8a41de17
fix(ui): drop unused BrandMark AppTheme import
Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-08-03 04:29:15 +00:00
Cursor Agent 1897dde10e
feat(ui): iMessage-inspired light default + soft charcoal dark
Default ThemeMode.light with white messenger stage, blue mine bubbles,
and gray peer bubbles. Dark theme uses elevated charcoal instead of
pure black; composer and CTAs follow common messenger patterns.

Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-08-03 04:29:15 +00:00
Claude 0d848bcb9a
Merge remote-tracking branch 'origin/main'
# Conflicts:
#	docs/deploy-checklist.md
2026-08-03 03:18:13 +00:00
Claude 64323b824e
feat: implement 단톡 따라잡기 (group catch-up summary) — roadmap.md §2.7-A
Closes the biggest content gap found against PRD.md §3.1 P0: group chat
catch-up was one of only two v1 MVP scenarios and had zero implementation.

Backend (core-backend):
- ConversationParticipant.LastReadMessageID read marker.
- POST /conversations/:id/read advances the caller's marker (never backward).
- GET /conversations/:id/summary builds context from messages since that
  marker and calls ai-service's new POST /summarize; returns unread_count
  and needs_reply.
- GET /conversations now reports unread_count per room.
- Safety: group conversations now unconditionally block twin-authored
  sends (POST /conversations/:id/messages), regardless of the sender's
  global autonomy level. PRD.md §2.3-③ requires this scenario stay L0-fixed
  with no auto-send; autonomy level is a per-user global setting today, so
  this closes the only path a global L2 whitelist match could otherwise
  auto-send into a group.

AI service (ai-service): new summarize.py module (same Gemini-call shape as
generation.py's draft_reply, no escalation/identity gating since nothing
generated here is ever sent) + POST /summarize.

Mobile: "새 대화" dialog now supports adding/removing multiple peer fields
(2+ peers -> is_group:true automatically); unread badge on conversation
rows; ChatScreen takes isGroup and renders its L1 panel as L0-locked for
groups; new "안 본 동안 요약" AppBar action opens a dialog with the summary
and, when a reply looks needed, a button that feeds straight into the
existing draft-request flow.

Verified with a real Flutter build against a live core-backend + ai-service
instance (Playwright driving 3 demo accounts through group creation, unread
badges, and the summary dialog) — this caught a real ordering bug: marking
the read marker on chat *open* meant the summary was always empty by the
time you could tap it, since opening the room already advanced the marker
past everything you'd come to catch up on. Fixed by marking read on screen
*exit* (dispose) instead, so the marker reflects what was unread that whole
visit and updates once you leave.

go test / pytest / flutter analyze+test all pass.
2026-08-03 03:16:54 +00:00
Cursor Agent 0aae8fb578
docs: mark Soft Neutral production web deploy done
msn.iykyka.com rebuilt from e05a0f0 after dual-push to Gitea.

Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-08-03 02:45:07 +00:00
Claude be9d5be7fe
Merge remote-tracking branch 'origin/main'
# Conflicts:
#	docs/deploy-checklist.md
2026-08-03 02:22:45 +00:00
Claude 497c0ab537
docs: add PRD content-gap checklist (단톡 따라잡기, 페르소나, 스팸 감지)
PRD.md §3.1 lists 10 P0 features for v1; cross-checking the actual code
against that table found three that are fully unimplemented despite being
required scope, not deferred PoC defaults:

- 단톡 따라잡기 (group catch-up summary) — one of only two v1 MVP
  scenarios, currently 0%: no summary endpoint, no AI-service logic, no
  client UI, and the "new conversation" dialog can't even create a group
  (server already supports is_group + multiple user_ids).
- 관계별 페르소나 (relationship-tier tone, min. 2 tiers) — TwinSettings
  only has AutonomyLevel, no tier concept anywhere.
- 스팸/도배 감지 — PRD explicitly calls this out as needing a v1-minimum
  version for safety, not deferred; nothing implemented.

Added as roadmap.md §2.7 (workstream breakdown, priority A→B→C) and
deploy-checklist.md N4 Track C (mirrors Track A/B's format), cross-linked.
Explicitly scoped out image/file sending, read receipts, and typing
indicators as a separate "not proposed, PRD scope change needed" note,
since AGENTS.md requires calling out in-scope vs future-phase ideas.
2026-08-03 02:20:27 +00:00
Cursor Agent e05a0f07ce
docs: note Soft Neutral main merge; prod web rebuild pending SSH
GitHub main is at 553cb62; gitea dual-push and msn.iykyka.com web rebuild
still need host credentials in this environment.

Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-08-03 02:11:35 +00:00
Cursor Agent 553cb624b0
fix(ui): drop unsupported tonalButtonTheme for Flutter 3.32
Keeps Soft Neutral ThemeData compatible with the web Docker Flutter image.

Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-08-03 02:01:01 +00:00
Cursor Agent 31695cfb86
feat(ui): Soft Neutral + surface hierarchy across all screens
Replace Quiet Ink teal chrome with neutral-first messenger UI: ink CTAs,
thin blue-gray accent, unified radii, no decorative icon tiles or number
badges, flatter lists/chat panels in light and dark.

Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-08-03 01:59:28 +00:00
Cursor Agent 7ee8192d95
chore: drop unused AppTheme import on tone screen
Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-07-31 09:08:17 +00:00
Cursor Agent 0b4dffd405
fix(ui): soften Quiet Ink dark chrome on tone onboarding
Use teal containers for sample indices instead of amber secondary,
and mute dark-mode teal so it reads calmer on charcoal.

Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-07-31 09:08:07 +00:00
Cursor Agent ca4aeb059d
feat(ui): Quiet Ink redesign — teal accent, light/dark
Replace aurora-glass purple with a calm messenger system: off-white/
charcoal canvas, Plus Jakarta Sans, solid teal CTAs, and quieter
panels across signup, chats, contacts, inbox, and settings.

Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-07-31 09:01:57 +00:00
Claude f470dd473c
docs: log the aurora-glass UI redesign in deploy-checklist.md
Keeps deploy-checklist.md's DONE list in sync with the actual UI redesign
work per AGENTS.md's "Phase 1 앱 빌드 작업 규칙". Also flags that this
pushed to GitHub main but has not been redeployed to the live
msn.iykyka.com production host, since this session has no access to that
host (deploy runs via scripts/server-up.sh on the iykyka box itself).
2026-07-31 09:01:12 +00:00
Claude bb3106434b
Merge remote-tracking branch 'origin/main'
# Conflicts:
#	mobile/lib/screens/conversation_list_screen.dart
#	mobile/pubspec.lock
2026-07-31 08:23:28 +00:00
Claude 79bce5e671
Redesign UI to a bolder aurora-glass system after visual QA with a real Flutter build
Actually installed the Flutter SDK, built the app (web + a local screenshot
harness through a real backend), and looked at the rendered screens instead
of judging the design from source alone. The previous gradient/glassmorphism
pass read as flat and generic: glass cards barely contrasted against the
pale background, the brand mark was a stock sparkle icon, and buttons were
flat solid fills.

Changes:
- Stronger, more saturated aurora gradient + blurred glow orbs in
  GradientBackdrop for real depth instead of a flat 3-stop pastel.
- Glass cards/inputs get higher-contrast fill/border and a brand-tinted
  shadow so they visibly lift off the backdrop.
- New BrandMark (gradient monogram), GradientText (gradient-filled
  wordmark), and PrimaryGradientButton (gradient CTA with shadow) replace
  the generic Material icon/flat button on splash, signup, onboarding and
  the conversation list empty state.
- Fixed a real pre-existing layout bug found via screenshot: the onboarding
  header badge was a direct ListView child with an explicit width, which
  Flutter's sliver list silently stretches to full width regardless of the
  Container's own width — invisible before because its old flat pale fill
  blended into the background. Wrapped it in Align to restore its intended
  size.

Verified with flutter analyze (0 errors) and flutter test (all passing),
plus manual screenshots of signup, onboarding, conversation list and a live
chat exchanged between two demo users through a real core-backend instance.
2026-07-31 08:16:44 +00:00
Cursor Agent ef73b93d83
feat(fcm): send pushes via HTTP v1 service account
Prefer FCM_SERVICE_ACCOUNT_FILE/JSON over legacy FCM_SERVER_KEY,
mount secrets/ into core-backend, and document Master JSON placement.

Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-07-31 07:33:23 +00:00
Cursor Agent 82a5809d4e
feat(n4): wire FCM token path and document Master secrets
Add PushTokenService with Firebase Messaging fallback to install
placeholders, conditional google-services Gradle plugin, fcm-setup.md,
and mark Android UI checklist api-done via prod e2e 16/16.

Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-07-31 04:51:57 +00:00
Cursor Agent fea1b555b4
docs: mark Track B production deploy done
N4-B4 verified: /demo returns pairing_steps on msn.iykyka.com.

Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-07-31 04:46:07 +00:00
Cursor Agent c7029ab2cd
feat: finish Track A polish and Track B demo pairing content
Add PATCH contact for missing peer IDs, contacts banner and edit UI,
enrich /demo with pairing steps, and update tester/signup guidance.

Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-07-31 04:43:25 +00:00
Cursor Agent fdd02d8252
docs: mark Track A production web rebuild done
N4-A5 verified on msn.iykyka.com after deploying 3d00b00.

Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-07-31 04:38:39 +00:00
Cursor Agent 3d00b00de7
feat(mobile): Track A messenger UX — ID chip, contacts chat, L0 draft
Show/copy numeric user ID, require peer ID for contacts, start chat in one tap,
clarify empty states, and route L0 twin drafts into the human composer.

Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-07-31 04:36:41 +00:00
Cursor Agent d614d9e5c4
docs: record Gemini key live on msn.iykyka.com (draft status=ok)
Server ai-service recreated with GEMINI_API_KEY; live draft smoke passed.

Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-07-31 04:19:44 +00:00
Cursor Agent 9065479e87
docs(ops): complete N3 stabilize — backup, tester guide, smoke results
Record invite/metrics/dashboard/draft(no_key) checks, pg_dump restore
rehearsal, and tester-facing guide for msn.iykyka.com.

Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-07-31 04:06:09 +00:00
Cursor Agent 597c9f07cc
docs: note msn.iykyka.com live after Ykavu cutover
Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-07-31 03:08:48 +00:00
Cursor Agent d60da60981
feat(deploy): cut over msn.iykyka.com to Ykavu compose stack
Attach web to nginx-proxy_default; record live cutover (NPM host #7,
old MSN stopped) and mark N2-B8–B12 done.

Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-07-31 03:08:34 +00:00
Cursor Agent 0a33ff3bcc
docs: mark N2-B8–B12 blocked pending SSH/Portainer access
Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-07-31 02:31:49 +00:00
Cursor Agent b38839666c
docs(deploy): Portainer cutover guide and server-up script (N2-B8–12)
msn.iykyka.com still serves legacy Express; agent lacks SSH/Portainer
credentials so cutover is documented and marked blocked pending access.

Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-07-31 02:31:32 +00:00
Cursor Agent 0f42ef806a
chore: ignore Flutter mobile/build output
Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-07-31 02:26:49 +00:00
Cursor Agent 4a39bc7b7d
feat(deploy): Docker Compose stack for msn.iykyka.com (N2-B)
Add Postgres + internal AI + core-backend + Flutter web (nginx API/WS
proxy). Document Portainer usage and env template; mark N2-B1–B7 done.

Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-07-31 02:26:40 +00:00
Cursor Agent c7e70ac18b
docs: mark N1 smoke done (E2E 16/16, DEMO-YKAVU)
Record local smoke results after restarting core-backend on current main.
Document msn.iykyka.com CORS/API change list for N1-6; next is N2-B Docker.

Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-07-31 02:13:51 +00:00
Cursor Agent e7a1233f84
docs: confirm N2-A1/A3–A6 deploy decisions
Master: replace old MSN, AI internal-only, Web-first client, secrets in
Portainer/env only, ALLOW_DEMO_INVITE on for testers. N2-A complete.

Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-07-31 02:08:03 +00:00
Cursor Agent 3a8b5b1a76
docs: confirm N2-A2 production DB as PostgreSQL
Master decision: msn.iykyka.com deploy uses Postgres (tech-design §8).
SQLite remains local/test only; update compose/volume/backup checklist items.

Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-07-31 02:04:53 +00:00
Cursor Agent 2eed4e492c
docs: add deploy/residual checklist (N1–N5) after Phase 1 A–C
Consolidate Claude + Cursor DONE state and the next execution track
(smoke → Docker msn.iykyka.com → stabilize → FCM/Android QA → human PoC).
Sync stale PLANNING Q1–Q7/stack status and point AGENTS/README/CLAUDE/roadmap
at docs/deploy-checklist.md.

Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-07-31 01:54:55 +00:00
Claude ce2e38e566
chore: refresh mobile/pubspec.lock after flutter pub get
Transitive dependency version bumps picked up while verifying the merge
actually builds with a real Flutter SDK (analyze/test/build web all pass).
2026-07-31 01:41:45 +00:00
Claude 6743bf0054
Merge origin/main: keep gradient/glassmorphism UI, port demo-invite + boot hardening, purge 분신 branding
- Resolve visual-direction conflicts (app_theme, main.dart, signup/onboarding
  screens, index.html) in favor of the soft-gradient + glassmorphism design;
  drop the competing Twin Shadow palette and TwinTokens usage.
- Port non-visual additions from the parallel branch: CORS middleware,
  FlutterError/PlatformDispatcher crash handlers + boot timeout/fallback
  screen in main.dart, and the shared demo-invite feature
  (core-backend/demo.go, demo_test.go, mobile/lib/config.dart), reskinning
  the demo panel to match the glass UI.
- Rename the shared demo invite code DEMO-BUNSIN -> DEMO-YKAVU on both
  client and server so the tester-facing feature keeps working.
- Purge remaining "분신"/"bunsin" identifiers app-wide: Dart package name
  (bunsin_mobile -> ykavu_mobile), Android applicationId/namespace
  (com.bunsin.bunsin_mobile -> com.ykavu.ykavu_mobile, incl. Kotlin source
  dir move), on-device DB filename, keystore alias/docs, PoC draft-generator
  system prompt, and the static web boot placeholder div.
2026-07-31 01:30:50 +00:00
Claude ebf333d287
제품명 변경(분신→와카뷰) + 소프트 그라디언트/글래스모피즘 UI + 브랜드 로딩 화면
명칭 변경:
- decision-log.md Q6 확정: "분신"(가칭) → "와카뷰 (Ykavu)" — 焚身(분신자살)
  동음이의 리스크도 있었고 메신저 브랜드로 부르기 무거웠음. Master가 최종
  선택한 이름으로 변경(2026-07-31), 파생 문서(AGENTS.md/CLAUDE.md/PRD 등)·
  Flutter 앱 텍스트·web manifest/index.html·AndroidManifest 라벨까지 전부 반영
- ai-service: 본인확인 고정 문구(identity.py)·시스템 프롬프트(generation.py)도
  갱신 — 새 이름 기준으로 "본인이야 와카뷰야?" 류 질문을 감지하도록 정규식도
  같이 손봄(단순 문자열 치환만으론 어미 형태가 안 맞아서 테스트 추가/조정)
- poc/tone-corpus/의 실험용 프롬프트는 의도적으로 그대로 둠(ai-service README에
  이미 명시된 대로 프로덕션과 분리된 실험 도구)

UI/UX:
- mobile/lib/theme/app_theme.dart: 시드 컬러를 인디고/라벤더로 변경, 화면 전체에
  깔리는 소프트 그라디언트(라이트: 라벤더→스카이→핑크 파스텔, 다크: 딥 인디고→
  네이비→플럼) + 카드/인풋/칩을 반투명 "글래스" 서피스로 전환
- mobile/lib/widgets/gradient_backdrop.dart(신규): MaterialApp.builder에 연결해
  모든 화면에 자동으로 그라디언트 배경 적용
- mobile/lib/screens/splash_screen.dart(신규) + main.dart 재구성: 기존엔
  session.restore()를 기다리는 동안 아무 것도 안 그려서 흰 화면/텍스트만 뜨는
  구간이 있었음 — runApp을 먼저 하고 restore 동안 브랜드 스플래시가 뜨도록 변경
- chat_screen·autonomy_settings_screen·data_flow_screen의 커스텀 패널들도
  글래스 스타일로 맞춤

BunsinApp -> YkavuApp (mobile/lib/main.dart, test/widget_test.dart 동기화)

Flutter SDK가 없는 환경이라 flutter analyze/run으로 직접 컴파일 검증은 못했음 —
중괄호/괄호 균형과 기존에 검증된 API 패턴 위주로 신중하게 작성함. go test·
pytest는 전부 통과.
2026-07-31 01:15:42 +00:00
Cursor Agent c4ecb5862b
chore: add push-both script for GitHub + Gitea remotes
Keeps o0kuma/hikikomori and gitea oh/iykyka in sync from this workspace.

Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-07-30 08:47:40 +00:00
Cursor Agent 17b10a0e8c
feat: show shared DEMO-BUNSIN invite on signup for testers
Seed a reusable demo invite (ALLOW_DEMO_INVITE, default on) and surface it
on the Flutter signup screen with one-tap fill so others can try without
asking for a one-off admin mint.

Co-authored-by: okuma <o0kuma@users.noreply.github.com>
2026-07-30 08:21:22 +00:00