Skip to content

Refactor/launcher python314 uiux#25

Open
toderian wants to merge 176 commits into
mainfrom
refactor/launcher-python314-uiux
Open

Refactor/launcher python314 uiux#25
toderian wants to merge 176 commits into
mainfrom
refactor/launcher-python314-uiux

Conversation

@toderian
Copy link
Copy Markdown
Contributor

@toderian toderian commented May 4, 2026

No description provided.

toderian and others added 30 commits May 3, 2026 01:50
What changed:
- Documented the current launcher runtime, Docker, state, UI, and packaging behavior.
- Added baseline pytest coverage for config persistence, Docker command construction, imports, and edge-node response models.

Why:
- Establishes a safety net before Python/runtime and UI refactor work begins.
What changed:
- Added pyproject metadata declaring Python 3.14 as the launcher runtime target.
- Updated README setup and test instructions for uv and Python 3.14.
- Updated build workflows to use Python 3.14.4 with setup-python v5.
- Documented Python 3.14 dependency, test, app startup, and PyInstaller feasibility results.

Why:
- Moves the launcher runtime target to Python 3.14 with verified baseline compatibility.
What changed:
- Added tests for Ansible host loading and SSH command construction.
- Added Qt widget tests for container list, log console, and node info baseline behavior.
- Updated the current behavior document with the expanded baseline test count.

Why:
- Broadens the fast regression suite before refactoring the launcher UI and app structure.
What changed:
- Replaced the fixed startup geometry with screen-aware initial sizing.
- Kept startup maximized without a later plain show call undoing that state.
- Added runtime logging for screen, available area, client, and frame geometry.
- Added tests for startup geometry calculation.

Why:
- Prevents the launcher from opening partly off-screen and gives us position/size evidence for future UI issues.
What changed:
- Moved startup window geometry calculation and formatting into a focused utility module.
- Updated the main form and geometry tests to use the utility.

Why:
- Keeps the window visibility fix testable while reducing responsibility in the large main form.
What changed:
- Added stable object names for launcher buttons, checkboxes, and dialog actions.
- Documented the action surface in docs/ui_action_matrix.md.
- Added static tests that enforce documented action IDs and object names near construction.

Why:
- Creates a regression guard for the upcoming UI/UX refactor so action coverage remains visible and testable.
What changed:
- Added Qt click/signal tests for safe launcher widgets and dialogs.
- Updated the UI action matrix with runtime coverage status.
- Declared the missing humanize runtime dependency used by the image pull dialog.

Why:
- Moves the action inventory from static presence checks toward executable UI coverage before visual refactoring.
What changed:
- Added mocked Qt click scenarios for the main launcher window actions.
- Covered navigation, copy, refresh, theme, force-debug, rename guard, add-node dialog, and start/stop dispatch controls.
- Updated the UI action matrix with main-window runtime coverage.

Why:
- Verifies the real main-window controls before deeper UI/UX changes while keeping Docker, browser, and config side effects mocked.
What changed:
- Kept metric plots inside their styled graph containers instead of reparenting them directly into the grid.
- Named the graph grid and plot containers for regression tests.
- Removed unsupported Qt word-wrap stylesheet properties and added style/layout tests.

Why:
- Improves visual hierarchy reliability and removes startup stylesheet warnings before broader UI/UX refactoring.
What changed:
- Added themed section labels for Node, Network, Status, and Settings in the launcher sidebar.
- Added regression coverage for the sidebar section structure.
- Stabilized mocked main-window tests by suppressing startup single-shot timers in that fixture.

Why:
- Improves sidebar scanability while preserving existing action IDs and button behavior for the UI/UX refactor.
What changed:
- Replace the rename restart path's legacy blocking stop modal with a threaded stop and relaunch flow.
- Add regression coverage for rename save/restart and a visible destructive Docker E2E runner for start, rename, stop, restart, and second-node scenarios.

Why:
- The visible scenario could block on the container-stopped message box after rename, so the app and runner now handle that flow without requiring manual dismissal.
What changed:
- Capture Docker pull launch targets instead of using the current combo-box selection after pull completion.
- Add lifecycle-operation guards so stale node-info failures cannot auto-restart another node during start, stop, rename, or add-node flows.
- Add regression tests for captured launch targets and stale restart suppression.

Why:
- The destructive E2E showed second-node creation could trigger a background restart of the primary node from stale node-info failures.
What changed:
- Add Qt deleted-object guards for stored dialog references during shutdown.
- Clear stale dialog attributes instead of calling close on wrappers whose C++ object is already gone.
- Add a regression for a deleted launcher dialog reference in closeEvent.

