- gate session-list nav on idle so in-session arrows/jk don't move the list (5a)
- approval dismiss on esc + in-session 'a' reopens a pending approval (5b)
- auto-focus a newly started workflow session (was running invisibly)
- approval actions on Ctrl chords (^a/^r/^x) matching the modal; bare/Alt letters no longer approve; diff closes on ^x/esc
- steer hint in the approval modal; session UUID in the input bar
- env-gated debug logging (CORREX_TUI_LOG) with k.Alt in the key trace
Go TUI decodes model.changed / model.list / resource.status and renders a
status-bar VRAM/GPU%/RAM gauge plus a models overlay (m key / palette 'models'):
lists configured models with the resident one marked, enter swaps (SwapModel),
c clears the pin (ClearModelPin). All three new server messages are
non-event-bearing control/gauge frames, applied immediately like
provider.status_changed.
Server addition required for the picker: ServerMessage.ModelList (model.list,
NonEventMessage) sent once in the initial snapshot from
ManagedInferenceRouter.availableModelIds()/currentModelId() — the TUI otherwise
cannot enumerate swap targets.
Completes the 5-slice model-lifecycle feature. ./gradlew check green; go build/vet clean.
Plan: docs/plans/2026-05-31-model-lifecycle-management.md (slice 5 of 5).
Final plane-2 step: the tool-call intent assessment was decided
server-side but never reached the client — DomainEventMapper dropped
ToolCallAssessedEvent through the else/null branch.
- ServerMessage.ToolAssessed (tool.assessed): disposition as a plain
String + AssessedIssueDto list; observations stay off the wire
(internal replay facts, invariant #9).
- DomainEventMapper maps the event 1:1 (no filtering — rendering
decisions belong in the client).
- Go TUI consumes tool.assessed, records an event entry only for
non-PROCEED or issue-bearing assessments (noise control), and is
added to IsEventBearing() so it buffers correctly during snapshot
replay like its sibling tool.* events.