Watch
1
0
Fork
You've already forked souveraine
0
Commit graph

571 commits

Author SHA1 Message Date
Fimeg
6f375286bf multitasking: the cards were zero pixels wide
ZoneOverview took its width from the Column it sits in, and a Column is as
wide as its widest child. The drawer's search widget supplies that; mission
control is the cards alone and has no search, so the only child left was the
loader — whose width came from the column, whose width came from the loader.
The cycle resolves to zero.

Full-height zero-width cards draw nothing, which is why multitasking was a
blurred backdrop and nothing else while every other signal read healthy:
zones 2, windows 1, subscribed true, loader active, item present, opacity 1,
progress 1. Bound to the panel's width instead, which is what this surface
covers anyway.

Also adds `overview missionControl` and `overview state` — the surface that
had been reported broken was the one nothing but a pill swipe could raise,
and the state readout is what located this.
2026-08-07 01:32:27 -04:00
Fimeg
5ec6bfdc63 overview: a verb for mission control, and a state readout
Multitasking was raised only by the pill's first-stage swipe, so the one
surface that has been reported broken was the one neither an agent nor a test
could reach. state() reports what the cards are drawn from.

Used it immediately: with a window open the model is not empty — zones 2,
windows 1, subscribed true — so the missing cards are not missing data.
2026-08-07 01:23:14 -04:00
Fimeg
075ddf19eb face: locking sends her away, and she stays away
Gated on screenLockSecure, the compositor's ack, not on screenLocked. The
request drifts: measured on the phone, `session lock` answered already-locked
while logind reported LockedHint=no and the phone was in use. That is a
shadow copy of state the protocol owns, and a face gated on it would have
been permanently dismissed with nothing on screen to explain why.

No return on unlock. You come back to the clock and summon her if you want
her, rather than finding whatever was left on.
2026-08-07 01:11:13 -04:00
Fimeg
c8dc24d3d1 face: follow the finger anywhere on the panel
Subscribes to viewtop's gaze feed and dispatches a synthetic pointer move on
the canvas, so live2d.js's own mousemove path drives head angle and eye
direction with its existing damping. Synthetic is the point: she is
deliberately not being given those contacts, and this lets her watch them
anyway.

Screen coordinates in, her window's coordinates out — the origin comes from
the compositor's furniture report rather than assumed, because the layout
decides it and it moves with the zone.
2026-08-07 01:01:05 -04:00
Fimeg
ae432e7654 dial: hold the camera to record the screen
Entries may carry a hold verb beside verb; the ring fills while it charges so
the commitment is visible while it is still cancellable, and sliding off
cancels. Holding the camera starts a recording, tapping or holding it again
stops it — the same seat, because the dial is muscle memory.

No wf-recorder or wl-screenrec on the device, so it is grim piped into
ffmpeg. Half scale: at 1080x2160 grim manages about 3.5 fps and a recording
that captures a third of its claimed frames plays back at triple speed.

Its own process group, and SIGINT to the group: only ffmpeg can finish the
file, so killing the shell alone would orphan a screen capture with no way to
stop it.

Reachable as a verb too, not only by thumb.
2026-08-07 00:24:12 -04:00
Fimeg
ac35b3436b her face on the glass: it draws, it listens, and it gets out of the way
The rig never drew. live2d.js is not only the Cubism runtime — it carries the
reference's character layer, which reads #live_talk every update as its
motion-state slot. Our page omitted the element, so it threw on the first
frame after the model and all four textures had loaded: assets 200, WebGL
live, no error reaching Rust, blank canvas.

--app-id was a no-op. set_prgname ran after GTK had already created the
surface, so the compositor saw souveraine-web and window rules could only
match the title. It has to run before the event loop.

Press and hold her to speak: pw-record at 16k mono s16, release transcribes
through souveraine-stt --file and goes out over Souveraine.send, so the
sidebar logs it. Whisper wraps with newlines and the transcript arrives
through a SplitParser, so it is collapsed here or one utterance becomes four
turns. Double tap dismisses; the clock and quote fade out when she is up and
the clock stops being a target, because a double tap on an invisible object
is not a way back.

The page reports its silhouette and the host installs it as the input region.
Claiming the GL context for preserveDrawingBuffer must happen after the
canvas is sized — before it, the context is born 300x150 and she renders as a
thumbnail in the corner.

