docs: add operator inbox + flow agent filter + flow collapse + home page docs (follow-up to #1469 #1472 #1473 #1464)

This commit is contained in:
lexis 2026-06-06 14:11:44 +02:00
commit a5268560e1

View file

@ -100,6 +100,17 @@ operator, with amber pulsing border. Anatomy of each card:
- **◆ answ3red (N)** — collapsible `<details>` below the pending
list; shows the last 20 resolved questions with their answers.
**0PER4T0R 1NB0X** — messages agents have sent to `to="operator"` but
the operator hasn't read yet. Cold-loaded from `/api/operator-inbox` on
tab activation + page load; appended live from the broker `sent` stream
(deduped on row id). Each row shows sender · timestamp · body (with
file-path linkification). A `✓ mark all read` button on the right acks
all rows via `POST /api/agent/operator/mark-all-read` (reuses the existing
mark-read endpoint). Unread count folds into the Y3R C4LL tab pill so
messages are visible from any tab even while inactive. Backed by
`GET /api/operator-inbox``{ messages: [...] }` (id, from, body, at,
in_reply_to, file_refs).
## SYST3M tab
Passive / rare-interaction state.
@ -422,20 +433,45 @@ mark-all read). FL0W stays the pure event firehose.
**MESS4GE FL0W** — live broker tail wrapped in a `.terminal-wrap`.
Cold load backfills the last ~200 messages from `/dashboard/history`;
live frames arrive on `/dashboard/stream`. Each row is one broker
event — `sent` or `delivered` — with `from → to: body`. The row is
a `flex-wrap: wrap` container holding ts / arrow / from / sep / to
chips inline; the **body wraps to its own full-width line below**
the chips (`flex: 1 1 100%`) so the body always gets the full row
width down to the content edge — long timestamps + agent names
used to push the body ~30ch in and force awkward narrow-column
wraps. `min-width: 0` keeps `word-break: break-word` effective so
the body doesn't force the row wider than its container. Sticky-
bottom auto-scroll + "↓ N new" pill. Below the stream sits a
terminal-style compose box: `@name` picks the recipient (sticky via
localStorage; auto-complete from the live container list, Tab/Enter
to confirm; `@*` broadcasts). `POST /op-send` drops
`{from:"operator", to, body}` into the broker; the resulting SSE
frame re-renders the terminal row. Manager is addressed as `@root`.
event — `sent` or `delivered` — with `from → to: body`. When a `sent`
and `delivered` event for the same message arrive within 3 seconds
(immediate delivery to a live recipient), the row is upgraded in place
(arrow becomes green ✓, title reads "sent + delivered") instead of
rendering two near-identical lines — genuine delivery latency (recipient
was busy) still appears as a second row. Each row carries `data-from` /
`data-to` attributes; an **agent filter select in the FL0W header** narrows
the timeline to messages involving the chosen agent (matched on `from` OR
`to`), with non-matching rows hidden (`.flow-hidden` class). The selection
persists in localStorage across reloads; new rows pick up the active filter
at render time. The dropdown populates from the live container list and
stays current on add/remove; a saved selection survives even if that agent
isn't currently listed.
The row is a `flex-wrap: wrap` container holding ts / arrow / from / sep
/ to chips inline; the **body wraps to its own full-width line below** the
chips (`flex: 1 1 100%`) so the body always gets the full row width down to
the content edge — long timestamps + agent names used to push the body ~30ch
in and force awkward narrow-column wraps. `min-width: 0` keeps
`word-break: break-word` effective so the body doesn't force the row wider
than its container. Sticky-bottom auto-scroll + "↓ N new" pill. Below the
stream sits a terminal-style compose box: `@name` picks the recipient
(sticky via localStorage; auto-complete from the live container list,
Tab/Enter to confirm; `@*` broadcasts). `POST /op-send` drops
`{from:"operator", to, body}` into the broker; the resulting SSE frame
re-renders the terminal row. Manager is addressed as `@root`.
## Home page (`/`, `/home.html`)
The H0M3 hub is the primary landing page (served at `/` by default). A
responsive grid of link tiles — Dashboard, Flow, Logs, Matrix (when enabled)
— each pointing to their respective surfaces. The page is a pure portal with
no tab-bar or SSE subscriptions. Typography + colours inherit from the shared
theme (Catppuccin Mocha via `common.css` + `theme.css`). The Matrix tile is
hidden until `home.js` confirms `matrix_gui_enabled` (same gating as the
dashboard's M4TR1X tab); `home.js` also fills the swarm/hive identity line
at the top. Dashboard is now served at `/dashboard.html` (route swap completed
in #1464 step 2); the home page at `/` replaces the old dashboard root. All
dashboard sub-pages include a `← Home` back-link for navigation.
## L0GS page (`/logs.html`)
@ -799,6 +835,13 @@ that's a browser-level decision, not ours.
not yet delivered and sets `acked_at = now`. Returns
`{ "marked": N }`. Agent name validated against
`[a-z0-9_-]`, 1-63 chars; 400 on bad input.
- `GET /api/operator-inbox` — list unread messages addressed to
`to="operator"` (broker rows with `acked_at = NULL`). Cold-loaded
for the Y3R C4LL tab's ◆ 1NB0X ◆ section on page load + tab activation;
live updates fed from the broker `sent` stream. Returns
`{ messages: [{ id, from, body, at, in_reply_to, file_refs }, …] }`,
newest-first. Reuses `/api/agent/operator/mark-all-read` to ack (filters
are identical so every listed row is exactly what mark-read clears).
- `POST /op-send` (`to=<name>`, `body=<text>`) — drop an
operator-authored message into `<name>`'s inbox. `to=*` fans
out to every registered agent. Returns 200; the broker