record the third sweep: a navigation that goes nowhere
This commit is contained in:
@@ -4,9 +4,10 @@
|
|||||||
> Every finding H1–H5 and M1–M10 is done, void, or decided-and-recorded, and so is every Phase 4 line and
|
> Every finding H1–H5 and M1–M10 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
|
> 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<` /
|
> 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.
|
> `useState`), six navigations on the Invoices dashboard (`grep "onClick={() => navigate("`), and one
|
||||||
> The two greps are written into the cross-cutting section as the standing re-check. What remains, and
|
> navigation to a URL that **had no route at all** (`/dashboards/new`, dead since `927267e` — the third
|
||||||
> only this:
|
> 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)
|
> **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
|
> 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.
|
> 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.
|
> 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.
|
> 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.
|
**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
|
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`),
|
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.
|
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.
|
- [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
|
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.
|
every route, and with it on the rest a detail route would lose its tile.
|
||||||
|
|||||||
Reference in New Issue
Block a user