Skip to content

v5.15.0 - DashClaw Pulse: the always-on-top ambient posture widget

Choose a tag to compare

@ucsandman ucsandman released this 10 Aug 03:08
· 197 commits to main since this release

[5.15.0] β€” 2026-08-09

DashClaw Pulse: an always-on-top ambient posture window (/widget) for the operator who is deliberately NOT watching. One glyph answers "is any of this mine?" from across the room β€” a dim dash when nothing is owed, the pending-approval count when something is. Design chosen by a 9-agent tournament (5 divergent concepts, 3-lens judge panel); full spec and precedence rules in docs/decisions/2026-08-09-widget-pulse.md. Not a revival of the culled status-widget PWA: no PWA manifest, no prefs, no stat tiles, no action log, read-only slice 1.

Added

  • /widget page: frameless dark field sized for a 300–400px always-on-top browser window. The window perimeter is the alert channel (luminance + shape, never hue alone); approval always outranks signals (a red signal demotes to a 2px left rail with an !N head, never silently dropped); activity moves only a 3px baseline strip; zero chroma at rest. Reveal layer on hover/focus lists the pending rows (type, agent, risk, age β€” no goals, no output, no secrets). The whole field is one button β†’ /approvals.
  • GET /api/widget/pulse: the snapshot behind the surface β€” whitelisted fields only, composed from existing repositories (no new ingestion, no direct SQL). Each sub-query is independently failure-wrapped: a failed query lands in queriesDegraded and renders as the DEGRADED posture, never as a zero (honesty rule H5).
  • Honesty rules as invariants, not polish: calm requires positive heartbeat evidence; no present-tense claim survives 90s of silence (graded FRESH β†’ DRIFTING β†’ STALE off the SSE heartbeat); reconnect refetches before repainting so a stale calm never flashes; a dwell budget scaled by risk (5m/20m/60m) escalates an overdue approval to the breathing error ring β€” the product's only loop, with a mandatory static double-ring tell under prefers-reduced-motion. Pinned by the widget-pulse unit suites (posture Γ— freshness Γ— boundary fixture matrix).
  • Desktop-presence reader (app/lib/widget/presence.ts): best-effort read of the machine-local OpenClaw presence store (OPENCLAW_DESKTOP_PRESENCE_DIR); absence of a verdict renders unknown, never live, and presence never drives the ring.
  • Pulse button on /approvals: opens the widget as a small popup window β€” the surface's one discovery path (deliberately no nav entry).
  • SSE heartbeat is now a named event: app/api/stream/route.ts previously emitted the keepalive as an SSE comment, invisible to EventSource; it is now a named heartbeat event and useRealtime exposes lastEventAt/connection state β€” without this, "no message in 90s = stale" would false-fire on every quiet fleet.
  • Demo fixtures for /widget and /api/widget/pulse, so the marketing demo renders the owed posture honestly (presence stays unknown β€” the demo host has no presence store).

Notes

  • Surface-budget ceilings amended in the same ship: active API routes 130 β†’ 131, app pages 51 β†’ 52 (THESIS.md amendment log + contracts/surface-budget.json).
  • No Node/Python SDK source change. The tag-triggered release workflow republishes the unchanged SDK content at 5.15.0 so registries stay aligned.

Maintained and released by DashClaw's AI maintainer (Claude), per MAINTAINER.md.
Full design record: docs/decisions/2026-08-09-widget-pulse.md