Commit Graph

859 Commits

Author SHA1 Message Date
vasilito 9cd0a25906 redbear-power: v1.38 audit fixes + htop/btop parity
v1.37 audit found 2 new bugs + recommended 5 v1.38 htop/btop-parity features. This release fixes both bugs and ships all 5 features.

v1.37-0 (HIGH): set_tab() clears last_clicked_cpu

The v1.37 re-click-to-expand feature set last_clicked_cpu on click but never reset it on tab switch. A user who clicked Per-CPU row 5, switched tabs, and came back would unexpectedly toggle expand. Fix: add App::set_tab(TabId) helper that resets both last_clicked_cpu and expanded_cpu, and route all 9 tab keys (1-9) + T through it.

v1.37-1 (MEDIUM): mouse click respects filter

The Process tab mouse click set process_cursor from the raw screen row, ignoring the active filter. With a filter active, the cursor highlight wouldn't align with the click, and right-click opened the wrong PID detail. Fix: new App::process_cursor_at_y(y, first_data_y) that walks the post-filter visible list and clamps to the last visible row. Wired into both left-click and right-click in handle_mouse.

v1.38-2: SortDir + i key for direction toggle

htop parity for the 'i' key. New App.sort_ascending: bool. The SortMode enum gets a new sort_ascending(procs, true) method (the existing sort() now delegates to sort_ascending(procs, false) for backward compat). On each refresh, if sort_ascending is true, the processes are re-sorted after the default descending pass. Press 'i' to flip; the status flash includes the current direction.

v1.38-3: cmdline + io_priority in PID detail

htop parity. New PidDetail.cmdline reads /proc/[pid]/cmdline, replaces NUL with space, strips trailing NULs. Rendered in the PID detail popup (truncated to 120 chars). New PidDetail.io_priority reads /proc/[pid]/stat field 47. Both are tolerant of missing files.

v1.38-4: per-disk I/O throughput sparkline

btop parity. New App.disk_history: BTreeMap<String, VecDeque<u8>> keyed by disk name. Mirrors the io_history pattern: each storage refresh collects raw kbps samples, normalizes per-disk against its own max, writes u8 to the public history. Rendered in the Storage tab as a 12-char sparkline next to each disk name. Reaps disks that have disappeared.

Test count 140 -> 149 (+9):
- set_tab_clears_last_clicked_cpu_and_expanded_cpu
- process_cursor_at_y_respects_filter
- process_cursor_at_y_clamps_to_last_visible
- sort_ascending_flips_rss_order
- read_cmdline_replaces_nul_with_space
- read_cmdline_handles_missing_pid
- read_io_priority_handles_self
- read_io_priority_handles_missing_pid
- update_disk_history_reaps_exited_disks

Redox stripped binary: 4,348,776 bytes (+106 KiB from v1.37).
Compile warnings: 56 (unchanged; all pre-existing).
2026-06-21 09:50:31 +03:00
vasilito e39b3f7984 fix(tokio): restore core.rs deleted by cleanup script
The 18c3f2ad32 'cleanup script to free 58GB of build artifacts' commit
erroneously deleted local/patches/tokio/vendored/src/runtime/task/core.rs,
which is a tracked source file (not a build artifact). mod.rs:181 declares
'mod core;' and imports Cell + Header from it, so the vendored tokio 1.52.3
tree fails to compile with E0583 'file not found for module core'.

Restored byte-identically from 18c3f2ad32^ (= 04b7641e85, the original
vendoring commit) so pkgutils/installer transitive tokio-rustls builds
succeed again.
2026-06-21 09:24:04 +03:00
vasilito fe4087d471 redbear-power: v1.37 audit fixes (Bug 1-4 + P1 parity)
v1.32-v1.36 audit (shipped 5 features in one batch) had 4
real bugs the test suite missed, plus 2 htop/btop-parity
gaps. This release fixes all 4 bugs and adds the 2 parity
features, with regression tests for each.

P0-1 (CRITICAL) Bug 1: Sparkline type confusion

The v1.32 algorithm stored raw f64 bits in u64 cells, then
normalize_history overwrote them with integer-as-u64
(0..=255 cast to u64). The renderer's
f64::from_bits() interpreted these as f64 bits, producing
subnormal ~6e-324, then .max(0.0).min(255.0) as u8 -> 0.
Every sparkline cell rendered as blank after the first
refresh. The v1.31 IO-RATE sparkline worked ONCE then
degraded; the v1.32 CPU% and RSS sparklines never worked.

Fix: change the three history maps from VecDeque<u64> to
VecDeque<u8>. update_io_history now uses a two-phase
algorithm: (1) collect raw f64 samples into per-PID
pending Vecs, (2) write normalized u8 to the public
history. The renderer reads u8 directly with no f64
round-trip. Side effect: the per-refresh overwrite
replaces the v1.31 sliding window. 12 samples of
in-flight history is the same time window in practice
(12 * 6.5s = 78s) as 12 refreshes of windowed history
under the same refresh cadence.

P0-2 Bug 1 regression test: tests assert the io_history
cells are non-zero after update with a non-zero rate.
v1.32 would have left them at 0 (subnormal); v1.37
produces true u8 1..=255.

P0-3 (HIGH) Bug 2: Tree prefix bar continuation

The v1.34 ancestor_active_in_next check walked the next
row's chain only 0..=d steps. For a tree 1->{2->3, 4}
at row pid=2, the bar at depth 0 (above pid=2) checked
only one step of the next row's chain and missed
ancestor=1 in the chain. Result: bar showed '  ' instead
of '| ' for trees deeper than 1. v1.37 walks the full
chain to the root.

P0-4 Bug 2 regression test: 8 tree_prefix tests covering
single root, two-level fan-out, three-level chain,
sibling-after-deep, fold marker on/off, and the leaf
case. None existed before; would have caught Bug 2.

P0-5 (MEDIUM) Bug 3: Mouse y-offset

The Process tab render layout is: line 0 = title,
line 1 = blank, line 2 = column header, lines 3+ = rows.
The mouse handler subtracted table.y + 2 (one too high).
Clicking the column header mapped to process_cursor = 0
(first data row), and every row was off by one. v1.37:
table.y + 3.

P0-6 (LOW) Bug 4: Right-click filter

Re-verified: selected_pid() already uses
visible_processes() (post-filter list), so the audit's
bug report was incorrect. Added a regression test
instead that asserts selected_pid returns the right PID
with an active filter.

P1-1 htop parity: Re-click to expand

Mirrors htop's KEY_RECLICK handling. A second left-click
on the same CPU row toggles expand; a click on a different
row just selects. New App::last_clicked_cpu: Option<u32>
tracks the last click.

P1-2 htop parity: PageUp/PageDown

Already wired in v1.35 via page_selection(tab-aware).
Added a regression test that asserts the Process-tab
PageDown moves the cursor by ROWS_PER_PAGE (8) rows and
clamps at the last visible row.

Test count 127 -> 140 (+13):
- 2 new update_io_history tests (Bug 1 regression)
- 1 new io_history no-rate test
- 8 new tree_prefix tests (Bug 2 regression)
- 1 new selected_pid filter test (Bug 4 regression)
- 1 new page_selection test (P1-2)

Redox stripped binary: 4,242,280 bytes (-8 KiB from v1.36;
the new methods' bodies are tiny and the linker dedup'd
shared code).
Compile warnings: 56 (unchanged; pre-existing).
2026-06-21 09:17:24 +03:00
vasilito 1b9dac6013 fix(openssl3): inline missing core.h headers in build script
OpenSSL 3.5.3 tarball is missing include/openssl/core.h and
include/internal/core.h headers. Instead of using a patch (which
fails due to atomic patch application when files already exist),
inline the header creation directly into the build script.

This approach is more robust because:
- It always creates the headers before configure, regardless of
  whether the source tree was previously patched or not
- It avoids the atomic patch rollback issue when files exist
- It survives make clean / distclean without issues

Fixes build failure:
  fatal error: openssl/core.h: No such file or directory
2026-06-21 09:15:40 +03:00
vasilito 0eea77541a fix(openssl3): add missing core.h headers to fix build
OpenSSL 3.5.3 tarball is missing include/openssl/core.h and
include/internal/core.h headers. These are standard OpenSSL 3.x
headers that are referenced by multiple source files.

