Watch
1
0
Fork
You've already forked souveraine
0
Commit graph souveraine/surfaces/quickshell/modules
Author SHA1 Message Date
Fimeg
e595ef6d72 subconscious panel: colLayer1Active, not the key that does not exist 2026-08-13 06:50:01 -04:00
Fimeg
525157250a shell: context pill tooltip states the real tiers, not the archivist
The tooltip claimed 'Archivist begins compacting around 70%'. The
archivist does not compact. It reads journal/ and writes
system/synthesized/ - a different substrate from the conversation
entirely (core/archivist/mod.rs:5).

The real advisory tiers are 80/90/95 in ConsciousnessEngine::
on_response, and they never force compaction. Icon thresholds moved
from 85/70 to 90/80 to match.
2026-08-12 20:30:34 -04:00
Fimeg
6f12fceea9 shell: apply 0007, 0010, 0011 — context occupancy, halt register, /new
0007 was fixing a live error: the server has carried named ContextPressure
fields since r463, so event.tokens was undefined and the pill assignment
failed on every turn. Applied and verified against the running shell.

0010 renders a halt in her own register rather than the tool's name.
0011 renames the reset command to /new, which is what clearMessages() does.
2026-08-12 19:50:32 -04:00
Fimeg
44acb11ab5 shell: two faults the load found that no gate did
Both were live in the running shell and invisible to every check that ran
before it. Found by reading the shell's log after Casey applied.

ThinkingCard: missing `import qs.modules.common.functions`

  ReferenceError: ColorUtils is not defined, on every render of every
  reasoning segment. My own defect, shipped through a lint that said clean.

  The lint was blind because I staged an approximation of the composed tree by
  hand instead of linting the composed tree itself. Against the real composed
  tree qmllint reports it plainly: 1 ColorUtils diagnostic before, 0 after.
  Lint the composed tree. A hand-built stand-in tests the stand-in.

Config: sidebar.ai.fontSize restored

  MessageTextBlock (vendor) reads Config.options.sidebar.ai.fontSize and got
  undefined, assigning undefined to font.pixelSize on every text render.
  Pre-existing, not from 0008 — the vendor delegate used MessageTextBlock too.

  Cause is structural: modules/common/Config.qml SHADOWS ii-base's Config
  wholesale, so every key ii-base adds after the fork silently disappears. The
  key even carries an ii-base comment explaining it was added deliberately as
  a live theme binding. Nothing failed; a number was just quietly absent.

  Restored as a live binding, never a literal and never null
  (null-in-a-serialized-config, 2026-08-11).

Verified: shell alive 12s after the Config edit (the crash-loop window),
config.json 46 keys and zero nulls, both fault lines gone from the log.
2026-08-12 14:51:09 -04:00
Fimeg
93fe30a8e7 shell: land the owned message delegate and the speech fixes
Applied 0009 then 0008 (0008's re-synthesize control calls a function 0009
adds). Casey applied and reloaded; verified against a running shell rather
than from a clean load.

0009 Speech.qml
  stop() could not stop. playProc ran `sh -c "mpv ... || ffplay ..."` — a
  compound command, so sh does not exec-replace itself and SIGTERM killed the
  wrapper while the player kept sounding as an orphan. Reproduced directly.
  That is the back-to-back TTS slam: every stop left audio playing and the
  next speak started a second player over it. Shell dropped; the pid held is
  now the pid making noise. ffplay fallback deleted rather than repaired —
  needing a fallback is what forced the wrapper that broke the kill.
  resynthesize() added, bypassing the cache: the button existed for "that came
  out wrong" and, being keyed on the same text, always replayed the identical
  file. synthesizing/playing split out of one `speaking` boolean.

0008 AiChat.qml
  One line: delegate AiMessage -> AgentMessage. The vendor block named 8 tools;
  the registry holds 19. The 11 it could not see were exactly the interiority
  surface — outfit, nickname, subagent, atmosphere, reach, consult, itinerary,
  todo, schedule, halt, intrusive.

  regenerate and edit dropped deliberately, per Casey: text regeneration is not
  possible (Ai.regenerate() already returned advice) and there is no in-place
  edit (the vendor wrote to a local array the server never sees). delete is
  armed and states that it hides locally only. Do not restore them.

