# Backlog Smells and small inconsistencies found during post-PLAN.md review. None of these block merging — they are tracked here so they aren't forgotten and so they don't reopen as "new findings" the next time someone reads the code. **Rule of engagement:** items in this file get touched only when (a) someone hits the symptom in practice, or (b) work in a nearby area makes fixing the smell incidental. No batch refactor passes. No "while we're here" cleanups that grow beyond the in-scope change. --- ## Legacy peer protocol fallback contradicts the wire policy CLAUDE.md / AGENTS.md: *"There is only one wire version — the current one. No legacy peers, no compatibility shims, no fallback paths for older builds."* Live legacy paths: - `crates/lanspread-peer/src/services/legacy.rs` exists and is called from `discovery.rs:183-188` when the `Hello` handshake fails. - `discovery.rs:134` synthesizes `legacy-{addr}` peer IDs when `proto_ver` is absent from mDNS TXT records. - `discovery.rs:169` treats `proto_ver.is_none()` as handshake-eligible. - `update_and_announce_games` (`handlers.rs:605-624`) branches on `FEATURE_LIBRARY_DELTA` and falls back to `announce_games_to_peer` (sending `Request::AnnounceGames`) for peers that don't advertise the feature. - `Request::AnnounceGames` is still defined in `lanspread-proto/src/lib.rs:75` and handled in `services/stream.rs:116`. Functionally inert today — current-build peers don't drop `Hello` — but code and stated policy disagree. Either delete the paths or revert the policy. --- ## Tauri keeps a parallel filesystem-derived scan The peer now owns the install state machine (per PLAN.md:11), but Tauri still re-derives local install/download state from disk on every event: - `refresh_games_list` (`src-tauri/src/lib.rs:489`) fires after every `update_game_db`, `update_local_games_in_db`, and `update_game_directory`. It calls `set_all_uninstalled()` and re-runs `update_game_installation_state` over every bundled-DB entry, re-reading `version.ini`, re-checking `local/`, re-parsing version strings. - `update_local_games_in_db` (`src-tauri/src/lib.rs:667-704`) just merged the peer's authoritative `Game` values into the Tauri-side `GameDB`. Immediately after, `refresh_games_list` re-derives the same fields from disk and overwrites the merged result. - The per-ID rescan optimization in `local_monitor.rs` is completely undone on the Tauri side: every peer event triggers a whole-library disk walk. Today both paths reach the same conclusion. The risk is forward-looking: the moment one of the two derivation rules changes (a new `availability` rule, a new sentinel, a new ignore name), the two scanners can disagree silently with no rule for which wins. **Fix when convenient:** `refresh_games_list` accepts the peer's `Game` slice and trusts it for local fields. Tauri's bundled DB stays as the source of truth for static metadata (name, description, max_players, thumbnail mapping), but `downloaded`/`installed`/`local_version`/ `availability` come from the peer. `update_game_installation_state` and `set_all_uninstalled` go away. The dead log branch at `src-tauri/src/lib.rs:397-402` is obviated naturally by this. --- ## `Availability::Downloading` is wire-defined but unreachable `crates/lanspread-db/src/db.rs:36-41`. The variant exists and serializes but `build_game_summary` only emits `Ready` or `LocalOnly`. Operation-table gating handles the in-progress case instead. `peer_db::get_all_games` has a code path that lets a remote-advertised `Downloading` summary contribute `eti_version` to aggregation. If a future maintainer re-enables emitting `Downloading` from `build_game_summary`, aggregation will treat such peers as not-downloadable but still pull their version info. **Decide-and-document task:** either remove the variant (matches the "current wire only" policy) or add a comment in the proto enum naming the contract. --- ## `update_game_installation_state` dead log branch `src-tauri/src/lib.rs:397-402`: ```rust if eti_package_exists(&game_path, &game.id) && !downloaded { log::debug!("Game ... has archives but no version.ini sentinel; treating as not downloaded"); } ``` Side-effect-only log line. Either delete or wire to a UI affordance ("partial download — retry?"). Obviated naturally if/when the Tauri parallel scan goes away. --- ## Untested edge: Tauri reconciliation with dropped lifecycle events The Rust `reconcile_active_operations` test (`src-tauri/src/lib.rs:1117-1153`) covers map replacement but not the realistic case of an event sequence with a missing `begin` or `finish`. The TS side merges in `App.tsx`. Real failure mode: a missing `finish` followed by a `LocalGamesUpdated` snapshot should clear the spinner, and today's code does — but it's not pinned by a test. Add a test if the spinner ever gets stuck in practice. --- ## Documentation drift `FOLLOW_UP_2.md` still lists two items as "Still open" that have landed: - **#10 `save_library_index` non-atomic** — landed in `fdad162`, atomic temp+fsync+rename at `local_games.rs:169-184`. - **#11 Split `download.rs`** — landed in `a251233`, split under `crates/lanspread-peer/src/download/`. Either mark the doc complete or delete it. Anyone reading it as status will be misled. The collection of plan/follow-up/review docs in the repo root (`PLAN.md`, `PLAN_AVAILABILITY.md`, `PLAN_ATOMIC_INDEX.md`, `PLAN_DOWNLOAD_SPLIT.md`, `FOLLOW_UP_PLAN.md`, `FOLLOW_UP_2.md`, `REVIEW_STEP_1..4.md`, `IMPL_DECISIONS.md`) is also getting noisy. A single retrospective archive folder for completed plans would help; a future PLAN.md should be self-terminating with explicit acceptance criteria so it doesn't spawn this many trailing docs. --- ## How items leave this file - Closed by fix → delete the entry, mention it in the commit. - Closed by decision ("we're not doing this") → delete the entry, no commit message ceremony needed. - Promoted to active work → move back to `FINDINGS.md` only when there's a concrete plan to fix it now. This file does not grow unboundedly. If it does, that's a signal to either close items or stop adding to it.