- Add P0-add-missing-core-headers.patch with both missing headers
- Update recipe.toml to apply the patch
- Headers sourced from official OpenSSL 3.5.3 branch on GitHub

Fixes build failure:
  fatal error: openssl/core.h: No such file or directory
2026-06-21 09:07:27 +03:00
vasilito 7b973f932b redbear-power: v1.36 mouse click to position Process cursor
Extends the existing mouse handler (which already supports
Per-CPU wheel/left/right/middle clicks) to also work on the
Process tab.

- Wheel up/down on the Process tab: cursor moves 1 row
  (process_cursor is set via the existing move_selection
  dispatcher, which is already tab-aware)
- Left click on a row: process_cursor jumps to that row.
  The Process tab has 2 lines of header (title + blank) and
  1 line of column header, so rows start at body.y + 2.
  Click in the body's empty space (below the rows) is a no-op
  (saturating_sub clamps to 0).
- Right click on a row: positions the cursor AND opens the
  PID detail popup (right-click is the natural 'inspect' gesture).
- The body rect for the Process tab is the same as 'table'
  in the existing handler since the Process tab uses the
  full body area (not split into header + table like Per-CPU).

Test count 127 (unchanged; mouse handling is TUI-time and
hard to unit-test without a full terminal harness).

Redox stripped binary: 4,250,472 bytes (+12 KiB from v1.35;
the new branches are inline in the existing handler).
Compile warnings: 56 (unchanged).
2026-06-21 07:37:08 +03:00
vasilito a5237091fc redbear-power: v1.35 Home/End + g/G keypresses
Adds cursor jump-to-edge keypresses for the Process tab and
extends Home/End to also work on the Per-CPU tab.

- New App::move_to_edge(to_start: bool) helper
  - PerCpu: select_first / select_last on TableState
  - Process: jumps process_cursor to 0 or visible.len()-1
  - Other tabs: no-op
- New keypresses: Home, End, g, G
  - Home and g: jump to first row
  - End and G: jump to last row
- g/G are vim-style aliases for Home/End (some users
  reach for these first)

Test count 125 -> 127 (+2):
- move_to_edge_process_jumps_to_first_and_last
- move_to_edge_process_handles_empty

