Files
lanspread/BACKLOG.md
T
2026-05-16 13:15:34 +02:00

6.1 KiB

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:

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.