Skip to content

fix(web): refresh the project list when a Discover run ends (#808) - #809

Merged
edspencer merged 1 commit into
mainfrom
fix/808-discover-refresh
Aug 10, 2026
Merged

fix(web): refresh the project list when a Discover run ends (#808)#809
edspencer merged 1 commit into
mainfrom
fix/808-discover-refresh

Conversation

@edspencer

Copy link
Copy Markdown
Owner

Fixes #808.

What actually happened

Reproduced on a throwaway instance with synthetic transcripts, before changing anything. It is candidate 2 — the deferral working exactly as designed, with a UX that lies about it — but with a twist the issue could not see from reading the code: the fix candidate 2 proposes cannot stand alone.

Candidate 1 is refuted. Clicking Get started works correctly today: await refresh() resolves, the sidebar populates, and Home swaps to the root workspace. No race, no stale closure, no lagging server. I drove it in a browser and watched it work.

What the user actually saw is on the screen before that click:

2 projects, 4 conversations
They are in the sidebar now. Anything that did not land says why below.

…rendered next to a sidebar reading "No projects yet." The success screen asserts the import has landed while every other surface still says the instance is empty. Someone who reads that sentence, looks at the sidebar, and sees nothing does not go hunting for a button labelled "Get started" — they reload the browser. That is the whole bug.

Why the obvious candidate-2 fix makes it worse

The issue suggests refreshing when the run completes, on the grounds that "the success screen is already showing; nothing is mid-run to unmount". I tried exactly that first, as a throwaway commit, and it is wrong: on the Home mount DiscoverView exists only while the instance is empty, and the refresh is what ends that condition. The success screen and every per-row outcome vanished the instant the list came back, replaced by the root workspace — the failure rows, the ones that had something to say, hardest hit.

So both of these must hold at once, and they pull in opposite directions:

  • the sidebar is current the moment the run ends, and
  • the screen reporting the run stays on screen until the user leaves it.

The change

Refresh once, on completion (submit) — not per row, which is the mid-run unmount the original comment rightly forbids, and not only on Get started, which is what left the sidebar stale.

Latch Home's empty-instance decision for the life of the mount (useInstanceEmpty). The instance's emptiness stays live data; Home's front door stops being live data. projects still updates underneath — that is the point, it is what populates the sidebar — but the answer Home routes on is pinned until something asks again.

recheck() is now wired up, not deleted. The issue flagged it as an escape hatch nobody called, and its docstring ("Re-ask. The import run creates projects, so Home has to re-evaluate") describes precisely the release side of this latch. It was written for a latch that was never built. RootHome passes it to DiscoverView as onLeave, because a screen rendered instead of Home cannot leave by navigating to Home — navigate("/") is a no-op there, and the latch releasing is what actually hands over.

One subtlety worth flagging for review: recheck had to clear rootHasChats itself, not just bump the nonce. Bumping alone releases the latch in the same render that still holds the pre-recheck answer, which re-pins the very value being discarded and then never moves again. My first draft had that bug; the pre-existing "re-asks on recheck" test caught it.

Tests

packages/web/src/routes/RootHome.discover.test.tsx — new, and the real guard. Mocks the API and nothing else: RootHome, useInstanceEmpty, ProjectsProvider and DiscoverView are all the real thing, because the seam between them is the defect. It asserts both halves — the list is refetched when the run ends, and the per-row outcomes are still rendered — plus that nothing refreshes between rows.

2 of its 3 tests fail on main (expected "spy" to be called 2 times, but got 1 times); verified by stashing the source changes and keeping the tests.

Also added: latch/release cases in useInstanceEmpty.test.tsx, the completion refresh and onLeave in DiscoverView.test.tsx, and a RootHome.test.tsx case that fails if the onLeave wiring is ever dropped (which would strand a first-run user on the success screen for good).

Verification

  • Reproduced, and the fix confirmed, in a browser against a real server: sidebar shows the imported projects while the success screen and both row outcomes are still on screen; Get started then hands over to the root workspace; the imported chats are listed. No reload at any point.
  • Also checked the /discover route mount (which passes no onLeave) with a second import on a now-populated instance — refreshes on completion, navigates away on Get started.
  • npm run typecheck clean; full web suite 85 files / 1782 tests passing; check:nul clean.

🤖 Generated with Claude Code

Reported from real first-run use: Discovery found the user's directories
and the import succeeded, but nothing refreshed — a manual browser reload
was needed before the imported projects appeared.

The refresh was deferred all the way to "Get started" on purpose, because
on the Home mount DiscoverView exists only while the instance is empty:
importing is the act that ends that condition, so refreshing mid-run made
the first successful row unmount the screen the user was watching the rest
of the run on. What the deferral cost was a success screen asserting "They
are in the sidebar now" over a sidebar that still read "No projects yet".

Refresh once, on completion, and latch Home's empty-instance decision for
the life of the mount so that refresh cannot yank its own success screen —
including the failed rows, which are the ones with something to say. The
latch is released by "Get started", which is what `useInstanceEmpty`'s
hitherto-uncalled `recheck()` was written for; RootHome now passes it to
DiscoverView as `onLeave`, since a screen rendered INSTEAD of Home cannot
leave by navigating to Home.

Co-Authored-By: Claude <noreply@anthropic.com>
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying paddock with  Cloudflare Pages  Cloudflare Pages

Latest commit: b12d455
Status: ✅  Deploy successful!
Preview URL: https://22d562d3.paddock-7u2.pages.dev
Branch Preview URL: https://fix-808-discover-refresh.paddock-7u2.pages.dev

View logs

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.

Discover: imported projects need a manual browser reload to appear

1 participant