Watch
1
0
Fork
You've already forked souveraine
0
Commit graph souveraine/surfaces/quickshell
Author SHA1 Message Date
Fimeg
cb3785bcbd patches: correct the queue; retire 0002 as obsolete, clear landed 0003/0004
The queue section claimed 0001-0004 were all unapplied. Verified with
git apply --check in both directions: 0003 landed as 8c434df, 0004 as
23cebc5, and 0002 can no longer apply at all.

0002 patched inThinkBlock in services/Ai.qml. That variable no longer
exists - typed segments made the think-fence collision impossible by
construction rather than by escaping harder. Retired, not abandoned.

0001 and 0006 were on disk and undescribed. Both now carry their
reasoning here. 0007's block records the specific installed version it
waits on, since 'needs the server first' is not actionable a month
later.

A queue is not an archive; git keeps history.
2026-08-12 14:12:26 -04:00
Fimeg
ba13d56afc patches: queue 0009 speech stop/resynthesize; unblock 0008
0008 was blocked because the owned delegate carried none of the vendor's
seven message controls. df11bba carries five and drops two deliberately;
the header now records which and why rather than only lifting the warning.

0009 depends on nothing but is a prerequisite for 0008's re-synthesize
control doing anything real.
2026-08-12 13:55:35 -04:00
Fimeg
df11bbab96 shell: carry the message control row into the owned delegate
Vendor AiMessage exposed seven controls; the owned delegate had none, which
made patch 0008 a parity regression rather than a swap. Five are carried, two
are deliberately dropped:

  regenerate — the conversation is forward-only and Ai.regenerate() is already
    a no-op returning advice. A button whose only behaviour is to explain that
    it does nothing is worse than no button.
  edit — there is no in-place edit. The vendor's wrote to a local array the
    server never sees, so the message read back was not the message held.

delete is kept but armed: removeMessage() splices two local arrays and leaves
the server transcript untouched, so it is a view filter wearing a delete icon.
The armed row says so in words and replaces the controls in place rather than
opening a modal, which on a layer-shell surface would fight for focus.

speak and copy are separated at the source. copy takes the whole content;
speak takes text segments only, so the synthesizer no longer reads reasoning
and tool payloads aloud. Legacy messages without segments fall back to full
content rather than to silence.

re-synthesize prefers Speech.resynthesize() when present and degrades to the
old stop+speak otherwise, because speak() opens with a cache check on the text
and re-synthesis is by definition the same text — the legacy path replays the
identical broken audio.
2026-08-12 13:50:07 -04:00
Fimeg
1951d2b69b shell: document which edits are live and block patch 0008
deploy.sh: name the hazard the composer already implements — a new file
plus a manifest line is inert until the next deploy, while editing a file
already in the manifest is live in the running shell immediately.
Registration is the dangerous act, not creation.

patches/README: 0008 swaps the message delegate to one that does not carry
the vendor control row (regenerate, speak, re-synthesize, copy, edit, raw,
delete). Applying it would remove all seven.
2026-08-12 13:24:34 -04:00
Souveraine
6d0f891d6e shell: own the agent message delegate and the reasoning card
TASK-72 step 2. AgentMessage consumes the typed segment list and dispatches
to owned primitives; ThinkingCard draws reasoning as a segment kind rather
than as <think> punctuation inside a flattened string, which removes the
think-fence collision class by construction.

MessageTextBlock and MessageCodeBlock are deliberately reused from the vendor
snapshot: they are markdown renderers, not agent vocabulary.

Composed by MANIFEST, imported by nothing. The activating edit is queued as
patch 0008. Qt6 qmllint: zero syntax findings; remaining warnings are the
widget-resolution class the vendor AiMessage also produces (38 vs 46).

Not verified: nothing has loaded this. No real tool round has rendered here.
2026-08-12 13:11:19 -04:00
Fimeg
3def2920b8 shell: owned agent surface — tool vocabulary and card
First step of TASK-72's owned destination. modules/souveraine/agent/ is
original Souveraine code; no further agent-surface work lands in ii-base.

ToolVocabulary transcribes src/ui/chat/tool_renderers.rs — the same event
stream, solved once already for the TUI. All 19 registered tools have a kind,
an icon and a summary. The vendor card knew 8: bash read write edit grep glob
list_dir memory. The 11 it could not name are the interiority verbs.

