- 주간/월간 '이상 달성' 다짐이 현재 주기 몫을 채우면 하루 게이지가 0% 대신
완료 상태(게이지 가득+초록 ✓+문구)로 표시 — 목표 탭 행·모음 카드·위젯 ②(체크)·
③(문구)·④(링 가득)·시리 하루 응답 공유
- 목표 하루 평균(combinedSpanRatio)에도 해당 다짐을 1.0으로 반영 —
위젯 ② 목표 바·워치 목표 게이지·시리 목표 응답·일기 헤더 자동 반영
- 판정은 QuestProgress.isPeriodFulfilled 단일 지점 — 기준일의 논리적 하루 끝
클리핑으로 일기 과거 날짜 소급 차단. spanProgress 수치·판정(judgment)·연속(streak)
불변(표시 계층 전용). 하루 다짐·특정 기간·atMost는 비대상, 잠금화면·워치
컴플리케이션은 공간 제약으로 수치 유지
- 도움말 '진행률 읽는 법' 문구 갱신, l10n en/ja 완료(전 카탈로그 stale 0·missing 0)
- 검증: -progressSelfTest 37→49건 ALL PASS(기존 37건 수치 무변경), 신규
-seedPeriodFulfilled 시드로 ko/en/ja·위젯 실렌더 확인, 시리 스모크 10건 OK,
Debug/Store 빌드 성공(워치 타깃은 Shared 미포함·무변경)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FVeduv1eNdXjk1ay4tSgBg
진행률 검증 보고에서 확정한 결정 반영 (사용자 위임):
- [계산 수정] 하루 단위 다짐의 주/월 집계를 **방향 무관 수행일 기록만** 합산 — 목표량(scaledTarget)이 수행일 수 환산인데 '이하 유지'만 비수행일 기록까지 값에 섞여 분모·분자가 어긋나던 비대칭 해소 (월수금 1시간 이하 다짐이 목요일 시청으로 한도 초과 표시되던 문제). atLeast의 하루 기여 캡·마감 창 클립은 기존 유지
- [표시 수정] 수행일 아닌 날(요일·날짜 다짐의 쉬는 날, 기간 밖 custom)의 '하루' 게이지를 '수행일 아님' 상태로 — 쉬는 날 기록은 주/월 집계에 안 잡히는 값이라 퍼센트(예 133%)로 보여주면 "오늘 채웠다"는 오해 유발. 목표 탭 행·모음 카드(문구+빈 바), 위젯 ③(문구·누적값 숨김)·②(— 대시)·④(링 흐림, 스냅숏 isRestDay), 시리 '오늘' 조회("오늘은 수행일이 아니에요") 공유. 워치·잠금화면 점은 공간 제약으로 수치 유지(문서화)
- [의도 확정·유지] atMost 하루 게이지의 환산 한도 페이스 경고 / 다짐 생성 이전 기록 인정 / 월 경계 주 혼입 / 적용일 없는 달 0% / custom 종료 후 게이지 — CLAUDE.md §4.2에 트레이드오프로 명시
- 검증: -progressSelfTest 37건 ALL PASS(E 비수행일 제외·M 비대칭 수정·N 기간 밖 판정 신규), 목표 탭 스크린샷(달리기 월수금: 하루 '수행일 아님'/주간 0%/월간 7%), 위젯 미리보기 렌더 무결, Debug·Store·워치 3스킴 빌드 성공
- 도움말 '진행률 읽는 법' 전면 보강(수행일 집계·페이스 캡·이하 유지 이분법+하루 경고) en/ja 완비, 신규 키 2종('수행일 아님', 시리 응답) IOS·위젯 카탈로그 클린(763/213키)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
- 보고된 버그: 주 2회 다짐을 목요일에 1회 수행 → 목표 탭 하루 진행률 350% (1 ÷ 주목표 2/7). 주기와 다른 span의 환산 목표는 페이스 가이드일 뿐인데 초과분까지 퍼센트로 표기되던 왜곡
- 수정: spanProgress에서 '이상 달성'이면서 환산 목표 span일 때 값을 목표에서 캡 (usesScaledTarget 분기) — 자기 주기 span(하루 다짐의 '하루' 200% 등)과 특정 기간 다짐(환산 없음)은 초과 표기 유지, '이하 유지'는 값 무캡(UI 초과 판정·페이스 경고 유지). 게이지(ratio)·달성 판정·연속·목표 종료 판정은 원래 캡·별도 경로라 무영향 — 바뀌는 것은 퍼센트 문구뿐
- 검증 도구 신설: -progressSelfTest (DEBUG) — 인메모리 컨테이너에 12시나리오·33검증(보고 케이스, 주간/월간/요일 스케줄/마감/atMost/특정 기간/잔존 deadline/무기록 + 목표 합산 회귀) 구성해 손계산 기대값과 대조, ALL PASS. 설정·날짜 고정이라 언제 실행해도 동일 판정
- 화면 확인: 목표 탭 '꾸준한 달리기'(주 2시간) 하루 233%→100%, 주간 67%·월간 30% 유지, 매일 다짐 117%/133%(자기 주기)·atMost·마감 다짐 표기 불변
- 도움말 '진행률 읽는 법'에 페이스 기준 설명 추가(en/ja 완비), CLAUDE.md §4.2 규칙·§14 인자 기재
- §2.3 l10n 루틴 강화: stringsdata를 Objects-normal/arm64로 한정 — x86_64·Release 등 낡은 구성 파일이 수정 전 문구를 계속 추출시키는 오염 발견·수정
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
하루 단위 다짐에 '마감 시각까지만 집계' 옵션 추가 (최소판 설계):
- 모델: Quest.deadlineMinutes(-1=없음) 필드 1개 — CloudKit 안전(기본값), 주기가
하루 단위가 아니면 값이 남아도 무시(hasDeadline이 주기·범위를 함께 검사)
- 의미론: 마감 = 그날 집계 창의 끝. dayMeasurementRange(forKey:) 단일 구현을
주기 범위(current/judgment)·주/월 span 하루 루프(spanValue)·연속 버킷팅
(perDayValues)·위젯 누적 라벨(spanRawValue)·일기 카드가 공유한다.
원본 기록은 불변 — 마감 뒤 기록은 남되 그 다짐에만 미집계. 시간형은 기존
겹침 클리핑이 마감을 걸친 세션을 부분 인정(추가 코드 0). '이하 유지'는
마감까지 한도 안이면 그날 달성으로 고정.
- 경계 규칙: 마감은 그 논리적 하루(24h) 안에서 그 시계 시각의 등장 지점 —
하루 시작보다 이른 시각은 다음 달력일 새벽, 시작과 같은 시각은 +24h(온전한
하루)로 0길이 창이 수학적으로 불가능(에디터 검증 불필요, 오류 상태 없음)
- 의도된 최소화: '마감 지남' 전용 표시 없음(게이지 값이 마감 시점에 연속이라
위젯 타임라인 마감 경계 불필요 — 위젯·워치·시리는 코드 변경 0으로 자동 일관),
연속 달성은 값 클리핑만(오늘 놓친 끊김 반영은 내일부터 — 유예 규칙 유지),
주간/월간/기간 마감은 미지원
- UI: 다짐 에디터 토글+시간 선택(하루 단위만, footer 설명), 주기 문구에
"· 오전 8:00까지" 표기(목표 탭·시리 요약·CSV 자동 반영), 일기 카드
"하루 목표 · 오전 8:00까지", 도움말 항목 추가, ko/en/ja 번역
- 검증: seedDemo에 마감 다짐 시드(창 안/밖/어제 실패 케이스) — 하루 100%
(창 밖 기록 포함 시 200%가 되는 함정 통과), 주간 29%(=2/7)·월간 6%(=2/31)
수기 계산과 정확 일치, streak-dump 연속 1일(어제 실패로 끊김) 확인,
마감 없는 다짐 전부 기존 수치 유지(경로가 hasDeadline 가드로 완전 동일),
일기 카드 1회/1회(원본 합계는 그대로), 영어 로케일 "By 8:00 AM" 렌더,
Debug·Store 빌드 성공, 카탈로그 9종 missing/stale 0
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
재분석에서 나온 잔여 항목 일괄 처리:
1) 판정 하루 키 엣지 (A)
judgmentReference가 종료일 '정오'를 경유해 논리적 하루를 찾던
것을 달력일 키 직접 조회로 변경 — '하루 시작 시간'을 12시 이후로
설정한 경우에도 판정 범위가 전날로 밀리지 않는다.
2) 주기 중간 종료 판정 (B — 설계 결정: 경과일 비례)
종료 판정 전용 QuestProgress.judgment(asOf:) 신설, 판정 평균
(questAchievementRatio)이 current() 대신 사용:
- 값은 기준 시점까지의 누적으로 제한 — 종료일 이후 같은 주기의
기록이 판정에 섞이지 않음
- 주간/월간/특정 기간 다짐의 목표량·한도를 주기 내 경과일 비율로
축소 — 수요일에 끝나는 목표의 주간 다짐이 남은 4일치 미달로
깎이지 않고, '이하 유지' 한도도 같은 비율이라 대칭적으로 공정
- 하루 단위 다짐은 축소 없음 (그날 목표는 온전히 채워야 달성)
- 수동 종료(manualFinish)도 같은 함수를 타므로 주중 수동 종료의
주간 다짐이 공정하게 판정됨. 표시 연산(combinedSpanRatio·
spanProgress)은 불변.
검증: 주간 2시간 다짐 목표를 주 시작일(월)에 종료 →
화요일 기록 40분이 배제되고 비례 목표(≈17분) 기준으로 판정됨을
DB에서 확인 (처음 실패는 '설치 직후 첫 실행 인자 무시' 시뮬레이터
특성이 원인 — 코드 문제 아님, §2.2 문서화된 사항).
3) 양식 렌더 트레이드오프 (C)
- 백그라운드 렌더 실패 시 renderedScale을 되돌려 다음 기회(줌·
재표시)에 재시도되게 함
- 썸네일 겸 첫 표시 플레이스홀더 해상도 320→512px — 본 렌더
도착 전의 흐릿함 완화 (저장 증가는 수십 KB 수준)
- 양식 관리의 사용 중 페이지 수를 행마다 재스캔하지 않고 1회 집계
빌드: Debug·Store·워치 3스킴 성공. CLAUDE.md §4.3에 주기 중간
종료 판정 규칙 추가. 신규 사용자 문구 없음(카탈로그 변경 없음).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
전체 재분석에서 확정한 4건 + 양식 개선 2건:
1) 목표 자동 판정 기준 시점 (핵심 수정)
기존에는 판정이 "실행되는 시점의 현재 주기" 기준이라, 종료일
며칠 뒤에 앱을 열면 목표 기간 밖의 데이터로 달성/미달성이
갈렸다. 이제 자동 판정(evaluateIfEnded)은 **종료일이 속한
논리적 하루의 마지막 순간**(judgmentReference) 기준 — 늦게
실행해도, 종료일을 과거로 고쳐도 종료일까지의 기록으로 판정.
(하루 시작 시간 설정으로 기준이 미래가 되는 경우 now로 상한)
수동 종료는 종료일 없는 목표 전용이므로 기존대로 "지금" 기준.
목표 편집 시 종료일 변경 처리: 진행 중 목표는 저장 즉시 판정,
완료된 목표의 종료일을 바꾸면 '진행 중'으로 재개 후 재판정
(미래/없음 → 진행 중 복귀, 다른 과거 날짜 → 그 시점 기준 재판정).
검증: -endGoalYesterday로 어제 종료 → 종료일 기준 '달성' 판정 확인.
2) 워치 컴플리케이션 지역화 2건
- 다짐 달성률 rectangular의 기간 라벨("하루/주간/월간")이 String
파라미터라 미추출 → en/ja에서 한국어 노출 → String(localized:)
- 빈 상태 문구("목표 없음"/"다짐 없음") 동일 문제 → 추출 + 워치
앱/워치 위젯 카탈로그에 en/ja 번역 추가 (타깃별 stringsdata로
sync — 카탈로그 오염 없음, 전 카탈로그 missing 0)
3) 배포 체크리스트: CloudKit 프로덕션 스키마 배포 항목을 CLAUDE.md
§1에 추가 (DiaryTemplate 등 새 레코드 타입은 출시 전 대시보드
Deploy Schema to Production 필수)
4) 일기 양식 렌더 개선
- 첫 렌더 비동기화: 저장된 썸네일을 플레이스홀더로 즉시 깔고
본 렌더(2×)를 백그라운드로 — 복잡한 벡터 PDF도 페이지 넘김이
걸리지 않음
- 비활성 페이지 고해상도 강등: 화면 밖 페이지는 래스터를 2×로
상한(allowsHighResolution) — TabView가 이웃 페이지를 유지해도
양식 여러 장의 메모리 사용을 절약, 활성 복귀 시 원래 배율 복원
검증: 양식 페이지 2× 프로그램 줌에서 점 노트 선명(회귀 없음),
시드 필기 페이지 획 유지 확인.
빌드: Debug·Store·워치 스킴 모두 성공. 도움말(목표 판정 문구
갱신 — 종료일 기준·재판정 규칙 안내)과 CLAUDE.md §4.3 갱신,
문구 수정 stale 1건 삭제 및 ko/en/ja 번역 완료.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
③ 다짐 진행률 위젯에서 '이하 유지' 다짐은 시작부터 링이 가득 차 있고
문구도 '오늘 한도 지킴'뿐이라 지금 몇 회/몇 시간 했는지 알 수 없던 문제.
퍼센트(또는 한도 지킴/초과) 문구와 연속 달성 문구 사이에 위젯 옵션의
진행률 기간 기준 실제 누적값 한 줄을 추가한다 ("1시간 20분" / "3회").
'이상 달성' 다짐에도 동일하게 표시. 주간·월간 진행률 캡과 무관한
원본 누적값이며, 다른 위젯(②④)과 나머지 레이아웃은 그대로.
- QuestCellSnapshot.valueLabel 추가 (spanRange 원본 값 포맷)
- QuestProgress.spanRange(_:now:) 헬퍼 추출
- 위젯 미리보기에 '이하 유지(소형)' 행 신설 (앵커 CM)
- l10n: '0분' ko/en/ja (IOS·Widgets 카탈로그)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
'이하 유지' 다짐은 기록 없는 날도 달성으로 집계되므로 연속 계산이
목표가 생기기 전 과거(스캔 상한 400일)까지 거슬러 올라가 '연속 401일'로
표시되던 버그 수정. 연속은 행동이 아니라 '목표 안 다짐'의 달성이므로
하한 = 목표 시작일:
- 하루 단위: 시작일이 속한 논리적 하루부터만 센다
- 주간/월간: 시작일이 걸친 부분 주기까지 포함, 그 이전 주기에서 중단
검증: 시드에 재현 목표(스크린 타임 관리, 3일 전 시작 + 초과 없는 이하
유지 다짐) 추가 → 기대값 연속 4일 확인. -streakDump 런치 인자 신설
(전 다짐의 연속 계산 결과를 Documents/streak-dump.txt로 덤프).
부수: 도움말에 '연속 달성 표시' 항목 추가(ko/en/ja). 지난 기능들의
문자열이 위젯·워치·InfoPlist 카탈로그에 미번역으로 남아 있던 것을
채움(제어 센터·연속 표기·즐겨찾기·캘린더 권한 문구) — l10n 루틴이
IOS 카탈로그만 확인하던 함정을 CLAUDE.md §2.3에 명시.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
다짐 단위 '연속 달성' 표기 추가 (QuestProgress.streak → QuestStreakInfo):
- 하루 단위 다짐: 적용일만 세는 연속 계산 — 매일이면 연속 일수,
'매주 수요일'이면 수요일들만 이어서 센다 (4주 연속 = 연속 4일)
- 주간/월간 다짐: 주기 전체 달성 여부로 연속 N주/N달
- 특정 기간 다짐: 반복이 없어 표시하지 않음
- 진행 중인 오늘/이번 주기는 '이상 달성'이면 미달이어도 끊기지 않고
건너뛰며, 채웠으면 포함. '이하 유지'는 한도를 넘는 순간 끊김
- 성능: 기록을 논리적 하루 키로 1회 버킷팅해 O(기록수+일수),
소급 상한 400일
표기(기존 디자인·데이터는 그대로 두고 추가만, 0이면 숨김):
- 목표 탭 다짐 행: 이름 옆 불꽃 + "연속 N일" 배지 (노랑)
- 위젯 ③ 다짐 진행률: 퍼센트 아래 한 줄
- 위젯 ④ 다짐 현황: 이름 아래 작은 글씨
- 위젯 ② 목표+다짐 구성: 퍼센트 아래 6.5pt — 연속 표기가 있을 때만
행 높이 14→19 (적응 채움이 자동 반영)
- 문구는 '스트릭' 대신 "연속 N일/주/달" (en은 streak, ja는 N日連続)
문구 정정: '몇째 주 요일' → '몇 번째 요일' — 구현(weekdayOrdinal)은
달력의 주차가 아니라 "그 달의 n번째 ◯요일"이므로 편집 화면 픽커와
주기 요약 문구를 실제 동작에 맞게 수정 (동작 변경 없음). en/ja 번역 포함.
검증: 시드 데이터로 목표 탭 배지 손계산 대조(독서 연속 3일 — 3일 전
기록 없음 / 영상 시청 어제 한도 초과로 연속 1일 등 전부 일치),
위젯 ②③④ 미리보기 스크린샷으로 레이아웃 넘침 없음 확인,
missing: [], Debug·Store 스킴 빌드 성공.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
목표 종료 판정이 '다짐 전체 달성'으로 고정되어 있던 것을, 목표를 만들 때
달성 판정 기준(%)을 정할 수 있게 확장. 다짐들의 평균 달성률(달성=100%,
미달성=현재 주기 진행률)이 기준 이상이면 달성 완료로 판정한다.
- Goal.achieveThresholdPercent (기본 100 = 기존 동작 유지, CloudKit 호환)
- evaluateIfEnded/manualFinish가 questAchievementRatio ≥ 기준으로 판정
- 목표 추가/수정 화면에 '달성 판정 기준' 슬라이더 (10~100%, 5% 단위)
- 수동 종료 안내 문구에 기준이 100% 미만이면 해당 기준 표기
- 검증용 런치 인자 -goalShowEditor 추가
- 그 외 진행률 표시·연산은 변경 없음
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
Weekly/monthly progress for a daily quest summed each day's raw value into
the numerator, so one over-achieving day leaked its overage into the span
total. Example: two daily quests with a 5-minute target; on one day quest A
did 5 min (100%) and quest B did 10 min (200%). Both are "done" for that day,
but the weekly ratio counted quest B as 600s vs quest A's 300s — B carried
double the weight, and its over-achievement masked other days' shortfalls and
could push per-quest weekly display past 100%.
spanProgress now aggregates a daily 'atLeast' quest's week/month value as the
sum of per-day values each capped at that day's target (min(dayValue, target)),
via a new private spanValue(for:range:now:). This equals averaging per-day
capped ratios, so a single 200% day contributes exactly one day's worth — no
day can cover for another, and per-quest weekly/monthly display never exceeds
100%. Scope is deliberately narrow:
- day span is untouched — a single day still shows 200% over-achievement.
- 'atMost' (stay-under) quests keep their existing per-day 100%/0% logic;
capping the value would make them always pass, so they use the raw value
unchanged — the two rules coexist without contradiction.
- weekly/monthly/custom quests accumulate freely within their period, so no
per-day cap applies to them.
Only the progress calculation changed; raw records are never altered, so the
records/stats screens still show the true 10-minute total.
Verified in the simulator with a temporary isolated in-memory self-test
(removed before commit): quest A (100%) and quest B (200%) produce identical
weekly ratios (0.1429 each), quest B's weekly display stays <= 100%, and its
day-span display remains 200%. Build succeeds.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
- 목표 하루 진행률은 오늘이 수행일인 다짐만 모수로 계산 (요일·날짜 지정으로
오늘 쉬는 다짐은 분모에서 제외, QuestProgress.isScheduled 신설)
- 오늘 수행할 다짐이 하나도 없는 날은 0% 대신 100%(완료 상태)로 표기
- 주간/월간 진행률은 기존대로 전체 다짐 기준 유지
- 이벤트 기반 위젯 새로 고침: 앱 내 모든 핵심 Mutation(측정 시작/종료,
횟수 추가, 기록 추가·수정·삭제, 행동·꼬리표·목표·다짐 CRUD, 순서 변경,
목표 상태 변경)의 끝단에서 DataChange.commit() 호출 — 저장 즉시 확정 후
Live Activity·위젯 타임라인·워치 스냅숏을 한 번에 동기화
- 주기적 백그라운드 새로 고침 없이 변경 시점에만 갱신해 WidgetKit
업데이트 예산 절약 (타이머 표시는 기존 Text(style: .timer)로 시스템이
자체 렌더링하므로 타임라인 소모 없음)
- 하루 시작 시간·주 시작 요일 설정 변경 시에도 위젯 집계 갱신
- 시뮬레이터 검증: 월·수·금 다짐이 있는 목표의 토요일 하루 진행률이
33%가 아닌 50%(오늘 수행 다짐 2개 평균)로 표시됨 확인
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
- 언어 설정 실적용: 변경 시 AppleLanguages 오버라이드 저장, 재시작 안내 footer
- 자동 추출되지 않던 일반 문자열(탭 이름, 픽커 라벨, 상태 뱃지, 포매터,
삼항 문구, 심볼 카테고리 등)을 String(localized:)로 전환
- 위젯·워치 앱·컴플리케이션 타깃에 Localizable.xcstrings 신설
(중복 리소스 방지 pbxproj 예외 추가), xcstringstool sync로 키 추출
- 4개 카탈로그 전체 키(고유 430개)에 en/ja 번역 주입
- 영어의 긴 횟수 단위("times")가 잘리지 않도록 모음 탭 셀 축소 허용
- 검증: -AppleLanguages "(en)"/"(ja)"로 모음 탭·설정 화면 확인
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
- DataStore: App Group 컨테이너의 HaruDanim.store 사용, 기존 default.store 1회 자동 이관
- 프리미엄 + 동기화 토글 시 CloudKit(.private) 구성으로 컨테이너 생성, 실패하면 로컬 폴백
- CloudKit 요건(모든 관계 optional)에 맞춰 to-many 관계를 optional 저장 + 기존 이름
접근자로 리팩터링 (originalName 매핑으로 기존 데이터 유지)
- Tag/Action/Goal/Quest에 uuid 추가 (시리 단축어·위젯·워치 식별자) + 중복 보정
- 모델 레이어(Models/Settings/DayMath/QuestProgress/Formatters/Theme)를 Shared/로 이동
— 위젯 확장과 공유
- 집계 설정(주 시작 요일·하루 시작 시간·대표 시간·짧은 기록 무시)을 App Group defaults로
이관해 위젯·워치와 공유, 설정의 '기기 간 동기화' 토글 활성화
- Goal.combinedSpanRatio 공용화 (모음 탭 카드·위젯·시리가 동일 산식 사용)
- DEBUG 검증 인자: -cloudSync YES, -settingsScrollPremium YES
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7