record the third sweep: a navigation that goes nowhere

This commit is contained in:
2026-08-07 14:04:14 +00:00
parent 19ba106265
commit 15a960897f
+29 -4
View File
@@ -4,9 +4,10 @@
> Every finding H1H5 and M1M10 is done, void, or decided-and-recorded, and so is every Phase 4 line and
> every cross-cutting line. **More sites were found by sweeping than by reading the table**, all after the
> listed rows were closed: the email folder and the Soulseek room/peer rails (`grep useGlobal<` /
> `useState`), and six navigations on the Invoices dashboard (`grep "onClick={() => navigate("`). All done.
> The two greps are written into the cross-cutting section as the standing re-check. What remains, and
> only this:
> `useState`), six navigations on the Invoices dashboard (`grep "onClick={() => navigate("`), and one
> navigation to a URL that **had no route at all** (`/dashboards/new`, dead since `927267e` — the third
> grep). All done. The three greps are written into the cross-cutting section as the standing re-check.
> What remains, and only this:
> **H4** (chat detail reading `sessionId` from `useParams` instead of the `chat:selected-session` channel)
> and the **"New Chat"** button that depends on it. Both are inside the chat nucleus, which has its own
> owner — they are not stalled here, they are somebody else's to land.
@@ -18,7 +19,14 @@
> Two components — `Combobox` and `BackButton` — were deleted rather than fixed, having never been used.
>
> The rules in this file are current and authoritative; the findings table is a snapshot.
> **Nothing below has had a runtime click-through.** Every "Needs runtime test" note is still true.
>
> **The runtime click-through has now happened** (2026-08-07, Playwright driving the system Brave against
> the live server on 9010): 23 of 25 checks pass, and the two that did not are missing *data*, not
> regressions — the email account list and the Soulseek room list are both empty on this machine, so there
> is nothing to click. Two further "failures" were the *test* being wrong, not the app: the Dock renders a
> user-pinned subset of 13 of 25 items, so `/plans` is absent by config; and `[data-sonner-toaster]` sits on
> an inner `<ol>` that only exists while a toast is showing. **Suspect the instrument first.** Individual
> "Needs runtime test" notes below may still be true — the sweep covered the routing claims, not every row.
**Date:** 2026-07-30 · **Origin:** written as exploration before any of the routing work was done.
@@ -292,6 +300,23 @@ publishers means changing the chat panel, which is another agent's, so it is wri
because they route through an `onOpen` prop. Every one was pure navigation to an already-addressable
URL that the destination genuinely reads (`useInvoicesSection` parses both `status` and `selected`),
so they were anchors written as buttons and nothing more. Fixed in `ea1dae5`; the grep is clean now.
**A third sweep, because a navigation can be well-formed and still go nowhere.** Neither grep above
can tell you whether the URL a control navigates to *exists*. React Router does not error on an
unmatched path — it falls through to whatever `path="*"` or `<Navigate replace>` guard is nearest,
which is exactly what a correct app does for a bogus URL, so a dead destination is indistinguishable
from a working one until you click it. The file browser's **"Create Dashboard here"** navigated to
`/dashboards/new?name=…&cwd=…`; `new` matched `/dashboards/:id`, `DashboardScreen` found no dashboard
with that id, and its `<Navigate to="/dashboards" replace />` swallowed the URL *and both params*.
The menu item had been silently doing nothing since the workspaces→dashboards rename in `927267e`.
The sweep is to extract every literal target and check it against the route table:
`grep -rhoE "(navigate\(|to=)['\"]/[a-zA-Z0-9/_.-]*" src/apps/officer-web src/workspaces/officerdev/src | sed -E "s/.*['\"]//" | sort -u`
against `grep -rhoE 'path="[^"]*"' src/apps/officer-web/App.tsx`. Sixteen distinct literal targets
today; all sixteen resolve (`/auth/register` is the only miss and it is inside a commented-out block).
Fixed by `useNewDashboardDraft` — the intent is a hook call now, not a URL contract with one end
unimplemented. **The general lesson: cross-app intent that is not pure navigation should not be
encoded as a URL.** Creating a dashboard is five ordered state writes; expressing that as a link was
what made it silently breakable in the first place. See the status note §24 for the full write-up.
- [x] Adopt `<NavLink>` (real react-router) for all nav chrome so active state stops being JS-derived.
Done — `39125b5`. Note `end={item.to === '/'}`: without it NavLink treats `/` as an ancestor of
every route, and with it on the rest a detail route would lose its tile.