Files
brain-of-reese/.agent/user_stories/nav-consistency.md
T

3.0 KiB

Story: One Navbar on Every Page

Phase: 34_consistent_navbar · E2E: tests/e2e/test_nav_consistency.py

Narrative

As any user (admin or anonymous), I move between the Chat, Sources, Document viewer, Global Tuning, and Sign in pages. Today the header bar is only similar between pages: the document viewer replaces it with a back + title bar (every nav button vanishes), the login page misses the Tuning link, and the functional controls are page-scoped — the Tuning steering toggle lives on chat only, the Sync sources button on Sources only — so buttons pop in and out as I switch tabs. I want ONE identical bar on every page.

  • Given any of the app's five pages
  • When I look at the header
  • Then I see the same controls in the same order — brand, nav [Chat, Sources, Tuning], Tuning toggle, Sync sources (admin), New chat, and exactly one of Sign in / Sign out — with none missing because of which page I happen to be on.

Acceptance criteria

  1. frontend/assets/header.js is the single owner of the functional header controls: the steering toggle + panel logic (moved from app.js, exported refreshSteering()), the Sync button state machine (moved from sources.js, dispatching bor:sync-status), one New chat binding (chat page: bor:new-chat event; other pages: clear + navigate), and the sign-in ?next= rewrite to the current page. No control logic remains in the page scripts.
  2. All five pages (index.html, sources.html, document.html, tuning.html, login.html) ship the identical header markup; the #steering-panel section exists on every page (chat: after #kb-banner as today; other pages: first child of <main>).
  3. The document viewer keeps its back link + title in a second titlebar row below the standard bar (phase 13 back-target behavior unchanged); the pinned 64px / 58px height contract applies to the standard row on every page.
  4. The locked A10 UI revision is preserved: admin-only controls (Sources / Tuning nav links, Sync button) ship hidden and are revealed only for a signed-in admin — for the admin every button is active on every page; anonymous visitors get the reduced bar, identically on every page (owner confirmation 2026-08-26).
  5. The chat page's per-bubble Tune button + inline form (phases 15/27) and the Sources page's sync result line + error banner (phase 32) keep working exactly as before.
  6. tests/e2e/test_nav_consistency.py green in isolation; test_header_consistency.py / test_shared_header.py updated to the new viewer contract; regressions green; app/ coverage >90% (frontend-only phase — unchanged); ruff + pyright clean; one --no-gpg-sign commit.

Playwright Mapping Rule

tests/e2e/test_nav_consistency.py — one story, one file, run in isolation. It asserts, per role (admin, anonymous), that the visible header control inventory is identical on all five pages, and that the viewer's back link + titlebar row survive the change.