ToolCard groups by what the act is rather than which subsystem serves it, so
acts on the machine and acts on herself read as different families. Status is
legible without opening the payload; collapsed by default except running or
failed.

Composed by the manifest, imported by nothing. Registration is a later step.
2026-08-12 12:55:11 -04:00
Fimeg
5a20307ddd patches: queue 0007, render context occupancy and stop reading hyprctl errors as cursor
Requires f266136 in the running server; without it the pill honestly shows
an em dash rather than a wrong number. Unapplied, unloaded.
2026-08-12 12:20:11 -04:00
Fimeg
e784fe48a3 patches: queue 0006, step-up authenticates through PAM
Authored in a parallel session (Rook, Codex side) on 2026-08-12; committed
here because untracked is the fragile state, not because authorship is mine.
Finding stands on its own: StepUpAuth called souveraine-pam-auth, a binary
never written, and fell back to pkcheck against an action never shipped, so
every grant request was silently denied. Unapplied, unloaded.
2026-08-12 12:20:11 -04:00
Fimeg
d02df0c6bd patches: the queue is 0001-0004, say so 2026-08-12 09:24:06 -04:00
Fimeg
b5671b0b8a patches: retire the stale 0005 entry, record what closed 2026-08-12 09:23:39 -04:00
Fimeg
f7e0e51116 config: never store a null option
Null-valued options serialised into config.json and segfaulted
JsonAdapter on the next launch, killing the shell after load.
Tristate strings (auto/on/off) with boolean fallback.
2026-08-12 09:23:19 -04:00
Fimeg
fb5e9bb80c osk: retire the dead dual-keyboard path 2026-08-11 19:21:21 -04:00
Fimeg
dd19ab227f agent sessions: show conversations, not storage ghosts 2026-08-11 18:47:54 -04:00
Fimeg
12da479c23 bar: finish the shared resource widget 2026-08-11 18:40:35 -04:00
Fimeg
013a06aacf patches: retire the old top-bar agent mount 2026-08-11 18:40:35 -04:00
Fimeg
62638e0e5f osk: recover with Squeekboard, not Stevia 2026-08-11 18:37:57 -04:00
Fimeg
692455c8f0 chat: raise the keyboard when the field is tapped 2026-08-11 18:24:24 -04:00
Fimeg
41d13c9468 dock: yield the bottom edge to the keyboard 2026-08-11 17:21:45 -04:00
Fimeg
7842c04053 turns: never mistake an empty success for Annie 2026-08-11 17:09:42 -04:00
Fimeg
2179b627d1 agent sessions: leave the bar and sit beside chat 2026-08-11 15:43:30 -04:00
Fimeg
3bdc1c8e3c patches: keep island work outside turn fix 2026-08-11 15:01:38 -04:00
Fimeg
3aa7019eb5 turns: survive the surface disappearing 2026-08-11 15:01:18 -04:00
Fimeg
783f09606a island: fix three defects found by actually loading the shell
The island had never been load-tested. All three were fatal or noisy and
none were visible by reading.

StyledToolTip takes `text`, not `content`. Two occurrences, each one a
hard "Cannot assign to non-existent property" that failed the entire
module chain up to shell.qml — the bar would not have come back.

The provider-health tooltip could never have shown even once fixed: a
MaterialSymbol has no `hovered`, and our own StyledToolTip fix treats a
non-hoverable parent as never-show. That block exists specifically so an
unavailable provider is not mistaken for "no sessions", so a tooltip was
the wrong carrier. Stated visibly now.

Island read root.QsWindow.window through a non-optional access; inside a
Loader the attached object is not resolved at construction and it threw.

Revealer takes implicitHeight from childrenRect, so anchoring its child
to its own centre closes a cycle once it sits in a Loader. ii-base hid it
by letting the layout drive the Revealer height directly.

Verified: qs -c souveraine reaches "Configuration Loaded" with no warning
naming any of these files.
2026-08-11 14:46:41 -04:00
Fimeg
391e239010 bar: one BarContent for every device, layout as data
ii-base and ii-phone each carried a 357-line BarContent to express eight
differences, all of them either "is this widget shown" or "which slot is
it in". No behaviour differed. Every bar edit had to be made twice or
diverge silently against the pin.

Widgets are now declared once as Components in a registry; each slot is a
Repeater over a list of widget names, so placement and order are data.
Config names a slot or a device profile picks it. "auto" derives the
profile from the same cramped-ness test behind useShortenedForm, so the
phone keeps its arrangement with no config file. Loaders are active only
when placed, so an unplaced widget is never constructed.

