.cargo/config.toml + aarch64-pkg-config wrapper are load-bearing for the
cross build (CI artifact job + local build-cross.sh both depend on them);
were gitignored before. souveraine.service is the systemd user unit the
packaging/deploy scripts template.
SendMessageRequest gains ambient (surface sensorium note). RemoteBackend
gains spawn_cancel_watch + spawn_interject_pump so TUI remote mode has the
same interrupt/type-while-busy semantics as local. StreamEvent is now the
full wire mirror of BackendEvent — a new engine event is a compile error
at the SSE seam, not a silent skip.
Speaks the Claude Code subscription wire protocol against api.anthropic.com
using the OAuth creds claude already stored, so Souveraine can drive a
Claude.ai subscription directly alongside Bifrost/openai-oauth. Translates
OpenAI-shaped internal requests to/from Anthropic /v1/messages, applies the
subscription shaping, refreshes the OAuth token under a mutex.
tuie now cloned from Fimeg/tuie (rgb patch committed) at a pinned SHA
instead of upstream HEAD — no floating ref decides if we build.
aarch64-artifact job runs on the new archdev host-mode runner, cross-
builds against ~/aarch64-sysroot (linker --sysroot flag proven to find
aarch64 libmvec), publishes the binary to a rolling edge prerelease
when CI is green. Phone updates itself from there.
Both live on Overlay; z-order was creation order, so an ii restart buried
the pill under the dock and it stopped taking touch. The pill now has
namespace quickshell:pill; a matching 'order = 1' hl.layer_rule in the
phone's hyprland.lua keeps it on top across restarts (rule is phone
config, not surface tree).
- dock icons center in the bar (DockApps top-margin was shoving the row
down; DockAppButton block now reserves half the dot strip)
- pill double-tap fullscreens the real app: routes through dock IPC
fullscreen() targeting Hyprland.activeToplevel.address, mode 0, so the
pill tap focusing the shell no longer redirects it
- pill must be re-created after the dock or it sits under it and drops
touch (both on Overlay; z-order = creation order)
- HOW-IT-WORKS.md: the concise contract for pill/dock/fullscreen
Both were stranded untracked in the Pixel3Arch tree; they source from
this repo, so they live here. deploy-phone.sh ships the cross-built
binary + user unit (seed-id excluded, machine binding stays doctrine);
PKGBUILD builds from a synced local checkout, no network fetch.
Dock fan-out stacks, drag-to-combine, pill gesture rewrite, and the ii
patch set (TaskbarApps stacks API, Config dock.stacks schema) — pulled
from the live phone and made canonical here. deploy.sh grew a manifest
and a --phone mode: rsync the surface over, symlink ii into it, so live
edits land in a git tree instead of drifting.
ToolCard styled the status glyph with a hardcoded byte offset 0..3, but
✓/✗/⟳ are 3-byte chars sitting at bytes 2..5 of " {glyph}". The split
landed mid-char and panicked at render in tuie's style slicing. Compute
the glyph region as 2 + glyph.len_utf8() instead.
Then took cargo clippy -- -D warnings from 312 failures to clean:
- scoped #![allow(dead_code)] on WIP scaffolding (federation, sensorium,
gitea_memory, model_router, session, subagent…); gate stays live on
active code so new orphans still fail
- scoped #![allow(deprecated)] on the legacy ratatui render path, marked
pending removal at tuie parity — no migration on code we're deleting
- declare the gui feature (forwards to tuie/gui) — the cfg was real intent
- real fixes: duplicate SaveAndGoBack arm + dead Err arm, base64::encode,
4 unused imports, dead assignment, private-type leak, dedup'd if/else
branches, manual clamp/strip, &PathBuf→&Path, collapsible matches
agents: wire the rest of the detail widgets into the section children so
PRIMARY badge etc actually render; drop the HARDCODED debug text.
settings: test needs a provider in the map before navigating to Providers
cat.
clippy: pin CI to rust 1.94 per Cargo.toml rust-version; also apply what
cargo clippy --fix could auto-fix for 1.96 compat.
new TUI work that had been living in a detached re-init'd checkout, replayed
onto the public lineage. keeps CI + skills. src-only; local scaffolding stays local.
Dep bump swapped StyledText's public .text field for as_ref/as_str
accessors and set_fg/set_bg/drop_end mutators; Theme now built from
(fg, bg, [16] indexed) instead of named slots. Mechanical port across
the widget set plus an ANSI-index mapping of the chat palette.
Vanguard gets his own inference pipe. z.ai GLM Coding Plan, /paas/v4.
BifrostClient learned to leave versioned URLs alone. ProviderRegistry
dispatches per agent; every engine asks who it's talking to before
dialing. Annie and Hal none the wiser.
- Replace unsafe raw-pointer render callback in message_list with Arc<Mutex<>>
- Replace unsafe Cell::as_ptr() in splash with safe Copy derive + .get()
- Add .max(0.0) guards on all f32→u16 casts in bloom animation
- Replace unreachable!() with bail/return/match in 4 locations
- Replace expect() with Result propagation in 4 constructors (RemoteBackend, VoiceClient, BifrostClient, OpenAiOAuth)
- Wire manager kill/restart keys to signals (backend TODO remains)
- Pass agent name through TUI message render chain (was hardcoded "Ani")
- Implement scroll_page in message_list using List::scroll_by
14 widgets now match the demo source exactly (import paths rewritten):
accordion, button, checkbox, counter, flat_button, focus_pane,
global_chords, horizontal_rule, link, page_layout, point_picker,
progress_bar, radio_group, segmented_control.
Theme simplified: accent color is now Color::YELLOW, which
apply_atmosphere resolves through harmonious to the agent's
current primary — no thread-local, no RGB arithmetic.
Added chord_macro + axis2d deps matching tuie-demo's Cargo.toml.
All 27 broken call sites (field_grid, settings, cockpit,
dropdown, model_picker, text_editor) migrated to demo APIs:
FlatButton::new().child(x), Button::new().children([x]),
Checkbox::new(label).set_checked(b), Counter::new(),
PointPicker::new().point(...), etc.
Replace the flat org-grouped list with a real tree. Sources and orgs
collapse (arrows expand/collapse, Enter toggles headers / selects models),
fuzzy search auto-expands matches, and the cursor opens pinned to the
currently-selected model's branch.
New tuie widgets (buttons, dropdown, slider, accordion, checkbox, etc.),
settings screen port with model picker + text editor, and screen ports
for chat, cron, presence, welcome, and the agents manager.
Introduce a parallel TUI built on the tuie widget toolkit, selectable at
runtime with `--engine tuie`. ratatui remains the default and its
crossterm/ratatui deps are retained, so default users see no behavior
change; this lands the full screen/widget tree for the new engine
side-by-side with the existing one.
Engine wiring:
- Cargo: add `tuie` (harmonious, images features)
- main.rs: `--engine` flag + run_tuie_tui() entry path
- src/ui: new `screens`, `widgets`, `theme`, `tuie_app` modules
- app::recent_commits made pub(crate) for dashboard reuse
Screens: splash (procedural bloom), welcome dashboard, chat (live
streaming), agents picker, settings, plus cron/presence stubs.
Widgets: brand_title, portrait, menu_list, message_list, chat_bubble,
chat_input, cockpit, phase_bar, tool_card, and a reusable `responsive`
container.
Responsive welcome: the welcome screen now offers two viewable modes the
way the old ratatui dashboard did — a side-by-side portrait/stats layout
at >=100 cols and a stacked single column below it — switched by the new
`Responsive` widget. It holds both subtrees and lays out / paints only the
one that fits, while exposing both to id lookups so the menu selection
survives a resize across the breakpoint. Flourishes: a breathing title
colour pulse and a portrait border that surfaces subconscious state.
Covered by a layout test driving a TestTerminal across the breakpoint.
PR #1 (LlmProvider + OAuth) fixes:
- Move provider selection from [bifrost].provider to [inference].provider
(Bifrost is a provider, not the parent category — they are peers)
- Add Inference category to settings TUI with provider picker
- Wire build_provider() into CLI/chat/model-refresh paths so OAuth
works outside server mode
- Update ServerConversation to use Arc<dyn LlmProvider> for consistency
PR #2 (web UI) assessment:
- Remove entire web/ directory — not aligned with substrate ethos
(client-side compaction model contradicts Constitution Article IV;
autoCommit toggle misunderstands git-backed memory physics;
vocabulary doesn't match project architecture)
- Keep the 3 new REST endpoints (config, compaction-logs, token metrics)
- Revert run_reflect path change (keep canonical ~/.souveraine/agents/)
- Delete souveraine_fixes.patch (dev artifact)
- Restore demo example (was commented out as workaround for missing file)
- Copy examples/demo.rs from primary branch (was never pushed to public)
Tests: 184 passed, 0 failed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Introduce an `LlmProvider` trait (the engine<->LLM seam, sibling to the
`Backend` harness<->engine trait) so inference can route to providers
beyond the Bifrost gateway. Two impls behind it:
- `BifrostClient` - existing OpenAI-compatible gateway (default).
- `OpenAiOAuthProvider` - rides the Codex CLI's ChatGPT login
(`~/.codex/auth.json`) and drives `chatgpt.com/backend-api/codex/responses`
(Responses API) with no API key. Self-refreshes the token (single-flight,
write-back, CLI re-read fallback) and translates the engine's OpenAI-chat
request to/from the Responses API + SSE accumulation.
Selected via `[bifrost] provider` ("bifrost" | "openai-oauth"). The engine
keeps speaking the existing ChatCompletionRequest/CompletionResult/
InferenceStrain currency, so all six inference call-sites are unchanged -
only the field type flips to `Arc<dyn LlmProvider>`.
Model ids are translated at the provider boundary (oauth/catalog.rs::resolve):
Bifrost-namespaced ids (`openai/...`, `-precision`) map onto served ChatGPT
models; `-fast` -> priority service tier.
Verified live to the wire level: builds+links, server boots in oauth mode
(reads the Codex token), and chatgpt.com accepts the request (auth, endpoint,
headers, payload all valid). The SSE->CompletionResult accumulation is NOT yet
verified against a successful completion (blocked by a subscription usage limit
at test time) - needs one live turn to confirm end-to-end.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>