Queue entries removed here, per the directory's own discipline.
2026-08-12 14:50:57 -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
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
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
12da479c23 bar: finish the shared resource widget 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
2179b627d1 agent sessions: leave the bar and sit beside chat 2026-08-11 15:43:30 -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
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
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
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
Fimeg
f699f57235 multitasking draws under a dwelling thumb
The overview loader was only active once missionControlOpen was already
true, so nothing existed during the pull and ZoneOverview.progress
following the rail was dead mid-drag. The cards appeared at release and
animated on their own clock — two motions, which is the seam TASK-60's
acceptance names.

missionPeek gates presentation only: visibility, mask, which body the
loader builds. Focus, dismissal and every commit path still read
missionControlOpen, so a preview draws and decides nothing. Masked to a
zero-size item while peeking so the in-flight gesture stays the rail's.

Dwell rather than any pull, so a flick to home never flashes the blur,
and it drops above the multitasking detent so the preview never shows a
destination the release would not commit.
2026-08-07 08:42:00 -04:00
Fimeg
57208c886a rail: the pose rides the drag, not each exit path
A partial slide left the app scaled small until another pull brought it
back (DUMP-bugs 8). Every path anyone checked did call endPull, so the
hunt for the one that didn't was the wrong shape: while restoring is a
step, some path skips it. It is now a function of `dragging`.

Release gates on speed and length as one projected number instead of a
distance test with a flick promotion bolted on. That promotion had never
fired anyway — it read rail.tapSlop, which is undefined, so the test was
`travel >= undefined`. Every commit on this rail has been distance-only.
2026-08-07 08:41:54 -04:00
Fimeg
630d6912fd sidebar: the keyboard leaves with the panel that summoned it
The drawer clears oskOpen on close and this did not, so the OSK outlived the
surface holding the only text field it was serving — and with nothing focused
there was no obvious way to put it away.

On the state, not on a visibility handler: the panel's `visible` is a binding
to that flag, so reacting to visibility would be reacting to our own effect.
2026-08-07 02:24:24 -04:00
Fimeg
f4caaae1cb drawer: the keyboard comes up on a tap, not on a press
Summoning on onPressed meant any gesture that merely began over the search
field raised the keyboard — including the swipe that scrolls the app grid,
which starts at the top of the drawer more often than not. The press now only
remembers where it landed and the release decides, with a generous slop: a
thumb reaching the top of a 540px panel is not steady, and a few pixels of
drift while tapping a text field is a tap.
2026-08-07 02:22:28 -04:00
Fimeg
e218601199 Revert the duplicate onCanceled on the rail
The handler already existed and already did this — a second one in the same
MouseArea is "Property value set multiple times", which failed the whole
module and took the shell down. The pill's stranded-pose symptom is
something else; the cancel path was never the hole.
2026-08-07 02:07:22 -04:00
Fimeg
4826574166 pill: a cancelled climb puts the app back
onReleased is the only thing that clears the pull's pose, and a MouseArea
whose grab is taken away never gets one — it gets onCanceled, which had no
handler. So a cancelled climb left `dragging` true, the pull progress set and
the app posed at 0.6: shrunken, with nothing on screen to say why, and no way
back except pulling the pill again to force a fresh press and release
through.

Never a commit. A gesture nobody finished only has to put the glass back.
2026-08-07 02:06:12 -04:00
Fimeg
5c44ea06d5 dock: scale it up, and put the scale in settings
44px buttons with 35px icons read small on a 540px panel, and a stack's
members were 12px inside a 35px box — unreadable, which is the whole job of
the collapsed form. 56/44 now, and the member icons give back the border and
padding that were being subtracted from them as well as the grid spacing.

Both numbers live in Config so this is a setting rather than a rebuild, with
spin boxes in Settings > Dock. Two numbers and not one ratio: the button is
the row's height and the icon is what you see, and fixing the ratio would
mean either cramped icons in a tall row or icons overflowing a short one.
2026-08-07 02:04:12 -04:00
Fimeg
a1d9a874e5 multitasking: inset the cards so neighbouring zones show through 2026-08-07 01:34:43 -04:00
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
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
c2dcbe7b7f rail: a keyboard-up climb means only a swap, never navigation 2026-08-06 11:54:45 -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
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
9b470b8e22 split chooser names its windows and brings the pick to the zone 2026-08-05 19:45:07 -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