Why:
- The destructive E2E exposed a shutdown warning when launcher_dialog had already been deleted before the main window closed.
What changed:
- Stop maximizing the launcher during startup and show the calculated bounded window instead.
- Add a post-show frame clamp that keeps the native title bar and frame inside the available screen area.
- Add regression tests for hidden title-bar and overlarge-window geometry cases.

Why:
- The window manager can override the safe startup geometry during maximization, leaving the top bar off screen for some displays.
What changed:
- Add a shutdown flag for close and forced-exit flows.
- Guard late Docker pull and launch callbacks so they do not mutate UI during teardown.
- Add a regression for launch success arriving after shutdown starts.

Why:
- The destructive E2E exposed lifecycle callbacks that could continue updating the UI after application shutdown had begun.
What changed:
- Move Docker launch command construction and container cleanup work off the Qt UI thread.
- Remove UI-thread sleeps and avoid extra synchronous Docker status checks in known-running launch follow-up paths.
- Harden destructive E2E with launch-activity detection, stale-main-window diagnostics, timeout-safe command diagnostics, and compatibility coverage for captured launch targets.

Why:
- Windows can mark the app as not responding when long Docker preparation or stale E2E waits block the Qt event loop or fail silently.
What changed:
- Use combo-box item data for selected-container Docker and config operations instead of display aliases.
- Add regression coverage for metrics, selection checks, and copy fallback with aliased nodes.

Why:
- E2E showed metric refresh calling Docker with node aliases after rename, which breaks Docker exec against real containers.
What changed:
- Add a small SelectedContainer helper for combo-box identity/display mapping.
- Route high-risk selected-node actions through the helper instead of repeated currentIndex/itemData reads.
- Add helper and main-window regression tests for aliased selections.

Why:
- Aliases are display text, while Docker/config operations need stable container ids. Centralizing that boundary reduces future target drift.
What changed:
- Polish the rename dialog copy and input constraints.
- Update destructive E2E automation to recognize the renamed dialog, prefer the stable input object name, and close with diagnostics on timeout.
- Add Qt coverage for dialog copy and runner title matching.

Why:
- The previous destructive run hung because the runner still searched for the old dialog title after the UI title changed.
What changed:
- Add a LifecycleState helper for active operation and pending Docker-pull launch context ownership.
- Route launcher lifecycle begin/end, pull state, and restart-guard checks through the helper while keeping diagnostic snapshots in sync.
- Add focused lifecycle-state tests and update main-window lifecycle tests to use the helper boundary.

Why:
- Lifecycle ownership was scattered through EdgeNodeLauncher and was a recurring source of stale callback, launch target, and restart guard defects.
What changed:
- Delete the unreachable direct-launch callback block left behind after the Docker pull path returns.
- Clarify that launch continuation resumes from Docker pull completion.
- Strengthen the launch-preparation regression to assert no launch starts before pull completion.

Why:
- The duplicate dead branch made lifecycle behavior harder to reason about and could mislead future refactors.
What changed:
- Move metrics graph grid construction into focused helper methods.
- Preserve the existing graph widget attributes, object names, plot-container styling, and grid placement.
- Strengthen the metrics layout regression to lock container classes, parentage, spacing, and row/column placement.

Why:
- UI construction in the main form was too dense, and a small helper boundary makes later UI polish safer without changing runtime behavior.
What changed:
- Move right-side dashboard panel and activity log construction into focused helper methods.
- Add stable object names for the dashboard container while preserving the existing logView target.
- Add a focused regression for log view identity, dimensions, read-only behavior, and panel placement.

Why:
- The main UI initializer is still too dense, and stable panel/log targets make future UI polish and E2E automation safer.
What changed:
- Put the metrics grid and activity log into a vertical non-collapsible dashboard splitter.
- Replace the fixed-height log view with a minimum height so users can resize the metrics/log balance.
- Add focused tests for splitter identity, placement, orientation, and log sizing.

Why:
- The activity log is part of normal troubleshooting, and a fixed 150px area made it harder to inspect while using the launcher.
What changed:
- Persist dashboard splitter sizes through ConfigManager settings.
- Restore saved dashboard splitter sizes on startup with a tested default fallback.
- Add config and main-window regressions for splitter size save/restore and invalid settings.

Why:
- Users should not have to re-adjust the metrics/activity-log balance every time they open the launcher.
What changed:
- Wrap the launcher sidebar controls in a stable QScrollArea.
- Add sidebarPanel and sidebarScrollArea object names for future UI automation.
- Add focused tests that confirm key sidebar controls remain reachable inside the scroll area.

Why:
- Sidebar actions should remain reachable on shorter screens, DPI changes, and future UI additions without forcing the main window taller.
What changed:
- Add centralized tooltip text for primary sidebar actions.
- Apply tooltips to add, start/stop, dApp, explorer, refresh, rename, theme, and force-debug controls.
- Add a focused regression to keep primary action tooltips present.

