164 Commits
Author SHA1 Message Date
Dax 8752c0f745 linux: recolor the tray mark with the panel's text color (#1691)
KDE's color-scheme portal describes window colors, so a mixed theme such
as Breeze Twilight picked a black mark for a dark panel. Bump rune for
TraySpec::icon_name, write anomaly.hex-symbolic.svg into the user's
hicolor theme at startup, and serve that name beside the pixmap so Plasma
6, GNOME's AppIndicator extension, and Waybar draw the mark in their own
text color. The icon keeps the old white/black default for hosts that
don't recolor, and the installer removes only a marked file.

Goldens follow the rune bump.
2026-11-11 10:46:08 -05:00
Kit Langton f6b2c9cdc5 fix(windows): keep Launch at login on the installed version after a manual upgrade (t1510) (#1670) 2026-11-10 17:34:25 -08:00
Dax f89b9689fb split control settings keys out of settings.rs (#1664) 2026-11-10 18:21:06 -05:00
Dax bce4d0451d add pause from menu bar lab (#1654)
* add pause from menu bar lab (#82)

* pause: hold a resume through Caps Lock and follow the pause in the menu

The neutral-keyboard check skipped Caps Lock and a stale Fn flag, the
menu kept saying Pause Hex while a resume waited, and every listener
pass took the pause lock. Also gate Caps Lock dictation on suspended
shortcuts, refresh secure-input hotkeys at once, and correct the labs
doc's claims.

* pause: drop the unused pause and resume entry points
2026-11-10 17:51:36 -05:00
Dax 6fa9f18bf4 labs: more dictation shortcuts, each with its own mode (#1603)
* more dictation shortcuts: up to four extras, each with its own mode

Labs › More dictation shortcuts (macOS) adds up to four more dictation
shortcuts beside the main one. Each saved row keeps its own binding and
activation mode, registers only while the Lab is on, and shares no key
with another active shortcut. Settings records, clears, and rebinds each
row; the listener runs every press through the same capture pipeline, so
each shortcut finishes with the mode it was pressed with.

* more dictation shortcuts: review fixes

* more dictation shortcuts: follow lone-modifier double-tap, narrow globe check

* more dictation shortcuts: doc nits

* more dictation shortcuts: rebase fixes

Moves the recorded-shortcut checks beside the rest of the shortcut text in
`control/settings/hotkeys.rs` so `control/settings.rs` stays under the
1,500-line ceiling, drops the `labs.rs` size exception now that dev moved the
Feature registry into `labs/feature.rs`, and counts Meeting notes file
alongside More dictation shortcuts in `Feature::ALL`.
2026-11-10 06:25:59 -05:00
Kit Langton c84998da53 feat(onboarding): the first run is one story, from a bad conversation to your first words (#1501)
* Onboarding: slower Without Hex comedy with a start button, a real conversation, and one focus at a time

* Onboarding comedy v2: Launch Room, visible slip, rewind into Hex

Jay's question is up before the click and the first reply comes 0.35 s after
it. The deady/dead slip holds long enough to read, then Return flashes red
with a heavy clunk. The scene is one iMessage group: the removal is a red pill
that wipes a frantic draft mid-word and locks the field. With Hex rewinds the
disaster, melts the keys down to the lit shortcut, and raises the HUD before
the key goes down. The caret no longer sits under a word as it lands. Adds
original chat sounds, a score counted in whole seconds with a chime, and a
live first run that waits for Continue.

* Onboarding comedy v3: one-way melt, clean act breaks, upward rewind, Skip

* Test that Skip appears two seconds in and leaves the comedy

* Fill the keyboard's pocket back in once the HUD has gone

* Onboarding comedy v4 engine: presenting pill, tapbacks, heartbeat, slow motion and the autocorrect slam

* Onboarding: scenes as plain-text files, with a celebration in With Hex

Each scene sets its own room, people, pill, ending and With Hex payoff
(replies, tapbacks, status pills, confetti and fireworks with their own
sounds). The validator reports line-numbered mistakes and the limits a
scene can hold.

* Scenes: document the limits and the folder check

* Onboarding: tapbacks stay on the line above, the pill keeps its own row, and With Hex can change it

* Polish the practice game: themed messages, transcript and high score, real Dot scope, logo build, Replay onboarding

* Scene folder check prints every scene's length

* Flush the ready soundtrack once the logo is built

* Scenes: only the theme's colours, and a clear error for any other

* Check the whole Advanced fold, down to Replay onboarding

* C-plus: v3's scene with the over-the-top With Hex

* Drop the whole-pixel bob now that Rune glides text with its box

* Onboarding chat: the real Messages sounds from macOS, pill in the header

Received, sent and each tapback's sound load at run time from macOS's own files, peak-matched to Hex's stand-ins, which still play where a file is missing and off macOS. The presenting pill moves into the conversation header, level with the title.

* Follow the dictation/ move, and keep a resized golden's render for CI

* Onboarding: keep Reply::Lines' shape so the game's card is untouched

The autocorrect mark goes to chat() as its own argument, and notice() draws sent_bubbles again as dev does.

* Golden: the whole Advanced fold, down to Replay onboarding

* Onboarding comedy: Model M typing, a real heartbeat, three triumph takes

The Without Hex keys are now cut from a CC0 recording of an IBM Model M
(scripts/sounds/comedy/SOURCE.md): eight presses at three pitches, a
deeper space bar and a heavier delete, each at a slightly different level,
whatever key sound the reader picked. The heartbeat is a synthesized
lub-dub under the clicks (HEX_ONBOARDING_HEARTBEAT=off drops it), and
HEX_ONBOARDING_TRIUMPH=1..3 picks brass, a chime run, or a cheer and pop.
scripts/sounds/comedy.py rebuilds them all.

* Follow dev: audio::input_level, and drop Labs' last icon_row import

* Onboarding comedy: tapbacks drawn like Messages

Round badges on the bubble's top corner with a ring in the card's colour
and two tail dots, grey for other people and blue for the reader's own,
every glyph a vector shape including the two-line HA HA. Stacks put the
newest on top. Prototypes/Onboarding/Tapbacks shows them all.

* Move the game's pieces into game/ and its share card into game/share.rs for the code-shape gate

* Labs: hold Paste last dictation to pick recent dictations (macOS)

* Unify the first run: Without Hex, microphone, the practice game, Accessibility

* Let the first run story play itself, game included

* Count the sound cues' third field in the logo-build tests

* Sound the comedy's triumph on the game's first score; Hex Test.app opens the new first run

* Move the stories' side panel into stories/side.rs for the code-shape gate

* First run: play the scripted With Hex payoff after Without Hex; start the heartbeat at the first typo

* Onboarding round 2: Launch Room inbox row, Messages-style senders, ending hold, float-off grants, idle HUD pill, Launch at login on Ready, Settings guide reopen

* Start the heartbeat at the first sent typo, much quieter

* Open the Launch Room like an island: a pointer clicks the row and it grows into the chat

Every first run autoplays: the row arrives with two even rings, a scripted
pointer glides in and presses it, and the row grows into the conversation
(width first, then height, on one straight path) while the group's faces,
the title and Jay's question fly over as themselves. The rest fades in once
the flights clear. Reduce Motion fades instead.

* Add a replay strip to the first run in test and debug builds

Restart, Back one beat, Joke (cycles the bundled scenes) and a fake
download speed (real, 100 Mbps, 25 Mbps; Restart downloads again at it).
Every build logs how long the download showed for. The swearing scenes A
and B are only in builds with hex_dev_onboarding (debug or HEX_TEST_BUILD=1).

* First run: Watch another one while the model downloads

Almost ready shows the download as a quiet bar with its size and time
left, and a button that plays one of three short Without Hex sketches.
The bar moves to the top pill while one plays; a finished download goes
on to the game at the sketch's next stop, after a reply has gone out.
The button goes once all three have played.

* First run: a whole-run story with a slow download and a sketch

* Onboarding: sound for the whole first run, the Launch Room opens itself, and a motion gate

- SfxTrack::clear keeps cues already fired, so the offline track keeps its first 73 s; the scripted game, the words and the cards burning get cues.
- The download pill no longer flies over the words it passes; the Launch Room opens itself 5 s after it parks.
- A motion gate over the first run in dark, light and Reduce Motion, plus a pixel check of the conversation opening: fixes its surface blinking as the plate hands over, Jay's doubled typing dots, the badge's one-frame pop and the preview's text swap.

* Onboarding: the Launch Room's click taps, whether a person or the pointer clicks

* Rune e6371c48: the motion gate checks what the first run paints

- Bump rune, rune-kit, rune-theme-opencode and rune-motion to e6371c48 (rune#71); nix outputHash follows.
- Mark the first run's deliberate motion where it's written (tapback bounces, the badge pop, keys, the game's shake) and narrow the allowlist to scoped, capped rows.
- The empty avatar slot keeps its border while its fill fades, so the ring no longer vanishes a frame early.

* Onboarding: the first run's clock runs on drawn frames, and its later pipelines warm on a thread (t1328)

* Onboarding: call out keyboard and voice-first modes, punch in on autocorrect, prototype first-screen backdrops

* Onboarding: drop the first-screen backdrop prototypes (t1328)

* Onboarding: prototype a bigger HUD and an up-next row on Setting up Hex (t1328)

* Onboarding: the Linux tests' page helper knows the two permission steps (t1328)

* Onboarding goldens: the voice-first chip beside the heading (t1328)

* Onboarding: first-screen prototype shows download size and an on-device note (t1328)

* Onboarding: the first screen shows download size and that your voice stays on this Mac (t1328)

* Onboarding: a failed download drops the size and privacy line; goldens for the first screen (t1328)

* Onboarding: drop the render scratch the branch carried

673 frames and one-off scripts under .render/ were the scratch of the
session that built this, not part of the change.

* Keep render scratch and scene stills out of the tree

* Onboarding: the scene tests that need a dev-only scene skip release builds

A and B swear, so release builds leave them out of the bundle; two tests
still asked for A by name and panicked where it was missing (the Nix
package's test run).

* Onboarding: goldens from the Linux run after the merge

Seventeen onboarding renders moved: the first screen's download size and
privacy line, the mic line from #1420, and dark text that sits a few pixels
lower with dev's Rune pin.

* Onboarding: a tighter opening and fireworks that light the page

The first run's Setting up Hex holds a second, then the Launch Room's
conversation is there as the download flies up: Jay's messages land in
it with their sounds instead of on an inbox row a pointer clicks open.
The Keyboard mode stamp goes (the heading's chip says it), Without Hex's
heading is one line, and the privacy line also shows on the microphone
step.

With Hex's fireworks move to the GPU: three shells rise on trails and
burst beside the conversation into a few hundred sparks each, white-hot
to hue to crackling embers under drag and gravity. Each burst lights
the page under it for a moment, multiplying what's drawn so surfaces
brighten by their own colour and the dark page barely does. Reduce
Motion gets one soft flash. The shipping scene drops its confetti.

* Onboarding: sketches keep their own opening; the motion gate follows the shorter intro

Sketches built their scenes from the first run's timing, so its shorter
opening reached them. The slow-download fixture lands the model 6.8 s
sooner, as much as the intro shrank, so the gate's windows see the same
story; the practice game's shake can still be moving as the handoff
window ends.

* Fireworks: stars light as they leave the break, the shell's glitter is quieter, and the page light fades with no edge

* Onboarding: fireworks in depth, and three compositions to compare

Fireworks burst in two layers. Far shells sit behind the conversation,
smaller, dimmer and softer, lighting it a little; near shells draw in
front, bigger and brighter, their sparks falling across the card's
edges for a moment and their light hitting it hard, with their cores
kept beside it. A break opens as a bloom: packed stars share its light
until the shell has spread, since sRGB-encoded blending adds a hundred
faint stars up to a white disc.

The demo's composition is now a layout the run picks, as it picks its
scene, with three playground variants beside today's: A, a tighter
centre (one two-line heading for both scenes, a larger conversation,
the keyboard tucked under it, Skip in the corner); B, a split (the
mode, a big title and one line in a left column, the conversation and
its keyboard on the right, the fireworks in the open page); and C, a
laptop (the conversation as its screen, the keyboard on its deck).
Today's layout is unchanged.

* Onboarding: the score pill hugs its count, and a near burst's break stays compact

The practice game's score pill was a fixed 112 pt with its content left
aligned, so "1 destroyed" sat 12 pt from its left edge and about 40 pt
from its right. It's now as wide as its number and label need, with
12 pt either side in every language, and the share card folds back to
that width. A near burst's bloom no longer spreads into a wide, faint,
whitish disc that read as smoke. Headless renders take
HEX_RENDER_LANGUAGE to check copy in another language.

* feedback: the onboarding's cues in their own file, under the size limit

* Onboarding: the card's landing nudge is a kick, and the motion gate gets the time it needs

* Onboarding: goldens after dev's language-switch change and the microphone step's privacy line; the playground's two-line heading stays English

* Onboarding motion: the game's idle pill fades on its clock, sent bubbles leave the field whole, and the Accessibility helper line fades out

From per-frame traces of the whole scripted run:

- The practice game's stage lands every change at once, so the idle
  pill's springs never ran: it vanished and reappeared in one frame at
  every take, and when the score card came and went. Its fade and
  settle are now worked out on the game's clock, from when the scope
  last came or went, and it steps aside with the chrome.
- A sent line is launched out of the field, but its bubble faded in on
  its own, so each send started as a ghost of the text it left (five
  sends in Without Hex, the spoken answer in With Hex). The bubble now
  enters with its line.
- The escaping Accessibility panel dropped its "Accessibility helper"
  line in one frame; it fades as the panel starts to move.

* Onboarding motion: the idle pill's spring is settled before the first take, not NaN

* Onboarding motion: a sent bubble's words leave the field at full strength too

* Onboarding fireworks: a burst opens on a point of light, not a grey disc

The bang was a wide glow at a quarter of white, which sRGB-encoded
blending flattens into a grey-beige disc for three frames before the
stars show. It is now small and brighter than white, gone as they open.
On light pages the bursts' tint has a soft shoulder instead of a flat
plateau of colour, and sparks paint a deeper hue so gold shows on white.

* Onboarding copy: the certificate's sentence, the game's full stop, Accessibility's row on one line

- "I hereby certify that I have completed Hex onboarding."
- The game's lead ends its sentence, as every other lead does.
- Accessibility's row drops "in any app", which the line above it
  says: allowed, it wrapped and left "app" alone on a second line.
- The permission pages' headings are translated like their titles.

* Onboarding: alignment and one main action

- Skip steps aside while autocorrect's camera is pushed in: the
  keyboard swelled down over it.
- The score card's two lines sit on the middle of the number.
- The score pill is as tall as Done beside it.
- Hex is ready keeps one contrast button: beside Start using Hex,
  Launch at login is a neutral one.

* Onboarding pacing: Setting up Hex holds long enough to read, the removal holds once

Setting up Hex held 1.0 s before the download flew up; 1.6 s reads.
The first run held the removal for the scene's own 2.0 s and 1.6 s
more, 3.6 s of silence; now 2.8 s.

The game's screen shake is marked where it's written, a kick and
steps, rather than allowed by where a gate window happens to end.

* Onboarding: the certificate in its own file, and no unused import

The motion fixes took game.rs past its size ceiling and left Spring
imported with no use; the certificate moves out to game/certificate.rs.

* Onboarding goldens: the game's full stop, and Launch at login beside Start using Hex
2026-11-09 17:29:51 -08:00
Kit Langton 0264d5a8e0 build-app: keep cargo's output off stdout, which carries the bundle path (#1612) 2026-11-09 12:20:58 -08:00
Dax 8201a4ce1c ci: read release secrets from aws secrets manager (#1606)
* ci: read release secrets from aws secrets manager

* ci: read the linux signing key from hex/release/RELEASE_SIGNING_KEY

* ci: hex's own aur and homebrew keys; the signing cert has no password

* ci: the signing certificate has no password

* ci: use the shared aur and homebrew keys

* docs: the shared homebrew deploy key is anomaly-release

* docs: the shared homebrew deploy key is anomaly-release

* site: own /hex/files, drop the r2 write credential (#1611)

* site: own /hex/files for installers, appcast, and dev notes

The site build now copies install-linux.sh, install-windows.ps1, and
packaging/macos/legacy-appcast.xml into its Worker assets, so the same
Worker serves them at /hex/files with the Content-Type and Cache-Control
the bucket objects had. The Installers and Legacy appcast workflows,
r2-put.sh, and their R2 write credential are gone.

The dev notes move to the one-commit dev-notes branch, published by
Release's dev-notes job with GITHUB_TOKEN only; the Worker proxies that
file at /hex/files/dev-notes.json (falling back to the bucket copy until
the first dev release creates the branch) and renders /hex/dev from it.

Both site Workers now bind hex-production-files, read-only in code, for
the frozen 2.3.1 feeds and artifacts, which lets hex-dev-files go. The
Site build runs the installer test and appcast check the removed
workflows ran, and the verify job compares the served bytes.

* docs: the site owns /hex/files and needs no R2 write credential

Hosting, secrets, old clients, and Linux packages describe the built
installers and appcast, the dev-notes branch, and the read-only bucket.
2026-11-09 15:18:26 -05:00
Kit Langton 66489c058a install-app: copy the new Hex in before removing the old one (#1608) 2026-11-09 19:32:14 +00:00
Kit Langton b303fd1246 scripts/check: name the root package without its checkout path (#1419) 2026-11-05 12:36:51 -08:00
Dax 3d87d0d7de fix(nix): truncate Cargo.lock stanzas in the pin check (#1408)
Stop a package stanza at the next table header, so a sourceless workspace
crate cannot borrow a following [[patch.unused]] Git source.

Assert the exact multi-crate problems instead of a string the script never
prints, and cover a sourceless package and a trailing patch table. Match the
test file in the compile path filter and the agent policy.
2026-11-05 14:52:49 -05:00
Dax b07b1a2083 fix(nix): follow Cargo.lock fragments in the pin check (#1405)
Read the resolved commit from the fragment, so branch, tag, short-rev, and
bare Git sources all work. Parse Cargo.lock's package stanzas with re so the
check runs on macOS's Python 3.9, reject lib.fakeHash, and normalize a .git
suffix when grouping repositories.

Add tests for each source form, a multi-crate repository, a stale revision,
and a fake hash. Flag the pin check itself in the agent policy.
2026-11-05 14:15:57 -05:00
Dax 83dcd3943b fix(nix): hash Rune's current revision and guard git pins (#1399)
The Rune 7d3ee6ca bump updated the Nix pin but not its output hash, so
nix build failed with a fixed-output mismatch.

cargoGitDependencies now records each Git dependency's revision beside its
output hash, and scripts/check-nix-git-pins.py fails when Cargo.lock names a
different revision. compile.yml runs it for Cargo.lock and nix changes.

Fixes #1397.
2026-11-05 13:03:19 -05:00
Dax 6958927696 Windows: hex.com console entry point beside the GUI hex.exe (#1374)
* Windows: ship hex.com, a console entry point beside the GUI hex.exe, on PATH

* lock, fmt, legacy adoption

* clippy

* build hex-console in its own cargo run: -p hex is ambiguous with the hex crate

* hex.com returns once the app starts; Ctrl+C only; install script and Setup replace a running hex.com; hex-console checks in Compile

* fmt

* installer test: exit 0 once every check passed
2026-11-05 06:52:51 -05:00
Dax 6cfefd3cd1 Windows: open with no console window or white flash (#850) (#1373)
hex.exe is now a GUI program. Commands run from a terminal join it
(AttachConsole) and print there; the app leaves it after startup errors
have had their chance to print. Rune 31dbcad cloaks a window until its
first frame presents. Release checks assert the GUI subsystem.
2026-11-05 05:42:29 -05:00
Dax 87797fe537 Windows: a receipted install always updates itself, and one that can't says why (#1352) (#1353)
* Windows: a receipted install always updates itself, and one that can't says why (#1352)

* Windows receipt repair: tolerate a byte order mark
2026-11-04 23:42:39 -05:00
Dax 9193c40ac0 windows: start without a Vulkan 1.2 driver (#1240) (#1249)
* windows: delay-load vulkan-1.dll and fall back to CPU without a Vulkan 1.2 driver (#1240)

* windows: note vulkan-1.dll is delay-loaded in restrict_dll_search
2026-11-04 03:51:13 -05:00
Dax ad1fb8b308 split app_settings under the shape cap, and cover meetings.opencode_model in the settings key check (#1117)
* test meetings.opencode_model's hex settings key and cover it in the cli key check

* split app_settings into meetings, capture and labs modules, under the shape cap without an exception

* make meeting retention encoding visible to app_settings, and rustfmt
2026-11-03 07:36:27 -05:00
Kit Langton ffea9ef19e Keep the old Sparkle key so 2.3.1 and Swift Hex can update into the new Hex (t1217) (#1092) 2026-11-02 21:44:19 -08:00
Dax 04f7ed0a7f Split suppression.rs under the code-shape cap (#1080)
* Split the dictation shortcut state machine and tests out of suppression.rs

No behaviour change: DictationHotkey and its state move to
suppression/hotkey.rs and the module tests to suppression/tests.rs, bringing
suppression.rs under the size cap; its exception is removed.

* Format history.rs (cargo fmt --check fails on dev since #1070)

* Gate Again::finished like the Rune UI tests that use it (macOS test build fails on dev since #1070)

* Keep recovery from counting as neutral evidence; fix the Hold-mode cancel test's Escape flags

Stale-key recovery rebuilds only the held modifier flags (#1076): its
non-atomic scan must not vouch for keys whose delayed edges may still
arrive. The Hold-mode case of the cancel-shortcut test sent Escape without
the held Option, which reads as a release.
2026-11-02 22:23:12 -05:00
Dax 5e4ad57ade Split app_settings, suppression and linux input under the code-shape caps (#1049)
* Split app_settings hotkeys, suppression's event taps, and linux input's X11 side into submodules

* Visibility for split submodules' tests

* Lower the split files' size ceilings
2026-11-02 13:00:18 -05:00
Dax c20aaec3cf Toggle mode: a cancel shortcut, Escape by default (#786, #1022) (#1046)
* Toggle mode: a cancel shortcut, Escape by default (#786, #1022)

* Cancel shortcut row: scenes, goldens test, restore test

* test: refresh after editing settings

* Docs, AGENTS invariants, and goldens for Toggle's cancel shortcut
2026-11-02 11:54:22 -05:00
Dax 1c70d227b5 Linux releases run on Debian 12 (glibc 2.36) (#1043)
* Linux releases run on glibc 2.36 (Debian 12) (#1026)

* Linux installer works with Debian 12's curl

* Linux build image: shaderc 2026.1 and Vulkan headers 1.4.341; fresh test-build cache

* Address review: capped stable probe, apt update, toolchain path, cache key
2026-11-02 11:45:38 -05:00
Dax 4f3a9e5e71 onboarding: skip only the demo and practice; continue without a model after a failed or stalled download (#1009)
* onboarding: skip only the demo and practice; continue without a model after a failed or stalled download

* settings: add model file button in model_import

* settings: status says no model

* goldens: no Skip on required pages; continue without a model

* clippy

* fmt
2026-11-02 08:52:22 -05:00
Dax fbd05ffdf7 GitHub's Latest release is the stable app release, never the SDK (#1004) (#1007)
* GitHub's Latest release is the stable app release, never the SDK (#1004)

* docs/releasing.md: the stable app release is Latest
2026-11-02 08:40:49 -05:00
Dax Raad c0f75df498 split rune_ui.rs and modes.rs under the code-shape limit
rune_ui.rs moves its sidebar (panes, nav items, footer) to rune_ui/sidebar.rs
and its --scene fixtures to rune_ui/scenes.rs, dropping its file-size
exception. modes.rs moves the transformations section to
modes/transformations.rs. No behaviour change.
2026-11-02 08:06:57 -05:00
Dax 36ac4d7140 Explain the desktop's paste permission before it asks (#932) (#935)
* Explain the desktop's paste permission before it asks (#932)

* Golden: the paste permission page
2026-11-01 17:00:18 -05:00
Dax dba85964b0 Onboarding: a quiet Skip on every page (#926)
* Onboarding: a quiet Skip on every page

* Skip in the quiet text colour, level with Back

* Goldens: Skip on every page but the last
2026-11-01 16:36:25 -05:00
Dax 2f442fbf6f Make the new onboarding the one first run on every build and OS (#902)
* Onboarding: stay on the model list once a pick is ready, and Back returns to it

* Docs: the model list stays once ready, and Back returns to it

* Test: allow the advance beat under load

* Make the new onboarding the one first run on every build and OS

* Drop the tour's Back and page dots, which only the old view used

* French for the first run's strings

* Test the story's stopped download names why and offers a model file

* Golden: the stopped download names why and offers a model file
2026-11-01 16:17:59 -05:00
Dax c782f5e39e Onboarding gates stable releases: scene goldens and a clean first run (#864)
* Onboarding gates stable releases: scene goldens and a clean first run (scripts/check-onboarding.sh), wired into Release

* Onboarding check: hero drawn, mic scenes, no false passes, locale pinned, dispatchable Check macOS

* Onboarding goldens: dark found scenes after #865

* Onboarding walkthrough: say what the fixture window doesn't do
2026-11-01 13:44:03 -05:00
Dax e041186c0d Linux: Background portal for running in the background and Launch at login (#812); launcher entry written once (#810) (#824)
* Linux: use the Background portal for running in the background and Launch at login (#812); fallback entry written once (#810)

* test names

* Docs: Background portal and Launch at login (#812)

* Background portal: only once registered (1.20+), symlinked entries are the user's, serialize entry writes and login changes

* doc comment
2026-11-01 07:41:50 -05:00
Dax 3a2304386d Remove dictation cancel: Escape ends nothing (#786) (#795)
* Remove dictation cancel: Escape ends nothing (#786)

* Format and refresh the sound sets and commands goldens

* Release Escape before finishing in the held-capture test
2026-11-01 06:16:03 -05:00
Dax cc286a09a2 Dev notes: parenthesize the title so jq 1.7 builds it (#780) 2026-11-01 02:29:33 -05:00
Kit Langton 37bc8642be fix(linux): keep custom data roots out of desktop recovery (#772) 2026-10-31 23:58:32 -07:00
Dax 47efc1a661 Dev builds say what's new: notes from PR titles in the dev feed, /hex/dev, and Restart to update (#763) (#774)
* Dev builds say what's new: notes from PR titles in the dev feed, /hex/dev, and Restart to update (#763)

* Dev notes: keep ReadyToRestart's wire format; canonical upload; script and refetch fixes from review

* Sidebar update in its own module (code-shape)
2026-11-01 01:56:38 -05:00
Kit Langton cf58816437 fix(settings): preserve invalid settings before saving repairs (#749)
* fix(settings): recover invalid fields and preserve original settings

* test(settings): keep malformed originals in place on load
2026-10-31 21:53:45 -07:00
Kit Langton e0a55b4d5f Add code-shape gate and ratcheted exception lists 2026-10-31 18:57:51 -07:00
Kit Langton fb87ecf28b Add agent marker and drop internal references (#702)
* Add agent marker and drop internal references

* Format
2026-10-31 18:30:32 -07:00
Kit Langton 0d5f1c3097 Fold linux_* into linux/ 2026-10-31 14:32:07 -07:00
Dax 46c3c76260 Linux: ship Hex's icon as anomaly.hex everywhere (#652) (#655)
* Linux: ship Hex's icon as anomaly.hex everywhere (#652)

* Linux icons: mark Hex-written PNGs, keep the user's own, tidy autostart Icon (review)

* AGENTS: icon mark

* Installer: touch hicolor best-effort
2026-10-31 15:33:04 -04:00
Dax ab2e819f1a x86_64: keep ggml on x86-64-v3; refuse older CPUs with a clear message (#592) (#614)
* x86_64: keep ggml on x86-64-v3 and refuse older CPUs with a clear message (#592)

Reverts #595's Ivy Bridge floor: it slowed CPU transcription for everyone. ggml goes back to its x86-64-v3 defaults (AVX2, BMI2, FMA, F16C). Hex's own Rust stays baseline x86-64, and the first thing main does on Linux and Windows x86_64 is check AVX2/BMI2/FMA/F16C with is_x86_feature_detected!. Without them Hex prints and shows "Hex needs a 2013 or newer processor (Intel Haswell / AMD Excavator or later) with AVX2. This PC's processor isn't supported." (a native MessageBox on Windows; stderr, which the journal logs, and zenity, kdialog or notify-send on Linux) and exits 1. Every command is covered except --version and --help, which installers and the updater run. ggml-cpu has no static constructors, so nothing runs v3 code before main.

The release guard now asserts the opposite: ggml's CPU libraries must hold AVX2 and FMA (the build targets v3) and no AVX-512 or AMX. Docs state the requirement.

* cpu_floor: harden DLL search first; no dialog under systemd, in a terminal or for hex service; guard rejects AVX-VNNI

* cpu_floor: always exit 1; Windows always shows the message box; Linux skips the dialog in a terminal, under NOTIFY_SOCKET, or for hex service
2026-10-31 13:20:56 -04:00
Dax 8a130e63e5 Lowercase release file names; README downloads by channel (#456) (#601)
* Lowercase release file names; README downloads by channel (#456)

Release builds and the GitHub release mirror now name files hex-<version>-macos-arm64.{zip,dmg}, hex-<version>-windows-<arch>.exe and hex-setup-<version>-windows-<arch>.exe (Linux was already lowercase), as @vixalien asked in #456. Already-published files and the frozen 2.3.1 feeds keep their names; the release service's published names (hex, Hex.dmg, Hex.zip, hex.exe, HexSetup.exe) and the bundle (Hex.app) are unchanged, so the updater, installers, Homebrew cask, AUR and Nix are unaffected.

The README downloads table has Stable and Dev columns for every target, including the updater files. The site Worker serves /hex/download/dev/<target> (the dev alias) beside /hex/download/<target> (stable, or dev while there is none), and both now cover the bare updater files.

* Lowercase names in two remaining examples

* Lowercase the Windows executable in the CPU check step
2026-10-31 12:51:09 -04:00
Dax 34b74d3e42 x86_64 releases: build ggml for the Ivy Bridge floor; guard against BMI2/AVX2/FMA (#592) (#595)
* x86_64 releases: build ggml for the Ivy Bridge floor and fail on BMI2/AVX2/FMA (issue #592)

GGML_NATIVE=OFF alone leaves ggml's GGML_AVX2/BMI2/FMA/F16C on, so Hex 3.0.0 on Windows x64 died with 0xc000001d (illegal instruction) on an Ivy Bridge Xeon E3-1220 V2 once transcription started (reported by @Hc-Web-Dev). Linux and Windows x86_64 release builds now pin SSE4.2 + AVX + F16C and turn AVX2, BMI2, FMA, AVX-VNNI, AVX-512 and AMX off (scripts/ggml-x86-baseline.txt), the floor transcribe.cpp already uses on Intel Macs. Runtime dispatch (GGML_BACKEND_DL + GGML_CPU_ALL_VARIANTS) needs shared ggml libraries, which our single static executable can't ship. CPU transcription on newer x86 CPUs loses AVX2/FMA kernels; Vulkan is unaffected.

.github/release/check-x86-baseline.sh guards both build jobs: the executable may hold no BMI2 instruction (3.0.0's Linux build holds 100; Rust crates that use AVX2/FMA/AVX-512 behind run-time detection use none), and the ggml static libraries no AVX2, BMI2, FMA or AVX-512. No crate sets target-cpu; the only rustflags are +crt-static; no other C/C++ dependency builds with -march=native or AVX2 (Moonshine/ONNX are gone).

* check-x86-baseline: fail on missing inputs or empty disassembly; match llvm-objdump's suffixed BMI2 mnemonics
2026-10-31 12:21:26 -04:00
Dax 1018aecdbb Linux: ship the desktop entry as anomaly.hex.desktop (#582)
* Linux: ship the desktop entry as anomaly.hex.desktop (#579)

* Linux desktop entries: keep symlinks, tidy fallbacks at startup, address review

* fmt
2026-10-31 09:00:45 -04:00
Dax fc92b99cc3 hex control rides the local API on every OS (#550)
Linux and Windows now hand the local API's POST /control to the shared
control host, so the CLI reaches every OS through local-api.json and
call_control. The Linux socket's Request::Control and the Windows named
pipe (windows_control) are gone.
2026-10-30 22:46:10 -04:00
Dax b9ba1eb4a2 One hex control CLI and protocol on every OS (#544)
* One hex control CLI and protocol on every OS

One command tree (control::cli) on macOS, Linux, and Windows, carried by
each OS's owner-only transport: the macOS local API, the Linux socket's
Request::Control, and a new Windows named pipe (windows_control) that only
this user's SID can open and whose server the client verifies. Linux and
Windows share one host (control::host) through thin adapters; what an OS
can't do answers unsupported at runtime.

Windows gains dictation (with stop --print), paste-last, quit, restart,
start, a live status, and every annotate command; Linux and Windows gain
settings, model, window, vocabulary, history clear, check-for-updates,
launch-at-login, onboarding reset, logs, commands init|check, and annotate
status. hex status reports the OS's capabilities, settings name the
capability they need (set refuses, list marks), and a parity test requires
a recorded reason for every capability that differs across OSes.

* Windows control pipe: always hold an unconnected instance; check the client's user

* Shared control: meetings, history, and mcp on every OS now that the meetings store does
2026-10-30 22:41:39 -04:00
Kit Langton f9f5984b46 Thock sound set from the team vote (#515)
* Thock sound set from the team vote (t1119)

* Regenerate the Sounds sheet goldens for Thock (t1119)
2026-10-30 15:10:19 -07:00
Kit Langton ce6f62e8b7 feat(experiments): gate experimental panes in production, promote Output tab, and remove Smart Turn (t965) (#430) 2026-10-30 09:02:45 -07:00
Kit Langton 17db1d66eb Onboarding: flat crisp UI, live Try, slow keyboard arrival, and 4 key-sound candidates (t405) (#409) 2026-10-30 06:43:58 -07:00
Kit Langton a8a4645d45 Remove spoken commands and Moonshine (#424) 2026-10-29 17:36:38 -07:00