Derived summaries have their own invalidation

An inventory-object cache and a summary derived from those objects can have different invalidation rules. ItemsRequester separately resets its cached crew inventory mapping and marks TankmenStatsCache dirty on specific update paths. Replacing an item mapping does not itself prove that every derived summary was recomputed.

The summary getters recompute lazily when dirty, without their own synchronization gate. Their results answer whether qualifying crew exist; the scan can stop once its required Boolean results are known. Reset/fill checks are disabled until explicitly enabled, so a false result is not universally an eligibility decision. Read from a synchronized owner and invalidate mod-owned summaries for all of their dependencies; do not treat a cached flag as a count, a full-inventory scan or a synchronization signal. The rebuild clears its dirty flag before reading and scanning. An escaping read or predicate exception can therefore leave reset or partial results reusable by the next getter until another invalidation. For mod-owned projections, commit freshness only after a successful rebuild. These are source contracts, not a diagnosis of stale client UI.

Cache completion is not synchronization success

The base requester can handle a negative response code by retaining unsynchronized state and completing its callback with default data. After requests finish, ItemsCache checks aggregate isSynced: an ordinary unsynchronized result clears its wait flag, records failure and emits onSyncFailed, while the update future completes normally.

GUI personality onClientUpdate does not check isSynced after normal completion, so later cache updates and path dispatch can still run. Login synchronization and shop-resync callers make explicit synchronization checks. If a mod requires current synchronized data, validate that state separately from completion.

An exception escaping the awaited request has another path: the post-await wait-flag reset and failure-event handling are skipped. Later direct updates may change those flags; this is not evidence of a permanent lock or an observed client defect. See ItemsCache invalidation, base requester response handling and GUI personality callers in the latest public source. These are version-sensitive Python control-flow findings; live failure and recovery were not tested.

Cache diffs and asynchronous GUI routing

Account synchronizes its own caches/components before onClientSynchronize and onClientUpdated. A diff is not an old-state snapshot; retain prior values before the owning update when a before/after comparison is required.

GUI personality processes a normal account diff through item-cache update, event-cache update, lobby-context update and then ClientUpdateManager callbacks, followed by offers. The player SafeEvent does not await its async personality listener. Subscription order therefore does not serialize all asynchronous consumers, and a rejected or raising cache update can prevent later dispatch. Normal completion does not by itself prove synchronization.

First/full synchronization takes another route and skips ClientUpdateManager dispatch. Initialize from the owning synchronized cache, then observe later diffs. Avatar diffs can also reach the manager without account item/event updates, so manager subscription alone is not a lobby-only lifecycle guard. Preserve account/player context with deferred work.

Account GUI entry does not prove a fresh clock anchor

Account.showGUI assigns the account ID, applies time correction when the decoded context contains serverUTC, then emits onAccountShowGUI(ctx). If that key is absent, this path leaves the existing module-global clock anchor unchanged. The clock has no account identity or readiness field, so the GUI event alone does not prove that a fresh server-time anchor arrived for the current account.

The time helper initially seeds an epoch from the host wall clock and advances its anchor using elapsed BigWorld.time(). Its server/local epoch correction is a changing clock difference, not a fixed timezone offset. Preserve a deadline's representation when comparing or converting it, and keep this GUI context path separate from component/diff synchronization. These are Python initialization and conversion contracts; live clock cadence, synchronization accuracy and expiry enforcement were not tested.