Why:
- The sidebar is dense, and hover context helps users understand actions without adding more always-visible text.
What changed:

- Move the rename-node action from Settings into the Node controls section.

- Add a focused layout regression so the rename action stays grouped with node controls.

- Preserve the same rename button object name, tooltip, and click handler.

Why:

- Renaming is a node-scoped action, not an application setting, and should be easier to find while managing the selected node.
What changed:

- Add widget contract tests that exercise NodeInfoWidget and MetricsWidget with current model dataclasses.

- Update node info display code to use alias and eth_address from NodeInfo.

- Update metrics plotting to use NodeHistory CPU, memory, GPU, and GPU memory series.

Why:

- The extracted widgets were stale and referenced fields that no longer exist, which made their shallow tests give false confidence.
What changed:

- Persist main window client size and position in launcher settings.

- Restore saved geometry through the existing screen-clamping path so stale offscreen positions are corrected.

- Save geometry during debounced move/resize logging and on close.

Why:

- Users need the launcher to remember window size/location without reopening with the title bar off screen.
toderian added 30 commits May 4, 2026 15:05
What changed:
- wrap Activity Log lines at widget width and hide the horizontal scrollbar
- remove unused horizontal log scrollbar styles
- update widget, main-window, and stylesheet regressions while preserving full copy text

Why:
- startup diagnostics should be readable without horizontal scrolling while keeping exact log text available for support
What changed:
- add stable metadata, wrapped text, responsive sizing, and progress clamping to ProgressBarWindow
- remove the stale QDesktopWidget import from the main form
- add focused dialog tests for metadata, centering, sizing, and progress behavior

Why:
- keep the legacy Docker pull progress path readable and testable without changing its thread signal contract
What changed:
- added a QThread-backed release lookup worker for launcher update checks
- moved main-window update result handling into explicit UI-thread handlers
- added updater timeout and no-event-pump regressions

Why:
- avoid blocking launcher startup and refresh cycles on network-bound update checks
What changed:
- replaced fixed Docker pull layer-row sizing with responsive label/progress/status columns
- preserved full layer and status values through tooltips
- added regressions for long statuses, row stretch, and horizontal-scroll policy

Why:
- make Docker pull progress easier to read when Docker emits longer status text
What changed:
- replaced HostSelector status-thread termination with tracked interruption and cleanup
- suppressed interrupted SSH status emissions and duplicate workers
- added focused thread-lifecycle and timeout regressions

Why:
- avoid unsafe QThread termination while keeping SSH status checks bounded and non-blocking
What changed:

- Added shared SSH command parsing for quoted args and Windows paths.

- Routed Ansible, HostSelector, and Docker remote setup through structured argv handling.

- Added focused parser, HostSelector, Ansible, and Docker tests.

Why:

- Remote SSH configs with ProxyCommand or spaced key paths should not be broken by plain string splitting.
What changed:

- Added the generated uv.lock for the Python 3.14 launcher environment.

- Verified the lock with uv lock --check and import smoke tests.

Why:

- Keep dependency resolution reproducible for future launcher setup and test runs.
What changed:

- Added default and status timeouts to DockerCommandHandler command execution.

- Applied short timeouts to image, list, and inspect status queries.

- Added timeout, Windows hidden-window, and direct-thread regression tests.

Why:

- Slow Docker status commands should fail predictably instead of making launcher refresh paths appear frozen.
What changed:

- Added bounded hidden-window subprocess helper for legacy Docker mixin checks.

- Applied timeouts to Docker availability, GPU probe, and legacy container status checks.

- Added focused tests for timeout routing and Docker check failure messages.

Why:

- Startup and status checks should fail predictably when Docker or GPU probes stall.
What changed:

- Added explicit timeouts to legacy Docker cleanup, launch, stop, and removal commands.

- Fixed the legacy local Docker readiness guard while preserving remote service restarts.

- Added focused tests for local/remote launch guards and timeout handling.

Why:

- Prevent stale Docker subprocesses from leaving the launcher stuck during lifecycle operations.
What changed:

- Routed active GPU detection through the bounded Docker command executor.

- Routed allowed-address reads through the same timeout-aware executor.

- Added focused tests for timeout and remote-prefix behavior.

Why:

- Prevent command preparation and settings reads from hanging on stale Docker or nvidia-smi probes.
What changed:

- Added a timeout to config-manager Docker volume inspection.

- Preserved Windows hidden-console behavior for the volume probe.

- Added focused tests for success and timeout behavior.

Why:

- Prevent pre-launch volume checks from hanging the launcher when Docker stalls.
What changed:

- Added a bounded Docker ps helper for generated node names.

- Preserved Windows hidden-console behavior for name probes.

- Added focused tests for query kwargs and timeout fallback.

