5.9 KiB
Bedrock Deferred Refactor Plan
This plan captures the remaining reusable extraction work that was intentionally deferred during the safe-core sync refactor.
Current Baseline (Already Done)
- Reusable sync lifecycle utility in Bedrock:
Bedrock/Sources/Bedrock/Storage/SwiftDataCloudKitSyncManager.swift
- Reusable refresh throttling utility in Bedrock:
Bedrock/Sources/Bedrock/Storage/SwiftDataRefreshThrottler.swift
- Bedrock-first setup guide:
Bedrock/Sources/Bedrock/Storage/SWIFTDATA_CLOUDKIT_SETUP_GUIDE.md
Deferred Items (This Plan)
Phase 1 - Derived Data Coordinator (Medium Risk)
Goal: Extract generic derived-state recomputation orchestration from app stores.
Candidate extraction:
- Generic coordinator to run ordered recompute steps after reload:
- fetch/load -> derive grouped/sorted slices -> invalidate downstream caches -> optional side effects
Bedrock target:
Bedrock/Sources/Bedrock/Storage/SwiftDataDerivedStateCoordinator.swift
App integration target:
Andromida/Andromida/App/State/RitualStore.swift
Guardrail:
- Keep ritual-specific filtering/sorting closures in app, only orchestration in Bedrock.
Phase 2 - Analytics Cache Framework (Medium Risk)
Goal: Reuse cache invalidation and lazy recomputation structure without moving domain metrics.
Candidate extraction:
- Generic keyed cache invalidation container
- "dirty flag + recompute-on-demand" helper patterns
Bedrock target:
Bedrock/Sources/Bedrock/Storage/SwiftDataAnalyticsCacheController.swift
App integration target:
Andromida/Andromida/App/State/RitualStore.swift
Guardrail:
- Keep metric formulas and ritual semantics in app.
Phase 3 - Refresh Orchestration Utility (Medium Risk)
Goal: Centralize recurring refresh sequences used across tabs/lifecycle transitions.
Candidate extraction:
- Reusable refresh runner with:
- optional overlay timing
- delayed aggressive refresh scheduling
- cancellation management
Bedrock target:
Bedrock/Sources/Bedrock/Storage/SwiftDataRefreshCoordinator.swift
App integration target:
Andromida/Andromida/App/Views/RootView.swift
Guardrail:
- Keep app tab selection and app-specific scheduler calls local.
Phase 4 - Migration Scaffolding (Higher Risk)
Goal: Reuse migration structure, not migration rules.
Candidate extraction:
- Versioned migration runner skeleton
- Shared logging and one-time version persistence wrapper
Bedrock target:
Bedrock/Sources/Bedrock/Storage/SwiftDataMigrationRunner.swift
App integration target:
Andromida/Andromida/App/State/RitualStore.swift
Guardrail:
- Keep ritual data integrity rule implementations in app.
Phase 5 - Documentation and Templates (Low Risk)
Goal: Expand Bedrock docs to cover phases 1-4 with copy/paste adapter examples.
Bedrock docs target:
Bedrock/Sources/Bedrock/Storage/SWIFTDATA_CLOUDKIT_SETUP_GUIDE.mdBedrock/README.md
Andromida docs target:
- Keep short pointers only; Bedrock remains source of truth.
Acceptance Criteria Per Phase
- No app-domain naming (
Ritual, etc.) in new Bedrock symbols/docs. xcodebuild -scheme Andromidapasses after each phase.- Existing iPhone/iPad sync behavior unchanged.
- No additional runtime-only workaround logic introduced without explicit opt-in.
Rollback Strategy
- Commit each phase separately in Bedrock and Andromida repos.
- If behavior drifts, revert only latest phase commit(s), keep previous phases.
- Avoid multi-phase combined commits.
Recommended Execution Order
- Phase 1 (Derived state coordinator)
- Phase 3 (Refresh orchestration utility)
- Phase 2 (Analytics cache framework)
- Phase 4 (Migration scaffolding)
- Phase 5 (Docs/templates refresh)
Notes
- This plan is intentionally incremental and conservative.
- Safe-core extraction stays as baseline; deferred phases should not block current product work.
Known Issue Backlog
KIB-001 - Mac runtime inbound CloudKit updates stall while app stays active
Problem statement
- Mac runtime does not reliably reflect incoming CloudKit changes from iPhone/iPad while app remains active.
- Updates appear after app lifecycle transition (foreground/background or relaunch).
Observed behavior
- Mac -> iPhone/iPad sync propagates quickly (about 1-2 seconds).
- iPhone/iPad -> iPhone/iPad sync propagates quickly.
- iPhone/iPad -> Mac often does not appear until activation transition.
- Remote change debug logs are absent on Mac during active-state misses.
Repro steps
- Keep Mac app active on Today or Rituals screen.
- On iPhone or iPad, toggle one or more habit completions.
- Observe Mac app does not update in real time.
- Trigger app activation transition on Mac (switch away/back or relaunch).
- Observe pending updates appear.
Impact
- Cross-device real-time expectation is broken for Mac runtime inbound updates.
- User trust risk for multi-device usage.
Current status
- Not a regression from Bedrock safe-core extraction; behavior also reproduced on original direct observer path.
- iPhone/iPad path remains healthy.
Hypothesis
- Runtime/platform-level import delivery behavior for SwiftData+CloudKit on Mac runtime while active (push/import callbacks not firing consistently).
Deferred investigation tasks
- Capture high-signal telemetry during active-state misses:
- last remote change callback time
- last lifecycle-triggered refresh time
- local store update timestamps
- Compare iOS-on-Mac runtime vs native iOS device callback cadence.
- Evaluate dedicated Mac sync architecture options:
- explicit sync UX fallback
- alternative persistence/sync stack for Mac runtime if real-time inbound is mandatory.
Acceptance criteria for closure
- While Mac app remains active, inbound updates from iPhone/iPad appear without requiring foreground/background transitions in repeated test runs.