Read `packages/ui/src/sync/DOCUMENTATION.md` and the nearest owning module documentation before editing. Context gathering is complete when every changed state has an identified owner, authority, scope, and lifecycle.
Give each state and its invariants one owner. Callers request domain transitions from that owner; they do not inspect one field, mutate another collection, and repair status externally. Split ownership only when the states have genuinely independent lifecycles.
Represent mutually exclusive lifecycle states with discriminated unions or equally precise contracts. Avoid boolean/nullable field combinations that permit impossible states. Reject invalid transitions at the owning boundary so downstream reducers and effects receive trusted state.
Any authoritative loader whose result can replace, delete, or clear state must distinguish failure from successful empty data.
Use an existing pattern:
- Throw when an outer logical block can catch and preserve prior state.
- Return `T | null` when follow-up work must continue and `null` exclusively means fetch failure.
Never swallow an SDK/API error into `[]`, `{}`, or another valid empty success. Verify that callers skip destructive replacement after failure.
Track completeness at the smallest entity/scope. One failed project or directory blocks destructive work for itself, not for unrelated complete scopes.
Inferring destructive cleanup from disappearance between snapshots requires an established authoritative baseline. This is separate from applying a complete snapshot whose contract explicitly authorizes first-load replacement.
- Never infer a disappearance event from the first snapshot, startup-empty state, filtered/visible subsets, or partially loaded scopes.
- Compare two complete authoritative snapshots from the same runtime and logical scope before treating disappearance as removal.
- Key disappearance by stable entity identity. Owner, directory, grouping, category, or presentation moves are not deletion unless the authoritative contract says so.
- Reset the baseline when runtime identity or authoritative scope changes.
- Prefer explicit deletion events; snapshot-difference cleanup is a fallback that requires completeness guarantees.
- Make the valid transition path explicit and flat. Return early for irrelevant entities and semantic no-ops; assert or reject transitions that violate an established invariant.
- Distinguish stale-scope rejection from same-scope mutation reconciliation. A generation token rejects obsolete owners but does not protect mutations made while a still-valid request is in flight.
- Capture a mutation revision when an authoritative load starts. At commit time, read current state and preserve or overlay entity mutations newer than that revision.
- Record removals as mutations even when the entity is already absent, so an in-flight response cannot resurrect it.
- Return committed reconciled state, not the raw fetched snapshot, when callers depend on the result.
- Keep optimistic promotion, reconciliation, and rollback behavior behind the store/module that owns both visible and shadow state; do not expose collections for callers to mutate independently.
When state exists in memory and one or more persistent stores, define an explicit authority and ordering protocol:
- Distinguish a missing snapshot from authoritative empty data, malformed data, and read failure.
- Preserve mutation order independently per owner by serializing writes or attaching monotonic revisions and rejecting stale writes. Do not rely on uncontrolled wall-clock timestamps.
- Capture runtime/owner identity with every debounced or asynchronous operation and verify it again before commit.
- Pending writes must complete against their captured owner, drain before an owner switch, or be canceled only under an explicit durability/data-loss contract. Apply the strongest available guarantee at page hide/freeze and shutdown boundaries.
- During hydration, capture the local mutation revision and do not replace state after newer local mutations.
- Validate persisted payload shape before granting authority. Malformed data is failure, not empty success.
- Define retention explicitly; never silently evict older owner namespaces unless bounded retention and resulting data loss are intentional contracts.
Cover every applicable lifecycle branch, not only static state. Verification is complete when failure cannot masquerade as empty success, stale or partial data cannot cause destructive replacement, and each transition remains with its owner:
- snapshot-difference cleanup establishing its first authoritative baseline without deletion, then cleaning a later authoritative disappearance exactly once;
- identity-preserving moves/category changes and runtime/scope changes resetting cleanup baselines;
- create, update, move, archive, and delete mutations surviving responses started before those mutations;
- missing versus empty persistence, malformed payloads, out-of-order writes, hydration races, and lifecycle durability behavior.