lios-bar 0.1.9

A native GTK4/VTE sidebar workspace for navigating live Lios terminal sessions.
Documentation
# LiosBar Architecture

LiosBar is one GTK application window with two primary children in a
horizontal `GtkPaned`: a sidebar and a `GtkStack`. These are owned by the
reusable `SessionWorkspace` library component. Moving the sidebar swaps
those two children after detaching them, so GTK never reparents a live widget
implicitly.

Each new entry owns:

- one opaque workspace-local session identifier;
- one `VteTerminal` and its PTY child;
- one list row with a bounded local name and bounded shell title;
- running or exited lifecycle state.
- one session-local clipboard controller with bounded, cancellable reads.
- one session-local Find overlay with a weak reference to its VTE widget.

The stack retains every terminal widget while the entry exists. Selecting a
row changes only the visible stack child, so hidden shells keep running and
scrollback remains attached to the correct VTE widget. New sessions prefer the
active terminal's reported local file URI, then the launch directory, then the
process directory.

Find queries are capped at 1,024 characters and escaped before compiling with
VTE's Unicode search API. Scans require Enter, navigation keys, or buttons;
the UI paints feedback before a queued scan. Query/mode edits, overlay unmapping,
and disposal cancel pending scans. Session queries/options remain in memory only.
The overlay is excluded from size measurement so opening it does not resize the PTY.

GTK signal handlers identify sessions by stable ID rather than list position.
Handlers use weak workspace references where they can outlive a session.
The component owns layout and selection; the standalone host owns VTE widgets,
shells, clipboard policy, close confirmation, and saved sidebar preferences.
Component mutations and GTK updates run outside host state borrows, avoiding
mutable `RefCell` borrow panics during synchronous callback re-entry.

The sidebar's bounded literal filter changes row visibility, never active
content. Selection reveals its row after allocation. Activation has a separate
callback so clicking an existing selection or returning from the filter can
restore terminal focus without manufacturing a session change. Shell-title
updates do not force-scroll a user who is browsing the list unless the preview
stops matching and needs a replacement. While the filter owns focus, a separate
candidate ID, cyan outline, and accessible active descendant support Up/Down
navigation. Browsing itself emits no selection/activation callbacks. Enter or
a row click commits the choice; Escape activates the original session without
switching it. Focus loss clears
the candidate, and query edits reset it to the first match. Removing an inactive
session preserves the query even when the active terminal is filtered out.

Sidebar layout is a small value object, separate from session identity and
content. The built-in menu updates row padding, running-title visibility, and
keyboard hints without replacing any widget. Exit details remain visible. Host
callbacks receive committed layout values only, with duplicate/superseded
notifications suppressed. The standalone host saves field-level edits; Lios uses
its own config writer. Scrolling waits for a layout frame after geometry changes
before reading row allocations.

Standalone saves resolve the config's final symlink chain, load a bounded regular
file, validate the typed settings, and edit only changed keys in a TOML document.
This preserves comments, absent defaults, and sequential edits made elsewhere.
The existing atomic writer replaces the resolved target and cleans up only a
temporary file it successfully created. No transaction lock spans processes.

Reordering changes only model order and the existing sidebar row's list position.
The terminal stack and host-owned sessions are untouched. GTK selection signals
are guarded while moving rows; navigation follows model order. Drag payloads are
non-serialized GTK row objects, accepted only when both rows still belong to this
workspace. Drop validation is repeated on release, not trusted from hover state.

LiosBar deliberately does not use `LiosBridge`: that bridge exposes lifecycle
management for separate processes but no terminal byte stream or widget
embedding contract. LiosBar instead owns the terminal widgets it must switch
inside one pane. It opens no network listener.

Closing a session removes its terminal widget and closes its PTY. The UI warns
first when the child is still running. This lifecycle behavior is not a
sandbox or durable session manager; shells that must outlive the GUI belong in
`tmux`, `screen`, or another multiplexer.