Cover the Brain Explorer panes and fix two routing bugs - #956
Merged
Conversation
Closes the last two zero-coverage surfaces from the #925 brains split, and fixes two real bugs the coverage work surfaced in brains-detail-pane.tsx. A malformed base64url repo root recovered by calling navigate() during render. React Router v7 refuses imperative navigation during render — it warns and no-ops — so the undecodable root stayed in the address bar and came straight back on reload or from a shared link. It is now a declarative <Navigate replace />. The collection path segment was decoded a second time on the way to the collection view, but react-router has already decoded it. A collection named "50%off" threw URIError and took the pane down; one named "%41" silently selected a collection that does not exist. Both names are reachable — the sidebar links to whatever collection an agent created. brains-detail-pane.test.tsx (20 tests) mounts the pane on the same three routes the real router declares and pins the repo-root decode and its malformed fallback, the collection round trip, the pill counts and active marker, the search wiring, and the destructive "Clear project" flow including its wire contract, summed toast, failure path and pending gating. 16/17 mutants killed; the survivor is the collections loading guard, which is unobservable because the query's data already defaults to []. brains-pane.test.tsx (14 tests) pins the encode half of the same URL contract plus the sidebar's list states, per-type count gating, keyboard activation and selection highlight. 18/18 mutants killed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The first battery never mutated the { replace: true } flags, so nothing
guarded the half of the malformed-root fix that matters most: pushing
instead of replacing leaves the undecodable URL one Back press away, and
going Back redirects forward again — a trap. A navigation-type probe now
pins REPLACE on all three redirects and PUSH on ordinary pill navigation.
Deleted the loading-pills test. It could not fail: useBrainCollections
already defaults data to [], so both collectionsLoading guards are
unobservable, and the assertion filtered for a collection no fixture
declared. The dead guards are recorded for a future run rather than
covered by a test that certifies nothing.
Renamed the post-delete test to the navigation it actually protects —
leaving the project unmounts the dialog either way, so that test cannot be
what proves the dialog closes.
Also: dropped a sidebar test that duplicated the routing case, split the
Enter/Space test so neither reuses a node captured before its own route
change, tightened the pill count assertions to exact text, relaxed the
skeleton count to presence, and stubbed Toaster alongside toast.
Batteries after the changes: 20/21 on brains-detail-pane.tsx (the survivor
is the proven-unobservable loading guard) and 19/19 on brains-pane.tsx.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Recurring Test Enforcer run. Local suite was green on first pass (26th consecutive), so the run went to the
next_focuscoverage target — the last two zero-coverage surfaces from the #925 brains split. The coverage work turned up two real product bugs, both fixed here.Product bugs fixed
Dead redirect on a malformed repo root.
BrainsDetailPanerecovered from an undecodable base64url repo root by callingnavigate()during render. React Router v7 refuses imperative navigation during render — it logsYou should call navigate() in a React.useEffect()and no-ops (verified with a probe). So the pane rendered the overview while the broken URL stayed in the address bar, came back on reload, and survived in a shared link. Now a declarative<Navigate to="/automations/brains" replace />.Double-decoded collection param.
selectedCollection={collection ? decodeURIComponent(collection) : null}decoded a path param react-router had already decoded. A collection named50%offthrewURIErrorand took the whole pane down; one named%41silently selected a collection that does not exist and rendered it empty. Both names are reachable — collection names come from agents, and the sidebar links to whatever exists. Nowcollection ?? null. There are no otherdecodeURIComponentcall sites inapps/web/src, and every producer of that segment already goes throughencodeURIComponent, so encode/decode is symmetric.Coverage added
brains-detail-pane.test.tsx(19 tests) mounts the pane on the same three routes the real router declares, souseParamsbehaves exactly as in production. It pins the repo-root decode and its malformed fallback, the collection round trip, pill counts and the active marker, search wiring, and the destructive "Clear project" flow — wire contract, summed toast, failure path, and pending gating. 20/21 mutants killed. The survivor is thecollectionsLoadingguard, which is unobservable in both branches because the query'sdataalready defaults to[]; it is recorded as a dead guard for a future run rather than papered over with a test that cannot fail.brains-pane.test.tsx(14 tests) pins the encode half of the same URL contract plus list states, per-type count gating, keyboard activation, and the selection highlight. 19/19 mutants killed.No new E2E test:
e2e/brains-page.spec.tsalready drives this route in a real browser, and the two fixes are unit-observable.Review
One general review agent inspected the diff. Its substantive findings were fixed in the follow-up commit: the first battery never mutated the
{ replace: true }flags, so nothing guarded the back-button-trap half of the redirect fix — a navigation-type probe now pinsREPLACEon all three redirects andPUSHon ordinary pill navigation. It also caught a test that could not fail, a duplicated sidebar test, and a keyboard test that reused a DOM node captured before its own route change.Validation
pnpm run check,pnpm run format(clean on a warm tree),pnpm run finalize:web,pnpm run test(server 2733 passed / 9 skipped, web 875, extension 60, scripts 4),pnpm run test:e2e(180 passed / 12 skipped),pnpm run test:e2e:live(11 passed, 20.8s, zero leakede2e-*tmux sessions).CI scan of the last 50 runs: 49 success. The one failure is the Release workflow's own
origin/main advanced after smoke testsguard firing during a merge race — not a test failure. No CI-only flakes found; the flakes list stays empty.🤖 Generated with Claude Code