종료일이 지난 목표의 자동 판정(evaluateIfEnded)이 목표 탭 진입 시에만
실행돼, 목표 탭을 열지 않으면 위젯·워치·모음 탭 카드에 '진행 중'으로
계속 남아 있었다. 앱 실행/포그라운드 복귀(scenePhase .active) 시점에
같은 판정을 추가로 실행한다.
- 목표 탭 onAppear 로직과 동일한 코드 — 진행 중 목표만 조회, 변경이
있을 때만 DataChange.commit (위젯·워치·라이브 액티비티 갱신)
- 다짐 없는 목표는 evaluateIfEnded가 건드리지 않으므로 '확인 필요'
직접 선택 흐름은 그대로
- 위젯 확장에서는 판정하지 않음 (프로바이더 경합·CloudKit 내보내기
지연 위험 회피)
- 검증용 DEBUG 인자 -endGoalYesterday "제목" 추가. 시뮬레이터에서
목표 탭을 열지 않은 콜드 스타트만으로 statusRaw가 achieved로
전환되는 것을 스토어 조회로 확인
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
위젯 동기화 크래시 수정:
- DataStore: CloudKit 미러링을 메인 앱 프로세스 전담으로 분리.
위젯 등 앱 확장(.appex)은 CloudKit 엔타이틀먼트가 없고 메모리·수명
제약으로 미러링 설정이 크래시/행을 유발하므로, 확장 프로세스는 항상
같은 App Group 스토어 파일을 로컬 전용(cloudKitDatabase: .none)으로
연다. 확장이 쓴 변경은 메인 앱이 히스토리로 집어 CloudKit에 내보냄
- CloudSyncMonitor 신설: 메인 앱이 NSPersistentStoreRemoteChange
(다른 기기의 CloudKit 가져오기·위젯 인텐트의 쓰기)를 디바운스로 받아
라이브 액티비티 → 위젯 타임라인 → 워치 스냅숏 순으로 즉시 갱신
- 인터랙티브 위젯(AppIntent)의 컨테이너 매핑 점검: IntentStore.commit이
저장 직후 reloadAllTimelines를 이미 보장함을 확인·문서화
모음 탭 목표 진행 현황 카드 개선:
- '다짐별로 보기'의 상위 3개 제한 제거 — 모든 다짐 확인 가능
- 화면 균형을 위해 접힘/펼침 UX 적용: iPhone은 3개, iPad는 6개까지
접힌 상태로 보여주고 '다짐 N개 더 보기' 버튼으로 카드 안에서 펼침
(카드 탭 이동과 충돌하지 않는 독립 버튼, 스냅 애니메이션)
- DebugSeed: 접힘/펼침 검증용 4번째 다짐 추가, -expandGoalCard 인자 추가
검증: iPhone 17 Pro·iPad Pro 11 시뮬레이터에서 접힘/펼침 렌더링과
사이드바 레이아웃 확인, 전체 타깃(iOS·워치·위젯) 빌드 성공
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
- Add Shared/LocalPrefs.swift: device-local UI preferences stored in App Group
UserDefaults (never synced by iCloud), read identically by app, widgets,
watch snapshot, and App Intents on the same device
- Move to local storage: main-tab action button order (UUID array), pinned
goal-progress cards on the main tab, goal quest-list collapse state, and
per-action memo-prompt popup — reordering or repinning on iPhone no longer
touches the iPad and vice versa
- Defense logic: actions not in the local order list (e.g. newly received via
CloudKit from another device) are automatically appended to the end, sorted
by legacy sortOrder then creation date
- One-time migration adopts existing @Model values (sortOrder, showsOnMain,
isCollapsed, promptsForNote) into local prefs at launch; model properties
stay in place so the CloudKit schema is untouched and records keep syncing
- Data remains fully synced: actions, goals, quests, sessions, count entries,
statistics, and goal/tag/quest list order are untouched by this change
- Verified in simulator: legacy data migrates losslessly, grid renders from
local order, unknown action lands at the end; iOS+watch+widgets build clean
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
- Implement drag-and-drop functionality for users to reorder the active goals list
- Ensure the custom order of goals is persistently saved and loaded
- Filter out completed goals from the main active list to reduce visual clutter
- Add a 'View Completed Goals' button to navigate to a dedicated screen for finished items
- Remove the maximum limit for selected goal widgets on the main tab
- Unify the display format (aggregate vs. individual) to apply globally across all selected goals
- Redesign the horizontal scrolling into a full-width snap carousel (pagination style)
- Ensure only one widget is fully visible at a time with no adjacent cards partially showing
- Apply snap scrolling so light swipes firmly transition to the next or previous widget
- Update the goal progress widget in the main tab to support up to 3 selected goals
- Add multi-selection capabilities to the widget settings menu
- Implement a horizontal or scrollable layout for multiple goals to optimize screen space
- Maintain existing routing to specific goal detail screens upon tap