Andromida/BEDROCK_DEFERRED_REFACTOR_PLAN.md

177 lines
5.9 KiB
Markdown

# 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.md`
- `Bedrock/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 Andromida` passes 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
1. Phase 1 (Derived state coordinator)
2. Phase 3 (Refresh orchestration utility)
3. Phase 2 (Analytics cache framework)
4. Phase 4 (Migration scaffolding)
5. 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**
1. Keep Mac app active on Today or Rituals screen.
2. On iPhone or iPad, toggle one or more habit completions.
3. Observe Mac app does not update in real time.
4. Trigger app activation transition on Mac (switch away/back or relaunch).
5. 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.