v5.15.0 - DashClaw Pulse: the always-on-top ambient posture widget
[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
/widgetpage: 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!Nhead, 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 inqueriesDegradedand 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 thewidget-pulseunit 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 rendersunknown, neverlive, 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.tspreviously emitted the keepalive as an SSE comment, invisible toEventSource; it is now a namedheartbeatevent anduseRealtimeexposeslastEventAt/connection state β without this, "no message in 90s = stale" would false-fire on every quiet fleet. - Demo fixtures for
/widgetand/api/widget/pulse, so the marketing demo renders the owed posture honestly (presence staysunknownβ 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.mdamendment 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