phase: 88_mobile_chat_hamburger_boot
All completion criteria verified green. Final state confirmed: phase stays in `todo/` per A4 (owner device gate), task files in `complete/`, no `app/` changes, no commits made (harness commits). ## Phase 88 — final verification pass report **Verified (all 6 tasks already complete):** `touch-action: manipulation` on mobile `#nav-toggle`; `#view-chat.chat-booted` double-rAF sticky handover (CSS gate + app.js boot IIFE); `body.nav-menu-open` marker in `setNavMenu` + ≤640px `visibility: hidden` rule; router boot contract (`wasMounted && !opts.boot` + `boot: true`); new unit module (10 pins) + 4-test real-touch E2E story. **Test / lint / coverage:** - `uv run pytest --cov=app --cov-report=term-missing` → 1741 passed, **99%** on `app/` (>90% ✓) - `tests/e2e/test_mobile_chat_hamburger_boot.py` 4/4, `test_mobile_hamburger_nav.py` 8/8, `test_pinned_composer.py` 4/4, `test_smoke.py` 3/3 — each in isolation, `--no-cov` ✓ - `uv run ruff check .` clean; `uv run pyright` 0 errors ✓ **Completion criteria:** (1) 360px cold-boot touch-action + sticky handover + tap-opens-menu-with-cluster-hidden (E2E 1–2) ✓; (2) boot fires no `bor:view-refresh`, re-show fires exactly one, `/sources.html` regression (E2E 3–4) ✓; (3) full gate green ✓; (4) diff limited to 4 assets + 2 new tests + phase files, 0 changes in `app/` ✓; (5) commit deferred to harness per executor rules ✓; (6) owner device re-verification **pending** (A4 — gates the archive; no Owner report recorded yet). **Deviations (both documented in-tree):** unit pins updated in `test_frontend_router.py`/`test_hamburger_nav.py` (their exact-text pins collided with the mandated new guard/marker text — without them the suite goes red); `boot: true` count pinned at 1 not 2 (codebase has one boot call site, no `history.state` branch — verified against git HEAD). **Next pending phase:** none in `todo/` — pipeline awaits the owner's on-device report (archive, or `?dbg=nav` instrumentation follow-up if the menu is still dead).
This commit is contained in:
@@ -169,7 +169,7 @@ let current = null; // the visible view name (null until boot resolves)
|
||||
head/nav state. `userInitiated` marks navbar-click / popstate
|
||||
switches: only those focus the target view (its tabindex="-1") and
|
||||
land the viewport at the top — a boot switch never steals focus. */
|
||||
async function switchTo(name, { userInitiated }) {
|
||||
async function switchTo(name, opts = {}) {
|
||||
const root = viewEls[name];
|
||||
if (!root) return;
|
||||
|
||||
@@ -222,7 +222,14 @@ async function switchTo(name, { userInitiated }) {
|
||||
a first show (the mount's own load is the first fetch) and boot
|
||||
never dispatch. A listening view re-runs its load; the chat view
|
||||
never listens (phase-76 stream survival). */
|
||||
if (wasMounted) {
|
||||
/* Phase 88: the BOOT show is the view's first display — the phase-77
|
||||
contract says the first show (mount) and boot never fire the
|
||||
refresh. `mounted.chat` starts true (app.js pre-mounts the chat),
|
||||
so the cold boot's switchTo("chat") was hitting the wasMounted
|
||||
branch; the explicit boot flag (the boot call site below) makes
|
||||
the contract hold. Every LATER show — re-click on the active
|
||||
link, popstate, any navigation — still fires exactly as before. */
|
||||
if (wasMounted && !opts.boot) {
|
||||
root.dispatchEvent(new CustomEvent("bor:view-refresh"));
|
||||
}
|
||||
|
||||
@@ -230,7 +237,7 @@ async function switchTo(name, { userInitiated }) {
|
||||
click / popstate) — never on initial boot (no focus steal on
|
||||
load). The top landing mirrors what the old per-view page loads
|
||||
did (user intent, not a streaming-frame autoscroll). */
|
||||
if (userInitiated) {
|
||||
if (opts.userInitiated) {
|
||||
window.scrollTo(0, 0);
|
||||
root.focus({ preventScroll: true });
|
||||
}
|
||||
@@ -279,4 +286,4 @@ if (nav) {
|
||||
falls back to chat (the shell's default view). userInitiated:false
|
||||
— boot never focuses (no focus steal on load). */
|
||||
const bootName = VIEW[window.location.pathname] ?? "chat";
|
||||
switchTo(bootName, { userInitiated: false });
|
||||
switchTo(bootName, { userInitiated: false, boot: true });
|
||||
|
||||
Reference in New Issue
Block a user