Wipe history & counters

Wipe persisted history as a server-side job that names its devices, survives reloads, and never freezes — and read every count as a live ledger with its freshness stated.

Wipe persisted history for exactly the devices you selected, watch the wipe as a server-side job that survives reloads and other tabs, and read every count on the dashboard as a live-maintained ledger with its freshness stated next to it.

What a wipe targets

The feed toolbar's Clear action (tooltip Clear the feed (wipes persisted entries)) permanently deletes the persisted entries that match the current view:

  • the effective device scope — the devices selected in the Devices panel; with nothing selected, every device you can see;
  • the tab's narrowing, if any — selected hosts, method / status-class chips, the search box, and the resent-vs-original filter;
  • no time window — a wipe removes the whole matching history, not just the loaded rows.

Live rows still streaming in after the wipe started are not part of it.

The confirm names every device

The confirm dialog (Wipe persisted history?) lists the exact devices the wipe will touch — their names and the exact count (a long selection shows the first 12 names and "…and N more"), or across ALL N devices for a fleet-wide wipe. Read that list: it is the set the server will delete, spelled out per device.

The dialog refuses to start when the effective scope holds a device the Devices panel is not currently rendering — one hidden by the panel's name search, its filter, or a collapsed group:

Wipe refused — 3 of the 8 targeted devices are hidden by the device search or filter. Make every targeted device visible in the Devices panel, then retry.

Range selection (Shift-click) in the Devices panel follows the rendered order — search, sort, pins and groups included — so a range between two rows you can see never sweeps in devices you can't.

The wipe is a server job

Pressing Wipe creates a wipe job on the server. The job row — device set, narrowing predicate, total, deleted so far, status, last heartbeat — is the single source of truth; every surface renders it:

queuedrunningdonecancelledfailedstalledstartall rows goneCancelerrorno heartbeat 90 sre-driventerminal states stay in thebanner until you Dismiss
  • An audit record is written before the first delete — who started the wipe, the named devices and their exact count, the narrowing predicate, and the total — and again when the job finishes or is cancelled, with the rows actually deleted.
  • The total is the ledger, not a guess. The job's total comes from the live counters ledger below: exact for a wipe scoped by device (and host), an upper bound — shown as ≤ N — when the predicate narrows further (method, status class, search, resent-only). Progress is therefore a real percentage that reaches 100 only when the rows are gone; it never sits at "96 %" of a moving estimate.
  • Batches shrink on load, the job never dies on one slow step. A step that hits the database's statement timeout halves the batch (down to a floor of 250 rows) and continues — under concurrent load the wipe slows down instead of failing.
  • Cancel while the job is queued or running stops it at the next step boundary; what was deleted stays deleted, the banner reports the count.

The banner is a view of the job

The wipe banner above the feed renders from the job row, pushed over Realtime, so it is the same on every screen that overlaps the wiped devices: navigate away and back, reload, open another tab, or look from another account in the workspace — the banner is there with the current progress. Its states:

BannerMeaning
Wipe queued — for "Staging"the job exists; the first step hasn't run yet
Wiping history — across 5 devices · progress barsteps are committing; the heartbeat is fresh
Wipe stalled — no progress from the server for 90s. It resumes automatically; you can also cancel.the driver behind the job died (its tab closed, a route crashed) — the server re-drives stalled jobs within a minute, so this is a wait, not a failure. It is never shown as a frozen percentage.
Wiped 858,261 entries — across 5 devicesdone — the counters have already been corrected
Wipe cancelled — 120,000 entries removed before the stop (…) / Wipe failed — … before the error (…)terminal; Dismiss clears the banner

The Wipe action is disabled while an active job overlaps the current scope.

Counters are a live ledger

Every count the dashboard shows for captured entries — the per-device counts in the Devices panel, the header's X of N, the totals on /stats — reads one per-device / per-host ledger that is maintained in the same transaction as the write that changes it: every capture adds to it and every delete, wipe, retention sweep or partition drop subtracts from it. Changes are pushed as COUNTS_DELTA broadcasts on the workspace and device topics, so the panel, header and badges move the moment a wipe step commits — no hourly lag, no polling.

An hourly reconciler recounts a bounded scope, diffs it against the ledger, corrects any drift and records that it ran; it is a check, never the source.

The freshness affordance

Next to the header count sits a small freshness marker:

MarkerMeaning
livea Realtime subscription is attached — counts move with every capture and every wipe as it commits
as of 09:07live updates are paused (not subscribed); the counts are exact as of that time
counts pendingthe counter seed has not landed yet

Its tooltip also reports the drift check — passed 08:00 — or flags it as reported when more than 2 hours have passed without a pass.

What you never see

  • A total the dashboard did not obtain. The header shows instead of a number before the counter seed lands, after it fails, and while a narrowed (entries_filtered_count) total is still pending or failed. It never falls back to a broader number.
  • A count zeroed by the client. The dashboard renders what the server says; it does not infer "0" from an empty page.
  • An empty list standing in for an error. A device-, host- or search-scoped history read that fails or times out renders Couldn't load the request history with a Retry button — live rows keep streaming in below it — never No entries match the current filters with a zero count.

The same job over MCP and REST

The dashboard, the MCP server and REST drive one seam, so a wipe started anywhere shows up everywhere:

SurfaceWhat
MCP wipe_entriesStart a wipe job for one device, a device_uuids[] set, or every device with all: true — always spelled out per device — with optional hosts / methods / status_class / search_q / origin narrowing (the feed's own predicate). Waits up to ~100 s for completion; wait: false returns the queued job immediately. Requires confirm: true.
MCP list_wipe_jobsThe workspace's wipe jobs: exact device set, predicate, total (+ whether it is exact), deleted, percent, status, heartbeat and a derived stalled flag. Filter by job_id, status (or active), device_uuid.
MCP get_entry_counts_freshnessThe one freshness surface for every counter — see Stats & status → Counter freshness.
MCP get_entry_countThe per-scope count, from the same ledger.
RESTThe entries_wipe_jobs table is readable with devices:view (or as the job's requester); the jobs are also pushed as WIPE_JOB broadcasts on ws:<workspace_id>.

Removing a device from the dashboard deletes its history through the same job, so a device removal shows the same truthful progress.

Related: The feed for scoping and the X of N header · Realtime channels for COUNTS_DELTA / WIPE_JOB · MCP tool reference for the entries tools.

Ask your mate