- prune expired recovery items on load/save and reject expired restores at worker boundary - add restoreExpired and restoreConflict protocol/application error mapping - disable expired restore actions in History and reload persisted state after restore failures - add recovery expiry/conflict coverage plus sync protocol, architecture, state-machine, and recovery contract docs - wire AtlasAppTests into the shared Xcode scheme and add app-layer regression coverage for expired restore reload behavior Refs: ATL-221 ATL-222 ATL-223 ATL-224 ATL-225, vibe-kanban SID-9
2.6 KiB
2.6 KiB
Recovery Retention Enforcement Plan
Goal
Align shipped recovery behavior with the existing Atlas retention contract so expired recovery items are no longer restorable, no longer linger as active recovery entries, and return stable restore-specific protocol errors.
Problem
The current worker restores any RecoveryItem still present in state, even when expiresAt is already in the past. The app also keeps the restore action available as long as the item remains selected. This breaks the retention-window claim already present in the protocol, task-state, and recovery docs.
Options
Option A: Narrow docs to match current code
- Remove the retention-window restore claim from docs and gate reviews.
- Keep restore behavior unchanged.
Why not:
- It weakens an existing product promise instead of fixing the trust gap.
- It leaves expired recovery items actionable in UI and worker flows.
Option B: Enforce expiry only inside restoreItems
- Reject restore requests when any selected
RecoveryItem.expiresAtis in the past. - Leave repository state unchanged.
Why not:
- Expired entries would still linger in active recovery state across launches.
- The app could still display stale recovery items until the user attempts restore.
Option C: Enforce expiry centrally and prune expired recovery items
- Normalize persisted workspace state so expired recovery items are removed on load/save.
- Recheck expiry in the worker restore path to fail closed for items that expire while the app is open.
- Return stable restore-specific error codes for expiry and restore conflicts.
- Disable restore UI when the selected entry is already expired.
Decision
Choose Option C.
Implementation Outline
- Extend
AtlasProtocolErrorCodewith restore-specific cases used by this flow. - Normalize workspace state in
AtlasWorkspaceRepositoryby pruning expiredRecoveryItems. - Recheck expiry in
AtlasScaffoldWorkerService.restoreItemsbefore side effects. - Map restore conflicts such as an already-existing destination to a stable restore-specific rejection.
- Disable restore actions for expired entries in History UI.
- Add tests for:
- expired recovery rejection
- repository pruning of expired recovery items
- restore conflict rejection
- controller localization for restore-specific rejections
- Update protocol, architecture, task-state, recovery contract, and gate review docs to match the shipped behavior.
Validation
swift test --package-path Packages --filter AtlasInfrastructureTestsswift test --package-path Packages --filter AtlasApplicationTestsswift test --package-path Packages