6 Commits

Author SHA1 Message Date
songyc macbook
b751247ba7 feat(keging): 아이폰 시작 세트의 워치 심박 측정 — startWatchApp + 미러링 세션, 배지·사전 경고 폐지 (9차)
- 의도(사용자 TestFlight 피드백): 폰으로 운동해도 워치를 차고 있으면 워치가 심박을 재고,
  진동은 시작한 기기에서만. 종전 '워치 연동됨' 배지는 워치 앱 포그라운드 여부(isReachable)만
  보여 주던 것이라 폐지
- iOS: WatchHeartRateBridge — 시작 시 HKHealthStore.startWatchApp(폰 설정 운동 유형)으로 워치 앱을
  깨우고, 워치가 미러링한 HKWorkoutSession을 workoutSessionMirroringStartHandler로 받아 심박 수신,
  완주/중단 명령 전송(finish/discard). 워치를 못 열거나 30초 안에 미러링이 안 붙으면 폰 단독
  (+설정에 따라 '워치 앱을 열지 못했어요' 알럿, app.watchWarn 재사용) 및 WatchConnectivity로
  워치 세션 폐기 명령. 워치 저장 결과(saved/failed)는 WC로 회신받고 15초 내 미회신이면 폰 사후 저장 폴백.
  워치 깨우기는 폰 건강 권한 응답 뒤에(첫 실행 경합 방지). 건강 읽기 권한(심박·활성 에너지) 추가
  — 워치 세션 센서 수집용(권한 공유)
- 워치: WatchAppDelegate.handle(workoutConfiguration) → MirroredWorkoutSession(라이브 빌더, 무진동·무타이머,
  심박을 미러링 채널로 전송, finish 시 저장+강도 relate 후 WC로 결과 통보, discard/끊김 시 폐기,
  미러링 30초 타임아웃, 앱 재기동 시 잔류 세션 복구·폐기). 화면 '아이폰에서 진행 중 ♥bpm'(중단 버튼).
  WatchHealthAuth로 권한 공용화
- UI: 첫 화면 배지·확인 창 제거, 운동 화면 횟수 아래 워치 상태 줄(연결 중/♥bpm/아이폰만),
  설정 토글 '워치 연결 실패 경고', 도움말 3건 갱신. l10n 카탈로그 3종 missing/stale 0
- DEBUG: -testConfig(35초 세트), -mockWatchHeartRate <bpm>(상태 줄 QA·스크린샷). watchHR 카테고리 notice 로그
- 시뮬 검증(페어링 심): startWatchApp → 워치 기동·권한·세션·가짜 심박·'아이폰에서 진행 중'까지 동작,
  워치 startMirroring 성공 반환 — 그러나 폰 미러링 핸들러는 시뮬에서 불리지 않음(애플 샘플도 실기기 전용)
  → 30초 타임아웃·알럿·WC 폐기·폰 폴백 저장 경로 확인, 워치 자체 세트 정상. 3타깃 빌드 그린·경고 0.
  미러링 수신·완주 저장·회신은 실기기 TestFlight 재테스트 필요
- 문서·마케팅: CLAUDE.md §3.8 신설·§1/§3.7/§4/§6/§7 갱신, 설명 3언어·whats-new·review-notes·PRIVACY.md
  (아이폰 읽기 권한 설명 — GitHub 게시본 갱신 필요), 스크린샷 01·08(배지 제거)·02·03(♥78 상태 줄) 재촬영·합성

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UPmp29DQHY6Ahfss5SRopT
2026-09-05 10:13:48 +09:00
songyc macbook
8f634c83f4 fix(keging): 실기기 3차 피드백 6건 — DI 멈춤 근본 원인(햅틱 엔진 세션 충돌) 제거·워치 세팅 pull 동기화·완료 진동·하루 타임라인·칼로리 정합
- CHHapticEngine을 공유 AVAudioSession에 부착(기본 생성 시 독자 오디오 정책이
  백그라운드 무음 루프를 끊던 것이 DI 멈춤 원인) + 오디오 키퍼 하드닝(루트 변경·
  미디어 서버 리셋·ensureAlive) + 운동 중 2초 하트비트(오디오·엔진·LA 자가 치유)
- Live Activity: 실제 phaseStart 사용·동일 상태 no-op·staleDate 8초·isStale 흐림
- 워치 세팅 동기화 3중화: 변경 push + reachability 재푸시 + 워치 앱 열릴 때 sendMessage pull
- 완주 진동 신설: 폰 2.4초 연속(백그라운드 6방 체인, 오디오 정지 4초 지연), 워치 retry×2+success
- 통계 하루 탭 맨 위 '오늘의 타임라인'(24시간 축 점 그래프, 시각 라벨·지금 룰)
- 폰 칼로리 공식을 애플워치 '기타' 운동 규칙(빠르게 걷기 상당)에 정합: MET 4.0+강도×0.15
- 도움말 4건 갱신·en/ja 번역·CFBundleName 보충, CLAUDE.md 현행화

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UPmp29DQHY6Ahfss5SRopT
2026-09-02 14:30:08 +09:00
songyc macbook
f5f8d3bde4 fix(keging): 실기기 1차 피드백 3건 — DI 백그라운드 멈춤·진동 패턴 동일·칼로리 0
① 다이나믹 아일랜드 멈춤(2중 방어):
- 오디오 키퍼 하드닝 — volume 0.1(0.0은 유지 풀림 사례)·prepareToPlay·인터럽션/씬 전환 revive()
- 엔진을 벽시계 기준으로 재설계 — 전 국면이 sessionStart로부터 결정적(computeTarget),
  타이머는 경계 재장전용, scenePhase .active에서 resyncAfterWake()로 정확한 국면 자가 교정

