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
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).
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).
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).
Closes the v1.13 §37.6 forward-work item. Process tab now shows
real-time CPU usage per process, computed from the delta of
total CPU ticks between successive 13th-tick refreshes.
Source code already landed (process.rs + app.rs + render.rs).
This commit captures full v1.14 docs:
- Improvement plan §38 (CPU% in Process Tab)
- CONSOLE-TO-KDE §3.3.2 v1.14
- RATATUI-APP-PATTERNS §13.14 (audit table +14) + §14 (19 modules, 47 tests)
Implementation summary:
- New cpu_pct: f64 field on ProcessInfo
- New ProcInfo::read_with_cpu_pct(prev, dt_secs, num_cpus)
- Wall-clock dt (SystemTime) — accurate even when TUI pauses
- saturating_sub on ticks prevents underflow if now < prev
- num_cpus from self.cpus.len() (Per-CPU detection result)
- 4 new unit tests (formula + zero + underflow + dt=0)
- 47/47 total tests pass
Math sanity check (verified by unit test):
utime=100→200, stime=50→80, dt=2sec, num_cpus=4
delta = 280-150 = 130 ticks / 2 sec = 65 ticks/sec
CPU% = 65 / 4 cpus * 100 = 1625.0%
Cross-compile SHA256: d46cd66b8e158e2327839ef502879951877a5500d4a40807d3dbc72ed7397231.
Phase 20 ships the editor's F9 menu bar as a self-contained,
testable widget. Mirrors Midnight Commander's
src/editor/editmenu.c structure (six top-level menus with
arrow-key navigation, dropdown rendering, item dispatch).
Components:
src/editor/menubar.rs — EditorMenuBar + EditorCmd + render()
src/editor/mod.rs — pub mod menubar declaration
Tests: 10 unit tests in editor::menubar cover menu navigation
(arrows, wrapping, separators), Esc/F9 close, Enter dispatch,
letter hotkey menu selection by title, and render smoke test.
Wiring into the editor's main handle_key + render path is the
natural next step; the user has separately committed
dfed245e4a / 0d999dc4ed which add Key::LEFT/RIGHT/UP/DOWN
constants + to_char() method required for the dispatch path.
PLAN.md header bumped to Phase 20 complete.
Adds the 6th tab in the multi-view system: Sensors, reading
hardware monitoring data from /sys/class/hwmon/hwmonN/ on Linux
hosts. Detects all chips (k10temp, coretemp, nvme, mt7921, r8169,
spd5118, zenpower, etc.) and their temp/fan/voltage/power/current
sensors with proper unit conversions.
New module sensor.rs (231 lines):
- SensorKind enum: Temp (m°C) / Fan (RPM) / Voltage (mV) /
Power (µW) / Current (mA), with #[default] on Temp
- SensorReading: kind, label, raw_value, display_value
- HwmonChip: name, path, readings
- SensorInfo::read() walks /sys/class/hwmon/hwmonN/, reads
name + all *_input files (with corresponding *_label for
human-readable names like 'Tctl', 'Composite')
- 7 unit tests covering unit conversions + empty state
Updated app.rs:
- New field sensors: SensorInfo, refreshed every 3rd tick
(1.5 sec at POLL_MS=500). 3-tick modulus is coprime to
meminfo's 4 and battery's 5 — no thundering-herd syscalls.
- TabId::Sensors variant (6th tab)
- TabId::next() cycles PerCpu → System → Info → Motherboard →
Battery → Sensors → PerCpu
Updated render.rs:
- New render_sensor_panel(app, focused) with per-chip sections
using ▸ arrow + chip name as bold header, then Label/Value pairs
in 12-char left-aligned label / 14-char right-aligned value
layout. Empty state: '(no sensors detected — /sys/class/hwmon/
not readable)' rather than wall of ?.
- render_tab_bar() updated for 6 tabs with hotkey 1/2/3/4/5/6
- render_once now dumps Sensors panel for headless verification
Updated main.rs:
- mod sensor; declaration
- New dispatch arm TabId::Sensors => render_sensor_panel
- Hotkey 6 jumps to Sensors tab directly
- render_sensor_panel added to imports
Linux host smoke test (Manjaro, Ryzen 9 7900X, 7 chips, 11 sensors):
▸ mt7921_phy0 temp 58.0 °C
▸ r8169_0_e00:00 temp 51.0 °C
▸ k10temp Tccd1 82.6 °C
Tccd2 57.1 °C
Tctl 85.6 °C
▸ nvme Sensor 2 53.9 °C
Composite 50.9 °C
Sensor 1 50.9 °C
▸ spd5118 temp 50.0 °C
▸ spd5118 temp 51.5 °C
▸ nvme Composite 48.9 °C
Unit conversions verified: m°C → °C (50850 → 50.9°C), mV → V,
µW → W, mA → A. Unit tests: 12/12 pass (5 bench + 7 sensor).
Source state: 4885 LoC across 16 modules.
Redox stripped: 3.8 MB (SHA256 7a7c31bc...).
Docs: improvement plan §33, CONSOLE-TO-KDE §3.3.2 v1.9,
RATATUI-APP-PATTERNS §13.14 + §14 (16 modules, 12 tests).
Cleans up §14 (Cross-Reference: redbear-power as a Reference
Implementation) which had three duplicate headers from successive
edits. Collapses to a single canonical version and adds the
v1.8-specific bullet:
'Testable — bench module has 5 unit tests covering all stress
modes + toggles'
Net change: -25 lines, +2 lines.
Source code for v1.8 (bench.rs + main.rs + render.rs) and full
docs for §32 + v1.8 in improvement plan + CONSOLE-TO-KDE plan
landed in commit d6ac3d1377 (qtbase bundled). This commit
completes the doc-only cleanup that didn't fit in that bundle.
Closes the v1.6 forward-work item from §30.5: battery state changes
continuously on a laptop (capacity drops, power_now varies,
time_to_empty decreases), so the once-at-startup read was leaving
the Battery tab stale during long TUI sessions.
Updated app.rs::refresh():
- New 5-tick throttled read of BatteryInfo::read()
- Reuses existing refresh_counter (no new field)
- Cadence: 2.5 sec at default POLL_MS=500 (0.04% CPU cost)
- Independent of meminfo's 4-tick modulus (coprime moduli prevent
thundering-herd syscalls — only 5% of ticks see simultaneous
meminfo + battery reads)
- find_battery_dir() re-checks on each refresh, so a laptop
plugged in mid-session populates the Battery tab on the next
5th refresh tick without any external trigger
Verification:
- Mock battery at /tmp/fake-battery/BAT0/ with capacity=67:
redbear-power --once shows Capacity: 67%
- Changed capacity to 50, re-ran --once: shows Capacity: 50%
- Strace confirms 14 sysfs opens per read() call
Cadence rationale (modulus 5 chosen):
- Every tick (500ms): 0.2% CPU — too aggressive
- Every 5th tick (2.5s): 0.04% CPU — chosen
- Once at startup: 0% CPU — too stale
- Every 4th tick would also work but 5 chosen for clean
coprime separation from meminfo's 4-tick modulus
Build: same 3.8 MB stripped Redox binary (single if branch added).
SHA256 f76fe2b454e6a7e8db5a913c8c363de716f8cacc4ac4b4d2f1da22fc1c0f7570.
Docs: improvement plan §31, CONSOLE-TO-KDE §3.3.2 v1.7,
RATATUI-APP-PATTERNS §13.19 (coprime moduli pattern) + §14.
Implements the three gaps from §26:
- Phase A: new platform.rs (291 lines) with runtime probes for
MSR, ACPI PSS, /proc/stat, cpufreq sysfs, hwmon — emits one
eprintln! diagnostic per source at startup
- Phase B: msr.rs reads /dev/cpu/{cpu}/msr on Linux via lseek+pread;
acpi.rs read_load falls back to /proc/stat; acpi.rs read_acpi_pss
reads /sys/devices/system/cpu/cpu*/cpufreq/scaling_available_frequencies;
cpufreq.rs reads/writes /sys/.../scaling_governor. Removed the
hardcoded P0..P5 fallback table (violates zero-stub policy).
- Phase C: replaced misleading "MSR: not available (QEMU?)" with a
"Sources: MSR=ok PSS=no load=ok gov=ok hwmon=ok" header line
that shows per-source availability at a glance.
Verified on AMD Ryzen 9 7900X (24 threads, AMD-pstate driver):
- /dev/cpu/0/msr detected (probes ok; reads blocked by CAP_SYS_RAWIO
for non-root users — kernel-level permission, not a code issue)
- /proc/stat readable (load populated after second refresh tick)
- /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor readable
(governor shows "powersave")
- hwmon2 (k10temp) detected (not yet wired into per-CPU temp column —
requires per-driver hwmon→tempX_input mapping, deferred to v1.4)
- PSS=no (amd-pstate driver does not expose scaling_available_frequencies)
v1.3 source: 3501 LoC across 12 modules. Cross-compiled Redox binary
3.3 MB stripped, SHA256 cbc0a6d04e9d9252314dd71a1c411d4c488417e25f8d860970f718990864431a.
What is NOT yet wired (deferred to v1.4):
- Hwmon→per-CPU temp mapping (k10temp Tdie is package-level only)
- MSR reads without root (CAP_SYS_RAWIO required)
- zenpower / zen 5+ per-driver logic
- Add x11proto to redbear-full.toml package list
- libxau recipe updated with x11proto dependency and custom build script
- Fixes libxau build failure: 'Package xproto was not found'
Adds comprehensive analysis answering the user's "no per-core info"
question. Documents:
§26.1 Why every per-CPU column is empty on Linux (root cause)
- 6-column trace (Freq, PkgW, Temp, P-state, State, Flags) + Load%
- Maps Redox scheme paths to Linux equivalents (where they exist)
- Identifies that two paths already have Linux fallbacks (detect_cpus,
read_cpu_id) and four do not
§26.2 cpu-x patterns reviewed
- 6-row comparison table: missing-MSR / daemon / per-source UI /
refresh logic / CLI flags / temperature fallback
- Concludes: redbear-power's "n/a" placeholder is already better UX
than cpu-x's empty cells; daemon broker pattern is NOT applicable;
retry-cache and per-source logging ARE worth adopting
§26.3 Recommended Phase A/B/C (v1.3)
- Phase A: new platform.rs with /dev/cpu/*/msr + /proc/stat +
/sys/devices/system/cpu/cpu*/cpufreq/ fallbacks, ~80-120 LoC
- Phase B: replace hardcoded P0..P5 fallback (acpi.rs:101-108) with
real sysfs reads; generalize read_load to /proc/stat
- Phase C: header per-source availability badge
§26.4 AMD-specific concerns (separate from Linux fallback)
- msr.rs reader is Intel-only by design (file comment)
- AMD Zen uses 0xC0010063/0xC0010064 for P-states and k10temp for
temp, not Intel MSR 0x19c
- Recommended: vendor detection branch + Linux hwmon fallback
§26.5 Conclusion
- Screenshot is NOT a bug — TUI is working as designed
- Three substantive gaps: no Linux fallbacks, no per-source
startup logging, no header availability summary
- All three addressable without violating zero-stub policy
Source: cpu-x v4.7 at /tmp/cpu-x-src/ (cloned in earlier session).
Adds P4a (Ctrl-Insert, Shift-Delete, Ctrl-N, Shift-Tab) and P4b (filepos) rows. Updates the binding table to mark them as completed. Bumps total parity estimate from ~90% to ~93%.
- Create local/docs/PACKAGE-BUILD-QUIRKS.md: central reference for all
known cross-compilation build issues (DYNAMIC_INIT behavior, m4
CFLAGS/LDFLAGS ordering, ninja-build BUILD_TESTING, general patterns)
- Update UPSTREAM-SYNC-PROCEDURE.md: add m4 LDFLAGS ordering quirk
(must be set AFTER DYNAMIC_INIT), ninja-build BUILD_TESTING=OFF,
DYNAMIC_INIT overwrite behavior, source reversion root cause summary
- Update AGENTS.md: reference PACKAGE-BUILD-QUIRKS.md in WHERE TO LOOK
table, add DYNAMIC_INIT and cross-compilation test conventions
- Fix ninja-build recipe: add cmakeflags=['-DBUILD_TESTING=OFF']
(tests require host gtest which conflicts with Redox sysroot stdlib.h)
Top-level + local docs audit (2026-06-18). Findings and fixes:
1. AGENTS.md CONVENTIONS section — corrected 'my-' prefix contradiction.
The legacy 'my-*' prefix is deprecated and git-ignored. Use 'redbear-*'
for tracked first-class configs.
2. README.md quick-start — promoted 'local/scripts/build-redbear.sh' to
the recommended entry point. Bare 'scripts/run.sh --build' remains as
a secondary path. Added note about build-redbear.sh's policy gates
(.config checking, REDBEAR_ALLOW_PROTECTED_FETCH=1).
3. docs/06-BUILD-SYSTEM-SETUP.md — restructured Building section to put
'build-redbear.sh' first, then 'make all' as legacy/advanced with
clear notes on what gates it bypasses.
4. docs/05-KDE-PLASMA-ON-REDOX.md — replaced 'Stub-only package for
dependency resolution' wording for kirigami. Per project policy
(local/AGENTS.md STUB AND WORKAROUND POLICY — ZERO TOLERANCE),
stubs are forbidden. The kirigami build is blocked at the QML gate;
the recipe is honest and ships no fake/fallback package.
5. local/docs/BUILD-TOOLS-PORTING-PLAN.md — replaced all 'python312'
references with 'python314' (matches V8.3 P0 bump from earlier).
6. local/AGENTS.md — added 'LOCAL RECIPE SOURCE IMMUTABILITY' section
documenting the cb8b093564 guarantee. Any path matching
/local/recipes/ is unconditionally immutable; no env var or flag
can override. REDBEAR_ALLOW_LOCAL_UNFETCH=1 was removed as a kill
switch and is now dead code. distclean-nuclear is now a no-op for
local recipes.
- git rm 50 stale .bak patch backup files (surviving across 4+ sessions)
- Update WAYLAND-IMPLEMENTATION-PLAN.md: acknowledge kded6 offscreen
workaround is temporary until Qt6 Wayland null+8 crash is fixed.
kded6 is a headless D-Bus daemon — Wayland adds no functionality.
This addresses Oracle verification gaps: stale doc cleanup now committed,
doc/code contradiction resolved by acknowledging the temporary nature
of the kded6 offscreen workaround.
- WAYLAND-IMPLEMENTATION-PLAN.md v2.0: document architecture decision
that Wayland is the only supported display path. Remove all
framebuffer fallback workarounds (offscreen QPA, redox QPA shim).
- qwaylanddisplay.cpp: add fprintf instrumentation for crash diagnosis;
skip xkb_context_new on Redox to eliminate potential xkb crash vector.
- greeter-ui/main.cpp: remove QT_QPA_PLATFORM=redox workaround.
The greeter must use Wayland. Accept the crash until Qt6 is fixed.
- Ruled out: relibc calloc (zeroes correctly), libwayland proxy_create
(correct), compositor protocol (compliant). Root cause is in Qt6
generated Wayland wrappers passing NULL to wl_proxy_add_listener.
Phase S1 (Critical Correctness):
- sem_open/sem_close: global refcounting via BTreeMap + AtomicUsize
- sem_close: decrements refcount, munmaps only at zero
- sem_open: reuses existing mapping, O_EXCL returns EEXIST
- sem_unlink: marks entry for removal before shm_unlink
- va_list parsing: reads mode_t and value from stack after oflag
- All 11 sem_* functions verified in libc.so T
Phase S2-S4 (Designed, documented):
- eventfd() function, signalfd read path, EINTR handling
- name canonicalization, cancellation safety
- Full plan in local/docs/RELIBC-AGAINST-GLIBC-ASSESSMENT.md
Reference: glibc 2.41 cloned to local/reference/glibc/
Boot verified: greeter ready on VT 3 with refcounted semaphores
dma.rs: IommuDmaAllocator (145 lines)
- New struct wires existing IOMMU daemon (1003 lines) to existing DmaBuffer (261)
- allocate(): phys-contiguous alloc via scheme:memory, then MAP through IOMMU domain
- unmap(): sends UNMAP to IOMMU domain, releases IOVA
- Inlined IOMMU protocol constants — no new crate dependency
- encode_iommu_request/decode_iommu_response for scheme write/read cycle
Documentation updates:
- IMPLEMENTATION-MASTER-PLAN.md: K2 DMA/IOMMU section expanded from 3-line gap
list to full audit with component inventory, gap analysis, implementation plan
(D2.1-D2.5), Linux reference table. Added K2b thread/fork audit.
- CPU-DMA-IRQ-MSI-SCHEDULER-FIX-PLAN.md: Phase 1 (MSI) marked complete with
per-task status. Phase 2 (DMA) re-scoped from 'create' to 'wire' based on
audit. Phase 3 (scheduler) marked mostly done.
- IRQ-AND-LOWLEVEL-CONTROLLERS-ENHANCEMENT-PLAN.md: kernel MSI support noted
as materially strong with P8-msi.patch reference.
Audit findings:
- IOMMU daemon is solid: 1003-line lib.rs with full scheme protocol,
427-line amd_vi.rs, host-runnable tests. Needs wiring, not rewriting.
- DmaBuffer exists but is IOMMU-unaware — IommuDmaAllocator bridges this.
- relibc rlct_clone is correct for threads (shares addr space implicitly).
'3 IPC hops' claim is microkernel-architectural, not a real perf issue.
- No stale docs to archive at this time.