The primary output of a sync is a QwkSyncResult which includes:
Outcome (overall result classification)Issues (a list of QwkSyncIssue entries) Progress and logging are informational only and do not affect behaviour.
This model allows callers to:
QWKSync.NET uses both. It uses exceptions for unrecoverable failures and cancellation, and it uses issues for structured reporting when a coherent result can be returned.
Exceptions: for unrecoverable errors that prevent producing a meaningful session result, or when cancellation is requested and must interrupt promptly.
Result issues: for structured reporting about what happened during the session, including failures encountered and policy decisions taken, as long as a coherent session result can still be returned.
Where a transport extension throws, QWKSync.NET should capture and translate into issues only when doing so does not hide cancellation, concurrency conflicts, or unrecoverable I/O errors that prevent a coherent result.
CancellationToken.TransferPolicy.Timeout exists and should be enforced deterministically per transport call, aligned to TransferPolicy.Timeout semantics in the public API doc. It should not introduce heuristic behaviour.
Retry behaviour is core-orchestrated, bounded, deterministic, and configured via policy:
MaxRetries = 0 (no retries). When retries are enabled:
Resume is transport-owned and disabled by default. QWKSync.NET never assumes resume exists. If a transport extension cannot resume, it must fall back to a full transfer or fail clearly.
QWKSync.NET error handling does not depend on resume being available.
Atomicity is mandatory:
Any failure during download finalisation:
QWKSync.NET enforces the single-flight guarantee:
This failure should be easy for the caller to detect and handle. It does not look like a transient transport error.