Console and errors are forwarded to the host's stdout. Without that a rig
that fails to draw is silent in every direction, which is what cost this
the afternoon.
2026-08-07 00:24:12 -04:00
Fimeg
78496e10e1 gamma goes to the compositor, not to a binary that is not there
hyprsunset does not exist under viewtop and execDetached cannot fail loudly,
so the brightness slider and the night light have done nothing since the
move. Same public surface, pointed at viewtop's gamma verb. TASK-61.

Keeps the upstream name: every consumer in the tree spells it, and renaming
across the base tree and the phone overlay is its own sweep.

import Quickshell was missing, which made the Singleton type unavailable and
failed the whole qs.services module — 29 singletons, 28 had it. The phone's
shell was in a restart loop with a 26-line cascade whose only real line was
the last one.
2026-08-07 00:24:12 -04:00
Fimeg
4ff8d2e236 gamma: the brightness slider drives viewtop's LUT, not hyprctl (TASK-61) 2026-08-06 18:57:01 -04:00
Fimeg
c2dcbe7b7f rail: a keyboard-up climb means only a swap, never navigation 2026-08-06 11:54:45 -04:00
Fimeg
7f294a5fa2 the face draws: relative asset paths over loopback, and a dead socket stops being a gate 2026-08-06 11:18:23 -04:00
Fimeg
d1e580ee00 drawer: the search field stops auto-focusing on the phone; tapping it summons the keyboard 2026-08-06 11:03:47 -04:00
casey
3d3eb2cc8e the avatar draws: serve the rig over loopback, not the opaque scheme 2026-08-05 22:14:07 -04:00
Fimeg
a5f0fadba8 unlocking closes a keyboard nobody asked for 2026-08-05 21:55:11 -04:00
Fimeg
269c151899 the wry host is optional through the whole pipeline; it must not block sessiond 2026-08-05 21:29:24 -04:00
Fimeg
d4f9213a34 wry host compiles: tao 0.36 event loop, Cow bodies, app id is the program name 2026-08-05 21:00:35 -04:00
Fimeg
620c7d313d placement grades a covered sensor instead of gating on it; squeeze test follows the fix 2026-08-05 20:23:29 -04:00
Fimeg
fe48bb76c5 the rig ships with the repo; it is self-hosted 2026-08-05 20:11:49 -04:00
Fimeg
8e3120c5a0 the face stays quiet when the rig is not staged; add stage-face.sh 2026-08-05 20:11:31 -04:00
Fimeg
bb81781007 the backdrop is the input region, so it owes the way out 2026-08-05 20:10:40 -04:00
Fimeg
1ac33afb25 dock is home's alone; the pill stops riding above it 2026-08-05 20:04:45 -04:00
Fimeg
425693a298 placement compiles: one field per snapshot, and it deserialises 2026-08-05 19:59:29 -04:00
Fimeg
b71f9c9d4f a refused subscribe stays refused; it was re-arming its own retry 2026-08-05 19:50:53 -04:00
Fimeg
9b470b8e22 split chooser names its windows and brings the pick to the zone 2026-08-05 19:45:07 -04:00
Fimeg
9ec031c8a8 wry host: sites as apps, the rig as a face; join loads the expression skill 2026-08-05 19:39:50 -04:00
Fimeg
d7965a57fd two swipes, one progress; home is zone 0; pocket is a belief 2026-08-05 19:16:41 -04:00
Fimeg
6c0730a790 the sheet scrims its own window, not the screen 2026-08-05 16:43:14 -04:00
Fimeg
0e7dec53d1 the app scales into multitasking; pill has two destinations 2026-08-05 16:34:51 -04:00
Fimeg
277a0d2b32 dock lives on zone one; short swipe multitasks, big swipe goes home 2026-08-05 16:17:47 -04:00
Fimeg
c3f998f17a move is a mode: grab, drag, done 2026-08-05 15:35:40 -04:00
Fimeg
b0688bc30b split chooser, home reaches the compositor, idle-inhibit comment was backwards 2026-08-05 14:52:48 -04:00
Fimeg
f7eba9f658 hold power for a device menu; usb-c state shown, not faked 2026-08-05 14:37:56 -04:00
Fimeg
bf8bc013ef three-finger tap opens a window sheet, not the overview 2026-08-05 14:12:22 -04:00
Fimeg
3aea8398a9 shell: intent wins the settle window, and a swap is a request for a keyboard
Two gaps in the owner-change handling, both found on device.

