diff --git a/docs/navigation-audit.md b/docs/navigation-audit.md index 5334b86b..26fd67e1 100644 --- a/docs/navigation-audit.md +++ b/docs/navigation-audit.md @@ -2,9 +2,11 @@ > **Status, 2026-08-07. Phases 1–4 and the cross-cutting section are closed except the two chat items.** > 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. Two selections that the audit never listed were found afterwards by sweeping -> for `useGlobal<` / `useState` rather than by reading the table — the email folder and the Soulseek -> room/peer rails — and are done too. What remains, and only this: +> 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: > **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. @@ -280,6 +282,16 @@ publishers means changing the chat panel, which is another agent's, so it is wri Sweep to re-check this later: `grep -rn "usePanelChannel\|useGlobal<" src/workspaces/officerdev/src src/apps/officer-web`. Everything it returns today is a registry, a refresh bus, a form draft, a connection state or a preference — no selections. + + **A second sweep is needed, because the first one cannot see the commonest opaque click.** A + selection held in a channel shows up in that grep; a selection that is *only* an `onClick` closure + does not, because there is no state to grep for. The one that finds those is + `grep -rn "onClick={() => navigate(" src/apps/officer-web src/workspaces/officerdev/src`. It + returned four sites after everything above was closed — all four in + `apps/Invoices/DashboardView.tsx`, plus two more row handlers in the same file that the grep misses + 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. - [x] Adopt `` (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.