Skip to content

Open Config File works and every item is audited; Adwaita settings; shadow fix; onboarding extensions; arm64; cargo-deny; pinned actions - #255

Merged
hanthor merged 33 commits into
mainfrom
claude/modest-bell-xqa0vv
Oct 1, 2026
Merged

hanthor merged 33 commits into
mainfrom
claude/modest-bell-xqa0vv

Conversation

@hanthor

@hanthor hanthor commented Oct 1, 2026

Copy link
Copy Markdown
Member

Fixes #244, #245, #246, #247, #248, #249, #250, #251, #252, #253, #254.

Launcher and Settings

  • Launcher window has a weird shadow along the bottom edge #251, the bottom-edge shadow. The card's shadow (16 px offset, 32 px blur) needed 48 px below the card, but the window has 24 px of padding. A full-height list left a hard band of alpha 29 on the window's last row. The shadow is now a 6 px offset with an 18 px blur, the window size is unchanged, and a const assertion checks that offset + blur ≤ padding. A new paint test, the_card_shadow_fades_out_before_every_edge, checks a short and a full-height card in light and dark. It fails with the old values on both wgpu and tiny-skia.

  • Settings controls look out of place on GNOME #252, Adwaita-style Settings. A new compass_ui::adwaita module styles Settings, with every colour taken from the palette:

    • boxed lists with 12 px corners and separators
    • flat neutral buttons, with an accent "suggested" button
    • pill switches with a white knob
    • filled entries with a 2 px focus ring
    • button-like dropdowns
    • a neutral selection in the sidebar

    No behaviour changes.

