# V2 Platform Cloud Save Sync

Phase 72.21.1.10 adds the public platform cloud-save sync surface for
auto-syncing save files, reading cloud saves, writing local saves to platform
cloud storage, and resolving conflicts through the existing persistence conflict
UI. `FV2PlatformCloudSaveSyncPolicy` owns provider coverage,
`FV2PlatformCloudSaveFileState` describes local and cloud revisions, and
`FV2PlatformCloudSaveSyncPlan` carries the platform SDK request plan.

## Operations

`PlanPlatformCloudSaveSync` supports:

- `AutoSyncSaveFile` writes dirty local saves to platform cloud storage, or
  reads a newer cloud save when local state is clean.
- `ReadCloudSave` queues `EV2PlatformSdkRequestType::ReadCloudSave` through the
  platform SDK abstraction.
- `WriteCloudSave` queues `EV2PlatformSdkRequestType::WriteCloudSave` with a
  payload hash and payload byte count.
- `ResolveCloudConflict` queues `UseCloud` as a cloud read and `UseLocal` or
  `MergeLedgers` as a cloud write after persistence accepts the final action.

Conflicts are not resolved inside `V2OnlineServices`. Divergent local/cloud
state blocks platform API calls and routes to the persistence conflict screen
`Save.CloudConflictResolution`, backed by cloud policy
`CloudSave.OnlineServices.V2` in
`V2/ue/Content/V2/Persistence/Profile/ProfileSaveGame_V2_Contract.json`.

## Provider Routes

| Provider             | Native storage surface               | Read command                      | Write command                      | Conflict command                       |
| -------------------- | ------------------------------------ | --------------------------------- | ---------------------------------- | -------------------------------------- |
| Steamworks           | `ISteamRemoteStorage`                | `ISteamRemoteStorage::FileRead`   | `ISteamRemoteStorage::FileWrite`   | `ISteamRemoteStorage::FilePersisted`   |
| Epic Online Services | `EOS_PlayerDataStorage`              | `EOS_PlayerDataStorage_ReadFile`  | `EOS_PlayerDataStorage_WriteFile`  | `EOS_PlayerDataStorage_DuplicateFile`  |
| GOG Galaxy           | `galaxy::api::IStorage`              | `galaxy::api::IStorage::FileRead` | `galaxy::api::IStorage::FileWrite` | `galaxy::api::IStorage::FileDelete`    |
| PlayStation SDK      | `V2PlayStationSavedDataInterface`    | `PsnSavedData.Read`               | `PsnSavedData.Write`               | `PsnSavedData.ResolveConflict`         |
| Xbox GDK             | `V2XboxGdkConnectedStorageInterface` | `XboxConnectedStorage.Read`       | `XboxConnectedStorage.Write`       | `XboxConnectedStorage.ResolveConflict` |

Console routes stay public stubs in `V2OnlineServices`. Proprietary PlayStation
and Xbox headers or symbols stay in restricted platform SDK modules.

## Rules

The default policy requires Steamworks, EOS, GOG Galaxy, PlayStation SDK, and
Xbox GDK route coverage. Every route must support auto-sync, reads, writes,
conflict callbacks, atomic writes, persistence conflict delegation, and
per-platform user namespaces. Platform API failures fail closed; offline
requests queue retry metadata but do not call native storage until the provider
API is reachable.

Auto-sync requires cloud sync to be enabled, a linked platform account, a valid
save slot, and a local or cloud save. Writes require payload metadata. Reads
require a cloud save. Unaccepted conflicts report `CloudSaveConflict` and block
native calls until persistence returns `UseLocal`, `UseCloud`, or
`MergeLedgers`.

## Verification

Run:

```bash
python3 V2/ue/Tools/check-v2-platform-cloud-save-sync.py
```

The checker validates the C++ API, contract, automation spec, CI workflow, Horde
gate, documentation, and TODO evidence for Section 72.21.1.10.
