phase: 26_ups_event_split
**Phase 26 `ups_event_split` — final verification pass (all 3 tasks already complete; nothing missing from `complete/`).**
Verified
- `page-ups.js`: `POWER_EVENT_KINDS = {status,test,action}` split, unconditional `refreshEvents()`, no `state.events`/toggle-fetch, shared `eventRow`, `#ups-errors-card.hidden = errors.length === 0`; `ups.html` error card above the disclosure, `hidden`, outside every `<details>`. Kind set cross-checked against the real writers (`collectors.py:393/409`, `api.py:1043/1058`, `poller.py:127/157/164/190`) — classification is correct.
- Re-ran the phase's browser pass live: `node data/logs/26-task03-verify.cjs` → **31 checks, 0 skipped, ALL PASS** (`data/logs/26-final-verify.out`) — poll-failure rows readable with the disclosure shut, card hidden on a power-only feed and appearing on the first `unreachable`, lists paging independently, 360 px clean.
Tests / lint (all green)
- `uv run pytest` → **1545 passed, 15 skipped**, exit 0 · `bash .agents/validate.sh` → exit 0, coverage **98.94%** (floor 94%) · `uv run ruff check src tests agent` clean · `uv run pyright` 0 errors · `node --check` clean · `uv run pytest -m live --live` (with `.env.dev`) → **11 passed**, dev server reads all 9 sources `ok`.
Completion criteria: poll-failure visible + power collapsed ✅ (pinned + browser); hidden-when-empty card, one `/api/events?source=ups` fetch, shared pager ✅; stale-last-good via the empty `catch` pin ✅; pytest/coverage/ruff/pyright ✅; `validate.sh` ✅; no behaviour change to prior work — `dash.css`/`app.js` untouched, disclosure CSS / pager / row-shape pins pass unchanged ✅.
Docs
- Fixed (pre-existing + this phase's drift): AGENTS.md "one helper with four call sites" → **five over four pages** and the `row(event)` sentence (phase 26 added a second `/ups` call site); invariant 5's `web/static/charts.js` → `src/dashboards/web/static/charts.js`; recorded the completion-pass transcript. README: "one helper renders every feed" now notes five lists. Full sweep otherwise consistent — all 38 env vars match `config.py` exactly, all served routes/scripts/contracts referenced exist, suite/coverage/live counts and marker splits verified.
Deviations: `fastapi 0.153.0 → 0.159.1` advisory left alone (validate.sh declares it advisory-not-a-gate; this phase touched no dependencies, matching prior phases' precedent). Next phase: **`27_mobile_tables_and_audit`**.
This commit is contained in:
@@ -892,14 +892,22 @@ certs.py ─ root CA + client cert, minted once at startup (unreadable row → n
|
||||
The four event feeds (`/system`, `/disks`, `/llm`, `/ups`) are a **paged window** over the `event`
|
||||
table rather than a printout of it: the list is a bounded box that scrolls, 50 events to a
|
||||
page, with `1–50 of 200` between `‹ prev` and `next ›` (disabled at the ends) underneath.
|
||||
One helper, `Dash.eventsPager()`, renders every feed and each keeps its own row markup; the fetch
|
||||
One helper, `Dash.eventsPager()`, renders every feed — five lists today, because `/ups` splits
|
||||
its one fetch in two — and each keeps its own row markup; the fetch
|
||||
asks `/api/events` for 200 so there is a page 2 to reach, and the endpoint itself is
|
||||
unchanged. Reading page 3 survives a poll; a refresh that brings new events goes back to
|
||||
page 1, because page 3 of a list that just changed is not the history you were reading.
|
||||
The `/ups` feed is also **expandable**: its card is a `Power events` summary line, closed until
|
||||
you open it, and the list inside is the same bounded, paged window. Closed, it is not fetched
|
||||
at all; the first expand fetches once, and re-opening inside one poll interval redraws what is
|
||||
already there instead of asking again.
|
||||
you open it, and the list inside is the same bounded, paged window. What sits behind that
|
||||
summary is only the *power* half of the feed — `status` transitions (the power loss and its
|
||||
return), self-test results, and the commands you sent — because the rest of it is connection
|
||||
trouble (`NUT server NutError: cannot reach upsd …` and its recovery line), which is not
|
||||
history to tuck away. That error half is its own **Connection & errors** card above the
|
||||
summary — the same bounded, paged window, the same row shape — hidden while it has nothing to
|
||||
say and appearing with its first unreachable/reachable line, so a poll failure is readable
|
||||
without opening anything. That is also why the feed is fetched on every poll rather than only
|
||||
while the summary is open: half of it is always on screen, and the two lists page
|
||||
independently of each other.
|
||||
|
||||
## Testing
|
||||
|
||||
|
||||
Reference in New Issue
Block a user