Commands (#253, #254)

  • Open Config File. Four separate failures:

    • there was no compass.json on a fresh profile, so it is now created first
    • GNOME's editors don't claim JSON, so text-like files now fall back to the text editor
    • terminal editors were started without a terminal
    • the engine acknowledged the open before launching, so failures only reached the log

    Opening now waits for the launch. If that fails it falls back to the OpenURI portal, which uses an fd and works from the Flatpak. Otherwise the launcher shows the reason and stays open.

  • The other file commands. Show Log File used the pre-rename vicinae state dir. Open Default Config File wrote into the sandbox-private $XDG_RUNTIME_DIR. Both are fixed.

  • Audit. 306 items are each run by app/tests/action_audit.rs, and any item that has no observable effect fails the test:

    • 59 builtin commands
    • 85 view-panel actions
    • 52 root-row actions
    • 104 Settings controls
    • 6 tray entries

    The inventory is generated into docs/rust-engine/ACTION-AUDIT.md. Dead items that were fixed: the three file commands, Show in File Browser, and the refusals of 19 power and media commands, which were drawn in a hidden window and now go to the HUD.

  • Settings sweep. The Settings audit finds controls by clicking a grid. The unscrolled pass now rebuilds the simulator for every grid line, so earlier clicks no longer hide controls further down. Before this, the restyle had dropped Quick launch and the appearance preset from the inventory.

Onboarding (#248–#250)

  • Onboarding 'Open Docs' button should open Compass docs on tunaos.org #248. "Open Docs" opens tunaos.org/docs/compass/getting-started#set-a-keyboard-shortcut, served from the new docs/getting-started.md. tunaos.org syncs top-level docs/*.md daily. The guide covers install, the shortcut setup for GNOME, KDE, Sway, Hyprland and niri, extensions, config paths, privacy and compass doctor, and was checked against the code.
  • Onboarding 'Setup complete' page links to vicinaehq instead of Compass #249. Every button on the last step goes to Compass, and a Simulator test asserts that none of them leads to Vicinae. There is no Sponsor button in onboarding; the tray still has "Sponsor Upstream Vicinae".
  • Onboarding should recommend extensions to enable #250. A new "Add extensions" step recommends five extensions, all of which render in Suite 1 and need no account: Bluetooth, Wifi Commander, Process Manager, Flathub and Google Translate. Installing uses the store's own install path. When the install fails, for example offline, the button says "Try Again" with the store's reason, and Continue still works. The onboarding version was not bumped, so people who have already finished setup don't see it again.
  • Links. The remaining links to docs.vicinae.com either point at the guide or say they lead to the Vicinae SDK docs.

CI and supply chain

Verification

  • Local checks: cargo fmt, workspace clippy with -D warnings, and cargo doc with -D warnings all pass.
  • Tests: cargo test --workspace passes, with 4,690 passing before the audit fix. The compass-ui suite passes after it, 576 of 576.
  • Extension tests: the engine e2e suite passes with a freshly built extension runtime (98/98, including Brew).
  • Parity: the score stays at 152/152. cargo deny check passes, and actionlint reports nothing new.

Visual checks, all looked at:

  • Paint tier: before and after for the shadow and every Settings page, in light and dark.
  • Real binary on headless Sway: Settings in light and dark, plus a 4x zoom of the shadow edge.
  • Onboarding on headless Sway: each step, a real store install, and the offline retry.
  • Open Config File on headless Sway: opening the config, the log and the default config with a fake editor, and the "No application opens this kind of file" case.

Only CI can show that the aarch64 build and its smoke tests work.

🤖 Generated with Claude Code

https://claude.ai/code/session_01UtGVEzDmYTdpsuEQErmmLn


Generated by Claude Code

iced's default scrollbar is a 10px square rail and scroller. Every
scrollable now goes through crate::scroll::scrollable, which draws the
C++ ViciScrollBar: 6px wide, radius 3, no rail, the text colour faint at
rest and stronger under the pointer or while dragging.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UtGVEzDmYTdpsuEQErmmLn
Every Markdown view (an extension's Detail, the store detail page, the
store intros, the created-extension page) built its settings with
`markdown::Settings::with_text_size(14, &theme)`, whose `style.font` is
`Font::default()` -- the generic sans-serif -- while every other text
widget uses `LauncherApp::font()`. cosmic-text maps generic sans-serif
to a hard-coded "Open Sans"; where that family is missing (a stock
GNOME install) each span goes through its fallback list instead, and
bold spans of a variable default family land on whichever family has a
static 700 face (DejaVu Sans Bold, Cantarell Bold...), so the page's
text was in a different, mixed face from the rest of the launcher.

`LauncherApp::markdown_settings` now sets `style.font` to the launcher
font (code keeps iced's monospace) and all four views use it; the
store viewer's image placeholder uses the same font.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UtGVEzDmYTdpsuEQErmmLn
publish-flatpak.yaml takes the bundle a green Flatpak run on main
already built and smoke-tested, exports it as an OCI image to
ghcr.io/tuna-os/compass and records it in the remote's index through the
org's shared publish-flatpak-index step. It refuses to publish an image
without AppStream labels.

The metainfo gains a developer, screenshots, branding colours and a
first release. The screenshots are rendered through the paint tier by an
ignored test, regenerated with `just screenshots`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UtGVEzDmYTdpsuEQErmmLn
… behind the card

Closes the last amber parity cell, src/services/window-material Rust ✓
(152 of 152). The maintainer approved an unsafe exception (ADR-0019):

- compass-wayland-foreign: a Linux-only crate that does not inherit the
  workspace's forbid(unsafe_code); it denies unsafe, restates the other
  lints, and allows it in one function (adopt) with two blocks,
  Backend::from_foreign_display and ObjectId::from_ptr. Its safe API,
  bridge(&window), takes both raw-window-handle handles from one window,
  accepts only Wayland ones, checks the pointer is a wl_surface, refuses a
  surface that is not a wayland-rs proxy, names the client_system backend
  so the wrong one does not compile, and keeps one Connection per display
  for the process's life.
- compass_platform::WindowMaterial (the seam), implemented by
  vicinae::window_material over the bridge and
  compass_wayland::material::BackgroundEffects, handed to
  compass_ui::run_resident by the binary.
- compass-ui measures the card with a sensor keyed on tint and corner
  radius and asks through iced::window::run for the card's rounded
  rectangle while the card is translucent, none when it is not.
- BackgroundEffects drops effects of destroyed surfaces before sending,
  since set_blur_region on one is a protocol error on winit's display.

Under the xdg_toplevel presentation only: iced_layershell drops
window::run, a declared difference. Tested on headless Sway (the bridge)
and an in-process compositor that blurs (the region traffic); real blur
on KWin is VM tier.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UtGVEzDmYTdpsuEQErmmLn
The README now leads with what Compass is and a measured comparison against
the pinned, unmodified Vicinae v0.29.0 AppImage: cold start (96 ms vs 1,746 ms
to IPC ready; 0.9 s vs 2.3 s to a populated launcher), keystroke to frame
(56 vs 153 ms), idle PSS (218 vs 263 MiB), 46 vs 136 shared objects and
72 MB vs 310 MB of program files. It also says where Compass loses: its fuzzy
scorer is 2-3x slower per core, and it runs more threads.

- scripts/bench/compare.sh and compare.py (just bench-compare): headless Sway,
  a private D-Bus bus with no activation, throwaway HOME/XDG, both engines
  under unshare --net, alternating runs, process trees found by an
  environment tag.
- scripts/bench/fuzzy/cpp_rank.cpp and compass-testkit's fuzzy-throughput
  bin: the two scorers over the same 10k haystack and queries.
- docs/rust-engine/BENCHMARKS.md: method, machine, raw per-run numbers,
  the SLA benches, and a still-to-measure list. The raw report is archived
  under benchmarks/2026-09-25-compare.
- Install: the TunaOS Flatpak remote (com.vicinae.Vicinae), CI bundle,
  flatpak-builder, the other packages and cargo. Stale migration-status
  prose and Vicinae-only instructions are gone; credit to Vicinae is kept.
- CONTRIBUTING.md points at Compass's tracker, not Vicinae's; CUTOVER.md
  no longer quotes 70/158.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UtGVEzDmYTdpsuEQErmmLn
…mand broker, and an overrides manifest

Measured first: of the top 300 Raycast store extensions, 153 carry a
macOS-only signal (90 AppleScript/JXA, 39 ~/Library paths, 28 `open`,
27 Homebrew prefixes, 0 pbcopy/pbpaste); docs/rust-engine/RAYCAST-LINUX-SHIM.md
has the table and scripts/suite1/macos_signals.py reproduces it.

- The runtime's shim (extension-manager/src/linux-shim): child_process and
  fs behind proxies for the extension's require. `open` runs xdg-open,
  pbcopy/pbpaste use the runtime's clipboard, osascript and other
  macOS-only programs fail by name (CompassRefusal/ENOTSUP) instead of
  ENOENT, Homebrew's macOS paths map to Linuxbrew's. process.platform
  stays linux.
- The broker (HostCommand/run, vicinae::host_commands): `brew`, for any
  extension, runs on the host as the engine's child (flatpak-spawn --host
  inside the Flatpak) once the person allows it: Allow Once / Always Allow
  (Ctrl+Enter) / Deny. Grants in $XDG_CONFIG_HOME/compass/
  host-command-grants.json, listed and revoked in Script Permissions. The
  extension's Landlock policy is not widened. IPC v22 for the alert's
  third answer. The Qt engine refuses the call by name.
- The overrides manifest (extensions/raycast-linux-overrides.json): per
  extension host programs, path and command maps, load-time patches and
  install redirects, read by the runtime and the engine.

Raycast's real Brew bundle renders Show Installed and Search against a
Linuxbrew `brew` behind the sandbox; an end-to-end test covers the same
path with a fake brew. The runtime gets unit tests (npm test).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UtGVEzDmYTdpsuEQErmmLn
Clicks on the root search list did nothing: its rows were the only list
rows not wrapped in a mouse_area, so a press reached no handler. A click
now sends ResultClicked, which selects the row and does what Enter on it
does, and hands focus back to the search field. Hover still never moves
the selection, as the C++ SelectableDelegate.

The window painted a light rectangle behind the card on both the layer
surface and the xdg_toplevel: no program style was set, so iced cleared
every frame to the theme's background (the card's surface colour).
LauncherApp::style clears to transparent and is wired into run,
run_resident and run_resident_layer_shell.

Tests: Simulator clicks on a root application row (launches that row,
not the selected one), on a root command and then a store row (opens the
store, then that extension), and a hover that must not select; the paint
tier checks the window below the card's shadow is alpha 0 with the app's
style, with the theme's base colour as a failing control.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UtGVEzDmYTdpsuEQErmmLn
The Rust side of the Phase 7 cutover (ADR-0012; spec in ADR-0020).

- crates/vicinae is now crates/compass: package, library and binary
  `compass`; the helpers are `compass-file-indexer` and
  `compass-input-server`, looked for in ../libexec/compass or
  ../lib/compass.
- Config, data, cache and state live under `compass`, the config file is
  `compass/compass.json`, the schema `compass.schema.json` (regenerated), and
  the IPC socket is `$XDG_RUNTIME_DIR/compass/ipc.sock`
  (`/tmp/compass-$USER` without a runtime dir).
- On `compass serve`, before anything creates a `compass` directory, each
  `vicinae` base directory is moved to `compass` and left as a symlink. When
  `compass` already exists (the pre-cutover engine kept scripts, grants and
  caches there), the entries it lacks are moved in and nothing is
  overwritten; `vicinae.json` becomes `compass.json` the same way.
- `COMPASS_*` environment variables, with the `VICINAE_*` spelling read as a
  fallback that logs a deprecation once. `VICINAE_API_URL` is
  `COMPASS_VICINAE_API_URL`.
- Compass emits `compass://` and accepts `vicinae://` and `raycast://`.
- D-Bus: `org.tunaos.compass.WindowTracker` for KWin, and the shell
  extension contract is `org.tunaos.compass.Shell.{Windows,Clipboard}` at
  `/org/tunaos/compass/Shell/*`. App id, tray item and icon are
  `org.tunaos.compass`; layer-shell namespaces `compass` and `compass-hud`.
- User-facing strings say Compass. Report Bug files against tuna-os/compass;
  the Discord builtin and tray entry are now "Compass on GitHub", and the
  sponsor entry is labelled as upstream credit.
- The extension runtime is given COMPASS_VERSION/COMMIT and reads the
  `VICINAE_*` names only as a fallback; the SDK dev client dials the new
  socket and emits compass:// links.

Kept on purpose: @vicinae/api, store.vicinae.* ids and the Vicinae store,
the keyring labels the importer reads, the vicinae-hotkey-v1 protocol, the
@Vicinae script-command scope, the vicinae-dark/-light theme ids and C++
references.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UtGVEzDmYTdpsuEQErmmLn
Rename the Flatpak manifest, desktop entries and metainfo to the
org.tunaos.compass ID and ship the `compass` binary, with libexec/compass
and share/compass layouts, across the Flatpak, AppImage, Arch and Nix
outputs. The metainfo <replaces> com.vicinae.Vicinae, the URL handler
takes compass:// alongside vicinae://, raycast:// and com.raycast:, and an
opt-in compass.service user unit is installed.

The GNOME Shell extension becomes compass@tunaos.org with its interfaces
under org.tunaos.compass.Shell.*. The config schema moves to
compass.schema.json and nix/vicinae.nix to nix/compass.nix. CI workflows,
the VM tier, Suite 1/5, tier 2, wlroots and the bench scripts build
`-p compass` and run target/*/compass; the benchmarks still launch the
pinned upstream Vicinae AppImage under its own name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UtGVEzDmYTdpsuEQErmmLn
…R-0020)

The README, CONTRIBUTING and the Rust engine docs use the new app ID, the
compass command, the compass crate and the compass config, data, cache,
state and runtime directories. The README says an existing
~/.config/vicinae is moved on first start instead of saying the old names
are kept.

ADR-0020 records the rebrand: the new names, what keeps the vicinae name
and why (@vicinae/api, vicinae:// deeplinks, the Vicinae Store, VICINAE_*
fallbacks, upstream credit, the C++ tree), the directory migration, and
why no Flatpak data migration is needed. It supersedes ADR-0012's
compatibility list.

The TypeScript READMEs and package metadata describe Compass. The
@vicinae/api module name stays.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UtGVEzDmYTdpsuEQErmmLn
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UtGVEzDmYTdpsuEQErmmLn
The Vicinae store's Linuxbrew extension now reaches brew through the
consent-gated broker, so a headless run sees its 'Allow Linuxbrew to run
brew?' prompt and nothing answers it. Record that as its own verdict, like
needs-sign-in for OAuth, rather than as an empty frame, and expect it in
the ledger.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UtGVEzDmYTdpsuEQErmmLn
…DR-0021)

The parity ledger reads 152/152 and the benchmarks already measure the
pinned upstream v0.29.0 AppImage, so the in-tree C++/Qt engine goes.

Removed: src/{server,cli,lib,data-control-server,file-indexer,snippet,
wayland-protocols,browser-extension}, CMake (top level, cmake/,
src/typescript's), clang-format/tidy/clangd/qmlformat configs, vendor/
except fuzzy-trigram, nix/vicinae.nix and default.nix, the C++ build
scripts (scripts/runners, macOS/Windows packaging scripts), the C++
Makefile targets and the C++ CI workflows (build-linux, build-macos,
build-windows, build-appimage, build-appimage-image, macos-dmg,
cpp-on-target) and release.yml's C++ jobs. The HostCommand C++ stub goes
with src/server.

Moved what Rust reads: the glyph table to crates/compass-core/glyph, the
builtin icons to extra/builtin-icons (names now from @vicinae/api's Icon
enum), the migrations into compass-db and compass-clipboard, the
script-command corpus to a compass-core fixture, the Qt catalogues to
extra/translations/qt, and upstream's fuzzy and crypto sources plus the
probes to scripts/bench so the differentials run against upstream.

figura is ported to Rust (crates/compass-figura, TypeScript only,
byte-identical output); the extension runtime's bindings are committed
and a test keeps them current, so building the runtime needs only npm.
Tests that parsed C++ sources pin upstream's values or are dropped where
Rust tests already pin them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UtGVEzDmYTdpsuEQErmmLn
- AGENTS.md rewritten for the Rust workspace: separation between
  compass-ui and the logic crates, the workspace lints, the platform seam
  test, the test ladder, cargo fmt/clippy/alejandra, and i18n as it stands
  (fluent-rs decided, catalogues not yet converted).
- nix/: programs.compass (Home Manager) and programs.compass.input-server
  (NixOS), with upstream's programs.vicinae names renamed or removed. The
  soulver/numen, browser-host, launchd and settingOverrides options go:
  the calculator is fend-core and the engine is Linux only.
- extra/: delete the C++ build's macOS, Windows, desktop, systemd,
  modules-load.d and config.jsonc files; nothing in the Rust build reads them.
- PARITY.md's C++ deleted column is green everywhere; the scorer's
  docstring says why it still reads 152/152.
- CONTRIBUTING.md, packaging/README.md, manifest.yaml, .envrc, .gitignore
  and helper comments lose their C++-era references.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UtGVEzDmYTdpsuEQErmmLn
The C++ removal's rewrite of extension-runtime.nix kept the pre-rename
share/vicinae path, so the compass derivation found no runtime bundle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UtGVEzDmYTdpsuEQErmmLn
deny.toml denies vulnerabilities and unmaintained crates, warns on
duplicate versions, allows crates.io only (the lockfile has no git
sources) and allow-lists the licences the graph actually uses, all
compatible with GPL-3.0-only. A new cargo-deny workflow runs it on
dependency changes and daily; the advisories leg does not block pull
requests, so news about an untouched dependency cannot hold one up.

No vulnerability was reported. Five unmaintained crates have no
semver-compatible fix and are ignored with their reasons: ttf-parser
and rustybuzz (Iced 0.14's text and SVG stack), bincode 1 and yaml-rust
(syntect 5.3 via iced_highlighter) and smartstring (rhai 1.26.1).
yoke-derive 0.8.3 was yanked; it moves to 0.8.4, with cargo-sources.json
regenerated to match.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UtGVEzDmYTdpsuEQErmmLn
Every `uses: owner/repo@tag` in the workflows and the vm-host composite
action now names the commit its tag pointed at, resolved with
git ls-remote, with the version in a trailing comment: 88 references
across 12 actions. The versions are unchanged; a major tag such as
actions/checkout@v4 is pinned to the release it currently points at.

taiki-e/install-action@just and @nextest were per-tool tags that move on
every release. They are now the v2.87.22 release with `tool:` as input,
which is the same install and gives Dependabot a version to track.

tuna-os/.github stays on @main: it is the org's own, and pinning it
would stop org-wide fixes to the index updater from reaching compass.

Dependabot now updates the pins weekly in one grouped PR.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UtGVEzDmYTdpsuEQErmmLn
flatpak.yaml's build job is now a matrix over x86_64 and aarch64, each on
a native runner (ubuntu-24.04 and ubuntu-24.04-arm), no QEMU. Every step
after the build runs per architecture: the installed-commit assertion,
doctor, Suite 5 and Spike B. The runtime cache is keyed by architecture,
and Node 22 is set up explicitly, since npm runs on the runner and the
arm64 image need not ship the same Node.

x86_64 keeps its artifact names, which the VM tier, Suite 1 and tier 2
download; aarch64 adds -aarch64. Those callers go through workflow_call,
whose new `archs` input defaults to x86_64 only, so they do not wait on
an arm build they never test.

publish-flatpak.yaml still republishes the bundles CI built and tested.
It downloads both, exports each as OCI with --arch, checks the image's
architecture field (the index keys its per-arch entry on it), pushes
latest-x86_64, latest-aarch64 and latest (x86_64, the org convention),
and updates the tuna-os/docs index once per architecture.

The manifest needed nothing: cargo-sources.json vendors every crate
from source, the SDK extensions (rust-stable, node22) exist for aarch64,
and the seccomp code already selects the aarch64 target.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UtGVEzDmYTdpsuEQErmmLn
The window is the card plus 24 px of shadow padding on every side, but the
card's shadow had a 16 px offset and a 32 px blur. Iced fades a shadow out
over blur_radius past its shape, so it reached 48 px below the card and
32 px to the sides. Once a long list grows the card to its full height,
only 24 px of window is left below it, and the surface's last rows still
had alpha 29 of 255: the shadow stopped in a hard band along the bottom
edge.

The shadow is now a 6 px offset and an 18 px blur, so it reaches exactly
24 px below the card and 18 px to the sides. The window stays 768x608, as
upstream's, the VM tier and the blur region expect. A const assertion
keeps offset + blur within SHADOW_PADDING, and a paint test renders a
short card and a full-height one, light and dark, and requires the
outermost row and column on every side to be clear and the shadow under
the card to fade monotonically. With the old values it fails on both
tiny-skia and wgpu.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UtGVEzDmYTdpsuEQErmmLn
Settings drew Iced's default widgets: square bordered buttons filled with
the accent, a switch with a dark knob, framed inputs, and loose rows. A new
compass_ui::adwaita module styles them after libadwaita 1.x, from the
palette only, so light, dark and the user's theme still apply:

- buttons: flat neutral fill (text at 10/15/30 %), 6 px corners, no
  border, about 34 px tall; the update's View Release Notes is the
  suggested action, in the accent fill
- switches: 52x26 pill track, round knob in the on-accent colour, accent
  when on, neutral fill when off
- entries: neutral fill, 6 px corners, a 2 px accent focus ring
- dropdowns: drawn as buttons with the chevron in the text colour, menus
  in the launcher's dropdown_menu style
- rows: AdwPreferencesGroup-style boxed lists, 12 px corners, hairline
  separators, a bold group title, rows at least 50 px tall
- sidebar: the selected page takes the neutral fill, as GNOME Settings'
  navigation sidebar does, instead of the accent

Layout and actions are unchanged; every control sends the same message.
The launcher's own rows and field keep their styles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UtGVEzDmYTdpsuEQErmmLn
docs/getting-started.md is synced to tunaos.org/docs/compass/getting-started:
install, first run, setting a keyboard shortcut (GNOME and KDE through the
GlobalShortcuts portal, Sway, Hyprland and niri bindings, custom shortcuts),
extensions, configuration, privacy and compass doctor.

The telemetry notice and DOC_TELEMETRY_URL, neither of which is shown,
now point at the guide's privacy section. "Build an extension" links say
they are the Vicinae SDK docs, which Compass extensions use, and the Raycast
store intro says Compass rather than Vicinae.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UtGVEzDmYTdpsuEQErmmLn
…, #249, #250)

- #248: Open Docs opens the getting-started guide's "Set a keyboard
  shortcut" section on tunaos.org.
- #249: verified the last step names Compass and its only button opens
  tuna-os/compass; Compass has no sponsor page, so there is no Sponsor
  button. A test clicks every button and checks none leads upstream.
- #250: an "Add extensions" step before the last recommends five store
  extensions Suite 1 shows rendering (Bluetooth, Wifi Commander, Process
  Manager, Flathub, Google Translate), kept as data in
  compass_core::onboarding with tests. Install goes through the store's own
  store_install; a failure, offline included, says why, offers Try Again
  and never blocks Continue. Installed ones show as Installed.
- Paint tier: every onboarding step paints its heading and primary button,
  in both appearances, including the failed-install state.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UtGVEzDmYTdpsuEQErmmLn
claude added 3 commits October 1, 2026 07:49
…254)

#253: Open Config File did nothing. compass.json is not written until a
setting is saved, so the engine refused a missing file; on GNOME no
application claims JSON (editors claim text/plain only); a Terminal=true
default such as Vim was started with no terminal; and the engine
acknowledged a launch before knowing it started, so the launcher hid with
nothing open. The command now writes the file first; a text file with no
opener of its own opens in the text editor; terminal editors run in the
terminal; the engine waits to hear the launch started, falls back to the
OpenURI portal (by descriptor, so it reaches the host from the Flatpak),
and otherwise answers with the reason, which the launcher shows. Show
Log File and the engine share one log path (compass_core::xdg_dirs::
log_file); Open Default Config File writes to the cache directory, which
the Flatpak's host editor can see, and .jsonc opens as text.

#254: an action audit in compass-ui enumerates the builtin commands, the
action panels of every builtin view and every kind of root row, and the
settings view's clickable controls (found by clicking a grid), runs each
in a fresh launcher over recording fakes and fails on any item with no
observable effect. Its inventory is generated into
docs/rust-engine/ACTION-AUDIT.md and checked. The tray e2e test now walks
compass_core::tray's menu model. The power and media commands' refusals,
set inside an already-hidden launcher, now also show in the HUD.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UtGVEzDmYTdpsuEQErmmLn
The grid clicked every line in one simulator, so state an earlier click
left in a widget hid controls further down, and which controls the audit
found moved with the layout: the Adwaita restyle dropped Quick launch,
the appearance preset and icons from it. The unscrolled pass, which holds
every short page whole, now rebuilds per line; a click on the card's
empty corner closes any opened list between lines. The inventory is
regenerated; only the long Commands page's sampled rows moved.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UtGVEzDmYTdpsuEQErmmLn
quay.io no longer serves the old fedora:44 digest (manifest unknown), so
the benchmark job failed at its first build step. The new digest is the
multi-arch index fedora:44 points at now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UtGVEzDmYTdpsuEQErmmLn
@hanthor
hanthor merged commit b710d68 into main Oct 1, 2026
35 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[sec-check] Missing cargo-deny configuration for supply chain security

2 participants