Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 27 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,27 @@ controller — the field renders `—` rather than a plausible-looking guess.
- **Hex Viewer** for raw firmware blobs (ACPI/SMBIOS on Windows and Linux)
- Configurable poll interval, min/max reset, light/dark/grey themes

### Task Manager
- **Processes** — PID, name, owner, CPU %, memory, virtual size, disk
read/write and uptime; sortable columns, a filter box, and end/force-kill
behind a confirmation. Rows are virtualised, so a 700-process list scrolls
without cost
- **Performance** — a sidebar of category rows (CPU, GPU, Memory, Disk *n*,
Network *n*), each with a mini sparkline and its current value, and the
selected category filling the pane with a large graph and a stats grid. It
reads the telemetry that is already being collected, so it adds no polling
Laid out after the Windows Task Manager, because that is the layout people
already know.

- **Processes** — name, CPU, memory, disk rate, PID and owner. The measured
columns are **heat-shaded**: the tint strengthens and shifts from amber to red
with the value, so the processes worth looking at are found by glancing rather
than reading. Each column header carries its machine-wide total. Sortable
columns, a filter box, and end/force-kill behind a confirmation. Rows are
virtualised, so a 700-process list scrolls without cost
- **Performance** — a sidebar of device cards (CPU, GPU, Memory, Disk *n*,
Network *n*), each with a live filled thumbnail and its current value, and the
selected device filling the pane with a large filled area graph over a fixed
grid. Every device class has its own colour — CPU blue, memory purple, disk
green, network rose, GPU teal — used for its card, its thumbnail and its
graph, so colour identifies the device rather than just decorating. Utilisation
charts are pinned to 0–100 % so an idle machine reads as idle. It reads the
telemetry that is already being collected, so it adds no polling

CPU percentages in the **Processes** table are a share of the whole machine, as
Windows reports them: a process saturating 4 of 16 threads reads 25 %. Hovering
gives the per-thread-summed figure (400 %), which is what `sensorview ps` prints.
- **The same data from the terminal** — `sensorview ps` and `sensorview kill`,
which is what you want over SSH on a box with no display
- The process collector runs **only while the window is open** — enumerating
Expand Down Expand Up @@ -263,7 +275,12 @@ cargo run --release
Platform prerequisites:

