fix(ui): reconcile active operations from local scans

Local operation spinners were driven by begin, finish, and failure event
history. If one of those lifecycle events was missed, the Tauri bridge could
keep a stale active operation and the React state would keep showing an
in-progress spinner until restart.

Peer local scan updates now carry an authoritative active-operation snapshot.
The peer still suppresses active game roots from peer-facing library deltas,
but it emits LocalGamesUpdated to the UI even when no library delta changed so
the snapshot can clear stale state after rollback or completion. The Tauri
bridge replaces its active-operation map from that snapshot, emits it with the
games-list payload, and the React merge uses it to restore download, install,
update, and uninstall spinners from current peer state rather than event
history alone.

This also enables the Tauri lib unit-test target so the reconciliation helper
can stay covered by the workspace test recipe.

Test Plan:
- git diff --check
- just fmt
- just clippy
- just test

Follow-up-Plan: FOLLOW_UP_2.md
This commit is contained in:
2026-05-16 09:01:17 +02:00
parent b5d20c1e72
commit 95e70ef520
7 changed files with 384 additions and 38 deletions
+11 -7
View File
@@ -1,6 +1,8 @@
# Follow-up Plan #2
State of FOLLOW_UP_PLAN.md after two implementation rounds. Items here are what's still open.
State of FOLLOW_UP_PLAN.md after two implementation rounds. Items here are
what's still open, plus notes for follow-up items completed after this file was
created.
## Context for next time
@@ -8,14 +10,16 @@ Branch `p2p-codex-muenchhausen` has uncommitted work that completes the bulk of
The OperationGuard ordering fix in `handlers.rs` is the structurally most important change: install/update/uninstall now drop the guard _before_ the finish event and `refresh_local_game`, so peers see settled state in the next announcement instead of waiting for a scan tick. Tests `*_refreshes_settled_state_after_guard_release` pin this.
## Completed after this file was created
- Tauri-side `active_operations` reconciliation: `PeerEvent::LocalGamesUpdated`
now carries an authoritative active-operation snapshot, the Tauri bridge
replaces its UI operation map from that snapshot, and the React game-list
merge uses the snapshot to clear stale download/install/update/uninstall
spinners even when a begin/finish/fail event was missed.
## Still open
### Correctness / runtime
#### 1. Tauri-side `active_operations` has no reconciliation
If a `PeerEvent::InstallGameFinished` / `…Failed` is dropped, the UI is stuck "installing" until app restart. Include an in-progress snapshot in `PeerEvent::LocalGamesUpdated` so the UI recomputes from authoritative state instead of accumulating from event history. (Was `#10` in original plan, deferred both rounds.)
### Tests still missing
#### 2. Install-recovery matrix (~10 rows)