Build the Panama Hyprland desktop

This commit is contained in:
Gabriel Brown
2026-08-17 10:32:55 -04:00
parent 67033f2a31
commit 5248883e4b
190 changed files with 18554 additions and 34 deletions
@@ -0,0 +1,94 @@
# Contextual Signal Glass Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Build a curated event broker, quiet shared Signal Glass host, and persistent privacy/activity indicators.
**Architecture:** Producers publish structured events to one bounded broker. A single per-screen host renders transient events ahead of existing focus controls, while persistent privacy state renders independently in the bar.
**Tech Stack:** Quickshell QML, QtQuick, Quickshell PipeWire/Bluetooth/Io APIs, Hyprland, Bash contract tests
**Spec:** `docs/superpowers/specs/2026-08-17-contextual-signal-glass-design.md`
## Global Constraints
- Initial discovery must not emit user-visible events.
- DND suppresses ambient events but never persistent privacy state.
- No idle visual animation or unbounded queue/process loop.
- Existing Focus behavior and tests must remain compatible.
---
### Task 1: Status event broker
**Files:**
- Create: `config/dot/quickshell/services/StatusEvents.qml`
- Modify: `config/dot/quickshell/shell.qml`
- Test: `tests/quickshell/status-events-contract.sh`
**Interfaces:**
- Produces: `publish(event: var)`, `dismiss(): void`, `invoke(): void`, `activeEvent`, `active`, and IPC diagnostics.
- [ ] Write an IPC contract that publishes ambient and critical fixtures, verifies replacement and DND filtering, and dismisses cleanly.
- [ ] Run the contract and verify it fails because the IPC target is absent.
- [ ] Implement broker normalization, priority, four-entry queue, stable-key replacement, expiry, and action routing.
- [ ] Wire a diagnostics-only IPC target and run the contract to green.
### Task 2: Shared Signal Glass host
**Files:**
- Create: `config/dot/quickshell/modules/signals/SignalGlass.qml`
- Create: `config/dot/quickshell/modules/signals/EventCard.qml`
- Create: `config/dot/quickshell/modules/signals/FocusCard.qml`
- Create: `config/dot/quickshell/modules/signals/qmldir`
- Modify: `config/dot/quickshell/shell.qml`
- Retire: `config/dot/quickshell/modules/focus/FocusCapsule.qml`
**Interfaces:**
- Consumes: `StatusEvents.activeEvent`, `FocusSession.active`, and `FocusSession.capsuleVisible`.
- Produces: one `qs-signal-glass` layer surface per monitor.
- [ ] Add a static source contract proving only one Signal Glass host is instantiated.
- [ ] Extract the existing focus presentation without changing its actions.
- [ ] Implement the compact event presentation and event-first/focus-second arbitration.
- [ ] Verify focus contracts and QML construction.
### Task 3: Event producers and persistent activity
**Files:**
- Create: `config/dot/quickshell/services/PrivacyState.qml`
- Create: `config/dot/quickshell/services/DeviceEvents.qml`
- Modify: `config/dot/quickshell/services/Capture.qml`
- Modify: `config/dot/quickshell/services/NightLight.qml`
- Modify: `config/dot/quickshell/services/FocusSession.qml`
- Test: `tests/quickshell/activity-state-contract.sh`
**Interfaces:**
- Produces: `PrivacyState.microphoneActive`, `cameraActive`, `screenSharingActive`, `recordingActive`, `activeKinds`, and transition events.
- [ ] Write contracts for capture events and independent persistent-state reporting.
- [ ] Instrument Panama-owned capture, Night Light, and focus completion transitions.
- [ ] Add initialized transition monitoring for output, Bluetooth, KDE Connect, and privacy activity.
- [ ] Run the contracts and verify missing optional integrations fail quietly.
### Task 4: Bar indicator and detail panel
**Files:**
- Create: `config/dot/quickshell/modules/bar/ActivityIndicator.qml`
- Create: `config/dot/quickshell/modules/bar/ActivityPanel.qml`
- Modify: `config/dot/quickshell/modules/bar/Bar.qml`
- Modify: `config/dot/quickshell/services/ShellState.qml`
**Interfaces:**
- Consumes: `PrivacyState` booleans and `Capture.stopRecording()`.
- [ ] Add the indicator beside Focus with semantic icon/color selection.
- [ ] Add a compact details popover and safe Stop action for Panama recording.
- [ ] Verify overlay exclusivity, click targets, and all active-state combinations.
### Task 5: System verification
- [ ] Run all Quickshell contract tests.
- [ ] Run QML/runtime diagnostics and inspect logs for warnings.
- [ ] Capture ambient, privacy, recording, and focus-restoration states.
- [ ] Restart the live Quickshell instance and repeat the smoke contract.
@@ -0,0 +1,82 @@
# Continuum Scratchpad and Window Actions Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Add address-scoped close and drag/drop workspace movement plus a global visual scratchpad shelf to Continuum.
**Architecture:** Window components emit intent; OverviewBody owns Hyprland dispatches. Workspace cards and the shelf are drop destinations, and the special scratch workspace remains separate from the positive-workspace filmstrip.
**Tech Stack:** Quickshell QML, QtQuick Drag APIs, Quickshell.Hyprland, Hyprland dispatchers, Bash contract tests
**Spec:** `docs/superpowers/specs/2026-08-17-continuum-scratchpad-design.md`
## Global Constraints
- Every close and move command must target one normalized window address.
- Existing click-to-focus, search, and focus-workspace integration must remain intact.
- `Super+X` and `Super+Shift+X` semantics remain unchanged.
- Drag feedback is event-driven and stops immediately after drop/cancel.
---
### Task 1: Address-scoped action boundary
**Files:**
- Modify: `config/dot/quickshell/modules/overview/OverviewBody.qml`
- Test: `tests/quickshell/overview-window-actions-contract.sh`
**Interfaces:**
- Produces: `addressOf(toplevel)`, `closeToplevel(toplevel)`, `moveToplevel(toplevel, workspaceName)`, and `restoreToplevel(toplevel)`.
- [ ] Write a static/live contract proving move and close operations include an exact disposable-window address.
- [ ] Run it and verify the missing IPC/action surface fails.
- [ ] Implement normalized address helpers and bounded post-dispatch refresh.
- [ ] Run the contract to green without touching non-disposable windows.
### Task 2: Draggable window chrome
**Files:**
- Modify: `config/dot/quickshell/modules/overview/WindowThumbnail.qml`
- Modify: `config/dot/quickshell/modules/overview/WorkspaceCard.qml`
**Interfaces:**
- Produces: activation, close, drag-start, and drag-finish signals carrying the toplevel.
- Consumes: workspace drop callback carrying toplevel and target workspace.
- [ ] Add a source contract for hover-only close chrome and drag payload identity.
- [ ] Implement restrained hover/drag states with activation suppression after drag.
- [ ] Make workspace cards highlight and accept the exact toplevel payload.
- [ ] Verify clicking still focuses and dropping leaves Continuum open.
### Task 3: Global scratchpad shelf
**Files:**
- Create: `config/dot/quickshell/modules/overview/ScratchpadShelf.qml`
- Modify: `config/dot/quickshell/modules/overview/OverviewBody.qml`
- Test: `tests/quickshell/scratchpad-shelf-contract.sh`
**Interfaces:**
- Consumes: Hyprland workspace named `special:scratch` and OverviewBody move/restore callbacks.
- Produces: always-available scratch drop target and populated live-card shelf.
- [ ] Write a contract confirming the global special workspace and existing keybindings.
- [ ] Implement the collapsed empty target and expanded populated shelf.
- [ ] Wire drop-to-hide, click-to-restore, and address-scoped close.
- [ ] Verify the selected positive workspace remains stable while hiding windows.
### Task 4: Keyboard navigation and visual refresh
**Files:**
- Modify: `config/dot/quickshell/modules/overview/Overview.qml`
- Modify: `config/dot/quickshell/modules/overview/OverviewBody.qml`
- [ ] Add workspace Left/Right, result navigation, Enter, Delete, and Escape handling.
- [ ] Refresh workspace/toplevel models and one-shot captures after successful actions.
- [ ] Verify keyboard and pointer flows do not double-activate.
### Task 5: System verification
- [ ] Run overview, focus, window-action, and scratchpad contracts.
- [ ] Use disposable windows to test move, hide, restore, and close end to end.
- [ ] Capture empty shelf, populated shelf, drop target, and close chrome states.
- [ ] Restart Quickshell and confirm the overview maps without warnings.
@@ -0,0 +1,115 @@
# Focus Glass and Continuum Overview Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Add a persistent focus-session workflow with a Signal Glass control capsule and replace the current workspace-card overview with the GNOME-like Continuum filmstrip.
**Architecture:** A singleton `FocusSession` service owns all timing and side effects, while focused QML modules render the capsule, bar indicator, Quick Settings entry point, and overview. `ShellState` carries only overlay selection and the requested overview workspace, keeping focus state independent from window state.
**Tech Stack:** Quickshell 0.3.0, Qt 6 QML, Quickshell Hyprland IPC, Quickshell Io `FileView`/`JsonAdapter`, Hyprland 0.56 Lua configuration
**Spec:** `docs/superpowers/specs/2026-08-17-focus-glass-continuum-design.md`
## Global Constraints
- Use the existing Tokyo Night Moon tokens and Prism edge; do not hardcode component colors.
- Use event-driven transitions only; no continuously repainting visual animations.
- Keep the current bar edge-to-edge and transparent.
- Preserve all existing overlay shortcuts and GNOME-derived workspace bindings.
- Add no package or background daemon.
- Persist only state transitions; do not write the remaining time every second.
---
### Task 1: Focus-session state machine
**Files:**
- Create: `config/dot/quickshell/services/FocusSession.qml`
- Modify: `config/dot/quickshell/config/Settings.qml`
- Test: temporary standalone Quickshell harness under `/tmp`
**Interfaces:**
- Consumes: `Notifs.doNotDisturb`, `Caffeine.enabled`, `Hyprland.focusedWorkspace`, `Hyprland.dispatch()`
- Produces: `active`, `paused`, `capsuleVisible`, `workspaceId`, `workspaceLabel`, `remainingSeconds`, `remainingText`, `start(minutes)`, `startDefault()`, `pauseOrResume()`, `dismiss()`, `reveal()`, `activateWorkspace()`, `end(completed)`
- [x] Add `focusDurationMinutes: 45` to `Settings.qml`.
- [x] Create a singleton with a wall-clock deadline and paused remaining duration.
- [x] Persist state atomically to `Quickshell.stateDir + "/focus-session.json"` with `FileView` and `JsonAdapter`.
- [x] Record and restore the pre-session DND and Caffeine values.
- [x] Resolve expiry on every one-second timer tick and immediately after state restoration.
- [x] Run executable contracts for active-to-ended state, pause stability, persisted restart restoration, and completion from an expired persisted deadline.
### Task 2: Signal Glass capsule and compact indicator
**Files:**
- Create: `config/dot/quickshell/modules/focus/FocusCapsule.qml`
- Create: `config/dot/quickshell/modules/focus/FocusIndicator.qml`
- Create: `config/dot/quickshell/modules/focus/FocusAction.qml`
- Modify: `config/dot/quickshell/modules/bar/Bar.qml`
- Modify: `config/dot/quickshell/shell.qml`
- Modify: `config/dot/hypr/rules.lua`
**Interfaces:**
- Consumes: Task 1's `FocusSession` public properties and functions
- Produces: a `qs-focus-capsule` layer surface and a clickable bar indicator
- [x] Build the compact indicator as a transparent-bar-native pill showing a focus glyph and tabular remaining time.
- [x] Build the capsule with a Prism glass surface, primary workspace target, explicit close control, and Pause/Resume, Workspace, and End actions.
- [x] Make the primary row activate the stored workspace and dismiss only the capsule.
- [x] Instantiate one capsule and add one indicator to the right-side bar row.
- [x] Add a focused Hyprland layer rule enabling blur, suppressing compositor animation, and excluding the capsule from screen sharing.
- [x] Reload Quickshell and verify dismiss/reopen and workspace activation through live state.
### Task 3: Discoverable start paths and IPC
**Files:**
- Modify: `config/dot/quickshell/modules/quicksettings/QuickSettingsPanel.qml`
- Modify: `config/dot/quickshell/shell.qml`
- Modify: `config/dot/hypr/keybinds.lua`
- Modify: `config/dot/hypr/README.md`
**Interfaces:**
- Consumes: Task 1's service and Task 2's capsule visibility
- Produces: Quick Settings Focus row, `focus` IPC target, `SUPER+SHIFT+F` binding
- [x] Add a full-width Quick Settings row that starts the default session while idle and shows the capsule while active.
- [x] Register typed IPC functions `start()`, `reveal()`, `pause()`, `workspace()`, `overview()`, and `end()`.
- [x] Bind `SUPER+SHIFT+F` to `qs ipc call focus reveal`, where `reveal()` starts a default session if none exists.
- [x] Verify every function using `qs ipc call focus ...` and verify the Hyprland config.
### Task 4: Continuum workspace filmstrip
**Files:**
- Modify: `config/dot/quickshell/services/ShellState.qml`
- Modify: `config/dot/quickshell/modules/overview/Overview.qml`
- Modify: `config/dot/quickshell/modules/overview/OverviewBody.qml`
- Modify: `config/dot/quickshell/modules/overview/WorkspaceCard.qml`
**Interfaces:**
- Consumes: `FocusSession.workspaceId`, `ShellState.overviewWorkspaceId`, Hyprland workspace and toplevel models
- Produces: `ShellState.openOverview(workspaceId)`, filmstrip selection, large workspace preview, cross-workspace window search
- [x] Add requested-overview-workspace state without coupling `ShellState` to the focus service.
- [x] Replace the centred equal-card row with a top filmstrip and a large selected-workspace preview.
- [x] Keep the trailing dynamic-workspace card and one-shot thumbnail capture behavior.
- [x] Add wheel navigation over the strip and keep the overview mapped while switching workspaces.
- [x] Add a keyboard-focused search field and filtered cross-workspace window results.
- [x] Mark the focus-session workspace subtly in both filmstrip and preview.
- [x] Verify workspace selection, window activation, scrolling, new workspace creation, search, Escape, and background dismissal.
### Task 5: Integration and visual verification
**Files:**
- Modify: `config/dot/hypr/DESKTOP-PARITY.md`
- Modify: `README.md`
**Interfaces:**
- Consumes: all previous tasks
- Produces: documented, live daily-driver feature
- [x] Run `Hyprland --verify-config` and reload the Lua configuration.
- [x] Reload the live Quickshell instance and inspect `qs log` for QML errors and warnings.
- [x] Exercise a short live focus session through start, pause, resume, dismiss, reopen, workspace overview, and end.
- [x] Capture screenshots of capsule open, indicator-only, Continuum default, and Continuum search states.
- [x] Update Panama's feature documentation and keybinding table with the verified behavior.
- [x] Inspect the exact Panama diff and ensure unrelated pre-existing changes remain untouched.
@@ -0,0 +1,128 @@
# Panama Settings Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Build the approved Luminous System Settings control center and map it to `Super+I` while preserving GNOME Settings as a launcher-accessible fallback.
**Architecture:** A persisted `DesktopPreferences` singleton owns user choices, `SystemSettings` owns allow-listed system reads and writes, and a normal tiled Settings window renders focused pages over those boundaries. Existing shell consumers continue through `Settings.qml`, while `ShellState` and typed IPC own window routing.
**Tech Stack:** Quickshell 0.3.0, Qt 6 QML, Quickshell Io and PipeWire, Hyprland 0.56 Lua configuration, systemd, Bash integration contracts
**Spec:** `docs/superpowers/specs/2026-08-17-panama-settings-design.md`
## Global Constraints
- Use Tokyo Night Moon tokens and the existing Prism edge; no component-local color literals.
- Apply only allow-listed Hyprland numeric settings; never execute UI-provided shell text.
- Do not expose full-time desktop HDR without tested automatic rollback.
- Do not continuously poll or animate while idle.
- Preserve GNOME Settings as an installed, searchable fallback.
- Keep unrelated pre-existing Panama changes untouched.
---
### Task 1: Persisted desktop preferences
**Files:**
- Create: `config/dot/quickshell/config/DesktopPreferences.qml`
- Modify: `config/dot/quickshell/config/Settings.qml`
- Test: `tests/quickshell/settings-preferences-contract.sh`
**Interfaces:**
- Produces: writable `use24Hour`, `showSeconds`, `showWeekday`, `showCpu`, `showMemory`, `showGpu`, `dockAutohide`, `dockRevealDelayMs`, `dockHideDelayMs`, `focusDurationMinutes`, `autoHdr`, `vrrPolicy`, `directScanoutPolicy`, and `lastPage` properties plus `resetDesktopDefaults(): void`.
- Consumes: `Quickshell.stateDir`, `FileView`, and `JsonAdapter`.
- [x] Write a standalone Quickshell contract that changes clock, dock, and display-policy values in a disposable state directory, restarts the harness, and asserts the literal values survive.
- [x] Run the contract and verify it fails because `DesktopPreferences` does not exist.
- [x] Implement the JSON adapter and bind dynamic `Settings.qml` values to it.
- [x] Run the persistence contract and the existing focus/dock consumers to green.
### Task 2: Allow-listed system boundary
**Files:**
- Create: `config/dot/quickshell/services/SystemSettings.qml`
- Test: `tests/quickshell/settings-system-contract.sh`
**Interfaces:**
- Consumes: `DesktopPreferences`, `NightLight`, `Notifs`, `Caffeine`, `hyprctl`, `systemctl`, and `pgrep`.
- Produces: monitor identity and geometry, display-policy setters, bounded `refresh(): void`, service status, `openGnomePanel(panel: string): void`, `openApplication(id: string): void`, and an inline `lastError`.
- [x] Write an IPC-backed contract that applies current policy values, refreshes the active monitor, and rejects an unsupported GNOME panel.
- [x] Run it and verify the `settings-system` diagnostics target is absent.
- [x] Implement fixed-command processes and strict numeric/panel allow lists.
- [x] Run the contract and confirm the live compositor returns to its original values.
### Task 3: Luminous window and core pages
**Files:**
- Create: `config/dot/quickshell/modules/settings/SettingsWindow.qml`
- Create: `config/dot/quickshell/modules/settings/SettingsShell.qml`
- Create: `config/dot/quickshell/modules/settings/SettingsSidebar.qml`
- Create: `config/dot/quickshell/modules/settings/SettingsCard.qml`
- Create: `config/dot/quickshell/modules/settings/SettingRow.qml`
- Create: `config/dot/quickshell/modules/settings/SettingsToggle.qml`
- Create: `config/dot/quickshell/modules/settings/HomePage.qml`
- Create: `config/dot/quickshell/modules/settings/AppearancePage.qml`
- Create: `config/dot/quickshell/modules/settings/DisplaysPage.qml`
- Create: `config/dot/quickshell/modules/settings/DesktopPage.qml`
- Create: `config/dot/quickshell/modules/settings/qmldir`
- Test: `tests/quickshell/settings-window-contract.sh`
**Interfaces:**
- Consumes: `DesktopPreferences`, `SystemSettings`, `NightLight`, and `ShellState.settingsPage`.
- Produces: a tiled `Panama Settings` window with Home, Appearance, Displays, and Desktop pages.
- [x] Write a live contract that opens the window to each core page and verifies one `Panama Settings` toplevel remains mapped.
- [x] Run it and verify the `settings` IPC target is absent.
- [x] Implement the two-pane Luminous shell and reusable row/card controls.
- [x] Implement real preference, Night Light, HDR policy, VRR, direct-scanout, clock, vitals, and dock controls.
- [x] Run the page contract and inspect Quickshell logs for construction warnings.
### Task 4: System pages and fallback handoffs
**Files:**
- Create: `config/dot/quickshell/modules/settings/SoundPage.qml`
- Create: `config/dot/quickshell/modules/settings/NotificationsPage.qml`
- Create: `config/dot/quickshell/modules/settings/ShortcutsPage.qml`
- Create: `config/dot/quickshell/modules/settings/ServicesPage.qml`
- Create: `config/dot/quickshell/modules/settings/AboutPage.qml`
- Modify: `config/dot/quickshell/modules/settings/SettingsShell.qml`
- Test: `tests/quickshell/settings-pages-contract.sh`
**Interfaces:**
- Consumes: existing PipeWire controls, `Notifs`, `FocusSession`, service status from Task 2, and fixed GNOME panel handoffs.
- Produces: Sound, Notifications & Focus, Shortcuts, Startup & Services, and About destinations.
- [x] Extend the page contract with search routing, live DND/focus changes, audio construction, service refresh, and GNOME fallback command validation.
- [x] Run it and verify the new page names fail before implementation.
- [x] Build the five pages using the same row/card vocabulary and no inactive fake controls.
- [x] Run contracts and verify absent optional services render as unavailable.
### Task 5: Shell, keybinding, launcher, and compositor integration
**Files:**
- Modify: `config/dot/quickshell/services/ShellState.qml`
- Modify: `config/dot/quickshell/shell.qml`
- Modify: `config/dot/hypr/keybinds.lua`
- Modify: `config/dot/hypr/rules.lua`
- Create: `config/local/share/applications/panama-settings.desktop`
- Modify: `setup/scripts/link-dotfiles`
- Modify: `README.md`
- Modify: `config/dot/hypr/README.md`
**Interfaces:**
- Produces: `ShellState.settingsOpen`, `settingsPage`, typed `settings` and `settings-system` IPC targets, `Super+I`, and a searchable desktop entry.
- [x] Extend the live contract to open, close, toggle, and route directly to a named page.
- [x] Wire the Settings window and IPC handlers into the shell.
- [x] Replace the GNOME Settings `Super+I` command with Panama IPC while retaining the GNOME desktop entry.
- [x] Let the titled window participate in the active Hyprland tiling layout.
- [x] Link the Panama desktop entry into `~/.local/share/applications` and refresh the launcher cache.
### Task 6: Full-system verification
- [x] Run every Quickshell contract, `Hyprland --verify-config`, and desktop-file validation.
- [x] Reload Hyprland, restart Quickshell, and inspect fresh logs for errors or warnings.
- [x] Exercise Home, Displays, Desktop, Sound, Notifications, Services, shortcut search, and a GNOME handoff.
- [x] Capture Home, Displays, Desktop, and Services pages for visual review.
- [x] Inspect the exact Panama diff and confirm unrelated pre-existing changes were preserved.
@@ -0,0 +1,105 @@
# Screen Intelligence Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Add polished local OCR and code recognition to Panama's existing capture experience.
**Architecture:** Capture keeps ownership of geometry and delegates Read captures to a focused `ScreenIntelligence` singleton. A deterministic helper emits JSON from local Tesseract and ZBar, while a transient Quickshell result surface owns presentation and explicit follow-up actions.
**Tech Stack:** Quickshell 0.3.0, Qt 6 QML, Hyprland 0.56 Lua configuration, Bash, Tesseract 5, ZBar, grim, wl-clipboard
**Spec:** `docs/superpowers/specs/2026-08-17-screen-intelligence-design.md`
## Global Constraints
- Recognition is local until Search, Translate, or Open is explicitly selected.
- Reuse the existing Screen, Window, and Selection picker.
- Use Tokyo Night Moon and Prism tokens; no component-local colors.
- Do not add idle animation or polling.
- Temporary screen captures must be removed when dismissed or replaced.
- Missing recognition packages must degrade into clear guidance, not shell errors.
---
### Task 1: Recognition boundary
**Files:**
- Create: `config/dot/quickshell/scripts/screen-intelligence`
- Create: `tests/quickshell/screen-intelligence-helper-contract.sh`
- Modify: `setup/packages/hyprland-packages`
**Interfaces:**
- Produces: `screen-intelligence probe` and `screen-intelligence analyze-file IMAGE`, each emitting one JSON object.
- Consumes: `tesseract`, `zbarimg`, and `jq`.
- [x] Write a contract that generates a high-contrast `PANAMA SCREEN INTELLIGENCE` fixture and expects that literal text from `analyze-file`.
- [x] Run it and verify it fails because the helper does not exist.
- [x] Implement strict argument validation, readiness probing, OCR, code recognition, JSON encoding, and user-safe errors.
- [x] Add `tesseract`, `tesseract-langpack-eng`, and `zbar` to the Hyprland package set.
- [x] Run the helper contract to green with the real engine.
### Task 2: Recognition state and actions
**Files:**
- Create: `config/dot/quickshell/services/ScreenIntelligence.qml`
- Test: `tests/quickshell/screen-intelligence-contract.sh`
**Interfaces:**
- Produces: readiness properties, `phase`, `text`, detected-code data, `analyzeRegion`, `analyzeFile`, copy/search/translate/open actions, and `close`.
- Consumes: the Task 1 helper, `grim`, `wl-copy`, `xdg-open`, and `Quickshell.cachePath`.
- [x] Write a live IPC contract that expects the target, readiness JSON, fixture analysis, and cleanup.
- [x] Run it and verify the IPC target is missing.
- [x] Implement bounded process state, JSON parsing, explicit network actions, and temporary-file cleanup.
- [x] Wire a typed diagnostics and command IPC target in `shell.qml`.
- [x] Run the live contract to green.
### Task 3: Capture integration and result sheet
**Files:**
- Modify: `config/dot/quickshell/services/Capture.qml`
- Modify: `config/dot/quickshell/modules/capture/CaptureBar.qml`
- Create: `config/dot/quickshell/modules/capture/IntelligenceResult.qml`
- Modify: `config/dot/quickshell/shell.qml`
**Interfaces:**
- Produces: Screenshot, Record, and Read action selection plus the transient result overlay.
- Consumes: Task 2's `analyzeRegion` and state/action API.
- [x] Extend the live contract to open Selection + Read mode and inspect the exposed mode state.
- [x] Run it and verify the Read state is absent.
- [x] Add mutually exclusive action selection and defer recognition until the picker unmaps.
- [x] Build processing, success, empty, code, and unavailable result states with keyboard dismissal.
- [x] Restart Quickshell and inspect fresh logs for construction errors or warnings.
### Task 4: Settings, shortcut, launcher, and documentation
**Files:**
- Create: `config/dot/quickshell/modules/settings/ScreenIntelligencePage.qml`
- Modify: `config/dot/quickshell/modules/settings/SettingsSidebar.qml`
- Modify: `config/dot/quickshell/modules/settings/SettingsShell.qml`
- Modify: `config/dot/quickshell/modules/settings/qmldir`
- Modify: `config/dot/quickshell/services/ShellState.qml`
- Modify: `config/dot/hypr/keybinds.lua`
- Modify: `config/dot/hypr/rules.lua`
- Create: `config/local/share/applications/panama-screen-intelligence.desktop`
- Modify: `config/dot/hypr/README.md`
- Modify: `README.md`
- Modify: `tests/quickshell/settings-pages-contract.sh`
**Interfaces:**
- Produces: Settings destination `screen-intelligence`, `Super+Shift+S`, and a searchable desktop entry.
- [x] Extend Settings and keybinding contracts with the new page and shortcut.
- [x] Run them and verify the route and bind fail.
- [x] Build the readiness/privacy page and add it to Settings navigation.
- [x] Add the keybinding, overlay privacy rule, desktop entry, and documentation.
- [x] Link and validate the desktop entry, reload Hyprland, and run contracts to green.
### Task 5: Full-system verification
- [x] Run the helper and live Screen Intelligence contracts.
- [x] Run every Quickshell contract and `Hyprland --verify-config`.
- [x] Restart the live shell and inspect fresh logs.
- [ ] Exercise a real screen-region OCR capture and confirm Copy reaches clipboard history.
- [ ] Review the complete diff, commit the Panama snapshot, and push `main` to `origin`.
@@ -0,0 +1,47 @@
# 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.
@@ -0,0 +1,46 @@
# Continuum Scratchpad and Window Actions Design
## Purpose
Complete Continuum as a practical GNOME-like window overview: windows can be moved directly between workspaces, closed without first focusing them, and set aside in one global scratchpad shelf.
## Experience
- Every window thumbnail is clickable, draggable, and gains a quiet close button on hover or keyboard focus.
- Dropping a thumbnail on a workspace card moves it there without leaving the overview.
- A global scratchpad shelf sits along the bottom of Continuum. Empty, it is a subtle drop target. Populated, it expands into a horizontal row of live cards.
- Dropping a normal window on the shelf sends it to `special:scratch`. Clicking a shelf card restores it to the selected positive workspace, focuses it, and closes Continuum.
- `Super+X` continues to toggle the global scratchpad and `Super+Shift+X` continues to send the active window there.
- Closing a thumbnail asks Hyprland to close exactly that address and leaves the overview open.
- Drag operations have restrained scale/highlight feedback, never continuous decorative animation.
## Architecture
`WindowThumbnail.qml` owns pointer drag initiation, hover chrome, and close intent. It emits `activated`, `closeRequested`, and `dragStarted/dragFinished` signals with its toplevel; it does not dispatch compositor commands.
`WorkspaceCard.qml` becomes a drop destination and forwards window actions to `OverviewBody.qml`. `OverviewBody.qml` is the sole compositor-command boundary for focus, close, workspace moves, and scratchpad moves, keeping address normalization in one place.
`ScratchpadShelf.qml` renders the special workspace model and provides the global drop target. `ScratchpadCard.qml` reuses the same thumbnail presentation at a compact size.
The shelf reads the Hyprland workspace whose name is `special:scratch`. Positive workspaces remain the only entries in the filmstrip and search model.
## Keyboard and Input
- Left/Right selects workspaces when search is empty.
- Enter opens the selected workspace or focused search result.
- Delete closes the keyboard-selected window.
- Escape closes Continuum.
- Pointer dragging never activates a window on release after a successful drag.
## Failure Handling
- Missing or stale addresses make the command a no-op and trigger a workspace/toplevel refresh.
- If the scratch workspace does not yet exist, the first drop creates it through Hyprland's normal special-workspace move dispatcher.
- Closing or moving a window invalidates captures; Continuum refreshes models and recaptures after the compositor reports the change.
## Verification
- Static contracts confirm all dispatches are address-scoped and the shelf only targets `special:scratch`.
- Live tests create disposable windows, move them across workspaces and into/out of the scratchpad, close only the intended disposable window, and restore the user's prior workspace.
- Visual captures cover the empty shelf, populated shelf, workspace drop target, and hover close control.
- Existing focus and overview-search tests remain green.
@@ -0,0 +1,65 @@
# Focus Glass and Continuum Overview Design
## Outcome
Panama gains a polished focus-session surface and a GNOME-like workspace overview. The focus surface uses the selected Signal Glass visual language, keeps Command Deck's useful controls, and treats its associated Hyprland workspace as a first-class destination. The overview uses the selected Continuum layout: a workspace filmstrip above a large, spatially familiar active-workspace preview.
## Focus session behavior
- A focus session starts with Panama's configurable default duration of 45 minutes and binds to the currently focused positive-numbered Hyprland workspace.
- Starting a session enables Do Not Disturb and Caffeine. Panama remembers their prior values and restores them when the session ends.
- The session uses a wall-clock deadline rather than decrementing persistent state every second. It therefore survives a Quickshell reload without losing time.
- Pause stores the exact remaining duration. Resume creates a new deadline from that stored duration.
- The session completes automatically at zero and posts a normal desktop notification through the existing Panama notification server.
- End deliberately terminates the session and restores the prior DND and Caffeine values.
- Only one focus session exists at a time. Starting again replaces the old session with a fresh session on the current workspace.
## Signal Glass surface
- The main capsule is a top-centred blurred glass surface below the bar, carrying Panama's Prism edge, Tokyo Night Moon palette, and event-driven open/close motion.
- Its primary row shows the focus icon, workspace label, remaining time, and whether DND and Caffeine are being held.
- Clicking the primary row activates the bound workspace and dismisses the capsule without ending the session.
- The action row contains Pause or Resume, Workspace, and End.
- Workspace opens the Continuum overview with the session's bound workspace selected.
- A labelled close button hides the capsule while the session continues.
- While a session exists, a compact bar indicator remains visible. Clicking it reopens the capsule, so dismissal never makes the running session undiscoverable.
- No focus UI animates while idle. The only periodic update is the once-per-second remaining-time text while a session is running and not paused.
## Discoverability and controls
- Quick Settings includes a full-width Focus row. When idle it starts a 45-minute session on the current workspace. When active it shows the remaining time and opens the capsule.
- `SUPER+SHIFT+F` performs the same start-or-show action.
- A `focus` Quickshell IPC target exposes `start`, `reveal`, `pause`, `workspace`, `overview`, and `end` for launcher integration and diagnostics.
## Continuum overview
- The overview keeps the existing full-screen dimmed and blurred layer, Escape behavior, outside-click dismissal, one-shot window captures, and dynamic-workspace support.
- A horizontally scrollable workspace filmstrip occupies the top of the surface. It contains every positive-numbered workspace plus the trailing new-workspace affordance.
- The focused or requested workspace is rendered as a large preview below the filmstrip. Clicking one of its windows activates that window and closes the overview.
- Selecting a workspace in the filmstrip activates it while keeping the overview open, matching GNOME's spatial workflow. Scrolling over the filmstrip moves left or right through workspaces.
- Opening from the focus capsule initially selects the session workspace and marks it with a subtle focus-session badge.
- A search field filters windows across all positive workspaces by title or application id. Selecting a result activates its workspace and window, then closes the overview.
- The overview IPC target can open directly into a search query, enabling deterministic diagnostics and future launcher actions without synthesizing keyboard input.
## State and boundaries
- `services/FocusSession.qml` owns session timing, persistence, DND and Caffeine coordination, and workspace activation. Visual modules only call its public functions and render its properties.
- `services/ShellState.qml` remains the owner of mutually exclusive overlays and gains only the requested overview workspace id.
- `modules/focus/` owns the capsule and bar indicator.
- `modules/overview/` owns the Continuum presentation and window search.
- Persistent state is stored atomically through Quickshell `FileView` and `JsonAdapter` under `Quickshell.stateDir`; no daemon or new package is required.
## Failure handling
- If the persisted workspace no longer exists, direct activation falls back to Hyprland's workspace dispatcher using the stored positive id.
- A malformed or absent state file falls back to an inactive session with no user-visible error.
- If the shell reloads after the deadline, the session is completed during restoration and its managed DND and Caffeine state is released.
- Search and workspace lists tolerate transient null Hyprland objects while IPC state refreshes.
## Verification
- Validate the focus state machine with a standalone Quickshell harness using a very short session.
- Validate every QML component constructs without warnings against Quickshell 0.3.0.
- Exercise start, pause, resume, dismiss, reopen, workspace activation, overview targeting, automatic completion, and manual end through live IPC.
- Reload the daily-driver shell and inspect its logs for QML errors.
- Capture the capsule, compact indicator, Continuum overview, and search state for visual review.
@@ -0,0 +1,75 @@
# Panama Settings Design
## Purpose
Panama Settings is the native control center for the Panama Hyprland desktop. It gives Gabriel one polished, understandable place to inspect the current desktop and change Panama-owned behavior without editing Lua, QML, JSON, or systemd units by hand.
The approved visual direction is **Luminous System Settings**: an Apple-like two-pane settings window, rendered with Panama's restrained Prism glass and Tokyo Night Moon palette. It is a real application window, not a transient layer-shell popover.
## Product boundaries
Panama Settings owns settings whose source of truth is Panama, Quickshell, or Hyprland. The first release includes:
- Home summary with the active display, current desktop profile, Night Light, notification/focus state, and startup-service health.
- Appearance controls for clock format and bar vitals.
- Display policy for game-aware HDR, content-aware VRR, direct scanout, and Night Light.
- Desktop controls for dock auto-hide and timing.
- A searchable, read-only shortcut reference generated from the established Panama mental model.
- Sound entry points that reuse Panama's live PipeWire controls.
- Notification, Do Not Disturb, and focus-duration controls.
- Startup/service health for Nextcloud, RustDesk, KDE Connect, Hyprpaper, Hypridle, and Vicinae, with safe open/restart actions where appropriate.
- An About page with the running Hyprland, Quickshell, and Panama identity.
Hardware configuration, user accounts, printers, online accounts, and other services owned by Fedora or GNOME remain delegated to GNOME Settings. Panama Settings labels those handoffs and launches the relevant GNOME panel with a one-process `XDG_CURRENT_DESKTOP=GNOME` override. GNOME Settings remains installed and searchable in Vicinae.
Screen Intelligence remains a separate subsystem with its own capture, recognition, and result lifecycle. Once that subsystem is installed, Settings exposes its real readiness and privacy page rather than duplicating the feature or presenting inactive controls.
## Interaction model
`Super+I` opens or raises Panama Settings. The shell also exposes a typed `settings` IPC target with `open`, `toggle`, `close`, and `page(name)` operations. A desktop entry makes Panama Settings searchable in Vicinae alongside GNOME Settings.
The sidebar is always visible at desktop sizes and contains a search field, category groups, and a quiet system-status footer. Search filters categories and setting labels rather than becoming a command palette.
The content pane uses a stable header, restrained cards, and rows with labels, concise explanations, and controls aligned to the trailing edge. Changes apply immediately. There is no global Save button.
## State and architecture
`config/DesktopPreferences.qml` persists user choices to `Quickshell.stateDir + "/panama-settings.json"` through `FileView` and `JsonAdapter`. Existing consumers continue reading `Settings.qml`; dynamic values in that singleton bind to `DesktopPreferences`, preserving one public configuration surface.
`services/SystemSettings.qml` is the machine boundary. It reads current monitor and service state, invokes allow-listed Hyprland runtime settings, opens GNOME panels, and reports command failures. UI components never construct arbitrary shell commands.
The display policy values are persisted and re-applied when the shell starts:
- Game-aware HDR maps to `render:cm_auto_hdr` with values `0` or `1`.
- VRR maps to `misc:vrr` with values `0` or `3`.
- Direct scanout maps to `render:direct_scanout` with values `0` or `2`.
Full-time desktop HDR is informational in this release because it can break screenshots, OBS, Sunshine, and lock-screen capture on the current Hyprland build. It must not be exposed as an unsafe one-click toggle without a tested automatic rollback path.
`services/ShellState.qml` owns whether the window is open and the requested page. `modules/settings/SettingsWindow.qml` owns the normal application toplevel, which participates in Hyprland's active tiling layout. Presentation components under `modules/settings/` call only public preference or service methods.
## Visual language
- Tokyo Night Moon is the only palette.
- A faint blue-to-orchid Prism hairline marks the selected category and major surfaces; orchid never appears as a standalone accent.
- The window is dense enough to feel professional but leaves generous breathing room around page headers and section groups.
- Typography uses Adwaita Sans for interface text and VictorMono Nerd Font only for version strings, dimensions, and key chords.
- Motion is event-driven and short. No pulse, shimmer, animated gradient, or idle repaint loop is allowed.
- Enabled states use the primary blue, warnings use amber, and destructive/error states use red only when there is an actual problem.
## Failure handling
- A malformed or absent preferences file falls back to shipped defaults.
- A failed `hyprctl` write restores the previous preference value and surfaces a quiet inline error.
- Missing optional applications or services are shown as unavailable, never as a shell error or empty card.
- Service refreshes are bounded and user-triggerable; no polling loop runs continuously.
- Closing Panama Settings only hides the window. It does not terminate Quickshell or alter another overlay.
## Verification
- Exercise preferences through a disposable Quickshell state directory and prove values survive a shell restart.
- Verify each display policy emits only its allow-listed numeric `hyprctl keyword` command.
- Verify `Super+I`, IPC open/close/page routing, and the searchable desktop entry.
- Construct every Settings page without QML warnings.
- Exercise live monitor refresh, Night Light, DND, audio controls, service refresh, and GNOME handoffs.
- Restart the live shell, inspect logs, and capture Home, Displays, Desktop, and Services pages for visual review.
@@ -0,0 +1,70 @@
# Screen Intelligence Design
## Purpose
Screen Intelligence makes text trapped in pixels feel like normal desktop content. It extends Panama's existing screenshot picker with a local **Read** action for a screen, window, or selection, then presents the result in a focused Prism glass sheet.
The feature is deliberately local-first. Screen pixels are captured into Panama's cache and processed by Tesseract and ZBar on the workstation. Nothing is uploaded unless the user explicitly chooses Search, Translate, or Open.
## Interaction model
- `Super+Shift+S` opens the existing capture picker in Selection + Read mode.
- `Print` keeps opening the complete picker, where Screenshot, Record, and Read are peers.
- Screen, Window, and Selection continue to use one shared target-selection model.
- Committing a Read capture dismisses the picker before taking the final image, then opens a result sheet while recognition runs.
- `Escape` dismisses the result and deletes its temporary image.
- The result provides selectable text and explicit Copy, Search, and Translate actions.
- A detected URL, QR code, or barcode is shown separately. Web URLs can be opened; all detected values can be copied.
- A searchable desktop entry opens Read mode without requiring the shortcut.
## Architecture
`services/Capture.qml` remains the owner of screen/window/selection geometry and frozen-frame behavior. It gains a third action state, `intelligenceMode`, and delegates committed Read geometry to `services/ScreenIntelligence.qml` only after the capture overlay has unmapped.
`services/ScreenIntelligence.qml` owns recognition state, process lifecycle, result actions, and cleanup. Its public boundary is:
- `refresh(): void`
- `analyzeRegion(geometry: string, outputName: string): void`
- `analyzeFile(path: string): void`
- `copyText(): void`
- `copyCode(): void`
- `search(): void`
- `translate(): void`
- `openDetected(): void`
- `close(): void`
`scripts/screen-intelligence` is the deterministic machine boundary. `probe` reports engine availability. `analyze-file IMAGE` emits one JSON object containing OCR text, detected code data, and a user-safe error. It never evaluates UI-provided shell text.
`modules/capture/IntelligenceResult.qml` is a transient overlay, not an application window. It renders a quiet processing state, the selectable result, detected-content card, actions, and actionable failure guidance.
## Recognition behavior
- OCR uses the installed English Tesseract language pack.
- Tesseract's automatic page-segmentation mode handles both short snippets and larger document regions.
- ZBar recognition is additive. A capture can return text, a code, or both.
- Empty recognition is not treated as a crash; the sheet explains that no readable text or code was found.
- Missing engines produce a precise install command and keep the rest of the shell healthy.
- Temporary captures live under `Quickshell.cachePath(...)` and are removed when dismissed or replaced.
## Visual language
- The result is a centered Prism glass sheet over a lightly dimmed desktop.
- Tokyo Night Moon tokens are the only colors.
- Processing uses a static status treatment; there is no spinner, pulse, shimmer, or idle animation.
- OCR text is readable interface typography in a selectable editor, not a terminal-like dump.
- The primary action is Copy. Network-leaving actions are visually secondary and clearly labelled.
## Settings and discoverability
Panama Settings gains a real **Screen Intelligence** page. It shows engine readiness, the `Super+Shift+S` shortcut, the local-processing privacy boundary, and the exact package requirement if recognition is unavailable. The page contains no fake toggles.
The shortcut reference, Hyprland README, root README, desktop package list, and desktop entry remain in sync.
## Verification
- A generated image fixture must be recognized as literal text by the helper.
- The live IPC contract must expose readiness, open Read mode, and route the Settings page.
- The capture picker must construct with Screenshot, Record, and Read actions without QML warnings.
- The result sheet must construct for processing, success, empty, and unavailable states.
- Hyprland must register `Super+Shift+S` as Screen Intelligence and pass config verification.
- The complete Quickshell contract suite must remain green.