The agent island becomes a placeable widget rather than a mount smuggled
into UtilButtons: it reaches every device bar from one declaration.

ClockWidget is unified for the same reason. Its phone fork existed solely
to add customFormat, which BarContent now sets on every device.

bar.agentSessions was landing under background.widgets, not bar, so
Config.options.bar.agentSessions was always undefined and only the ?? true
fallback made the island appear wired. Moved, and merged into the existing
bar.indicators rather than declaring a second one.
2026-08-11 14:40:07 -04:00
Fimeg
d87d6117a4 patches: queue 0005, mount the agent island 2026-08-11 14:22:42 -04:00
Fimeg
b21184217e agent sessions: use shellPath convention for collector path 2026-08-11 14:21:37 -04:00
Fimeg
47ce2d1970 agent sessions: one collector, one island
Collector emits a single JSON envelope for every agent session (Souveraine,
Claude Code, Codex) and always exits 0; a failing provider reports
available:false rather than taking the envelope down.

AgentSessions.qml owns the cadence and projects the envelope. Transport is not
the contract: when the TASK-69 daemon lands, only the source changes.

Island is a morph host for the bar - dot on a cramped bar, pill where there is
room, derived from the same threshold BarContent uses.

Inert until registered in services/qmldir and mounted; see patches/0005.
2026-08-11 14:19:45 -04:00
Fimeg
928bd8d143 face: recreate a refused rig socket
Quickshell retains the failed QLocalSocket object, so toggling its requested state cannot reconnect. Replace the Socket body until the host answers.
2026-08-11 14:08:12 -04:00
Fimeg
5afa132ff4 face: keep knocking until the rig answers 2026-08-11 14:03:23 -04:00
Fimeg
e314d4fa23 face: expose the two live gaze links
Let the remote shell deploy accept the assets its caller already staged, so a successful composition does not fail after switching the tree.
2026-08-11 14:02:02 -04:00
Fimeg
8fd1a72edd face: reconnect to the rig after host startup 2026-08-11 13:33:09 -04:00
Fimeg
d290b12441 patches: queue QML compatibility fix 2026-08-11 09:37:09 -04:00
Fimeg
23cebc531d shell: keep typed segments QML-compatible 2026-08-11 09:35:53 -04:00
Fimeg
8c434dfb74 shell: render typed chat segments
Keep assistant, reasoning, tool-call, and tool-return frames structured through the sidebar delegate. Tool cards bind returns by wire id and fold their output by default.

Reasoned from the SSE contract and existing TUI renderer. Diff check passed. Untested against a running shell: Casey applies and reloads staged patches.
2026-08-11 09:13:50 -04:00
Fimeg
a8f7f62471 shell: stop sensor calls closing an open reasoning fence
A tool_call/tool_return arriving while a <think> block was open emitted its
own self-closing fence, whose </think> closed the outer block early. Every
reasoning token after that point rendered as prose, and the stray close left
the trailing assistant text mis-segmented. Append inside the open fence
instead; only open one when arriving in prose.
2026-08-11 09:13:50 -04:00
Fimeg
52f379f230 patches: queue typed chat segments 2026-08-11 08:56:08 -04:00
Fimeg
f17fa7c31b patches: queue think-fence collision fix 2026-08-11 08:10:39 -04:00
Fimeg
aaea09fdd6 shell: patches queue — agent stages, human applies
The composed config is symlinked into the repo and quickshell reloads on
write, so an agent editing QML edits the live shell mid-turn. Stage changes
as patches instead; the human applies and reloads on their own beat.