② 진동 패턴 동일(톡=톡톡): 시스템 바이브는 재생 중 재호출이 무시됨(실측) —
  시간 오프셋 방식 폐기, AudioServicesPlaySystemSoundWithCompletion 완료 체이닝으로 재작성
  (톡 1방 / 톡톡 0.25s 쉬고 1방 / 드르륵 0.15s 3연타 / 지잉 즉시 이어붙인 3방)

③ 운동 칼로리 0: 빌더 운동은 에너지 샘플 직접 추가 필요 —
  iOS는 MET 추정(1.8+강도×0.17, 70kg 가정) activeEnergyBurned 샘플 add,
  워치는 심박·활성 에너지 읽기 권한 추가로 센서 실측 수집, 권한 문구 3언어 갱신

검증: Debug·Release·워치 빌드 그린, 완주 경로 시뮬 재검증(엔진 재설계 후).
DI 갱신·진동 구분·칼로리는 실기기 재확인 필요(재실행 시 '활성 에너지' 권한 시트 뜸)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UPmp29DQHY6Ahfss5SRopT
2026-08-29 22:42:00 +09:00
songyc macbook
9c9df03571 polish(keging): 메인·운동 화면 그래픽 강화 + 도움말 취소선(마크다운 ~) 수정
- 메인: 텍스트 한 줄 요약 → 수축·이완·횟수 카드 3장(아이콘+큰 숫자, 탭=세팅)
- 운동 화면: 국면 색 전환(수축=그린·이완=앰버, 카운터 색 연동) + 세트 진행 링 +
  큰 현재 횟수 카운터(numericText 전환)
- 도움말 취소선 원인 = SwiftUI Text 마크다운의 ~쌍 해석 — 사용자 문구의 ASCII ~를
  전각 ~로 전면 교체(4곳), CLAUDE.md에 금지 규칙 기록
- 신규 QA 인자 -noHealth(권한 시트가 캡처 가리는 것 방지)
- 검증: Debug·Release 빌드 그린, 화면 QA(메인 카드·수축/이완 국면·도움말), 카탈로그 0/0

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UPmp29DQHY6Ahfss5SRopT
2026-08-29 20:49:30 +09:00
songyc macbook
f91968f8ce feat(keging): 애플 건강 운동 유형 선택 — 기타 ↔ 코어 트레이닝 (설정)
- HealthWorkoutType(WorkoutConfig 필드, 워치 자동 동기화) — 폰·워치 저장 모두 반영
- 설정 → 애플 건강에 '운동 유형' 피커, 푸터·도움말 문구 유형 중립으로 갱신
- 신규 문자열 번역(en/ja), 옛 문구 stale 2건 정리 — 전 카탈로그 missing·stale 0
- 하루 다님 연계 조사 결과 CLAUDE.md 기록(종목 다짐·타임테이블=자동 집계,
  운동 시간 지표=워치 실행분만 운동 링 경유 반영)
- 검증: Debug·Release·워치 빌드 그린, 설정 화면 QA

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UPmp29DQHY6Ahfss5SRopT
2026-08-29 20:13:37 +09:00
songyc macbook
893545e7be feat(keging): 애플 건강 연동 — 완주 세트 운동 기록 + 운동 강도(1~10) 자동 저장
- 완주한 세트만 애플 건강에 '기타' 운동으로 자동 기록 (중단=미기록 규칙 일관)
- 폰=사후 HKWorkoutBuilder, 워치=라이브 HKWorkoutSession(심박 포함·손목 내림 유지 겸용,
  실패 시 확장 런타임 세션 폴백)
- 운동 강도: 설정 → 애플 건강 → 자동 기록(기본 2·쉬움, 안 함 가능) — relateWorkoutEffortSample,
  워치 11+/iOS 18, 워치 10은 운동만 기록
- 쓰기 전용 권한(첫 시작 때 요청·거부 시 조용히 스킵), 건강 문구 3언어, 새 UI 문자열 11키 번역
- WorkoutConfig 전 필드 decodeIfPresent 디코더 (필드 추가에도 기존 설정 보존)
- 검증: Debug·Release·워치 빌드 그린, 권한 시트·설정 ko/ja 화면 QA, 카탈로그 missing·stale 0
  (건강 실제 저장은 권한 시트 조작 불가로 실기기 확인 필요)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UPmp29DQHY6Ahfss5SRopT
2026-08-29 19:51:49 +09:00