Commit Graph

17693 Commits

Author SHA1 Message Date
Trey Moen 179718dcb0 esim: mici profile download UI (#38813)
* esim: MICI profile download UI

* Show temporary feedback for non-LPA QR codes

* Scan eSIM QR codes every 250 ms

* Shrink eSIM error text and log displayed errors

* Activate downloaded eSIM through the profile tap flow

* Let the eSIM connectivity error wrap naturally

* Release add-profile button feedback immediately

* Check internet before opening the eSIM QR scanner

* Use UI network state and standard connectivity dialog for eSIM

* Drop LPA prime settings change from eSIM download UI

* Scope eSIM UI constants to their owning classes

* Remove unused ot codespell exception

* esim: simplify profile download operation and UI state

* esim: share activation code validation with QR scanner

* esim: match QR scanner video to cabin preview

* esim: show errors in a scrollable text dialog

* esim: require nonblank profile nicknames
2026-09-08 23:16:17 -07:00
Trey Moen d70df67366 mici: process eSIM notifications after profile deletion (#38832) 2026-09-08 21:39:24 -07:00
Trey Moen 66b4dbe2a1 qrcode: add QR decoder (#38814)
* qrcode: add QR decoder

Decodes a QR code from a grayscale image or a module matrix: adaptive
binarization, finder pattern search by run ratios, perspective sampling
with alignment pattern refinement, format info, unmasking, block
de-interleaving, Reed-Solomon correction, and numeric, alphanumeric,
byte (with ECI), and Kanji segments.

Fixtures are packed matrices from python-qrcode 8.2 covering every
version and level, plus Segno 1.6.6 matrices for the ECI cases.

* qrcode: tune decoder for the device

Measured on a comma mici with real cabin frames downsampled to 672x380,
the size the eSIM screen scans at. Per frame: 30 ms -> 8 ms with no
code in view, 42 ms -> 13 ms with a code.

- binarize: fixed two-radius fill from one integral image instead of an
  iterative outward fill (a dark cabin is almost all flat tiles), tile
  stats on a contiguous layout, flat tiles decided whole so sensor noise
  cannot become speckle, uint8 threshold compare
- finder search: scan every 4th row, build column runs only at
  candidate columns
- alignment search starts at a 2-module radius
- Reed-Solomon syndromes through table lookups, placement order cached

* qrcode: simplify decoder

Fold the function-module mask into _data_coords and the format
coordinates into _read_format, evaluate masks directly on the data
coordinates, compact the ECI, numeric, and alphanumeric parsing, and
flatten the retry loop in decode. No behavior change.
2026-09-09 04:23:55 +00:00
Trey Moen ef769c173d qrcode: generalize EC, format, and GF tables (#38828)
Replace the level-L-only Reed-Solomon parameters, the single hardcoded
format word, and the bitwise GF(256) multiply with the full EC table,
the 32 format words, and log/antilog tables. Block splitting and
interleaving move into _block_lengths and _interleaved. This is the
structure a decoder needs to read any version, level, and mask; the
encoder's module matrices are unchanged and test_encoder pins them.
2026-09-08 19:15:39 -07:00
Trey Moen a4a24d5d87 qrcode: fix alignment pattern positions for version 32 (#38827)
The closed-form step between alignment patterns rounds the wrong way
for version 32 (28 instead of 26). Use the form that is right for every
version. The encoder only emits versions 1-20, so its output is
unchanged.
2026-09-08 19:05:18 -07:00
Trey Moen 1fb3edb7dd qrcode: test alignment pattern positions (#38829) 2026-09-08 18:53:33 -07:00
Daniel Koepping dd4615850c replay chestnut in CI (#38826)
run model replay on chestnut in CI
2026-09-08 18:05:03 -07:00
Daniel Koepping f23e65768c ui: resize status icons (#38749)
* ui: resize status icons

* Update orange GPU icon to 108px height

* Trigger CI after LFS upload

* ci
2026-09-08 17:06:12 -07:00
Adeeb Shihadeh 96be8c7eb5 check dependency footprint (#38825) 2026-09-08 16:46:19 -07:00
Daniel Koepping 23d0474b95 compile big model in jenkins CI (#38822)
compile chestnut in ci
2026-09-08 15:37:12 -07:00
ZwX1616 60d8ae2d4f modeld/SConscript: fix chunk_targets estimate (#38821) 2026-09-08 15:27:11 -07:00
Trey Moen 7bfe6ba4d0 pandad: allow disabling driver camera IR offroad (#38812) 2026-09-08 15:21:03 -07:00
Pramish 9946c521f7 modeld: build DM warp and model JITs for all camera configs (#38767)
* modeld: build DM warp and model JITs for all camera configs

In #38684, camera_configs on comma_arm64 was restricted to only the host device
running SCons (selecting either _os_fisheye or _ar_ox_fisheye).

However, prebuilt release and nightly bundles are built on TICI/tizi runners
in Jenkins and distributed to both Comma 3/3X (TICI) and Comma 4 (MICI) devices.
Because the build machine was TICI, dm_warp_1344x760_tinygrad.pkl was omitted
from the packaged bundle, causing dmonitoringmodeld to fail with FileNotFoundError
on Comma 4 and leaving driver-monitoring calibration stuck at 0%.

Restore CAMERA_CONFIGS so both camera resolutions (1928x1208 and 1344x760)
are built for all platforms.

Fixes #38762

* simplify

---------

Co-authored-by: ZwX1616 <zwx1616@gmail.com>
2026-09-08 14:16:21 -07:00
Trey Moen 25d9d41c90 esim: comma four profile management UI (#37844)
* esim: MICI eSIM profile management UI

* esim: align rename button position regardless of delete button

* esim: skip profile UI when SIM is not an eUICC

Probe is_euicc() on the first profile poll and cache it; non-eUICC SIMs
avoid list_profiles/process_notifications (which hang on a plain SIM) and
the eSIM button shows ICCID/MCC-MNC metadata instead of opening the
profile management screen.

* esim: satisfy ruff E731 in action_pressed helper

* esim: get modem info from modem.py state instead of shelling out

* esim: simplify switch lifecycle, drop active flag and settle window

* esim: only show 'switching...' on the target profile

* esim: read cell strength directly from HARDWARE

* esim: hide checkmark and dim cell icon during switch; keep rename available

* esim: disable active profile button (rename still clickable as overlay)

* esim: stop rename/delete buttons and labels from flashing during operations

* esim: show 'comma prime' on network button for comma profile

* esim: move display_name and is_comma onto Profile dataclass

* esim: anchor rename button to rightmost slot to prevent shift

* esim: include iccid prefix check in Profile.is_comma

* esim: drop process_notifications from cellular manager

* esim: disable network button when SIM isn't an eUICC

* esim: rename ESim* classes to Esim*

* esim: sort imports

* esim: default to 'loading...' instead of 'no active profile'

* esim: rename PROFILE_POLL_INTERVAL to PROFILE_POLL_INTERVAL_S

* esim: slim EsimNetworkButton

* esim: use DEFAULT_TEXT_COLOR; load delete dialog texture in __init__

* esim: revert cell-icon index trick, name each NetworkStrength explicitly

* esim: tighten delete/rename spacing so 'switch' label fits on one line

* esim: shrink delete/rename buttons by 25%

* esim: keep rename button at full size, only delete shrinks

* Revert "disable modem.py for now"

This reverts commit 1eeba86ec1.

* Revert "modem.py is disabled"

This reverts commit d238a1ccc4.

* lpa: inline comma iccid prefix

* ui/cellular_manager: clear switching state when LPA returns

* ui/cellular_manager: lock callback queue, drop poll log noise

* esim: sort NetworkStrength/NetworkType imports

* esim: drop switching_iccid concept

* esim: show 'switching...' on the clicked profile button

* esim: optimistic switch, skip post-switch list_profiles to avoid flicker

* esim: only style profile button from local op flags, not global busy

* esim: remove deleting/switching state, collapse profile button branches

* esim: show GSM settings on full prime when non-comma profile is active

* esim: expose CellularManager.active_profile, dedup callers

* esim: apply comma prime defaults on switch (roaming, metered, no APN)

* esim: restore re_sort on show_event to avoid first-frame jank

* lpa: apply comma prime defaults inside TiciLPA.switch_profile

* lpa: lazy-import Params to break circular import

* lpa: treat +CME ERROR 13 (SIM failure) as non-eUICC in is_euicc

* esim: show 'obtaining IP...' on non-eUICC path while connecting

* Revert "lpa: treat +CME ERROR 13 (SIM failure) as non-eUICC in is_euicc"

This reverts commit 475ca448ea914ff8f9892b4cbf4525d961d7618b.

* esim: poll profiles every 5s

* lpa: tighten Profile.is_comma to require both Webbing provider and comma BIN

* lpa: fall back to '<unnamed>' instead of iccid prefix in display_name

* esim: re-probe is_euicc each poll for runtime SIM swaps

* esim_ui: rename EsimUIMici to EsimUI

* esim: simplify cellular manager and profile UI

- optimistic profile switch at click time so the active button no longer bounces back
- unify LPA worker threads, refresh_profiles resets the poll timer
- deterministic profile ordering on show
- reuse wifi ForgetButton for delete, drop DeleteButton
- construct CellularManager inside NetworkLayoutMici
- drop comma prime param defaults from LPA.switch_profile (moved to a separate PR)

* esim: drop eUICC state change log

* ui: gate cellular settings on prime subscription

* ui: disable eSIM management for full prime

* ui: keep eSIM management disabled for full prime

* ui: unify eSIM profile action buttons

* ui: tighten eSIM profile action spacing

* ui: place rename before delete in eSIM actions

* esim: restrict individual profiles and process switch notifications

* esim: defer poll after operations and confirm eUICC loss before clearing profiles

* ui: allow cellular settings for unregistered and unpaired devices

* ui: disable all profile switching for full prime

* ui: simplify cellular access to not full prime

* ui: make profile poll interval a CellularManager constant

* ui: read modem state on the profile poll cadence

* ui: scope eSIM profile colors to their class

* ui: inline modem state read in cellular polling

* ui: rely on hardware modem state fallback
2026-09-07 21:55:28 -07:00
Trey Moen 8f2d66d0e5 cabana: round only the outer video frame (#38808)
* cabana: remove video frame corner rounding

* cabana: round the outer video frame including letterboxing
2026-09-07 21:26:53 -07:00
Trey Moen 3eafb658bf mici: remove duplicate pairing button from main settings (#38809) 2026-09-07 17:48:33 -07:00
Trey Moen 10b9e73859 cabana: fill event bar to camera edges (#38807) 2026-09-07 17:06:01 -07:00
Trey Moen bb86bee688 cabana: clean up UI wording and formatting (#38803) 2026-09-07 14:56:19 -07:00
Trey Moen 3e54af9db8 cabana: playback controls for live streaming (#38802)
* Hide Cabana playback controls during live streaming

* cabana: retain pause and go-live controls for live streams
2026-09-07 14:47:20 -07:00
Trey Moen 20ae4ac44d cabana: standardize settings step buttons (#38801)
* cabana: align and brighten settings step buttons

* cabana: use standard settings icon button color
2026-09-07 14:08:32 -07:00
Trey Moen 7c1f224443 cabana: stack the undo/redo zoom buttons in the chart menu (#38800) 2026-09-07 13:03:12 -07:00
Trey Moen 2b4d050e9c cabana: fix video startup and desktop interactions (#38798)
* cabana: fix video startup and desktop interactions

* cabana: remove util comments
2026-09-07 12:43:41 -07:00
Trey Moen 1bb019521e cabana: fix chart ranges and control layout (#38797) 2026-09-07 12:42:41 -07:00
Trey Moen 624d5b9995 cabana: fix stream and replay lifetimes (#38796) 2026-09-07 12:33:14 -07:00
Trey Moen 0f9ec7158b cabana: validate message IDs and include recorded CAN messages (#38799) 2026-09-07 12:32:22 -07:00
Trey Moen 9c02eebb72 cabana: fix clipped control outlines and filter sizing (#38795)
* cabana: fix clipped control outlines and filter sizing

* cabana: remove added comments

* cabana: document control helper API usage
2026-09-07 12:05:26 -07:00
Trey Moen cb70ba89aa cabana: smooth startup layout (#38794)
* cabana: smooth startup layout

* cabana: remove camera tab startup comment

* cabana: initialize dock geometry on the first frame

* cabana: remove route loading placeholder
2026-09-07 11:50:13 -07:00
Trey Moen 65c411433b cabana: reduce downloader startup and dense chart rendering overhead (#38793)
* cabana: reduce downloader startup and dense chart rendering overhead

* cabana: remove downloader spawn tests
2026-09-07 01:22:23 -07:00
Adeeb Shihadeh 6bbdf8ad18 remove sentry (#38790) 2026-09-06 21:20:39 -07:00
Trey Moen 9d1f0d4171 cabana: restyle (#38789)
* cabana: connect palette theme, rounded cards, floating page switch

Move the jotpluggler port's connect palette into a shared theme module
(ui/theme.h/.cc) and apply it to all of cabana: Palette struct for dark
and light, applyTheme fills ImGui and ImPlot styles, readableCurveColor
and sectionTitle for reuse by the analysis workspace. Drop the old
DarkTheme constants and per-theme color branches in widgets.

Docked panels are borderless with content in rounded bordered cards;
custom-drawn rects use the style radii. The detail widget's bottom tab
bar is replaced by a floating Messages/Logs pill.

* cabana: scrollbar and menu contrast, page switch below the page

The scrollbar grab uses the border color on the window-colored track.
Selection colors are stronger so an open menu reads as blue in both
themes and the hovered item is visible in light mode. The Messages/Logs
pill sits in a strip below the page instead of covering its last rows.

* cabana: even spacing around the page switch, steady top menu highlight

* cabana: inner spacing before the clear button of a clearable input

* cabana: center the page switch below the page, space the signal row buttons

* cabana: logs table cells padded and bordered like the messages table

* cabana: recess the signals card in the window color

* cabana: one button vocabulary

Three button shapes, all one frame height with the style padding and
rounding: ImGui::Button for framed text, iconButton for a framed square
icon, toolButton for a flat square icon (or flat text). Adjacent buttons
are ItemInnerSpacing apart, groups ItemSpacing apart. Tool bars drop
their private padding and 1 px spacing, the signal row, chart header,
detail header, logs export and signal selector buttons all use the
shared sizes, and the page switch is built from the same style values.

* cabana: center the glyph ink in square icon buttons

* cabana: framed tool buttons and plain icon glyphs

toolButton is now iconButton with an optional text, so every button in
the app is framed. Boxed glyphs (plus-square, x-square, dash-square,
arrow-*-square, window-stack) are replaced by their plain variants
(plus-lg, trash, arrows-collapse, box-arrow-*, window-plus), the light
x/plus/dash by their -lg forms, the chart menu by three-dots-vertical
and the toolbar overflow by chevron-double-right.

* cabana: draw square button glyphs at 80% so full bleed icons keep a margin

* cabana: signal values in the mono font

* cabana: center square button icons on their atlas ink, snapped to framebuffer pixels

* cabana: draw square button glyph quads directly, AddText truncates the position

* cabana: right align the messages and signals tool bars to the table edge, full size collapse button

* cabana: detail header and tab scroll buttons flush with the right edge

* cabana: header and footer strips, gap above the panels, video splitter as a separator

The menu bar and the status bar are strips in the surface color with a
separator line towards the panels, and the dockspace sits one item
spacing below the menu bar, matching the spacing above the status bar.
The video/charts splitter draws the same 1 px separator line as the
dock splitters, centered in a gap as tall as the side padding, and a
double click snaps the video back to its natural height.

* cabana: top menus flush with the menu bar, 2 px video splitter without double click

* cabana: dropdowns continue the menu bar, splitter in the border color, row button gap

Top level menus draw no top border and square top corners, and the menu
bar leaves its separator out under the open dropdown. The video splitter
uses the border color like the dock splitters. The signal row buttons
keep one inner spacing before the scrollbar.

* cabana: dropdowns share the bar's 1 px border line, messages toolbar spacing matches the video card

* cabana: tool bar groups, framed dropdown buttons, chart content flush with the tool bar

Tool bar items are ItemSpacing apart and the items of a group (a button
pair, a separator and its neighbor) ItemInnerSpacing apart, instead of
a private 1 px spacing. The dropdown buttons are framed like the other
buttons. The video time is a plain mono readout that toggles on click.
Chart cards have no horizontal margin so their header and plot line up
with the tool bar above.

* cabana: chart list spacing: gap above the scroll area, charts clear of the scrollbar, even legend gaps

* cabana: loop and speed buttons grouped like the playback buttons

* cabana: survive narrow panels and small windows

Stress tested by dragging the column and video splitters to their
limits and shrinking the window to 640x480. Fixes: the messages tool
bar and the message detail header overflow into the >> menu instead of
clipping (the view button and the name stay); the binary view keeps a
minimum cell width and scrolls sideways; the Messages/Logs switch drops
to icons when the strip is too narrow; the camera keeps its last frame
across reconnects, so a video restored from a collapsed splitter while
paused is no longer black.

* cabana: range slider spans the charts >> menu, remove all and float as menu entries

* cabana: the charts card keeps its tool bar row or collapses, like the video at the other end

* cabana: uniform >> menus: dropdowns become submenus, the time readout an action entry

* cabana: video/charts splitter gap matches the column splitters

* cabana: drop unused lambda capture in chart type menu

Claude-Session: https://claude.ai/code/session_01XTFaJpf235LeHBmyFRgeJ1

* cabana: the menu bar and the status bar stay in full screen

* cabana: simplify theme helpers and toolbar actions

* cabana: preserve panel width for overflow edit dialog

* cabana: keep message editor usable in narrow panels

* cabana: group heatmap modes in a dropdown

* cabana: trim redundant restyle comments

* cabana: fix review findings from the restyle

- set the caret and other unset colors so the light theme has no white caret
- tolerate float error in the toolbar fit check to stop spurious overflow
- restore the full screen chrome hiding
- clear stale camera frames when the server changes, keep them across a collapse
- cache icon glyph ink bounds instead of scanning the atlas every frame
- drop dead plot_bg and ImPlot globals, add a badge palette role
- add toolbarMenu and use toolbarAction for the remove message item
- derive the signal view button size seed from the font and style

* cabana: remove remaining redundant comments
2026-09-06 19:46:02 -07:00
YassineYousfi c51e3e5a71 cinque terre model 🇮🇹 (#38771)
a4c5f1d1-1f5d-4807-9593-54afa27099d5/12864
2026-09-05 19:03:12 -07:00
Trey Moen 3bc6701f34 cabana: fill video pane and reset video height (#38786) 2026-09-05 17:02:05 -07:00
Trey Moen cb0da74b41 cabana: center speed dropdown label, add divider after loop button (#38785) 2026-09-05 15:34:00 -07:00
Trey Moen a4f7c50d2a cabana: fix sparkline edges and stroke rendering (#38784)
cabana: preserve sparkline edges and improve stroke rendering
2026-09-05 14:54:17 -07:00
Trey Moen 444be0a649 cabana: pace frames instead of relying on vsync (#38783)
On Wayland a vsynced glfwSwapBuffers blocks until the compositor sends a
frame callback, which it stops doing while the window is on another
workspace or otherwise off-screen. The main thread never gets back to
glfwPollEvents, so Hyprland reports cabana as not responding.

Run with swap interval 0 and pace the loop to the monitor refresh rate.
2026-09-05 14:49:37 -07:00
Trey Moen a989bc0b50 cabana: misc UI tweaks (#38782) 2026-09-05 14:13:15 -07:00
Trey Moen f9dacd0d6b cabana: build binary directly, drop wrapper script (#38781) 2026-09-05 13:45:12 -07:00
Trey Moen 0ec3a082c7 op: support all the linuxes! (#38776) 2026-09-04 21:10:04 -07:00
Trey Moen c8603fb3ce op: point git-lfs config at the vendored binary (#38775)
git-lfs is vendored in the venv, but `git lfs install` writes filters and hooks that invoke a bare `git-lfs`, which is only on PATH inside the venv. With filter.lfs.required set, any checkout from a plain shell fails.

git runs filters and hooks from the worktree root, so a relative path into the venv resolves from anywhere.
2026-09-04 21:09:40 -07:00
Trey Moen 69ad376fef Revert "op: support all the linuxes!" (#38774)
Revert "op: support all the linuxes! (#38773)"

This reverts commit 33790c855c.
2026-09-04 19:09:45 -07:00
Trey Moen 33790c855c op: support all the linuxes! (#38773) 2026-09-04 18:30:45 -07:00
Adeeb Shihadeh 675ff56981 tools: add op docs command (#38770) 2026-09-04 15:20:43 -07:00
YassineYousfi e3def37695 revert 38742 (#38760) 2026-09-03 09:45:51 -07:00
Trey Moen 3a13b67b6f bye bye Qt! (#38753)
* cabana: remove Qt implementation
2026-09-02 20:44:11 -07:00
Trey Moen 7bade9a67a cabana: halve dock panel min width (#38759) 2026-09-02 20:28:53 -07:00
Trey Moen c163743e32 cabana: better colors (#38758) 2026-09-02 20:20:23 -07:00
Trey Moen 06d76bdb24 cabana: imgui port (#38725)
* cabana: imgui frontend base infra (ui/)

* cabana: line-for-line imgui ports of the Qt widgets and dialogs into ui/

* cabana ui: fixes from the side by side parity test

* cabana ui: deqt.md status after the line-for-line ports

* cabana ui: fixes from the line-for-line review

* cabana ui: parity fixes from the end to end matrix, event driven frame pacing

* cabana ui: preserve F1 help formatting

* cabana ui: parity fixes from the end to end matrix, event driven frame pacing

* cabana ui: deqt.md status

* cabana: fix macOS build of imgui frontend

- link Security.framework (libusb's darwin backend needs
  SecTaskCreateFromSelf/SecTaskCopyValueForEntitlement)
- drop unused loop counter in SignalView::updateChartState
- avoid -Wshadow on Sparkline::size and SignalView::highlight

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana ui: parity round 3 fixes, thread pool and one malloc arena for flat memory

* cabana ui: toolbar overflow budget, menu button carets, help overlay colors, signal editor validation

* cabana ui: deqt.md status

* cabana: let vsync pace the frame loop

The loop threw away frames with glfwWaitEventsTimeout() to hit a 30fps
(10fps idle) target while glfwSwapBuffers() was already blocking on
vsync, so two clocks beat against each other. Input events also reset
frameInterval() to 0 for a few frames, so a click swung the cadence from
~33ms to ~13ms and back -- the camera view redraws on the UI's schedule,
so that showed up as a visible hitch on every message selection.

Poll and draw every iteration and let glfwSwapInterval(1) do the pacing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana: fix macOS build of thread pool / malloc arena changes

- malloc.h and mallopt(M_ARENA_MAX) are glibc only; guard on __GLIBC__.
  macOS has a single allocator zone, so there is nothing to cap.
- capturing structured bindings in a lambda is a C++20 extension and
  clang rejects it under -Werror; bind the event range to plain locals.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana ui: chart axis label precision, signal list click on empty space clears the selection

* cabana ui: codespell

* cabana ui: taller signal rows, system theme detection, full dark palette

- signal rows are 1.5x a frame tall with the sparkline sized to the row,
  so the graphs are readable. The expanded sub-rows keep the Qt height.
- "Automatic" resolved to the light theme regardless of the system: Qt
  gets this from QStyle::standardPalette(), which follows the macOS
  appearance, so read AppleInterfaceStyle and match it. Other platforms
  stay light, like standardPalette() does there.
- widgets that tested settings.theme == DARK_THEME themselves went light
  under AUTO_THEME while the style went dark; they now ask isDarkTheme()
  for the theme applyTheme() actually resolved.
- the dark branch only set 10 ImGuiCol_ entries, so buttons, scrollbars,
  tabs, title bars, separators, tables and grips still came from imgui's
  stock dark theme. Derive the whole palette from DarkTheme instead.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana ui: drop the dead y axis alignment chain and chart cache stub

ImPlot::BeginAlignedPlots aligns the chart y axes, so the hand-rolled
alignment protocol ported from Qt no longer feeds anything: align_to was
write-only. Remove the whole chain (y_label_width and its measuring loop
in draw(), axisYLabelWidthChanged, align_timer, alignCharts), which
reduces updatePlotArea(int, bool) to updatePlotArea().

resetChartCache() has been an empty stub since the port (imgui redraws
every frame); drop it and its four call sites. Also replace the empty
move_icon_rect branch in mousePressEvent with an early return.

No behavior change. updateAxisY's "|| y_label_width == 0" guard only
fired after a unit change, and y_precision/y_tick_count depend solely on
min_y/max_y/tick_count, so the recompute it triggered was a no-op.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana ui: stop the main window from scrolling

The host window that holds the dockspace uses zero WindowPadding but the
default ItemSpacing, so the dockspace and the status bar below it summed
to ItemSpacing.y (5px) more than the viewport, leaving the whole UI
scrollable by a few pixels.

Reserve the spacing along with the status bar height, and mark the host
window NoScrollbar/NoScrollWithMouse: it is pinned to the viewport work
area and should never scroll, as QMainWindow does not. Full screen is
unaffected, it draws no status bar and reserves no height.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana ui: inset the status bar so its ends are not clipped

A borderless BeginChild gets WindowPadding forced to zero, so the status
bar text sat flush against both edges and the first glyph of "For Help,
Press F1" was cut off. Inset both ends by WindowPadding.x, which lines
the text up with the content of the docked panels above it.

Right align the cached minutes / FPS label to the captured child width
rather than calling GetContentRegionAvail() again after the message
text, which only returned the full width because the text had already
wrapped the cursor to a new line.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana ui: drop the leftover imgui object census log

The block printed an imgui/implot object count to stderr every 10s,
which was instrumentation for tracking down a leak, not something the
port needs. It was the only user of implot_internal.h in mainwin.cc, so
drop that include with it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana ui: keep the selected row highlighted while hovered

Selectable() picks its background as HeaderActive when held, else
HeaderHovered when hovered, else Header. The hovered test comes before
the selected one, so a selected row under the cursor takes the hover
color. Both tables push a transparent HeaderHovered to suppress the hover
highlight that QTreeView/QTableView do not have, which also blanked the
selection: clicking a row walked press (HeaderActive, visible), release
(HeaderHovered, transparent, looks unselected), then mouse off the row
(Header, visible), so the selection appeared to flicker until the cursor
moved away.

Only make HeaderHovered transparent for rows that are not selected.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana ui: draw the binary view hex column in bold and in the text color

The Qt delegate never sets a pen for the hex column, so it inherited the
black QPainter default and the two halves of a row did not match. Use
paletteText(is_message_active), the same color the bit columns use, so
both halves read as one row and dim together when the message goes
inactive.

JetBrains Mono ships no bold variant and imgui has no embolden option, so
give drawStaticText a bold flag that redraws the glyphs a fraction of a
pixel to the right. That keeps the monospace advance, which switching to
the proportional bold face would not.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana ui: highlight the whole row in the speed menu

MenuItem spans from the cursor to the right edge, so the Indent() that
made room for the radio bullet also pushed the highlight in by one
FontSize and left the bullet column outside it. QMenu highlights the
whole item, indicator included.

Draw each row as one full width Selectable with the bullet and the label
inside it. Every row declares the same width, so the popup is as wide as
the widest entry and the highlights reach both edges; a label-less
Selectable sized zero would declare no layout width and collapse the
auto-sizing popup. Selectable auto-closes its parent popup like MenuItem
does, so clicking still works in the dropdown and in the Speed submenu of
the toolbar overflow menu, which shares this function.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana ui: fix help menu overlay, Ctrl+F11, time label clipping, toolbar overflow and tool table parity

* cabana ui: click to edit signal cells, light theme selection, logs cell selection and filter fixes

* cabana ui: chart x label margin, zoom context menu items, video splitter collapse, signal editor close

* cabana ui: signal editor lifetime and close, logs cell hover, tool table headers

* cabana ui: branch indicator clicks, editor swallows shortcut and button clicks, selection colors

* cabana ui: float dock windows into real OS windows

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana ui: toolbar menu arrow spacing, only open the editor on editable cells

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* op: add cabana2 to run the imgui cabana

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana: cabana2 launcher script builds _cabana_ui before running it

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana ui: only float the dock panels into their own OS windows

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana ui: open the video pane at the camera's natural aspect ratio

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana: default fps to 30

* cabana ui: fusion palette, shared fusion slider, chart grid colors

* cabana ui: smaller checkbox indicator, closer to the Fusion size

* cabana ui: video toolbar height and item centering, separator extent and menu arrow like Fusion

* cabana ui: message and signal row heights match Qt

* cabana ui: timeline slider height, groove and stacking match the Qt video layout

* cabana ui: fix crash opening a live stream, the video pane default height read the missing camera widget

* cabana: drop the FPS setting, the streams update the UI at a fixed 30 fps

* cabana ui: video and charts pane run edge to edge with a uniform toolbar margin like the Qt frames

* cabana ui: binary view M/L marker size and timeline event fills match Qt

* cabana ui: signal view keeps its sparklines while filtering, number label size matches Qt

* cabana ui: no modal dim fade, QDialog does not animate in

* cabana ui: collapse all is an auto-raise tool button with the Qt icon size

* cabana ui: dialogs and tool windows open as real OS windows like QDialog

* cabana ui: hold back a focus loss while a mouse button is down so tearing a panel off does not abort the drag and create its window twice

* cabana ui: speed menu rows pad the label on the right like QMenu

* cabana ui: raise the dark theme contrast, the Darcula grays all sat on top of the background

the chart y axis guides are opaque and 2 px in dark mode, and text, outlines,
separators, table borders, scrollbar and slider grabs move away from the window
and base grays. light theme is unchanged.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana ui: simplify comments, drop the Qt references and the ones that only restate the code

* cabana ui: keep the sparkline antialiased, thin peaks sparkled as the window slid

Qt dropped antialiasing above 500 points because it rasterized into a pixmap. drawing
straight into the frame, an aliased 1 px segment between two columns rounds into one of
them and the rounding flips as the window advances, so the peaks of the dense signals
popped between columns. updateState runs at STREAM_UPDATE_FPS, which at a 30s range moves
the curve well under a pixel per update, so the flip is all that is visible.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana ui: anchor the sparkline to the time window, it jittered sideways as samples expired

x was measured from the first sample still inside the window, which changes whenever the
oldest one falls out, so every update slid the whole curve sideways by the sample spacing.
measuring from the start of the window pins the right edge and lets the samples flow left
with the clock. the density heuristic wanted the data span, which is no longer the x of the
last point, and the flat line started at x 0 instead of at its first sample.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana ui: scroll the sparkline at the frame rate, it stepped at the message rate

the window ended at the last message of the id and updateState only runs when one arrives,
so a slow message held the sparkline still for several frames and then jumped it. the window
now ends at the playback clock, and draw() slides the rendered polyline by the time that has
passed since it was built, clipped to the cell.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana ui: keep the signal value on the right of the column before there is a sparkline

it was drawn left aligned from the start of the column, so the value sat next to the name
until the first samples arrived and then jumped across the row.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana ui: read a little past the sparkline window so the oldest points slide out of it

a sample used to disappear the moment it aged out, which on a fixed rate signal is a point
popping off the left edge. the query reaches back a bit further and the clip rect hides it
instead. the lead in must not move the scale, so it is left out of the min and max.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana ui: use the macOS fullscreen space, taking over the monitor rendered at the old size

glfwSetWindowMonitor switched the display mode and returned a drawable at that mode, so the
ui was rendered at the windowed size and stretched over the screen. NSWindow toggleFullScreen
keeps the backing scale. the green button goes through the same space, so the state is read
back from the style mask rather than tracked.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana ui: let the signal value column shrink again, it held the widest value ever seen

max_value_width only ever grew, so one long value left the sparklines ending
well short of the text for the rest of the message. Track the current widest
value instead, growing on demand and giving room back once it is a couple of
characters too wide, which keeps the width from jittering per sample.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana ui: make the signal rows a quarter taller so the sparklines read better

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana ui: lift the binary view heatmap alphas in dark mode, the tints washed out

The alphas were tuned against a white background; over the dark base the same
values left the cells barely colored. The floor comes up and the ramp gets a
gamma in dark mode only, which keeps the flip counts in the same order.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana ui: saturate the sparkline color in light mode, the pastel lines vanished

Signal colors are low saturation and high value, which is aimed at dark fills;
a 1 px line of one of them on white is hard to see. Draw the sparkline with
twice the saturation and less value when the theme is light.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana ui: give the docked panels a minimum width, the dividers ran over content

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* replay: capture the downloader's stderr so the progress lines reach the handler

file_downloader.py writes PROGRESS:<cur>:<total> to stderr while it streams a
file, but runPython() only piped stdout and left stderr attached to the parent,
so the progress handler only ever fired on failure and cabana downloaded a
segment with no progress bar. Pipe stderr as well, turn the PROGRESS lines into
handler calls, and pass everything else through to the parent's stderr.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* replay: read the downloader's stderr on a thread, the two fd select was overkill

getline() handles the line splitting, partial lines and EOF, so the manual
splitter, the second drain loop and the multiplexing bookkeeping go away and
the stdout loop goes back to what it was.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana ui: one toolButton helper in imgui_util.h

* cabana ui: one toImU32/toImVec4/paletteBrightText in imgui_util.h

* cabana ui: string helpers live in utils/strings.h

* cabana ui: share the fusion slider handle from imgui_util.h

* cabana ui: style.cc declarations move to imgui_util.h

* cabana ui: validatedInput and the qt validators move to imgui_util.h

* cabana ui: viewSelectable helper for the item view rows

* cabana ui: drop the comboBox pass-through

* cabana ui: tabbar moves to its own file, ready for the charts port

* cabana ui: find signal searches on the main thread again, deferred one frame like QTimer::singleShot(0)

* cabana ui: find signal computes its button and label state from the model instead of caching it

* cabana ui: share the queued popup owner protocol between the message box and the file dialog

* cabana ui: one beginDialog helper for the three centered modals, with the reopen recovery

* cabana ui: tool dialogs share the title, begin/end and escape handling, and own their connections

* cabana ui: comboBox helper replaces the hand rolled zero separated item buffers

* cabana ui: drop the unused dialog isOpen accessors

* cabana ui: one validatedText helper for the ip, double and int line edits

* cabana ui: route info reads the route segments instead of caching a row copy

* cabana ui: settings drops the phantom fps label, the constant spin flags and the raw log path buffer

* cabana ui: find similar bits drops the no-op find button disable and the address round trip

* cabana ui: message box warning overload without the empty detailed text

* cabana ui: help overlay only collects rects while it is up, skips torn off panels, and the fingerprint compare is ordered

* cabana ui: drop the glfw callbacks that only forward to the imgui backend, which already installs them

* cabana ui: elided label renders with RenderTextEllipsis instead of a paint time cache

* cabana ui: one save loop, inline cached minutes label, and drop the dead help parser branches

* cabana ui: signal cell bands are built from the two corner notches instead of a region sweep

* cabana ui: binary view items go through itemAt and updateItem assigns unconditionally

* cabana ui: message bytes read the cell padding inline and colored bytes keep the qt default pen

* cabana ui: detail widget drops createToolBar, the welcome widget flag and the unused whatsThis

* cabana ui: messages widget owns its view, header and model directly, fixed size filter editors, from_chars range parsing

* cabana ui: colored hex bytes keep the row pen, the qt delegate does not reset it per cell

* cabana ui: closeEditor drops the queued commit, its item is about to be deleted

* cabana ui: rowsInserted carries the insert position so the selected row follows its message

* cabana ui: the log filter and the message name editors use the shared validators

* cabana ui: the log header sizing and painting are free functions, no HeaderView object

* cabana ui: the visible row range is the change detector, no mirrored scroll position

* cabana ui: the line editor takes the focus flag as an argument and lets InputText revert on escape

* cabana ui: signal view drops the unreachable column parameters, unused item values and repeated sparkline tests

* cabana ui: rows outside the tree viewport are measured but not painted

* cabana ui: one toolbar item table, playback state read in draw()

* cabana ui: draw the stored thumbnail scaled by AddImage, no cpu prescaled copy

* cabana ui: one radioMenuItem helper for the speed and series type menus

* cabana ui: drop dead camera members, hoist the jpeg colour space branch, decode qlog thumbnails on the thread pool

* cabana ui: stop the vipc thread when the splitter collapses the video pane

* cabana ui: the toolbar strings and enabled state are computed in drawToolBar

* cabana ui: chartswidget uses the shared tabbar widget

* cabana ui: the chart header layout is recomputed in resizeEvent, no updateTitle

* cabana ui: updateLayout has no force flag

* cabana ui: one condition hides the value tip

* cabana ui: signal selector uses the shared dialog buttons and row indexes

* cabana ui: the chart tile geometry is one Layout struct saved and restored by drawGhost

* cabana ui: drop the empty theme branch, the unused size hint and the charts container indirections

* cabana ui: the chart holds its tip label by value

* cabana ui: one toolbar item list for both toolbar groups

* cabana ui: the sparkline polyline is emitted through the draw list path

* cabana ui: the tab bar latches a programmatic selection and defers the close request past EndTabBar

* cabana ui: validatedText refuses an invalid edit inside the imgui buffer and the ip field keeps its char filter

* cabana ui: drop the ambiguous three argument warning overload

* cabana ui: combobox reports a real change, menu rows span the popup, one popup protocol for the dialogs

* cabana ui: the startup stream is owned by the window until the first frame opens it

* cabana ui: the slider toolbar index has an out of range sentinel

* cabana ui: the find signal search runs on the frame after the pending state is painted

* cabana ui: the log clears its selection when the rows are dropped and cells are identified by their message

* cabana ui: the open editor survives a scroll, collapse all commits it and escape in the size editor does not

* cabana ui: the header display order is filled with iota

* cabana ui: qlog thumbnails decode on their own threads, the hover thumbnail is mipmapped and the time tooltip appears on the first toggle

* cabana ui: a collapsed video dock stops the vipc thread

* cabana ui: one TOOLBAR_ITEM_SPACING, the signal view used the QCommonStyle 4 instead of Fusion's 1

* cabana ui: sparkline includes imgui_util.h for isDarkTheme

* cabana ui: imgui_util.h becomes util.h and util.cc

* cabana: delete deqt.md

* cabana ui: panel min width, matching video panel padding, centered tabs

The dock panels stop shrinking at the width where the signal view tool bar
squishes instead of at a hardcoded 440. The video/charts panel keeps the
standard window padding so it lines up with the other panels, and the
Msg/Logs tabs are centered in their bar. The cached minutes label is gone
from the status bar.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana ui: persist imgui state in cabana.json and migrate the Qt frontend's layout blobs

* cabana ui: 2px sparkline stroke

a 1px antialiased line is all fringe and no solid core, so the curve
faded and shimmered as the window scrolled.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana: drop the Automatic color theme

it only did anything on macOS: the Qt frontend fell through to
standardPalette() for both Automatic and Light, so the two were
identical everywhere else.

LIGHT_THEME and DARK_THEME keep their values so a persisted dark theme
still reads as dark; the old Automatic 0 falls back to light on load.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana ui: window color between the binary and signal views, fixed split

the binary view sits at its size hint and no longer resizes, and the gap
below it takes the window color instead of leaving a white seam.

also border the video and chart panels like the signal view.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana ui: bigger tab bar scroll buttons

imgui's built in scroll arrows are fixed at FontSize - 2 wide with the
glyph drawn in a FontSize box, so they are small and sit off center.
draw chevron buttons at the frame height instead, spaced and disabled at
the ends of the scroll range like the rest of the tool buttons.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* cabana ui: 1.5px sparkline stroke

* cabana ui: stable sparkline scrolling, one sample per column, aliased spikes

Scroll the polyline by whole physical pixels with each sample's subpixel
phase fixed to its timestamp, thin to one sample per pixel column, and
draw near-vertical segments aliased so spikes stay crisp while smooth
curves keep antialiasing.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* cabana ui: fix spelling

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* cabana ui: size the value column for the widest value a signal can produce

Sizing it to the values in the last message moved the sparklines every
time a value changed length.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* cabana ui: center the tab bar scroll chevrons and give the buttons a frame

The icon font glyph sits off center in its padded advance, so the
chevron is drawn in the button rect. The buttons take the theme's
button background and border like the tool buttons next to them.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* cabana ui: darker grid lines between table cells

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* cabana ui: the gap between the video and the charts matches the side padding

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* cabana ui: plus-square icon for the new chart button, like the remove all button

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* cabana ui: video toolbar buttons as tall as the charts toolbar buttons

The buttons carried 10 px of vertical padding, so the hover rect was
much taller than the glyph and the row looked off center.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* cabana ui: the time display in the mono font at the ui font size

With proportional digits the time changed width as it ticked and the
items after it moved.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* cabana ui: closing a floated side panel docks it back, no hide tab bar button, the charts container never scrolls

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* cabana ui: the message tabs use the TabBar widget, chevron scroll buttons for both tab bars

The chevron scroll buttons move into a scrollable tab bar widget that
both use. The wheel scrolls the tabs, both tab bars get Close Other
Tabs, and the Msg tab is labeled Messages.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* cabana ui: deliver a focus loss right away on macOS, holding it back swallowed the first click in a popup

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* cabana ui: draw the remote routes dialog at the modal's level, opened inside the tab's child window it never appeared

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* cabana ui: --no-cache turns off the local route file cache, same as replay

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* cabana: parse merged segments on replay's merge thread, the parse on the main thread dropped frames on every merge while downloading

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* cabana ui: Esc leaves full screen on all platforms

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* cabana ui: an app bundle on macOS so the menu bar and the dock show Cabana

A bare binary shows its file name there. The build wraps _cabana_ui in
a minimal Cabana.app with an Info.plist and the launcher runs that.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Revert "cabana ui: an app bundle on macOS so the menu bar and the dock show Cabana"

This reverts commit 1a45540125847ca46fcd4d7ac0522918e315057d.

* cabana ui: the app menu on macOS says Cabana

A bare binary gets an info dictionary with its file name in it, which
glfw reads for the app menu. The name is set there before glfw brings
up cocoa.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* cabana ui: macapp moves into ui/util

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* cabana ui: setMacAppName lives in ui/util.cc

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* cabana ui: apply the code review

Bugs: an empty decode batch dereferenced vals.front(), the chart x comparator
took a float, reserve used capacity(), the bit text went black while resizing
a signal, byte cells under-sized non-multiple-of-8 payloads, the CAN speed
lookup read the data speed table, the export tooltip never showed while
disabled, and the thumbnail parser and the signal search joined ad-hoc
threads on the render thread. Both now run off the pool; the search fans out
over it from its own thread.

Shared helpers in ui/util: the tool bar with its overflow menu, the menu
button, modal dialog setup, Escape inside dialogButtons, drawText,
drawElidedText, color markers, alignRight, clearableInput,
disabledItemTooltip, inputTextMultiline, tableHeadersRow with the right
click, withAlpha, boldFont, the Cocoa full screen glue, the messages panel
id. utils gets hexByte, guarded and nonEmptyDBCFiles; threadpool gets
parallelFor.

The help overlay leaves mainwin.cc for its own file, the stream teardown is
one releaseStream(), the charts own their views through unique_ptr, the
find-similar-bits message list follows the source bus, the clipboard copies
every open DBC, and the Qt vestiges (event names, model API, protected
sections, restating comments, stale TODOs, mixed member naming) are gone.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* cabana ui: collapse the model/view/delegate split

The Qt-era model, view and delegate classes were ported one to one, but
imgui draws a table in one function. MessageView, MessageViewHeader and
MessageListModel's string API fold into MessagesWidget over a plain
MessageList; HistoryLogModel folds into LogsWidget; BinaryViewModel and
BinaryItemDelegate fold into BinaryView; SignalItemDelegate folds into
SignalView, and SignalModel keeps only the item tree with three predicates
instead of the flags bitmask; FindSignalModel becomes SignalSearch. The
byte cell painter is a set of free functions shared by the two tables.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* cabana ui: load the route behind the window

The route file listing is an HTTPS round trip to the comma API and took
the whole first second of startup before the window existed. The replay
branch of main() now hands run() a loader that a worker executes after
the first frame; the window maps in ~0.1 s instead of ~1 s. On a failed
load the app stays open in the No Stream state with the error box
instead of exiting before a window ever appeared.

* cabana ui: fix the live stream video controls layout

* cabana ui: only copy dbc to clipboard with a single file

* cabana ui: report route loading failures instead of hanging

* cabana: launch the imgui frontend by default, --legacy for Qt

---------

Co-authored-by: Trey Moen <trey@Treys-MacBook-Pro.local>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-02 08:06:41 -07:00
YassineYousfi 50fb67f718 bump tg + TC_MIN_GLOBALS (#38751)
bump op + TC min globals
2026-09-01 23:12:28 -07:00
Daniel Koepping 6249f4d5b0 AGNOS 19.7 (#38750) 2026-09-01 18:32:59 -07:00
Daniel Koepping 8b88f7dd6e ui: show one GPU status (#38748)
ui: show one GPU status icon
2026-09-01 18:32:39 -07:00