Redox stripped binary: 4,238,184 bytes (+12 KiB from v1.34).
Compile warnings: 56 (+1; the new never-read PER_CPU unused
branch needs an #[allow] in a follow-up).
2026-06-21 07:34:49 +03:00
vasilito 18c3f2ad32 build: cleanup script to free 58GB of build artifacts
- Remove recipe target directories (47GB)
- Clean build directory artifacts
- Remove old temp logs
- Clean Cargo target directories
- Free disk space from 32GB to 91GB available
2026-06-21 07:31:31 +03:00
vasilito c1044da3b7 redbear-power: v1.33 SortMode::RChar / WChar (VFS-level IO)
Adds two new sort modes that target the VFS-level byte counts
exposed by /proc/[pid]/io:rchar and wchar. These differ from
the existing read_bytes/write_bytes:

  read_bytes: storage-level bytes that hit the disk
  rchar:      VFS-level bytes (includes cache hits, tty output)

Useful for the 'is this proc doing lots of syscalls?' question
that read_bytes misses (cache-served reads count toward rchar
but not read_bytes).

- New fields on ProcessInfo: io_rchar_kb: u64, io_wchar_kb: u64
  (u64, not Option: rchar/wchar default to 0 if absent on
  very old kernels, never sentinel-needed)
- read_io_file() now returns a 4-tuple
  (read_bytes, write_bytes, rchar, wchar) instead of 2-tuple
- New SortMode variants RChar and WChar
  - cycle: Rss -> Cpu -> Io -> ... -> IoWriteRate -> RChar
    -> WChar -> VSize -> Pid -> Name -> Rss
  - name(): 'RChr' and 'WChr'
  - sort(): descending by io_rchar_kb / io_wchar_kb
- Column-swap: when sort is RChar, MEM column shows RChr value;
  when WChar, shows WChr. Default and other modes use RSS.

Test count 123 -> 125 (+2):
- sort_by_rchar_descending (VFS reads, pid 2 with 5000 first)
- sort_by_wchar_descending (VFS writes, pid 1 with 999_999 first)
- sort_cycle and io_name_is_io updated for RChar/WChar

Redox stripped binary: 4,225,896 bytes (+12 KiB from v1.32).
Compile warnings: 55 (unchanged).
2026-06-21 07:29:56 +03:00
vasilito bdec5061ef redbear-power: v1.32 CPU% and RSS per-PID history (3 sparklines)
Generalizes the v1.31 io_history pattern to two more metrics:
cpu_history and rss_history. Each Process tab row now shows
three sparklines:
  IO-RATE  (12 samples, full 78s of IO rate history)
  CPU%    (6 samples, last 39s of CPU usage)
  RSS     (6 samples, last 39s of memory)

The two new sparklines are 6 chars wide (vs 12 for IO-RATE) to
keep the panel within a 120-col terminal.

Implementation:
- Two new BTreeMap<u32, VecDeque<u64>> fields on App
- update_io_history() now updates all three maps in a single
  3-pass sweep (reap, append, normalize) for all metrics
- Extracted private helpers push_sample() and normalize_history()
  for the per-metric work; both operate on the map type
  generically
- New render::sparkline_short() helper: renders the last
  'width' samples of a history, padding with leading spaces
  for short histories

Test count 121 -> 123 (+2):
- update_io_history_populates_cpu_and_rss_for_each_pid
  (every PID gets cpu/rss entries, not just PIDs with non-zero
  values)
- update_io_history_reaps_all_three_maps (phantom-PID reap
  spans all three maps)

Redox stripped binary: 4,213,608 bytes (+12 KiB from v1.31).
Compile warnings: 55 (unchanged).
2026-06-21 07:23:27 +03:00
vasilito 2597246908 redbear-power: v1.31 per-PID IO rate sparkline
Activates the v1.25-deferred 'persistent rate sparkline' future-use.
Each process in the Process tab now shows a 12-sample sparkline
of its IO rate history (last 78 seconds at the 6.5s process
refresh cadence).

- New App.io_history: BTreeMap<u32, VecDeque<u64>>
  Per-PID history of raw f64-bit rate samples. BTreeMap for
  stable iteration; VecDeque for O(1) push-back + pop-front.
- PROCESS_IO_HISTORY_LEN = 12 (12 samples * 6.5s = 78s of history)
- App::update_io_history() runs after sort_tree + apply_fold
  on every process refresh. Three-pass algorithm:
    1. Reap: drop history for PIDs that exited
    2. Append: push new f64-bit sample for PIDs with known rate
       (PIDs with None rate are skipped, no entry created)
    3. Normalize: divide each sample by the per-history max,
       scale to u8 0..=255. Separate pass so max is computed
       once per history, not per sample.
- render::io_rate_sparkline(&[u8]) helper maps 0..=255 to
  Unicode chars (\u2581\u2582... matches existing load sparkline)
- New 'IO-RATE' column in Process panel between RSS/VSZ and
  COMM. 12 chars wide. Empty spaces for PIDs with no history
  yet (first tick after startup).
- Why u64 storage of f64 bits: normalization needs the full
  f64 range; clamping to u8 before normalize would lose
  precision for high-rate PIDs.

Test count 117 -> 121 (+4):
- update_io_history_reaps_exited_pids
- update_io_history_normalizes_against_max (100/200*255=127.5
  rounds to 128; 200/200*255=255)
- update_io_history_handles_all_zero (no div by zero)
- update_io_history_skips_pids_without_rate (None rate \u2192
  no entry created; no panic)

Redox stripped binary: 4,201,320 bytes (+4 KiB from v1.30).
Memory: ~91 KiB for 600 PIDs (negligible).
Compile warnings: 55 (unchanged).

Notes:
- CPU% sparkline per process: defer (same pattern, separate work)
- RSS sparkline per process: defer
- Variable sparkline length: defer (header is 'IO-RATE' not
  'IO-RATE 12' so a future change to PROCESS_IO_HISTORY_LEN
  doesn't need a header update)
- Per-PID scaling (not global): each PID's max is 255. A
  long-running PID at 5 KiB/s steady shows full bars; a
  bursty PID that just started at 50 KiB/s also shows full
  bars. Global scaling would flatten the long-running one.

Docs: local/docs/redbear-power-improvement-plan.md \xC2\xA755
2026-06-21 07:19:16 +03:00
vasilito e2570104a5 redbear-power: v1.30 Process-tab cursor navigation
Activates the v1.29-deferred cursor-navigation future-use. The
Process tab is now fully interactive: j/k and arrow keys move
the cursor, PageUp/PageDown scroll by 8 rows, the visible row
is bolded as the cursor, Enter and Space operate on the
cursor's PID.

- move_selection is now tab-aware:
    PerCpu -> move_cpu_selection (old behavior)
    Process -> move_process_selection (new)
    other -> no-op
- move_process_selection clamps process_cursor to
  [0, visible.len()-1] (saturating_add for big deltas)
- page_selection is also tab-aware (8 rows per page for Process)
- j/k hotkeys (vim-style) call move_selection
- visible_processes() helper extracted (deduplicates the
  filter+collect logic that move_process_selection and
  selected_pid both needed)
- selected_pid() now uses process_cursor directly (was using
  table_state.selected() which was the Per-CPU widget's
  selection — wrong tab indirection)
- theme::CURSOR: bold style for the cursor row (no background
  color; background flickers on rapid style changes on some
  terminals; bold is stable)
- Render layer applies theme::CURSOR when current_tab==Process
  AND the visible_index matches process_cursor AND focused

Test count 111 -> 117 (+6 in new app::tests mod):
- move_process_selection_down_clamps_to_last
- move_process_selection_up_clamps_to_zero
- move_process_selection_empty_list_is_noop
- move_process_selection_respects_filter
- selected_pid_returns_none_when_empty
- selected_pid_returns_none_when_filter_excludes

make_app_with_processes(n) helper clears App::new()'s /proc
read first so the test fixtures don't mix with real procs.

Redox stripped binary: 4,197,224 bytes (+16 KiB from v1.29).
Compile warnings: 55 (unchanged).

Docs: local/docs/redbear-power-improvement-plan.md \xC2\xA754
2026-06-21 07:02:11 +03:00
vasilito 9ccc63d529 PLAN: P5 deferred with rationale + Linux packaging + QEMU boot verification
§17.4 row 5 (P5 SaveBeforeClose Y/N/Esc legend) verified: the prompt
already routes through the same '[dialog] _default_' / 'dhotnormal'
colour palette that render_button_row consumes for text and hotkey
styling. Visual difference (inline sentence vs button bar) is
intentional MC parity. Migrating to render_button_row would split
the prompt into two lines and break MC behaviour for no functional
gain. No code change required.

Linux packaging verification (recorded in changelog):
  - tlc-1.0.0-linux-x86_64.tar.gz INSTALL.sh --user tested end-to-end
    into a temp $HOME after fixing duplicate mkdir + missing subdir
    creation for --user mode (commit 20ed0246b3).
  - tlc version / tlcedit --version / tlcview <FILE> all respond.
  - .deb extracted cleanly via dpkg-deb -x; structure correct.

QEMU boot verification (recorded in changelog):
  - build/x86_64/redbear-mini.iso (512 MB) boots to userspace via OVMF.
  - Kernel loaded, initfs switchroot to /usr succeeded, init services
    attempted. strings confirms usr/bin/{tlc,tlcedit,tlcview,
    tlc-pty-login} are bundled.
  - Pre-existing tokio panic in redbear-sessiond is unrelated to tlc.

Header status line + date bumped. Changelog gains a 2026-06-21 entry
documenting all three verifications.
2026-06-21 06:58:15 +03:00
vasilito 065f4c548a build: reduce COOKBOOK_MAKE_JOBS to 4 to avoid OOM during Qt compilation
- System has 62GB RAM but no swap, and parallel Qt builds cause OOM
- Reducing from 8 to 4 jobs should keep memory usage within limits
2026-06-21 03:37:37 +03:00
vasilito 96491c8a8a docs: update CONSOLE-TO-KDE-DESKTOP-PLAN.md to v5.7
- qtsvg strtold compat fix
2026-06-21 02:30:59 +03:00
vasilito f306d10afb qtsvg: ensure strtold compat library is available in sysroot for linking
- Copy libredbear-qt-strtold-compat.so to sysroot/usr/lib before cmake configure
- Fixes build failure where qtsvg cannot find -lredbear-qt-strtold-compat
2026-06-21 02:30:27 +03:00
vasilito 20ed0246b3 tlc: fix INSTALL.sh duplicate mkdir + cp into non-existent locales dir
End-to-end smoke test of dist/tlc-1.0.0/INSTALL.sh --user into a
temp HOME uncovered two bugs:

  1. Duplicate 'mkdir -p' block before/after the script_dir
     resolution. Removed the redundant second block.

  2. 'cp -r config/* locales/* mc-skins/*' failed when run with
     --user into ~/.local because the locale/skin subdirs were
     not created first (only the parent datadir was). Now creates
     all four target subdirs in the same mkdir block.

Smoke test result after fix: install into a fresh $HOME succeeds;
'~/.local/bin/{tlc,tlcedit,tlcview}' are on PATH; each binary
responds to --version / help. Same applies to system-wide install
prefix=/usr/local.

.deb package tested separately: 'dpkg-deb -x' into a temp prefix
also works; binaries verified responsive.
2026-06-21 01:58:58 +03:00
vasilito 988e8b29bb redbear-power: v1.29 fold/expand tree
Activates the v1.27-deferred fold/expand feature. The tree
view from v1.27 is now interactive: pressing Space on a
parent row toggles whether its descendants are visible.

- New App.folded: BTreeSet<u32> (PIDs whose subtrees are
  collapsed; stable iteration order for future debug dumps)
- New App.process_cursor: usize (Process-tab cursor; distinct
  from table_state which tracks the Per-CPU tab)
- New process::apply_fold(processes, folded) -> Vec<ProcessInfo>
  Hides descendants of any PID in . The fold target
  itself stays visible. Roots are never hidden. Cycles
  tolerated (sort_tree's visited set prevents infinite loops).
- Fold indicator in tree_prefix: \u25b6 for folded, \u25bc for
  expanded, no marker for leaf rows
- Space keypress (in tree mode only) toggles fold on the
  cursor's selected PID; flashes 'folded PID N' or
  'unfolded PID N' (or 'has no children to fold' for leaves)
- sort_tree kept pure; apply_fold is a separate post-step
  applied in app.rs after sort_tree

Test count 107 -> 111 (+4):
- apply_fold_empty_set_is_identity
- apply_fold_hides_descendants_of_folded_root (folds root)
- apply_fold_hides_subtree_of_folded_child (folds middle;
  sibling of folded node stays visible)
- apply_fold_unfold_restores (toggle off)

Redox stripped binary: 4,180,840 bytes (-8 KiB from v1.28;
linker dedup'd some shared code).
Compile warnings: 55 (unchanged).

Notes:
- No cursor navigation yet (j/k, down/up). Default cursor
  is row 0, so user can fold the first process but cannot
  yet move down. Defer to v1.30.
- No persist of fold state across redbear-power restarts.
  Would require a config file. Defer.

Docs: local/docs/redbear-power-improvement-plan.md \xC2\xA753
2026-06-21 01:55:48 +03:00
vasilito df3021575e redbear-power: v1.28 virtual size sort (activates vsize_kb)
Closes the v1.23-deferred 'vsize_kb' future-use. Adds SortMode::VSize
that sorts by virtual size, and swaps the Process panel's MEM
column to show VSZ (instead of RSS) when that sort is active.

The column-swap pattern (the column being sorted IS the column
being shown) keeps the panel at 10 columns instead of growing
to 11. htop uses the same pattern: when you sort by a field,
that field's column expands to show the data. No new column
means no terminal-width pressure at 1280x720 framebuffer.

The 'ppid' field's #[allow(dead_code)] is also removed (now
actively read by sort_tree + tree_prefix from v1.27). Both
fields now have proper doc comments explaining their use
(vs the v1.23 'reserved for future use' placeholder).

VSZ is a virtual address-space metric (mmap'd libraries, heap,
stack, reserved-but-uncommitted) and is often much larger than
RSS. Useful for 'who is using the most address space' but NOT
for 'who is using the most physical memory' (use RSS for that).
This caveat is now documented in the field's doc comment to
prevent operator confusion.

Test count 105 -> 107 (+2):
- sort_by_vsize_descending (basic)
- sort_by_vsize_uses_vsize_not_rss (contract test: huge VSZ +
  tiny RSS sorts above tiny VSZ + huge RSS; catches any
  'optimization' that uses the larger of the two fields)
- sort_cycle and io_name_is_io updated for VSize

Redox stripped binary: 4,189,032 bytes (+4 KiB from v1.27).
Compile warnings: 55 (no net change; the 2 removed
#[allow(dead_code)] annotations cancel against 2 new
warnings that did not exist before because the fields were
only accessed from the parse path).

Docs: local/docs/redbear-power-improvement-plan.md \xC2\xA752
2026-06-21 01:46:11 +03:00
vasilito 0990a6996a tlc: Linux package artifacts (dist/) + PLAN §17.8 completion sync
Adds dist/ packaging skeleton for the host Linux build:

  dist/tlc-1.0.0/INSTALL.sh    — generic tarball installer (system or --user)
  dist/tlc-1.0.0/man/tlc.1     — man page for the file manager
  dist/tlc-1.0.0/man/tlcedit.1 — man page for the standalone editor
  dist/tlc-1.0.0/man/tlcview.1 — man page for the standalone viewer
  dist/PKGBUILD                — Arch Linux build recipe
  dist/build_deb.sh            — Debian/Ubuntu .deb builder
  dist/deb/DEBIAN/control      — Debian control file (binary-arch template)
  dist/.gitignore              — excludes built binaries + config (rebuilt at packaging)

Build outputs (NOT in git, produced locally on demand):

  tlc-1.0.0-linux-x86_64.tar.gz   5.5 MB   generic tarball
  tlc_1.0.0-1_amd64.deb          2.3 MB   Debian package

PLAN.md §17.8 added documenting that §17.4 P1-P4 are now complete
(commit 6c30edaf3e already landed). The §17.6 acceptance criterion
is met: grep for raw 'frame.render_widget(Clear' returns exactly 4
sites (terminal/popup.rs itself, filemanager/tree.rs full-screen,
and the two F9 top menu bars — all intentional). widget/dialog.rs
no longer appears.

P5 (SaveBeforeClose Y/N/Esc legend), P6 (viewer/editor SaveBeforeClose
unification), P7 (~15 decorative key-legend hints) remain deferred —
see §17.4 for rationale.

Header status line bumped to reflect P1-P4 completion + P5-P7 deferral.
2026-06-21 01:44:17 +03:00
vasilito 3dcdb758e7 redbear-power: v1.27 process tree view
Activates the v1.23-deferred 'ppid' future-use: parents render
above their children with ASCII tree connectors. The default
view is flat (no behavior change); the 'T' hotkey toggles
tree mode and flashes the status line.

Algorithm (in process::sort_tree):
1. Build pid -> index map
2. Group children by ppid (ppid -> Vec<index>)
3. Roots = ppid==0 or ppid not in pid set
4. Sort each sibling group by current SortMode (so e.g. RSS
   sort still shows top-RSS child first within a parent)
5. DFS from each root, emitting parent + descendants pre-order
6. Defensive: append unvisited procs at end (cycle fallback)

Cycle protection: visited set; revisiting a PID stops recursion
(its children are still emitted once).

Render: tree_prefix(pid, ppid, all) returns
  ''  (root)
  '  \u2514\u2500 ' (last child)
  '  \u251c\u2500 ' (non-last child)
Walks ppid chain to compute depth (max 64 hops).

Status line: 'view: tree' shown when on; help text mentions 'T'.

Test count 101 -> 105 (+4):
- sort_tree_emits_parents_before_children (4-proc tree)
- sort_tree_handles_orphans (ppid not in list)
- sort_tree_handles_cycles (1->2->1 cycle)
- sort_tree_empty_input

Redox stripped binary: 4,184,936 bytes (+16 KiB from v1.26).
Compile warnings: 55 (unchanged).

Notes:
- vsize_kb still has #[allow(dead_code)]; will be activated in
  a future memory-detail panel release.
- Tree is static (no fold/expand); defer to a v1.28 if needed.
- ppid's #[allow(dead_code)] can be removed in a follow-up
  (now actively read by sort_tree and tree_prefix).

Docs: local/docs/redbear-power-improvement-plan.md \xC2\xA751
2026-06-21 01:39:29 +03:00
vasilito 6c30edaf3e dialogs: complete P1-P4 unification (PLAN §17.4)
Executes the four high-priority items from PLAN §17.4 backlog,
bringing all 4 of the remaining bespoke dialog surfaces onto the
unified render_popup / render_button_row path.

P1 (HIGH) widget/dialog.rs — Dialog::render now delegates the
      shell to terminal::popup::render_popup instead of building
      its own raw Clear + Block. This closes the only shadow
      regression in the unified stack: Dialog::info / confirm /
      confirm_all now inherit MC-matching rounded borders +
      drop shadow + Clear + skin-driven palette, identical to
      every other migrated dialog. New test
      render_draws_drop_shadow_at_bottom_right_corner asserts the
      shadow bg is painted at the popup's bottom-right cell.

P2 (HIGH) overwrite_dialog.rs — Y/N/All/Skip/Abort legend replaced
      by 5-element render_button_row (Yes=Default, No=All,
      SkipAll, Abort=Normal). Was 40 lines of hand-rolled Span
      with hand-picked theme.executable / theme.error /
      theme.title_bg / theme.warning colors. New test
      render_uses_mc_bracket_button_shapes asserts Default uses
      '[<' / '>]' brackets and Normal uses '[ ' / ' ]'.

P3 (MED) confirm_dialog.rs — '[ Save ]  [ Cancel ]' Paragraph
      replaced by 2-element render_button_row (Save=Default,
      Cancel=Normal). New test asserts the same MC bracket shapes.

P4 (MED) editor/menubar.rs — F9 dropdown migrated to render_popup,
      matching the already-migrated filemanager/menubar.rs
      dropdown (committed in c032c9a787). Top menu bar (full-width
      by design) intentionally untouched.

Acceptance criterion from §17.6 is met: grep for raw Clear returns
exactly 4 sites, all defensible:
  - terminal/popup.rs (the renderer itself)
  - filemanager/tree.rs (full-screen, intentional)
  - filemanager/menubar.rs top bar (intentional full-width)
  - editor/menubar.rs top bar (intentional full-width)
widget/dialog.rs no longer contains a raw Clear.

Tests: 1184 passing, 0 failing (was 1180; +4 new). Both release
builds (default + --features sftp) clean.
2026-06-21 01:08:16 +03:00
vasilito 04894a18c9 redbear-power: v1.26 remove dead code (BREAKING)
Completes the v1.22 audit W2 cleanup. v1.23 deferred this for a
CHANGELOG note; this release documents the breaking change.

REMOVED (no callers anywhere in the source tree):

- ProcInfo::read_with_cpu_pct(prev, dt_secs, num_cpus)
  Was a 1-line wrapper around read_with_cpu_pct_sorted(..., Rss)
  that no caller actually used. Migration: call
  read_with_cpu_pct_sorted(prev, dt, ncpu, SortMode::default())
  inline (or just use ProcInfo::read() if RSS is fine).

- ProcInfo::available() -> bool
  Was a pre-flight check ('is /proc mounted?') that no caller
  used. read() already returns ProcInfo::default() when /proc
  is absent, so the empty result is the same signal. Migration:
  check !proc.is_empty() after a read, or call read() and
  handle the empty case.

OTHER CHANGES:

- Removed unused 'use std::path::Path;' (was only used by the
  removed ProcInfo::available).
- Updated read_with_cpu_pct_sorted doc comment to mention
  'CPU% and IO rates' (reflects the v1.25 addition).

BREAKING: any external consumer of redbear-power's process module
that called either of these methods will fail to compile. The
recipe's own source (the only known consumer) is updated.

Test count: 101 (unchanged; removed methods were untested).
Compile warnings: 55 -> 54 (the unused Path import is gone).

Redox stripped binary: 4,168,552 bytes (unchanged; the removed
code was tiny and the linker dedup'd the wrapper body).

Docs: local/docs/redbear-power-improvement-plan.md \xC2\xA750
2026-06-21 01:05:09 +03:00
vasilito aaa1b950b4 redbear-power: v1.25 IO rate column + rate sort modes
Per-process IO is now also a throughput metric (KiB/s), not just
cumulative. Cumulative bytes favor long-lived processes regardless
of activity; rate is what operators actually want for 'what is
hammering the disk right now'.

- New fields on ProcessInfo: io_read_rate_kbs, io_write_rate_kbs
  (Option<f64>; None when prev missing, current None, or dt<=0)
- New method: io_total_rate_kbs() (sum; same None semantics)
- New helper: compute_rate_kbs(prev, now, dt) -> Option<f64>
  uses saturating_sub for clock-reset safety
- read_with_cpu_pct_sorted now also computes the two rate fields
  (negligible cost: 2 subs + 2 divs per process per refresh)
- New SortMode variants: IoRate, IoReadRate, IoWriteRate
  inserted in cycle after IoWrite
- name() returns 'IO/s', 'R/s', 'W/s' for status line
- New sort_by_io_rate_field() helper (Option<f64> partial_cmp)
- New format_rate_kbs() on ProcessInfo (KiB/s, MiB/s, GiB/s, TiB/s;
  saturates negative to 0)
- New RATE column in the Process panel between IO and RSS

Test count 87 -> 101 (+14):
- 6 compute_rate_kbs edge cases (basic, None prev/now, dt<=0,
  saturating underflow, idle = zero)
- 2 io_total_rate_kbs (sum, None)
- 2 sort-by-rate (total, read-pushes-missing)
- 4 format_rate_kbs (sub-KiB, 1 MiB, 1 GiB, negative)
- sort_cycle and io_name_is_io updated for new variants

Redox stripped binary: 4,168,552 bytes (+49 KiB from v1.24;
14 new tests + 2 sort modes + 2 fields + render column + 3 helpers).
Compile warnings: 55 (unchanged).

Docs: local/docs/redbear-power-improvement-plan.md \xC2\xA749
2026-06-21 00:50:30 +03:00
vasilito c8e19ea47f PLAN §17: dialog consistency assessment (44/46 unified, 4-item P1-P4 backlog)
Comprehensive audit of every dialog in tlc — render path, button
source, shadow source, hotkey consistency. Verifies the Phase 16-18
work brought 44/46 dialog surfaces onto the unified render_popup
path (33 filemanager + 5 editor/render + 1 ops/progress), with MC
rounded borders + drop shadow + skin-driven palette inherited
automatically.

Identifies the remaining 7% (the four high-priority items in §17.4):

  P1 (HIGH) widget/dialog.rs:194 — Dialog::render uses raw Clear +
       own Block instead of render_popup, so Dialog::info / confirm /
       confirm_all render flat-border popups with NO drop shadow.
       Only shadow regression in the unified stack. ~5-10 LOC.

  P2 (HIGH) filemanager/overwrite_dialog.rs:138-181 — hand-rolled
       Y/N/All/Skip/Abort colored Span legend. Single most visually
       inconsistent button strip in the codebase. Migrate to
       render_button_row of 5 ButtonSpec. ~25-40 LOC.

  P3 (MED)  filemanager/confirm_dialog.rs:186-191 — '[ Save ] [ Cancel ]'
       Paragraph with theme.hidden. Migrate to 2-button row. ~8-15 LOC.

  P4 (MED)  editor/menubar.rs:520 — F9 dropdown still uses hand-rolled
       Block + Clear instead of render_popup. Filemanager menubar
       dropdown was migrated (c032c9a787); editor was not. ~5-10 LOC.

Plus lower-priority items:
  P5 editor SaveBeforeClose Y/N/Esc legend migration
  P6 viewer/editor SaveBeforeClose unification
  P7 (optional) ~15 decorative key-legend hints migrated to
     ButtonKind::Narrow rows

§17.3 documents the intentional non-targets (full-screen TreeDialog,
F9 menu-bar top rows, viewer render_prompt_overlay) so future
auditors know not to migrate them.

§17.5 codifies the three hotkey patterns (Action OK/Cancel,
Yes/No confirm, Yes/No/All/Skip confirm) and the locale keys
that drive them.

§17.6 sets the acceptance criteria: after P1-P4, grep for raw
Clear should return 5 sites, all defensible. Zero shadow
regressions. Zero hand-rolled button strips that look like
real buttons.

Tests: 1180 passing, 0 failing (no code changes, audit only).
2026-06-21 00:50:05 +03:00
vasilito 6f99194049 redbear-power: v1.24 split IO sort (IO-R, IO-W)
htop has had separate read/write sort modes since 2.0; v1.22
conflated them via io_total_kb(). v1.24 splits SortMode::Io
into three variants so operators can find read-heavy (DB
servers) vs write-heavy (log shippers) processes.

- New variants: SortMode::IoRead, SortMode::IoWrite
- Cycle updated: Rss -> Cpu -> Io -> IoRead -> IoWrite -> Pid
  -> Name -> Rss
- name() returns 'IO', 'IO-R', 'IO-W' for disambiguation
  (shown in status flash on 'o' keypress)
- Extracted sort_by_io_field() helper: shared 4-arm comparator
  for (Some, Some) descending, (Some, None) Less,
  (None, Some) Greater, (None, None) Equal. Eliminates the
  DRY violation of repeating the 4-arm match in three places.
- Sentinel semantics preserved: None still sorts below Some;
  column still renders em-dash for unreadable /proc/[pid]/io
- Column header unchanged: 'IO' column shows per-process
  total; sort direction is in the status line. Minimal change;
  adding separate R/W columns would push the panel past 100
  chars and lose comm truncation.

Test count 83 -> 87:
- sort_by_io_read_ignores_writes
- sort_by_io_write_ignores_reads
- sort_by_io_read_pushes_missing_to_bottom
- sort_by_io_write_pushes_missing_to_bottom
- io_name_is_io now also locks IO-R and IO-W strings
- sort_cycle and sort_cycle_includes_io updated for new cycle

Redox stripped binary: 4,119,400 bytes (-8 KiB from v1.23;
the helper dedup actually shrunk the binary).
Compile warnings: 55 (unchanged; all new variants are used).

Docs: local/docs/redbear-power-improvement-plan.md \xC2\xA748
2026-06-21 00:41:30 +03:00
vasilito fb146063a7 docs: update CONSOLE-TO-KDE-DESKTOP-PLAN.md to v5.6
- qtbase GLES3/KHR header fix
- KWin added to build
- KF6 packages unblocked (all 48 build)
- D-Bus daemon socket binding fixed
- Mesa virgl verified wired
2026-06-21 00:24:15 +03:00
vasilito 129b08eff9 dbus: add explicit --address flag to dbus-daemon for deterministic socket binding
- Add --address=unix:path=/run/dbus/system_bus_socket to dbus-daemon args
- Add before = ["13_redbear-sessiond.service"] for strict ordering
- Fixes redbear-sessiond "failed to read from socket" errors
2026-06-21 00:23:30 +03:00
vasilito b26559e9a9 PLAN: reconcile with Phase 27/28/29 completion (2026-06-21)
Update PLAN.md to reflect the SFTP known_hosts wiring (Phase 27),
viewer hex edit mode (Phase 28), and mc.ext Include resolver
(Phase 29) work that landed in commits d55bef9a2d, 79d00e2372,
4738b722fd.

§0 header status line now says 'Phases 14a, 14b, 15a, 15b, 15c,
15d, 14e, 16-29 substantially complete' with a 2026-06-21 stamp.

§3.1 stats refreshed to current code reality: 1180 tests (was 847),
138 .rs files (was 106), ~56k lines (was ~41k), binaries 5.4/3.9/3.8
MB (was 4.2/1.2/0.66 MB after hex edit + Include resolver landed).

§4.1 #26 audit row now marked DONE (Phase 27) instead of DEFERRED.

§15d table:
  - row 27 (Viewer hex edit) DONE (Phase 28) — full description of
    nibble pipeline, SaveBeforeQuit prompt, dirty marker, and tests.
  - row 28 (mc.ext Include resolution) DONE (Phase 29) — full
    description of find_action_in_section recursion and resolve_rule.

End-of-doc changelog gets three new dated entries (2026-06-21)
for Phases 27, 28, 29 plus refreshed test count and binary sizes.
2026-06-21 00:22:22 +03:00
vasilito 6dd2ddafd9 redbear-power: v1.23 IO sentinel + single-pass parse
The v1.22 audit + htop cross-reference surfaced a real defect:
on Redox, daemons whose /proc/[pid]/io is not exposed (permission
denied, proc scheme gap) silently clustered at 0 B in the IO
column, indistinguishable from genuinely idle processes. This
made SortMode::Io unreliable for finding the real IO hogs.

This release promotes the IO column to a proper sentinel model:

- io_read_kb / io_write_kb change from u64 to Option<u64>
- io_total_kb() returns Option<u64>; None when either field is None
- SortMode::Io uses 4-arm match on (a_total, b_total):
    * both Some -> descending by total
    * Some/None -> known sorts above unknown
    * None/None -> stable tie (input order)
- Render layer shows em-dash (\u2014) when total is None
- Single-pass /proc/[pid]/io parse replaces two-helper double-read
  (read_io_file returns Option<(u64, u64)> in bytes; caller /1024s
  to KiB so the None sentinel propagates end-to-end)
- #[allow(dead_code)] on ppid, vsize_kb with documented future use
  (process tree view, memory detail panel) per project warning policy

Test count 80 -> 83:
- Replaced misleading 'io_total_saturates_on_underflow' (tested
  normal sum) with 'io_total_saturates_at_u64_max' (genuine edge)
- Added 'io_total_returns_none_when_fields_missing'
- Added 'sort_by_io_pushes_missing_to_bottom'
- Added 'io_name_is_io' to lock the SortMode::Io.name() string

Compile warnings 56 -> 55 (the ppid/vsize_kb dead_code warning
is now suppressed; remaining 55 are pre-existing in other modules).

Redox stripped binary: 4,127,592 bytes (+4 KiB from v1.22).
Linux smoke test confirms em-dash renders for kscreenlocker_g,
kwin_wayland, tailscaled, polkit-kde-auth (all owned-UID procs
that the kernel hides /proc/[pid]/io from on this dev host).

Docs: local/docs/redbear-power-improvement-plan.md \xC2\xA747
2026-06-21 00:20:45 +03:00
vasilito 4738b722fd qtbase: ensure KHR/khrplatform.h exists in sysroot for OpenGL/EGL includes
- Add fallback to copy from sysroot/usr/include/KHR/ if available
- Generate minimal khrplatform.h stub if neither exists
- Fixes build failure where Qt's qopengl.h cannot find KHR/khrplatform.h
2026-06-20 23:41:21 +03:00
vasilito 79d00e2372 viewer: hex-edit mode with byte-level edit cursor (Phase 28)
tlcview now supports in-place byte-level editing in Hex view:

  F4 (Text -> Hex), F2 (Hex -> HexEdit) toggles between read-only
  hex view and an editable overlay. HexEdit mode draws an extra-
  bright cursor over the *active nibble* (H or L) so the user
  always knows which digit the next keystroke will replace.

Nibble pipeline (mirror of MC's mcedit hex cursor):
  - type 'a'..'f' or '0'..'9': stash the high nibble and advance
    to the low nibble; the byte is NOT yet written
  - second nibble: combine with stashed high, write the byte,
    advance the cursor by 1, reset to high nibble
  - arrow keys: H/L toggle (Right/Left), row navigation (Up/Down),
    page jump (PgUp/PgDn)
  - F10/Esc/Ctrl-Q on a dirty buffer opens the
    'Save before quit? (Y/N/Esc)' prompt; Y saves, N discards,
    Esc cancels and stays in HexEdit

Byte storage:
  - Inline and Compressed sources (the default for files < 1 MiB
    and all .gz/.bz2) are mutated in place via the new
    FileSource::write_byte(offset, value) helper.
  - FileSource::save_to(path) persists the buffer byte-exact.
  - Chunked sources (≥ 1 MiB plain files) refuse to enter
    HexEdit — caller gets a silent no-op. The new
    SourceError::NotMutable variant carries the diagnostic.

Header / footer:
  - mode label changes from 'Hex' to 'HexEdit' in the header
  - footer shows 'Nibble H' or 'Nibble L' (which digit is next)
  - '[+]' marker appears after the mode label when the buffer
    has unsaved edits

8 new tests cover: F2 enter, nibble commit + cursor advance,
dirty F10 opens prompt, clean F10 closes, Y/N/Esc prompt
resolution, Chunked refusal, arrow-key nibble toggling.

Total: 1172 tests passing, 0 failing.
2026-06-20 23:32:54 +03:00
vasilito 31e7c9d484 docs: update CONSOLE-TO-KDE-DESKTOP-PLAN.md to v5.5
- redox-drm kernel GPF fixed (IOPL acquisition)
- Qt6 Wayland null+8 crash verified already fixed
- tlc compile errors fixed
- Redox git forks research completed
2026-06-20 23:15:32 +03:00
vasilito b4237bb12e redox-driver-sys: fix kernel GPF by acquiring IOPL before PCI I/O port access
Root cause: PciDevice::open_io_ports never called acquire_iopl(),
so the first outl to 0xCF8 triggered #GP(0) when redox-drm tried
to scan virtio-gpu PCI capabilities.

- Add ensure_iopl_acquired() helper (thread-local Once)
- Call it in PciDevice::open_io_ports before any I/O
- Add P1-pci-open-io-ports-iopl.patch to recipe
- Mirror patch to local/patches/ for durability
2026-06-20 23:14:11 +03:00
vasilito d55bef9a2d vfs: wire SFTP handler to known_hosts store (Phase 27)
Replaces the AcceptAnyKey stub with KnownHostsHandler that pins
server keys against ~/.config/tlc/known_hosts (or
$XDG_CONFIG_HOME/tlc/known_hosts).

Storage model: each entry stores the SHA-256 fingerprint of the host
key (64-char lowercase hex), not the raw base64 key bytes.  This
sidesteps the absence of a PublicKey::key_data() round-trip in
russh 0.44 and keeps the file format self-describing — fingerprints
are what the user sees in 'ssh-keygen -lf', so a quick visual
diff is enough to spot a MITM.

Three matching outcomes:
  Match     — host + fingerprint in store, accept connection
  Mismatch  — host in store, fingerprint changed → SshHandlerError::KeyMismatch
  Unknown   — host not in store → TOFU: append + save + accept

A mismatch returns Err, which surfaces to the caller as
VfsError::Connection("ssh: ...") with the presented and stored
fingerprints in the message — the user sees a hard reject, never
a silent re-trust.  Save failures during TOFU are non-fatal (the
in-memory append is enough for the current session); the user will
see the TOFU prompt again next connect.

Tests: 9 known_hosts + 2 SFTP error-display = 11 new tests.
Total: 1172 passing, 0 failing.
2026-06-20 23:08:11 +03:00
vasilito cca510465d redbear-power: v1.22 sort by IO (per-process read+write bytes)
Process tab gains a new IO column sourced from /proc/[pid]/io
read_bytes and write_bytes, summing them as a single sortable value.

- New fields on ProcessInfo: io_read_kb, io_write_kb
- New method: ProcessInfo::io_total_kb()
- New helpers: read_io_bytes, write_io_bytes (silent on failure;
  /proc/[pid]/io may require CAP_SYS_PTRACE for owned UID)
- New SortMode::Io variant inserted into the cycle
  (Rss -> Cpu -> Io -> Pid -> Name)
- Updated render header: VIRT replaced by IO (RSS preserved)
- 4 new unit tests; total 80 pass
- Redox stripped binary: 4123496 bytes
- Linux smoke test confirms opencode dominates IO, kscreenlocker_g shows 0.0 KiB

Docs: local/docs/redbear-power-improvement-plan.md \xC2\xA746
2026-06-20 22:59:20 +03:00
vasilito 24511fbde8 tlc: fix known_hosts.rs compile errors (fingerprint type mismatch, format string)
- Convert String fingerprint to Vec<u8> for VerifyResult::Mismatch
- Fix format string to include comment placeholder
2026-06-20 22:56:06 +03:00
vasilito d1f2e59755 redbear-power: v1.21 — SMART UI integration (Storage tab badges)
Wires the v1.20 SMART data module into the Storage tab UI.
Each disk now shows a health badge (✓ PASSED / ✗ FAILED / error).

Implementation:
- App.smart: SmartInfo field + 11-tick refresh (paired with Storage)
- Conditional refresh (if self.smart.available guard — avoids
  re-running smartctl if we already know it's missing)
- render_storage_panel: 4 SMART badge states
  1. !available → '(SMART: install smartmontools)'
  2. health.passed → ' ✓ PASSED'
  3. !health.passed → ' ✗ FAILED'
  4. health.error → ' (SMART: <error>)'

Linux host smoke test (this dev host without smartctl):
- Each disk shows '(SMART: install smartmontools)' hint
- No panic, graceful degradation
- Storage tab still works (no regression)

Performance: smartctl subprocess ~5-50ms per disk, 3 disks = 15-150ms
per 11-tick refresh (5.5 sec), well within budget.

76/76 tests pass (no new tests — UI integration only).

Cross-compile SHA256: ed804710fa834f4453a236aa034d50668b948b391ec1d2ccea294d438016d855.

Docs: improvement plan §45, CONSOLE-TO-KDE §3.3.2 v1.21,
RATATUI-APP-PATTERNS §13.14 + §14 (6400 LoC, 21 modules, 76 tests).
2026-06-20 22:50:04 +03:00
vasilito 1e86a8b0e0 docs: update CONSOLE-TO-KDE-DESKTOP-PLAN.md to v5.4
- redox-drm virtio-gpu crash fixed
- Greeter/SDDM Wayland socket timeout fixed
- ISO boots to text login prompt in QEMU
- Redox git forks research completed
2026-06-20 22:43:01 +03:00
vasilito 6006d20178 redox-drm: add virtio-gpu detection (1AF4:1050/1052) and Intel ARC PCI IDs
greeter: fix Wayland socket timeout (45s wait, dual-path probe)
sessiond: add D-Bus socket candidate probing with better error logging
config: align greeter/sddm runtime dirs and DRM wait timeouts
2026-06-20 22:41:26 +03:00
vasilito f5311f16c8 redbear-power: v1.20 — SMART data module (graceful when smartctl missing)
Adds the smart.rs module for disk health monitoring. Since
smartctl is not installed on most systems (this dev host has it
absent), v1.20 implements the module with three-tier graceful
degradation per the zero-stub policy.

New module smart.rs (222 lines, 7 unit tests):
- SmartInfo struct with available + per-disk health records
- SmartHealth struct with passed + attributes + error
- SmartAttribute struct with id + name + value + worst + threshold + raw
- SmartInfo::smartctl_available() — checks smartctl --version
- SmartInfo::read(disks) — orchestrates per-disk smartctl -A -H
- parse_smartctl_output(text) — extracts passed/failed + attrs
- parse_attribute_line(line) — single 10-field SMART attribute
- parse_smart_value(s) — handles both hex (0x33) and decimal
- health_for(disk_name) — convenience accessor

Three-tier graceful degradation:
1. smartctl missing → available=false, disks=[]
2. smartctl errors per disk → error captured in SmartHealth
3. NVMe permission issues → error message, no fabrication

Updated main.rs: mod smart declaration.

76/76 tests pass (5 bench + 12 sensor + 13 network + 12 storage +
20 process + 7 pid_detail + 7 smart).

Linux host smoke test (this dev host without smartctl):
- available=false (graceful, no panic)
- Storage tab still works (no regression)

Cross-compile SHA256 unchanged from v1.19 (smart.rs is dead code
on Redox — compiles but never called).

Docs: improvement plan §44, CONSOLE-TO-KDE §3.3.2 v1.20,
RATATUI-APP-PATTERNS §13.14 + §14 (6360 LoC, 21 modules, 76 tests).
2026-06-20 22:39:27 +03:00
vasilito 006c59b88c tlc: phase 26 — PLAN.md reconciliation with code reality
Reconcile PLAN.md audit and feature tables with current code
state after Phase 25. Several rows are stale relative to the
code (resolved earlier but PLAN never updated):

  §2 audit rows marked FIXED/VERIFIED:
    #22 (Tui::default non-tty panic → Tui::new returns Err)
    #23 (save.rs non-UTF-8 silent drop → from_utf8_lossy fallback)
    #25 (Cmd enum missing_docs → all 73 variants documented)
    #28 (F9 unbound in keymap → km.bind(F9, Cmd::MenuBar) exists)
    #33 (move_one discards errno → preserves io::Error fully)

  §15d feature rows marked DONE with file/line citations:
    Row 25 (Save/restore cursor pos → P4b done)
    Row 30 (PTY persistent subshell → terminal/subshell.rs:1-617)
    Row 33 (Growing buffer / tail -f → viewer/mod.rs:84-89, 295-357)

Phase 26 is documentation-only — no code changes.
2026-06-20 22:37:36 +03:00
vasilito 3b251a1ea1 redbear-power: v1.19 — PID detail view (modal popup)
Closes the v1.13 §37.6 PID detail forward-work item. Press Enter
on a process row in the Process tab to open a modal popup with
detailed /proc/[pid] info.

New module pid_detail.rs (237 lines, 7 unit tests):
- read_status(pid) → ProcStatus: Name, State, Pid, PPid, Tgid,
  Threads, Uid (3-tuple), Gid (3-tuple), 12 Vm* memory fields
- read_io(pid) → ProcIo: rchar, wchar, syscr, syscw, read_bytes,
  write_bytes, cancelled_write_bytes
- read_smaps_rollup(pid) → ProcSmapsRollup: Rss, Pss, Private_Clean,
  Private_Dirty, Swapped (CAP_SYS_ADMIN gated)
- PidDetail::read(pid) — aggregator

Updated app.rs:
- pid_detail: Option<PidDetail> field
- selected_pid() method — returns PID of selected row (filter-aware)

Updated main.rs:
- Enter on Process tab → opens pid_detail for selected PID
- Enter on other tabs → toggle P-state expansion (existing behavior)
- Esc or any key while popup open → closes popup
- Popup rendered with Clear + centered Rect (70% × 80%)

Updated render.rs:
- New render_pid_detail(detail, pid) — full PID detail layout
  with [Identity] / [Memory] / [smaps_rollup] / [io] sections
- Fixed missing render_system_panel import (existing bug)

69/69 tests pass (5 bench + 12 sensor + 13 network + 12 storage +
20 process + 7 pid_detail).

Cross-compile SHA256: e34a22ed518b2e918bf8fb07eec77d8c5e2e2389a01ad00dad0d76f5c09578a4.

Docs: improvement plan §43, CONSOLE-TO-KDE §3.3.2 v1.19,
RATATUI-APP-PATTERNS §13.14 + §14 (6160 LoC, 20 modules, 69 tests).
2026-06-20 22:27:06 +03:00
vasilito 601d08bdc2 tlc: phase 25 — verify Alt-P format paragraph + add integration test
Format-paragraph was already implemented (Editor::format_paragraph
in src/editor/mod.rs + Alt-P keybind wired in handlers.rs at
0x70 within the Alt-modifier match arm). The function uses
editor::format::reformat_paragraph_at which walks contiguous
non-blank lines and re-flows them at DEFAULT_WRAP_WIDTH (72).
Undoable via begin_undo_group / end_undo_group pair.

This phase adds an end-to-end handler test that exercises the
keybinding path: insert a long paragraph, press Alt-P, verify
the buffer is marked modified. Pre-existing format.rs unit tests
cover the formatting details (wrap widths, blank-line
boundaries, undo); this test verifies the integration.

PLAN.md §15d row 32 marked Done.

Tests: 1154 passed (was 1153, +1). Release binaries build clean.
2026-06-20 22:23:46 +03:00
vasilito 848d0fad94 redbear-power: v1.18 — Process filtering (closes v1.13 forward work)
Closes the v1.13 §37.6 forward-work item (the last one). Process
tab now supports case-insensitive substring filtering on the
process name (comm).

Implementation summary:
- New App.process_filter: String field
- Hotkey 'f' opens text-input mode (pattern reused from refresh-
  interval input):
  - chars → push to filter buffer
  - Backspace → pop
  - Enter → commit filter, flash match count
  - Esc → discard buffer + clear filter
- Filter applied in render_process_panel:
  - For each process, skip if non-empty filter doesn't match
    (case-insensitive substring on comm)
- Header line shows filter indicator + hint
- Helper proc_filter_match_count(app) for status message
- 4 new unit tests (case insensitive + substring + no match + empty)
- 62/62 tests pass

Build: clean
Cross-compile SHA256: 12913dedc9b0ea58ed3e7418527da34c903f70be703b8676e4273042c73ac875

Docs: improvement plan §42, CONSOLE-TO-KDE §3.3.2 v1.18,
RATATUI-APP-PATTERNS §13.14 + §14 (5840 LoC, 62 tests).
2026-06-20 22:11:37 +03:00
vasilito 28906f16cf tlc: phase 24 — editor word sort (Alt-F8)
Mirrors MC's edit_sort_cmd flow (CK_Sort / M-F8 →
src/editor/editcmd.c::edit_sort_cmd):

  1. Require a marked block; surface error message if no
     selection is active.
  2. Stash the active selection to a unique temp file under
     /tlc-sort-<nanos>/in.txt (per-call unique dir to
     avoid races between concurrent sort runs).
  3. Run via 'sh -c sort <opts> <in> > <out>' so user-supplied
     options pass through verbatim (matches MC g_strconcat).
     Empty options means default lexical sort.
  4. On non-zero exit: surface exit code + first stderr line.
  5. On success: delete the original selection, insert the
     sorted output at the cursor, mark buffer modified, and
     surface a status line ('Sort: ok (N bytes, M lines)').

Components:
  src/editor/mode.rs — new PromptKind::Sort variant.
  src/editor/handlers.rs — Alt-F8 keybind (errors if no
    selection, otherwise opens the sort prompt); commit_prompt
    routes PromptKind::Sort to Editor::sort_block(options).
  src/editor/render.rs — title ('Run sort') + label ('sort
    options (empty for default)') + mode tag (' [Sort]') for
    the prompt.
  src/editor/mod.rs — Editor::sort_block(options).

Tests: 1153 passed (was 1150, +3):
  - sort_block_sorts_active_selection (apple/banana/cherry)
  - sort_block_with_no_selection_reports_error
  - sort_block_with_reverse_flag (-r → c/b/a)
Release binaries build clean.

PLAN.md §15d row 32a marked Done.
2026-06-20 22:09:49 +03:00
vasilito 08561033ae redbear-power: v1.17 — Sort modes in Process tab (closes v1.13 forward work)
Closes the v1.13 §37.6 forward-work item. Process tab now supports
sorting by RSS, CPU%, PID, or Name — cycle with hotkey 'o'.

Implementation summary:
- New SortMode enum: Rss (default) / Cpu / Pid / Name
- SortMode::next() cycles through all 4 modes
- SortMode::sort(&mut Vec<ProcessInfo>) reorders in place
- ProcInfo::read_sorted(sort_mode) — read with custom sort
- ProcInfo::read_with_cpu_pct_sorted(prev, dt, num_cpus, sort_mode)
  — re-sorts at end because CPU% may change rank
- App.process_sort: SortMode field
- 13-tick refresh uses sorted variant
- Hotkey 'o' cycles sort mode (with status flash)
- Header line shows 'sort: <mode> (press o to cycle)'
- 6 new unit tests (default + cycle + 4 sort modes)

Restored v1.16 changes (prior session left them partial):
- NetInfo::rx_kbps + tx_kbps fields + init
- NetInfo::read_with_throughput(prev, dt_secs)
- App::prev_net field
- 7-tick refresh uses read_with_throughput
- render_network_panel RX/TX lines show '{X} KiB/s'
- 3 network throughput unit tests

58/58 tests pass (5 bench + 12 sensor + 10 network + 12 storage + 19 process).
Cross-compile SHA256: 5d01429b91b5c8399f6772251fd28a44a083cc53f13f2b9dff6f92245787c393.

Docs: improvement plan §41, CONSOLE-TO-KDE §3.3.2 v1.17,
RATATUI-APP-PATTERNS §13.14 + §14 (5800 LoC, 58 tests).
2026-06-20 22:00:05 +03:00
vasilito 0b0e65a643 tlc: phase 23 — viewer FileNext / FilePrev (Ctrl-F / Ctrl-B)
Mirrors Midnight Commander's
MC src/viewer/actions_cmd.c::mcview_load_next_prev (CK_FileNext
/ CK_FilePrev).

Components:
  src/viewer/siblings.rs (new) — pure helper next_or_prev_sibling:
    reads current file's parent directory, filters out hidden
    files (dot-prefixed), sorts case-insensitive, locates current
    by file_name, returns next (direction=+1) or prev (direction=-1)
    entry. Returns None at directory boundaries or on I/O error.
    6 unit tests cover next/prev/last/first/hidden/no-parent.

  src/viewer/mod.rs — Viewer::open_next / Viewer::open_prev
    public methods that look up the sibling and reload viewer
    state via a private reload_at helper (mirrors MC's
    mcview_init/mcview_done pair around mcview_load). Source
    errors are converted to std::io::Error so the Result type
    matches the existing open() signature.

  src/viewer/mod.rs — Ctrl-F / Ctrl-B keybinds in handle_key.
    Each delegates to open_next / open_prev.

  PLAN.md §15d row 29 marked Done; status bumped to Phase 23.

Tests: 1150 passed (was 1141, +9: 6 siblings module tests +
3 viewer integration tests covering open_next, open_prev,
Ctrl-F/Ctrl-B keybinds). Release binaries build clean.
2026-06-20 21:52:12 +03:00
vasilito d209b64ce9 redbear-power: v1.16 — Network throughput (closes v1.11 forward work)
Closes the v1.11 §35.7 forward-work item. Network tab now shows
real-time R/W throughput (KiB/s) per interface, computed from delta
of rx_bytes/tx_bytes between successive 7th-tick refreshes.

Source code already landed (network.rs + app.rs + render.rs).
This commit captures full v1.16 docs:

- Improvement plan §40 (Network Throughput)
- CONSOLE-TO-KDE §3.3.2 v1.16
- RATATUI-APP-PATTERNS §13.14 (audit table +16) + §14 (5755 LoC, 52 tests)

Implementation summary:
- New rx_kbps: f64 + tx_kbps: f64 fields on NetInterface
- New NetInfo::read_with_throughput(prev, dt_secs)
- Wall-clock dt (shared prev_refresh_secs with v1.14 + v1.15)
- saturating_sub on bytes prevents underflow
- 3 new unit tests (formula + underflow + zero dt)
- 52/52 total tests pass

Math sanity check (verified by unit test):
prev=1MB, now=5MB, dt=2sec → 1953.125 KiB/s
prev > now → saturating_sub → 0

Cross-compile SHA256: 053f1a0cca5185637d0316d56f5cf5832cf2e754b689bc24edf16ea5d0404fa2.
2026-06-20 21:41:07 +03:00
vasilito 6729409b4d redbear-power: v1.14 + v1.15 — CPU% + disk throughput + restoration
This commit restores and completes v1.14 (CPU% in Process tab) and
v1.15 (disk throughput in Storage tab). Previous sessions landed
partial work (cpu_pct field on ProcessInfo, read_kbps/write_kbps on
DiskStats) but never wired them up. This commit:

v1.14 — Process CPU% (Process tab):
- ProcInfo::read_with_cpu_pct(prev, dt_secs, num_cpus)
- App::prev_processes + prev_refresh_secs fields
- 13-tick refresh now uses read_with_cpu_pct with wall-clock dt
- 3 new unit tests (formula + zero + underflow)

v1.15 — Disk throughput (Storage tab):
- StorageInfo::read_with_throughput(prev, dt_secs)
- App::prev_storage field
- 11-tick refresh now uses read_with_throughput
- 3 new unit tests (formula + underflow + zero dt)

Updated render.rs:
- Process panel column header: PID STATE PRIO NI THR CPU% RSS VIRT COMM
- Storage panel Read/Written lines show 'X I/Os, Y KiB/s'

Tests: 49/49 pass (5 bench + 12 sensor + 7 network + 12 storage +
13 process).

Cross-compile SHA256: d1207b648ce89e19f8dd040f234648e1665f053ec31f8511ea187627d79bde2d.

Math sanity checks (verified by unit tests):
CPU%: delta=130 ticks, dt=2sec, num_cpus=4 → 1625.0%
Disk: prev=1MB, now=5MB, dt=2sec → 1953.125 KiB/s

Docs: improvement plan §38 (CPU%) + §39 (disk throughput),
CONSOLE-TO-KDE §3.3.2 v1.14 + v1.15, RATATUI-APP-PATTERNS §13.14 +
§14 (5720 LoC, 49 tests).
2026-06-20 21:30:39 +03:00