```bash
# Windows — also build the sensor sidecar (needs .NET 8 SDK)
# Windows — MSVC Build Tools are required, not optional: the default feature set
# includes `push`, which pulls in rustls → ring, and ring compiles C and assembly.
# Build from a developer prompt (vcvars64.bat) so cl.exe and the Windows SDK are
# on PATH. Without a C toolchain, use --no-default-features --features gui,web,tui.
#
# Also build the sensor sidecar (needs .NET 8 SDK):
dotnet publish sidecar -c Release -o sidecar/publish

# Linux
Expand Down
130 changes: 111 additions & 19 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,116 @@ that should eventually change.

## Build

### `ring` needs a C compiler (debug on Windows)
### `ring` needs a C compiler

Enabling `--features push` pulls in `rustls` → `ring`, which compiles C and
assembly rather than being pure Rust. GitHub's runners all ship a toolchain and
CI is green on all three platforms, but this is a **new build requirement** for
anyone compiling that feature locally — notably MSVC on Windows.
assembly rather than being pure Rust. This is a **build requirement** for anyone
compiling the default feature set, notably MSVC on Windows.

Two known consequences:
Verified on Windows 11 with VS 2022 (MSVC 14.36.32532) + Windows SDK
10.0.18362: `cargo build --release` compiles `ring` 0.17.14 and `rustls` 0.23.43
with no workaround beyond running inside the MSVC environment. So the
requirement is real but ordinary — it is now stated in the README's "Build from
source" section rather than left implicit here.

- Cross-compiling to `x86_64-pc-windows-msvc` from macOS fails at `ring`'s build
script for exactly this reason. Windows-target checks have to skip `push`:
What remains open:

- Cross-compiling to `x86_64-pc-windows-msvc` from macOS still fails at `ring`'s
build script. Windows-target checks have to skip `push`:
`cargo clippy --target x86_64-pc-windows-msvc --no-default-features --features gui,web,tui`
- A contributor on Windows without Build Tools installed will hit this on a
default `cargo build`, since `push` is in the default feature set.
- Worth investigating: whether `rustls` can be pointed at a pure-Rust crypto
provider (`aws-lc-rs` has the same problem; `rustls` supports pluggable
providers) so `push` needs no C toolchain at all.

## Confirmed Windows bugs

Found by running the **release** binaries on Windows 11 for the first time
(2026-07-31), which is also what retired the old "Windows CLI console handling
is untested" entry. Three reproducible defects, plus the reason CI missed all of
them. None are fixed yet.

What *does* work, so it is not re-investigated: `AttachConsole` itself (a
GUI-subsystem binary's subcommand output does reach a real console), the
feature-gated `windows_subsystem` attribute (GUI subsystem only with `gui` +
release, console otherwise), exit codes (0/1/2 as documented), stdout/stderr
separation, redirection and piping, and the TUI's panic-hook terminal
restoration under `panic = "abort"`.

### `kill` without `--force` can never succeed on Windows

`procs::kill` maps `force = false` to `Signal::Term`, and `sysinfo` supports no
signal but `Kill` on Windows, so the call always returns:

```
sensorview: Term is not supported on this platform
```

Confirmed against a disposable child process: it survived the plain `kill` and
died on `kill --force`.

This also breaks the GUI. The Task Manager's confirmation modal passes
`force = false` for its default **"End process"** button — described in the
dialog as *"SIGTERM — asks the process to exit"* — so on Windows that button can
only ever report an error. Only "Force kill" works. The error is surfaced rather
than swallowed, so this is a capability gap, not a reporting bug.

Fix: on Windows either fall back to `Signal::Kill` with the wording changed to
match, or disable the non-force action rather than offering something the
platform cannot do.

### Every release build demands elevation, including the headless one

`build.rs` gates the `requireAdministrator` manifest on `PROFILE == "release"`
alone, not on the `gui` feature. So the headless binary — the one the README
offers "for servers and containers" — also requires admin. A non-elevated
parent cannot start it at all:

```
CreateProcess FAILED: The requested operation requires elevation (error 740)
```

With `UseShellExecute = false` there is no UAC prompt to accept: the process
simply never starts, so a service, scheduled task, container entrypoint or CI
step running as a normal user fails outright — and with it every documented
scripting use of the CLI, since nothing can be piped or redirected from a
process that never ran.

Scope of the claim, measured: this is specific to **non-interactive parents**.
An interactive `ShellExecute` launch (double-click, a shortcut, `Start-Process`
without `-NoNewWindow`) would raise a UAC prompt and succeed if the user
consents — that path was not tested here. The failure case is the
server/container/CI one, which is exactly what the headless build exists for.

Fix: gate the manifest on the `gui` feature as well as the profile. An
unelevated CLI should degrade to reading fewer sensors — which is what
`lhm_bridge.rs` already documents — not refuse to launch.

### `--help`, `--version` and every clap error print nothing

In the shipped GUI-subsystem build these produce **zero** console output, while
the same commands on a console-subsystem build print normally. A mistyped
subcommand fails in complete silence — clap's "a similar subcommand exists"
hint is never seen.

Cause: `main()` calls `Cli::parse()`, and clap handles `--help`, `--version` and
all parse errors *inside* that call, printing and exiting there. But
`attach_console()` is not called until `cli::run()`, which is only reached after
parsing succeeds. Everything clap emits goes to a process with no console yet.

Fix: call `attach_console()` at the top of `main()`, before `Cli::parse()`. It
is already a no-op when there is no parent console and on non-Windows builds, so
moving it earlier costs nothing.

### CI cannot catch any of the above — it never runs a release binary

The headless smoke test builds and runs `target/debug/sensorview`, which is
`asInvoker` and console-subsystem, so it passes while telling us nothing about
the artifact that ships. The `Build (release)` step only compiles; nothing ever
executes a release binary on any platform. That is precisely why all three bugs
above survived a green CI.

Worth investigating: whether `rustls` can be pointed at a pure-Rust crypto
provider (`aws-lc-rs` has the same problem; `rustls` supports pluggable
providers) so `push` needs no C toolchain at all. Until then, document it in the
build instructions.
Worth adding: a step that runs the *release* binary's `--help` and asserts it
produces output and exits 0.

## Task Manager

Expand All @@ -51,12 +142,13 @@ missed:
- **macOS fan sensors are not implemented.** Fans would come from the same HID
sensor plane as temperatures, on a different usage page, but development
happened on a fanless MacBook Air with nothing to read or verify against.
- **Windows CLI console handling is untested.** The `AttachConsole` path and the
feature-gated `windows_subsystem` attribute compile and are exercised by CI,
but nobody has run `sensorview.exe get ...` from a real `cmd.exe`.
- **The TUI has never run on a real terminal.** `sensorview top` is covered by
ratatui's `TestBackend` (layout, values, filtering), but the keystroke handling
and the panic-hook terminal restoration have only been reasoned about.
- **The TUI is only partly verified.** `sensorview top` has now been run on a
real Windows console — rendering, `q`/`Esc`/`Ctrl-C`, and panic-hook terminal
restoration under `panic = "abort"` all check out (see below). Two things
still have not been observed: whether `r` actually resets min/max (no visible
sensor had a spread to reset at the time), and behaviour under legacy
`conhost` rather than the default terminal. It has also never run on a Linux
or macOS terminal.
- **The Linux GUI has never been rendered.** It compiles and its tests pass in
CI, but the build server is headless, so every window has only ever been
*looked at* on macOS. Fonts, DPI scaling and the Task Manager's table layout
Expand Down
1 change: 1 addition & 0 deletions app/src/cli/procs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ mod tests {
virt_bytes: 20 * 1024 * 1024,
disk_read_bytes: 0,
disk_write_bytes: 0,
disk_bps: None,
run_time_s: 1,
}
}
Expand Down
Loading
Loading