Skip to content

fix(projects): keep worktrees when unreachable [2]#145

Draft
AbysmalBiscuit wants to merge 1 commit into
mathix420:masterfrom
AbysmalBiscuit:fix/wsl-discovery-authoritative
Draft

fix(projects): keep worktrees when unreachable [2]#145
AbysmalBiscuit wants to merge 1 commit into
mathix420:masterfrom
AbysmalBiscuit:fix/wsl-discovery-authoritative

Conversation

@AbysmalBiscuit

Copy link
Copy Markdown
Contributor

A transient wsl.exe failure silently collapses a WSL project's worktree list to a single pseudo-worktree. Project::discover now reports whether its answer is authoritative, and callers adopt through Project::apply, which drops a result the backend could not vouch for.

The bug

discover_wsl returned Project::placeholder on a failed round trip — the same single pseudo-worktree a non-git folder gets. Both Project::refresh and AlacritreeApp::poll_project_refreshes copied that straight over worktrees and default_branch, so one flaky round trip was indistinguishable from "every worktree in this project was deleted". The sidebar collapsed to one row and stayed that way until a later refresh happened to succeed.

Same failure shape as 17f95c23 fix(wsl): keep last probe when helper is briefly down, which fixed the foreground-TUI probe cache: a transport error collapsing into the same value as a definitive negative answer.

The change

  • Project::discover returns Discovered { project, authoritative }.
  • classify_wsl_answer(reached, is_repo, worktrees_parsed) -> WslAnswer is a pure function, so all three outcomes are reachable in a test without a WSL host. discover_wsl classifies once at the end rather than returning early three times.
  • Project::apply adopts a result, ignoring a non-authoritative one. expanded, shell_override, and label remain untouched either way, as before.
  • Callers in app.rs and cli/offline.rs take .project; the background refresh channel carries Discovered.

A distro that answers "this is not a repository" is still authoritative — that is the truth, and the placeholder is correct. Only a round trip that never landed, or one that came back claiming a repo with no main checkout, is treated as unknown.

Testing

Four new tests in projects::tests. They failed to compile first, then the finished code was hotpatched to drop the if !found.authoritative { return; } guard, reproducing the bug:

assertion `left == right` failed
  left: 1
 right: 2

Guard restored, green. Full suite: 480 passed. cargo clippy -p alacritree --all-targets warning count unchanged from master, none in the touched files.

Still to verify manually: add a project on a WSL path, break wsl.exe on PATH, force a refresh, and confirm the worktree list survives.

🤖 Generated with Claude Code

A failed wsl.exe round trip returned Project::placeholder, the same
single pseudo-worktree a non-git folder gets, so refresh and
poll_project_refreshes copied it over the real worktree list. One
transient WSL outage was indistinguishable from "every worktree in this
project was deleted", and the sidebar collapsed to a single row until a
later refresh happened to succeed.

Discovery now returns Discovered, pairing the project with whether the
backend could vouch for the answer, and callers adopt through
Project::apply, which drops a non-authoritative result. A distro that
answers "not a repository" is still authoritative; only a round trip
that never landed, or came back without even a main checkout, is not.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@AbysmalBiscuit
AbysmalBiscuit force-pushed the fix/wsl-discovery-authoritative branch from 1c97a30 to a4da122 Compare July 25, 2026 08:32
@AbysmalBiscuit AbysmalBiscuit changed the title fix(projects): keep worktrees when unreachable fix(projects): keep worktrees when unreachable [2] Jul 25, 2026
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