First in the queue: 0001-resume-offer — the agent-established hook offers
the latest thread instead of silently attaching it. Explicit resume paths
and the e4e6594 amnesia fix are untouched. Untested against a running
shell.
2026-08-10 23:04:59 -04:00
Fimeg
28ed6f2151 lens: explicit status guard instead of optional chains 2026-08-10 22:35:37 -04:00
Fimeg
29ec9fe223 fingerprint-preview: root in Singleton, not QtObject
The reload killer: FileView under a QtObject root — QtObject has no
default property, so the whole service tree failed to compile. Every
working service singleton roots in Quickshell's Singleton type.
2026-08-10 21:41:24 -04:00
Fimeg
cb7dd73d2b sidebar: the garden's micro-view — Lens service, vault card in the right panel
The vault card lives where notifications were — header with sync pill
(clean/ahead/behind/dirty), today's note entry, five freshest notes,
cold start and push rows — over the notification list. Lens.qml owns
souveraine-lens the way Face owns the rig: one socket, event lines up,
no vault access of its own. Kiyoshi's slash grammar and tool registry
are noted for the fuller app; the micro view only opens and plants.
2026-08-10 21:24:23 -04:00
Fimeg
658217e72e polkit: add temporary FPC confirmation 2026-08-10 20:46:28 -04:00
Fimeg
902a724855 lock: add FPC wiring preview 2026-08-10 20:10:50 -04:00
Fimeg
bf469c4216 lock: answer touchKeypad on a cold start, not just a reload
PersistentProperties is in-process, so it carries the surface choice
through a reload and not through a fresh shell. sessiond locks before the
shell exists, so a greetd-started shell adopts a live lock with
Config.ready still false and binds the desktop surface — and
WlSessionLock.surfaceComponent cannot change once active. A lock screen
that will not take your PIN, on the iPhone 7 tonight.

Reads the environment, which answers at construction. Unset behaves
exactly as before, so nothing changes on blueline until it sets it.
2026-08-09 22:21:14 -04:00
Fimeg
b2774c8aac sessiond: a power seam that cannot report an outcome it does not have
Power is the one irreversible transition and it bypassed the authority
entirely: both menus called Session.poweroff() straight into systemctl, so
there was no Action, no trail entry and no refusal path.

The daemon gains the verb and the shell gains a transport for it. The
request rides its own short-lived connection, never the heartbeat, because
suspend can hold the daemon's handler until resume while the heartbeat
must stay free to carry locked_ack and the EOF that means shell death. A
disconnect after the request was sent reports outcome_unknown rather than
guessing.

Session.qml keeps the legacy executor until this is exercised on hardware.
Unbuilt and unrun; CI is the first reader.
2026-08-09 19:31:33 -04:00
Fimeg
32c019875c usb: land the HID controller the doorway was already calling
78d6743 committed PowerMenu's half and never added the file, so the
singleton in qmldir resolved to nothing and the shell would not load on a
tree that had not been hand-linked.

HidController streams to usb-hid-inject and acknowledges every accepted
report, closes both endpoint fds on the busy edge before usb-signaller
tears the functions down, and refuses non-ASCII on the glass instead of
clearing a field whose first report was never written.

The face reports the agent and host results back to the page, and
deploy.sh stages the tracked face assets before the QML switch so a new
control cannot arrive without the page that implements it.
2026-08-09 19:31:07 -04:00
Fimeg
78d6743776 usb: make the HID controller doorway honest 2026-08-07 17:36:25 -04:00
Fimeg
8cd2adb828 usb: build the full KVM composite surface 2026-08-07 14:48:07 -04:00
Fimeg
16c6ee1033 multitasking: one owner for the transition, and the release travels
ZoneTransition owns the card rect, the four overview verbs, the end-target
table and the gesture clock. ZoneOverview and the rail read it; neither
derives a geometry.

Deletes poseActiveZone/clearPose/_posed, zoneCard.scale and
zonePullProgress. The card's ColumnLayout went too — its margin was a second
opinion about where a window sits in its zone; panes are the compositor's
tiling scaled.

The swipe felt wrong because the release committed where the thumb left it.
settleTo() travels to the destination first and commits on arrival, with
quickstep's numbers (350ms cap, min(1/0.7, 1/0.3)). Abandoned half-swipes
settle to last_zone instead of snapping. Dwell gate restored — quickstep
gates the same way and "ever paused" is a latch.

Card box is measured from the surface, not assumed from the screen: the
overview panel respects exclusive zones and its height moves.

Strand repro passes on hardware.
2026-08-07 12:26:12 -04:00
Fimeg
72171accec the card is the window's size through the whole pull
Two fixes to the same seam. columnLayout was still gated on
missionControlOpen, so a peek raised a panel whose contents were
invisible — the same line that had been left behind once before, with
its own comment saying so.

The card scaled 0.6 -> 1.0 while pose runs 1.0 -> 0.6 against the same
progress, so at the handoff the window was at 0.6 of the glass and the
card arrived near full-bleed. Same curve now, and the 26/12 inset is
gone: scale is the inset, and stacking both squashed the aspect because
the bottom label margin has no counterpart at the top.
2026-08-07 08:52:58 -04:00