Skip to content

fix: state-integrity pass on the update loop (detail by name, honest checks, badge lifecycle) - #30

Merged
MotherSphere merged 1 commit into
mainfrom
fix/state-integrity
Jul 20, 2026
Merged

MotherSphere merged 1 commit into
mainfrom
fix/state-integrity

Conversation

@MotherSphere

@MotherSphere MotherSphere commented Jul 20, 2026 •

Copy link
Copy Markdown
Member

Why

Five confirmed defects where the UI misreports state or loses it.

Changes

  1. The detail page is tracked by name, not index. The catalog vector is replaced AND reordered by every refresh (GitHub sorts by last push), so a refresh while a detail page was open silently swapped it to another app. Selection now goes by name through App::active_repo(), and a repository that disappeared falls back to the grid.
  2. Update badges are cleared. After a successful update the card showed "Update vX → vX" until the next full check, and an uninstall kept its badge too.
  3. An honest launcher check. check_launcher_update turned every error into "up to date" (offline, rate limit, non-semver tag). It now returns a Result: the failure is shown (an error toast on a manual click, the status line for an automatic check) and never claims Colony is current. The "up to date" toast only appears for a manual check, and boot no longer runs the check twice.
  4. auto_check_updates is ON by default. A store that never checks leaves its badges invisible forever. The check is batched and costs zero API calls for apps pinned to a fixed tag.
  5. The scan cache is finally read. It was written on every scan and never read back, so with the startup scan off every boot showed "0 apps". Boot now restores the cache when the scan is skipped.

Testing

cargo build and clippy --all-targets clean, 88 tests pass, boot smoke test OK (session restored, 3 repositories detected, no double launcher check).

…checks, badge lifecycle)

Five confirmed audit findings, all in the category 'the UI lies about
state or loses it':

- The open detail page was tracked by raw index into the catalog vector,
  which every refresh replaces AND reorders (GitHub sorts by last push):
  a refresh landing while a detail page was open silently swapped it to
  a different app's page. The selection is now keyed by repo name and
  resolved through App::active_repo(); a repo that vanished falls back
  to the grid instead of showing someone else's detail.
- Update badges were never cleared: after a successful update the card
  kept showing 'Update vX -> vX' until the next global check, and an
  uninstalled app kept its badge. Both paths now clear the entry.
- The launcher update check swallowed every failure into 'up to date':
  offline, rate-limited, or a bad tag all pretended the check ran.
  check_launcher_update now returns Result; failures surface (as an
  error toast for a manual click, in the status line for the automatic
  check) and never claim currency. 'Up to date' only toasts on a manual
  check - the automatic boot check stays quiet - and the boot no longer
  runs the check twice (the direct dispatch duplicated the
  CheckUpdates-chained one).
- auto_check_updates now defaults ON: a store that never checks leaves
  its update badges permanently invisible. The check is batched and
  makes zero API calls for apps pinned to a fixed tag.
- The scan cache was written on every scan but never read: with the
  startup scan disabled, every boot showed '0 apps'. Boot now restores
  the cached scan when the scan is skipped.
@MotherSphere
MotherSphere merged commit e5870da into main Jul 20, 2026
3 checks passed
@MotherSphere
MotherSphere deleted the fix/state-integrity branch July 20, 2026 16:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant