Skip to content

Make the Activity Log "Clear" button stick - #36

Open
the-real-orca wants to merge 1 commit into
SensorsIot:mainfrom
the-real-orca:fix/log-clear
Open

the-real-orca wants to merge 1 commit into
SensorsIot:mainfrom
the-real-orca:fix/log-clear

Conversation

@the-real-orca

@the-real-orca the-real-orca commented Sep 9, 2026 •

Copy link
Copy Markdown

Make the Activity Log "Clear" button stick

Base: SensorsIot/Embedded-AI-Harness main (b7bc87e) · Head: fix/log-clear
Diff: 2 files, +40 / −5 · one commit
Scope: UI only — no new endpoint, no change to /api/log or the server-side buffer


Why

Clicking Clear under the Activity Log emptied the panel for about a second, then the
next poll put every entry straight back. On a bench with a flapping USB device the button
looked broken, because it was.

lastLogTs is the delta-poll cursor, and an empty cursor means "send everything":

// portal.py:5467
const url = lastLogTs ? '/api/log?since=' + encodeURIComponent(lastLogTs) : '/api/log';

clearLog() reset exactly that cursor, so setInterval(fetchLog, 1500) re-fetched the
unfiltered deque — up to 200 entries — one and a half seconds later. A page reload had the
same effect for the same reason: the panel's contents are server state, and the client kept
no record of what the operator had dismissed.

What changed

The cursor now doubles as a watermark, so the filtering stays where it already was —
server-side, via ?since=.

Location Change
portal.py:5471–5486 LOG_WATERMARK_KEY + loadLogWatermark() / saveLogWatermark(), and lastLogTs initialised from storage rather than ''
portal.py:5536 clearLog() parks the cursor on the newest rendered entry and persists it, instead of resetting it
portal.py:5544 showLogHistory() — new, drops the watermark and redisplays everything the bench still holds
portal.py:5293–5296 Second button in .log-actions, plus title= on both spelling out that this is a display state and the bench keeps the entries
docs/Harness-FSD.md §10 Activity Log bullet, and revision row 10.1

Two details worth calling out:

  • localStorage is wrapped in try/catch. Private browsing and blocked site data make
    the accessor itself throw. The clear then holds for the current page load only, which still
    beats not clearing.
  • clearLog() fetches first if the cursor is still empty. A click landing before the
    first poll would otherwise persist an empty watermark, and the bug would be back for that
    one case.

Why not a server-side clear

DELETE /api/log would have been three lines and is the reading of "Clear" a first-time user
probably expects. I did not take it, because the deque is shared: TestbenchDriver.get_log()
reads it, the MCP surface exposes it as testbench_log, and a second browser tab has its own
idea of what it has already seen. A UI button that wipes the buffer deletes another client's
evidence, possibly mid-run — and the panel is at its most useful exactly when something has
just gone wrong.

Display state was the smaller claim, and it also fixes the reload case, which a server-side
wipe would not have addressed on its own. If you would rather have the bench-wide version, or
both, say so and I will follow up.

Verification

  • ruff check pi/portal.py clean · py_compile OK
  • UI script extracted from _UI_HTML and run through node --check — clean
  • Behaviour covered by a headless harness that loads the real UI script against a fake
    /api/log reproducing _handle_get_log's string comparison: initial load, Clear followed
    by repeated polls, a new event arriving after a Clear, reload with the watermark in place,
    Show History, and a Clear racing the first poll. All pass.
  • Deployed to a Pi 3 B running main and checked at the panel: Clear holds through the 1.5 s
    poll, a fresh USB event shows up on its own, F5 keeps the log empty, Show History brings the
    full buffer back with no duplicates.

No test was added to pytest/testbench_test.py. The change is entirely client-side, and
the suite is HTTP-against-the-portal with no JS or DOM harness.

`clearLog()` emptied the panel and then reset `lastLogTs` to ''. That
variable is the delta-poll cursor, and `/api/log` without `?since=`
returns the whole server-side ring buffer — so the 1.5 s poll put all
200 entries straight back. The button cleared the log for about a
second.

The cursor now doubles as a watermark. Clear parks it on the newest
rendered entry and persists that timestamp in `localStorage`
(`wt.log.hideBefore`); the page initialises the cursor from there, so
the filtering still happens server-side via `?since=` and the log stays
empty across a reload. A new "Show History" button drops the watermark
and redisplays everything the bench still holds. Where `localStorage` is
unavailable the hide holds for the current page load, which still beats
not hiding at all.

Deliberately not a server-side wipe.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@the-real-orca the-real-orca changed the title Keep the test report on the panel until it is explicitly cleared Make the Activity Log "Clear" button stick Sep 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant