Files
Panama/docs/superpowers/specs/2026-08-17-contextual-signal-glass-design.md
T

3.8 KiB

Contextual Signal Glass Design

Purpose

Extend the existing focus-session Signal Glass into a quiet, shell-wide status surface. It should acknowledge meaningful desktop transitions without becoming a second notification system or a stream of routine telemetry.

Experience

  • Only curated events appear: capture completion, recording transitions, audio-output changes, Bluetooth/KDE Connect connection changes, Night Light changes, focus completion, and privacy-sensitive activity.
  • Volume adjustments, ordinary clipboard changes, Wi-Fi signal fluctuations, and background health polling do not appear.
  • Transient events use one compact glass capsule below the clock for roughly three seconds. A newer event replaces an equivalent event, while higher-priority privacy and recording events preempt lower-priority device events.
  • Events are not retained as history. Actionable events may be clicked; every event may be dismissed.
  • Focus controls remain the richer, persistent Signal Glass state. A transient event may briefly occupy the surface, after which the focus controls return.
  • Microphone, camera, screen sharing, and recording show a brief start/stop event. While active, a tiny semantic glyph remains in the right status area. Clicking it opens a compact activity detail card with the responsible activity and a safe stop action when Panama owns that activity.

Architecture

StatusEvents.qml is the broker. Producers call publish(event), using stable keys, semantic priority, duration, and an optional action identifier. The broker deduplicates, bounds its queue, expires transient entries, and routes actions without allowing render components to spawn commands.

PrivacyState.qml derives persistent activity from Panama capture state and PipeWire metadata. It publishes transition events through the broker but exposes current booleans independently so the bar never depends on transient UI state.

SignalGlass.qml becomes the only per-screen host. It chooses the current transient event first, then the existing focus-session card. EventCard.qml and the extracted FocusCard.qml remain presentation-only.

ActivityIndicator.qml renders persistent privacy state beside the existing focus indicator. ActivityPanel.qml explains active states and only offers Stop when Panama owns the recording operation.

Event Policy

  • critical: recording, screen sharing, camera, or microphone transitions; shown immediately.
  • important: screenshots saved, focus completion, and failed user-initiated shell actions.
  • ambient: output-device, Bluetooth, KDE Connect, and Night Light changes.
  • Equivalent keys replace instead of stacking. The pending queue is capped at four entries and discards the oldest lowest-priority entry first.
  • Initial service discovery never emits an event. Only transitions after initialization do.
  • Do Not Disturb suppresses ambient events but not privacy transitions or Panama-owned recording state.

Reliability and Performance

  • No visual element animates while idle.
  • PipeWire privacy discovery is event-triggered where available and falls back to a low-frequency bounded probe; only state transitions repaint UI.
  • Missing optional commands or malformed service data disable that producer and log one concise warning rather than creating a respawn loop.
  • A Quickshell reload reconstructs persistent privacy state but does not replay old transient events.

Verification

  • Contract tests exercise broker priority, replacement, dismissal, and DND filtering through IPC.
  • Capture tests prove screenshot and recording transitions emit the intended events.
  • Activity tests prove persistent glyph state is independent of capsule expiry.
  • QML lint/runtime logs must contain no new warnings, and visual captures must cover ambient, privacy, recording, focus-restoration, and detail-panel states.