Brightness is a singleton nothing instantiates, so 'qs ipc call
brightness increment' answered 'Target not found' while still exiting
0 — the lever's || brightnessctl fallback never fired. Pull the
singleton in so the lever owns brightness again.
Move agent and conversation authority into truthful footer controls, keep external sessions observed-only, and give recent server conversations an explicit picker.\n\nProject itinerary state into a persistent ribbon, invalidate it on every itinerary mutation, and keep failures in the transcript while successful route chatter yields to the ribbon. Long tool returns now scroll in place.\n\nThe SAF now owns the full Panel contract and parity boundary; the abandoned green observer card is removed.
Souveraine.send returns false for a busy turn exactly as it does for a dead
server, and the sidebar rendered every false as "server unreachable" — so
typing while she worked showed the words, then a lie, and dropped the text.
The verbs existed on both sides since 93fe30a and nothing called them.
Type-while-busy now interjects, as the TUI has always done
(src/ui/app/mod.rs:1006). Esc with nothing attached raises a hand. A queued
count sits in the status row and says sent, not read, because 202 from
/interject means only that it was taken.
Deliberately unchanged: the two drain sites and their system/user registers.
Providers disagree about which one they want and that choice is not ready to
be made. Latency is unchanged too — turn.rs:600 runs a whole tool round
without looking, so a note sent into a fifteen-call round waits for it.
pose is instant on the far side and the compositor must not ease it —
it honours, it does not adjudicate. So the curve is the shell's, on
Android's own scale spring: stiffness 200, damping 0.75, underdamped
on purpose and separate from the position spring's 0.8.
The sheet also stayed open over a window something else closed, where
all six buttons then refused with gone.
Written, deployed to the phone, absent from pages[] — the only registry.
13 to 25. Power, search, updates, VPN and saved networks were finished
all along. MonitorConfig and KdeConfig stay out: hyprctl and Plasma.
Two laptop-isms cut from GeneralConfig first — it sed'd a hyprlock.conf
nothing reads, and shelled to a hardcoded Gemini script.
The rail takes its handle to opacity 0 on home and the dock went on
reserving 32px for it, in the drawing and the input mask alike. Only the
drawing collapses — the rail still takes both swipes there, and a dock
that claimed those pixels would eat the gesture.
Appearance.animationCurves is Material 3 Expressive and every spatial
curve in it overshoots. Twelve souveraine surfaces, 31 hand-typed linear
animations, three calls into that bank from two files.
The card's entry rise is gated on inFlight; unguarded it is TASK-60's
second writer over the carry.
The cycle placed every step at the zone origin, so the first tap took
the whole top. Corner handles now, opposite corner latched as the anchor
at the press, snap detents on the zone's edges, thirds and half with a
tick at each, one place per painted frame.
pose has been in the wire since 2026-08-05 with no caller — poseActiveZone was
the only one, and TASK-60 deleted it. Zoom composes pixels the client already
drew; Resize places a new rectangle and the client relays out inside it.
The card was the whole panel scaled, so the bar's reservation rode inside it as
dead space above every window. Subtracted in targetFor and the pane layout both,
or the carry lands a bar-height off its own picture. Minting a zone needed no new
verb: Request::Workspace already pushes one when asked for the zone past the end.
The card's bottom sits at 805 of 1080 logical, so the travel is 275px and the
detent fired at 194 — every release committed with the window short of its card.
Latched at the press. Velocity is the last 100ms rather than the whole-drag mean,
and the settle is a critically damped spring on the frame clock, seeded with it.
A transport error cleared the whole queue, so a lost overview_commit left the
compositor carrying windows the shell believed it had released. 52 dropped
queues and 113 PeerClosedErrors in one boot on blueline. commit, cancel and
workspace are idempotent, so each gets one retry; progress is a level and does not.
settleTo gave home and overview the same end shift, so a release past the
multitasking detent animated *down* to it, held the overview fully present, and
teleported — the release never reached its end target. detent is the boundary
between the two (rail: pullTo(travel, missionAt)), and presence is built to
reach 0 at clock 2, which is where home lives.
The authority takes ext-session-lock before any surface exists, which is the
window -pre reserves. It cannot start earlier — ext-session-lock is a Wayland
protocol and needs the compositor's socket. Also drops the injected venv
variable from eleven surface scripts; each finds the path itself.
The compositor answers one request per connection and returns. `connected`
lags that close, so the 2 s poll's second tick wrote to a spent socket and
died as PeerClosedError — once per shell start, 4 of 4 loads on 2026-08-13,
while the same socket answered a hand-written request that second.
The error also blamed reachability, which it never established; it now names
the verb that was lost and how many were dropped behind it.
The unified BarContent applied the desktop gate (useShortenedForm < 2)
to every device, but ii-phone had shown battery ungated — note 5 in this
file's own header. A 1080-wide panel sits at form 2, so the icon vanished
on 2026-08-11 while the critical-battery alert kept firing beside it.
0007 and 0010 landed in 6f12fce and their files were removed in that same
commit, but this list went on describing them as pending. 0001 and 0006 have
now landed too. A queue file is a claim with a shelf life; so is the README
that indexes it.
The durable notes from the removed entries are kept under Recently closed --
the halt wording is coupled to migraine_text() in src/server/turn.rs, and the
context pill and the tokens endpoint measure different things and must not be
shipped side by side unlabelled.
StepUpAuth ran `souveraine-pam-auth`, else `pkcheck --action-id
org.souveraine.stepup`. Neither exists: no such binary was ever written
and no polkit action was ever shipped, so both branches failed and every
grant request was silently denied. The header also described passing a
password through SOUVERAINE_STEPUP_PASSWORD, which the code never set.
Now a PamContext against the system souveraine-stepup service, shipped by
cc541d1. The prompt is not owned here: pamMessage raises
promptRequired(family, message, secret) and a surface answers with
respond(). An empty answer is legitimate, not a cancel -- the FPC factor
prompts "Touch and hold" and consumes its ticket on a blank response.
Deliberately unchanged: grant model, TTL, revocation and break-glass all
still live in the shell. Moving them to sessiond is a separate pass.
Authorship: this patch is Rook's work, staged in surfaces/quickshell/
patches/ on 2026-08-12. The patch file carried my identity in its From
header but I did not write it; recording that here rather than wearing it
silently.
Verified: /usr/lib/qt6/bin/qmllint exit 0 against the composed tree, gate
proven able to reject (exit 255 on a deliberately broken control).
Untested: no shell has loaded this and no surface calls respond() yet.
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.
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.
Verified against a running shell rather than a clean load, which immediately
found two faults every prior gate had called clean. Both controls dropped from
0008 recorded as decisions so a later session does not restore them.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.