The push at adopt time can lose a race. osk-switch sleeps 0.3s before
its deliberate SetVisible(true), and stevia self-shows once it has
finished coming up - both land after the shell has spoken. Measured:
adopt+hide 07:37:51, Visible=true 07:37:52, leaving oskOpen=false with a
keyboard on the screen. Re-assert when the settle window closes so the
last speaker is not the winner.

And the oskSwap gesture never recorded that a swap means the user wants
a keyboard, so osk-switch's re-show and the shell's stale false were
racing with nothing to arbitrate them. Declare the intent first.
2026-08-05 07:41:02 -04:00
Fimeg
d7a04f27d5 shell: an owner change is not a visibility event
sm.puri.OSK0 is a name, not a process. Boot, a crash-restart and an
osk-switch swap each put a fresh keyboard behind it, and the visibility
monitor mirrored the newcomer's opening claim into oskOpen as though the
user had asked for a keyboard. Measured: shell up 03:03:38, self-showed
at 03:03:43, nobody near the phone.

Track the bus owner - gdbus already prints it and the 'Visible' filter
was throwing it away - and on a change push oskOpen at the new owner
instead of pulling state out of it. A process that just started has no
history; the shell is the continuity of intent across the keyboard's
lifetime.
2026-08-05 07:34:53 -04:00
Fimeg
bc09480375 claude: adopt rotated credentials instead of failing until restart
The credential file is shared with `claude` itself and its refresh token is
one-time-use, so whichever process refreshes first rotates the other's copy to
spent. On a failed refresh the provider kept the stale token and 400d every
turn until the service was restarted by hand — measured 2026-08-05, invalid_grant
from 00:03 onward while the file on disk already held a valid pair written at
00:08.

Re-read the file on refresh failure and adopt the token when it is different and
still live. oauth/refresh.rs already does this for the Codex path; the Claude
path never got it.
2026-08-04 20:25:24 -04:00
Fimeg
ca272d1d7d shell: the bar claims its space instead of asking to be ignored
exclusionMode was ExclusionMode.Ignore, which tells the compositor to
disregard the exclusive zone outright — so the expression below it computed
a height that was thrown away and every window laid out underneath the bar.
The bar is not app space while it is visible.

Auto-hide still yields 0, so a bar configured to hide gives its space back;
the mode only says "honour what I claim".

Not deployed: the phone locked itself on session start, which is
lock-on-startup firing for the first time under viewtop (80cb4b2), and
deploy.sh refuses a live deploy into a locked session.
2026-08-04 19:27:53 -04:00
Fimeg
80cb4b289d shell: read the instance file synchronously, or it is empty when asked
FileView loads async, so text() was still empty when onReadyChanged read it
once to decide whether this is a new session. It fell through to the unset
env var and persisted "" — the same bug, reached by a different route.
Verified on device: the stored signature now matches viewtop.instance.
2026-08-04 19:25:59 -04:00
Fimeg
95dd21b998 shell: take the instance signature from viewtop, not from Hyprland's env
HYPRLAND_INSTANCE_SIGNATURE is unset under viewtop, so this compared "" to
"" and isNewHyprlandInstance was false on every start. It gates
lock.launchOnStartup, which has therefore never fired once under viewtop,
and both Idle.qml copies read it as well.

viewtop publishes viewtop.instance beside its control socket — pid plus
startup nanos, different every start. Read that first, fall back to the env
var so a Hyprland session (the laptop is still one) keeps working, and
treat "neither" as the session continuing, which re-locks rather than
assuming a fresh boot.
2026-08-04 19:19:31 -04:00
Fimeg
6b67512c4f sensord: stop claiming the accelerometer
Measured on the phone, idle, screen on, same session, one flag apart:

  monitor-sensor --proximity --light --accel   iio-sensor-proxy  15.3%
  monitor-sensor --proximity --light           iio-sensor-proxy   1.1%