Why:

- Prevent Add Node name generation from hanging when Docker stalls.
What changed:

- Removed an unused duplicate container-name generator from frm_utils.

- Added a regression that the main form uses the bounded docker_utils generator.

Why:

- Eliminate stale Docker query code after bounding the active Add Node naming path.
What changed:
- removed the unused app_forms volume-name helper copy
- added a regression test that frm_main imports the canonical Docker utility helper

Why:
- keeps Docker naming behavior in one module and prevents future drift between UI helpers and lifecycle code
What changed:
- added a shared terminate_process_by_pid helper with Windows timeout handling
- routed launcher and updater force-exit paths through the helper
- added subprocess utility tests for Windows timeout and POSIX behavior

Why:
- prevents direct unbounded shutdown process calls from freezing or surfacing console windows
What changed:
- added timeout and hidden-window handling to SSH command execution
- kill timed-out SSH processes and return timeout code 124
- added SSH service tests for normal, sudo, and timeout paths

Why:
- prevents remote SSH operations from waiting forever and making launcher workflows appear stale
What changed:
- short-circuit SSH connection checks when no configuration exists
- apply hidden-window flags to Windows SSH connection probes
- added tests for unconfigured, timeout, and Windows command-shape cases

Why:
- avoids misleading process launches and keeps remote probes bounded and non-disruptive
What changed:
- tightened sidebar section labels and action-button metrics
- kept the start/stop button aligned with the same compact sizing
- added tests that bound sidebar control heights

Why:
- improves first-viewport sidebar usability while preserving the existing layout and automation targets
What changed:
- Center metric empty-state labels and give them stable sizing.
- Restyle empty labels as compact status chips.
- Add regression coverage for metric empty-state layout.

Why:
- Make empty graph panels read as intentional dashboard states without changing metric behavior.
What changed:
- Carry semantic log colors into the dashboard activity log.
- Keep log insertion plain-text based and add an empty placeholder.
- Cover the widget and launcher color path with tests.

Why:
- Make Docker lifecycle progress, warnings, and errors easier to scan during long operations.
What changed:
- Normalize unknown Docker pull progress lines before deriving synthetic row ids.
- Parse size progress across B, KB, MB, and GB units.
- Add tests for stable row reuse and size-unit progress parsing.

Why:
- Avoid noisy duplicate progress rows during Docker pulls when output does not include layer ids.
What changed:
- Add dark and light style tokens for the Docker pull dialog.
- Apply theme-aware styles to progress rows and dialog chrome.
- Pass the launcher theme into the live pull dialog path.
- Cover theme switching and launcher wiring with tests.

Why:
- Keep long Docker pull feedback visually consistent with the rest of the launcher.
What changed:
- Record available-screen geometry in smoke window snapshots.
- Fail smoke runs when the launcher title bar opens outside the available screen area.
- Add unit coverage for hidden title-bar detection.

Why:
- Prevent regressions of the startup window placement issue that hid the top of the app.
What changed:
- Record startup window geometry in the destructive E2E runner.
- Fail destructive runs when the title bar starts outside the available screen area.
- Add unit coverage for hidden title-bar detection.

Why:
- Keep safe and destructive UI validation aligned around startup window placement.
What changed:
- Extract shared window and rect snapshot helpers plus title-bar assertions.
- Route smoke and destructive E2E runners through the shared visual helpers.
- Add direct helper coverage for hidden-title-bar detection.

Why:
- Keep startup geometry evidence and visible-window assertions consistent across the UI scenario runners.
What changed:
- Add lifecycle busy labels and disabled sidebar control handling during Docker operations.
- Preserve the existing completed-stop supersede path so users can start again once Docker reports stopped.
- Add disabled action-button styling and lifecycle busy-state tests.

Why:
- Make long-running start, stop, rename, and add-node flows communicate progress and prevent accidental repeated actions.
What changed:
- Add shared E2E lifecycle control snapshots and busy-state assertions.
- Record and validate the sidebar busy state during destructive primary launch activity.
- Cover the new visual evidence helpers with unit tests.

Why:
- Ensure visible E2E runs prove lifecycle controls are locked while Docker launch work is active.
What changed:
- Move settings controls above passive status cards in the sidebar.
- Split status details into a dedicated status section.
- Update layout tests to keep settings visible in the default desktop viewport.

Why:
- Keep all primary action and settings controls immediately reachable while preserving scrollable status details for compact layouts.
What changed:
- Move lifecycle sidebar busy-state handling into a dedicated presenter.
- Keep main-window lifecycle call sites as thin wrappers around the presenter.
- Preserve busy labels, tooltip locking, and completed-stop supersede behavior.

Why:
- Reduce main-window UI state responsibility while keeping the verified lifecycle behavior intact.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant