docs(web-ui/shape): add routes header, trim historical framing

This commit is contained in:
iris 2026-08-15 11:43:50 +02:00 committed by mara
commit 721a99ed64

View file

@ -3,6 +3,8 @@
> Part of [Web UI](../web-ui.md). See also: > Part of [Web UI](../web-ui.md). See also:
> [Dashboard layout](dashboard.md) · [Per-agent page](agent.md) > [Dashboard layout](dashboard.md) · [Per-agent page](agent.md)
## Shared routes
- `GET /``index.html` from the bundled frontend dist (see - `GET /``index.html` from the bundled frontend dist (see
`frontend/`). Both binaries' routers declare their dynamic `frontend/`). Both binaries' routers declare their dynamic
endpoints first and then `fallback_service(ServeDir::new(...))` endpoints first and then `fallback_service(ServeDir::new(...))`
@ -19,8 +21,8 @@
`dashboard.css` / `flow.css` / `logs.css`); `common.css` inlines `dashboard.css` / `flow.css` / `logs.css`); `common.css` inlines
`base.css` + `terminal.css` via esbuild's `@import` resolution. `base.css` + `terminal.css` via esbuild's `@import` resolution.
`terminal.js` exports `{ create, linkify }` as ES module `terminal.js` exports `{ create, linkify }` as ES module
members (no more `window.HiveTerminal` global outside the members; a back-compat shim in the IIFE bodies still exposes
back-compat shim the IIFE bodies still use). The dashboard's a `window.HiveTerminal` global for callers that need it. The dashboard's
`#msgflow` and the per-agent `#live` log are both backed by `#msgflow` and the per-agent `#live` log are both backed by
this terminal — sticky-bottom auto-scroll, "↓ N new" pill, this terminal — sticky-bottom auto-scroll, "↓ N new" pill,
history backfill, SSE plumbing all live there. Each page history backfill, SSE plumbing all live there. Each page
@ -209,13 +211,11 @@ soon as they blur.
**Atomic section repaint:** every managed-section renderer goes **Atomic section repaint:** every managed-section renderer goes
through `paintAtomic(liveRoot, build)`: the builder appends into through `paintAtomic(liveRoot, build)`: the builder appends into
a fresh `DocumentFragment` (off-DOM) and the commit is one a fresh `DocumentFragment` (off-DOM) and the commit is one
`replaceChildren` call. The naive `root.innerHTML = ''; root.append(...)` `replaceChildren` call, so the intermediate empty state is never
shape was visibly flashing empty on every poll cycle — on async visible — clearing and re-appending directly into the live root can
paths the await yield gave the browser a paint opportunity between leave it empty for a paint (on async builders) or a whole frame (on
the clear and the re-append, and on complex builds (many `el()` large synchronous ones), which reads as a visible flash on every
allocations) layout could escape the per-task budget even on the poll cycle. Builders receive the fragment as their
synchronous path. The fragment approach keeps the intermediate
empty state invisible. Builders receive the fragment as their
`root`, so existing renderer code carries over unchanged; early `root`, so existing renderer code carries over unchanged; early
returns inside the builder still commit whatever was appended returns inside the builder still commit whatever was appended
before they returned. before they returned.