Claiming the accelerometer makes iio-sensor-proxy poll the IIO device
continuously; nothing else here does. Fourteen points of a core, forever,
for the reading §4 weights least (+0.3) and calls a weak signal — and one
the keepalive had to actively decay, because monitor-sensor speaks only on
orientation change, so a stationary phone paid the full poll cost to
report nothing.

The parser, the motion decay and MOTION_WINDOW go with it; all three
existed only to turn orientation into a motion edge. The 2026-07-27
finding behind the decay is kept in comment — 165 Moving(true) against 8
Moving(false) on one boot — because whatever reports motion next owes a
decay too.

This does not say accel is unwanted. It says a subprocess holding a
continuous claim is the wrong way to get it; TASK-36's SLPI batching is
the right one. Restore the source together with that, or the cost returns.
2026-08-04 16:17:21 -04:00
Fimeg
f320a0221d shell: answer to the ipc target sessiond actually calls
Action::Overview shells out to `ipc call overview toggle`. The only handler
here was `search`, so that call reached nothing and the three-finger tap
did nothing, without an error anyone would see.

It has been invisible from the device because the shipped sessiond has no
`gesture` verb yet and refuses the op long before the executor runs, so
only the first half of the break was observable.

This makes the existing binding reach the surface it already names. What
the tap should raise is TASK-55 Q1 and is not decided here.
2026-08-04 15:02:34 -04:00
Fimeg
44a54330c2 shell: mission control draws the cards it was already building
The panel, its mask and the loader all moved to overviewOpen ||
missionControlOpen when mission control landed; the Column holding them
did not. So the second-stage pill swipe raised a panel whose entire
contents were invisible — WindowOverview instantiated, laid out, and never
shown.

Search stays overview-only: mission control takes no keyboard focus on
purpose, so a field there is one you can see and cannot use. Outside-tap
now clears both states, because with no focus grab that tap is mission
control's only way back.
2026-08-04 14:43:35 -04:00
Fimeg
1a3c24fadb claude: fix Opus 5 wire incompatibilities
Drop temperature for models that removed sampling params (400 otherwise).
Preserve signed thinking blocks across tool rounds — Anthropic rejects a
tool_use whose preceding thinking block was dropped. Raise default
max_tokens to 32k for thinking-by-default models and request summarized
display so the reasoning pane is fed.
2026-08-04 11:27:13 -04:00
Fimeg
d0c6488099 deploy: WindowOverview is in the qmldir and was not in the manifest 2026-08-04 09:39:00 -04:00
Fimeg
356cfc6462 overview: viewtop has workspaces; the header said it did not 2026-08-04 09:32:03 -04:00
Fimeg
914e48f2d3 shell: locking closes the keyboard, and unlocking does not bring it back
The hold machinery remembers whether the keyboard was up when the first
hold was taken, so releasing the last hold restores rather than clobbers
it. Across a lock that restore is wrong: the keyboard was up because of
something being typed before the phone went down, and the first thing
you see on unlocking is a keyboard sitting over whatever you came back
for.

Intent to type does not survive the screen going away. Anything that
still wants the keyboard — a field taking focus again — asks for it, on
the path that already works.
2026-08-03 22:20:51 -04:00
Fimeg
cc4bb83573 shell: the overview arrives as one surface, and mission control finally lands
Everything drove off a visible/not-visible flag, so the cards appeared
rather than the overview opening. One shared `progress` now: the strip
slides 24px, each card takes its own share of it staggered by index and
capped at the fifth, and scale runs 0.86 to 1.0 — the reference shell's
numbers, driven from the same clock instead of a timer per card. The cap
is what stops the tenth card starting half a second after the first,
which reads as loading rather than opening.

This is also SHELL-ECOSYSTEM's stated model, taken from Phosh: state
gates visibility, never the reverse.

`missionControlOpen` has been set by the pill's second-stage swipe since
July and consumed by NOTHING — TASK-14 records the Auxo-like card
surface it was meant to raise as never built. WindowOverview is that
surface. The state reaches something now instead of being set and
dropped.

Mission control is the cards alone: no search, and no keyboard focus,
because it is "switch to what is running" and not "find something" — and
taking the keyboard would summon the OSK over a surface with no field.
2026-08-03 22:18:43 -04:00
Fimeg
133daa94ef sessiond: the wake latch is per button, not one field for all of them
An audit found the fix from earlier tonight reintroduced through a
second button. A tap never resolves on the UP edge — the recogniser
returns None and the tap lands when the 300 ms multi-tap window closes
on a later tick, up to about 1.3 s after the press — so a single shared
latch had to survive that whole gap, and any other button's DOWN edge
inside it overwrote the answer.

Concretely: power wakes a dark phone, the volume rocker under the same
grip gets nudged within the second, and the pending power tap resolves
as "the panel was lit" and blanks the screen. That is exactly the
regression 8c7567e was written to fix.

`buttons` is already keyed per button so they cannot interfere; this
latch had reintroduced the coupling one level up. The test fails without
the fix — checked by reverting it.
2026-08-03 21:12:36 -04:00
Fimeg
91ea54ebf5 sessiond: touch gestures are a verb, so the compositor stops deciding
viewtop recognises three fingers and had nowhere to send it. The obvious
move — have the compositor call `qs ipc call overview toggle` itself —
is the eighth blind actor §12 forbids by name, and wiuf-vpn-gate is what
that costs: 652 tunnel recycles in ninety minutes with no way to turn it
off.

So `gesture` joins `button` on the socket. The asymmetry between them is
the interesting part and is written down where it happens: `button`
carries raw edges because recognition is an accumulation over time and
the machine owns time, while `gesture` arrives already named, because
touch contacts exist only inside the compositor and nothing else CAN
recognise them. The line §12 draws still holds — the compositor names
what the fingers did, the machine decides what it means, and behaviour
leaves through the one executor table.

Three fingers raise the overview. Everything else is recognised,
recorded and inert, which is deliberate: a gesture that fires something
nobody chose is worse than one that fires nothing. The real binding
table belongs in DeviceStatePolicy, persisted and agent-writable.

Not on a dark panel. The overview is content, and content on an
unauthenticated glass is what the disclosure rules exist to prevent — a
tap on a dark panel is a wake, and that is the power button's business.

The reply says whether the gesture was bound, so a caller can tell "the
machine had no binding" from "the machine did not understand".
2026-08-03 20:53:18 -04:00
Fimeg
8c41f45420 shell: the overview swipes sideways, and stops rejecting its own buffer
Two faults in the first cut.

cacheBuffer was height * 2, and height is -1 until the first layout
pass, so ListView refused it outright and said so on every open. Clamped
at zero.

The strip was vertical. TASK-14 asks for "horizontally swiped live app
cards" and the reference shell's carousel says the same thing in its own
comment — the whole strip slides in horizontally. On a phone the thumb
travels sideways, and a vertical list fights the flick-up that dismisses
a card, so the two gestures were competing for the same axis. Horizontal
with snap-one-item, cards filling the viewport.
2026-08-03 19:15:18 -04:00
Fimeg
fdb0acfdce shell: the overview shows windows, because there are no workspaces here
OverviewWidget draws a grid of workspaces and places windows in them by
Hyprland coordinates — HyprlandData.windowList, monitorData,
Hyprland.monitorFor. Under viewtop none of it resolves, and more to the
point viewtop has no workspaces at all: one space, a tiling layout. The
old overview could not be repaired by repointing it at another data
source, because the thing it draws does not exist. It rendered an empty
frame, which reads as the overview being broken.

WindowOverview lists what does exist. Cards from
ToplevelManager.toplevels — the same list the dock and TaskbarApps
already read, so there is one idea of what is open — each holding a
live ScreencopyView of one window, which only became possible when the
compositor started serving a per-window capture source; until then a
card could have shown nothing but the screen it was covering.

The motion is the reference shell's, read out of
overview_window_card.dart rather than invented: stagger at index * 45 ms
capped at the fifth card, intro scale 0.86 to 1.0, dismiss past 32% of
the card height, 56 px of downward rubber-banding, settle under 200 ms.
The cap is the part worth keeping — without it the tenth card starts
half a second after the first and the overview feels like it is loading
rather than opening.

Captures run only while the overview is up. A live capture per window is
a render of that window every frame, and leaving them going behind a
closed overview is battery spent drawing what nobody can see.
2026-08-03 18:37:56 -04:00