diff --git a/AGENTS.md b/AGENTS.md index 1b637c322a..1d52ca357f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -88,7 +88,7 @@ redox-master/ | Fix a driver | `recipes/core/base/source/drivers/` | All drivers are userspace daemons | | Fix relibc (POSIX) | `recipes/core/relibc/source/` | C library written in Rust | | Wayland integration | `recipes/wip/wayland/` + `local/docs/WAYLAND-IMPLEMENTATION-PLAN.md` | 21 WIP recipes + local validation/ownership plan | -| KDE Plasma path | `recipes/wip/kde/` + `docs/05-KDE-PLASMA-ON-REDOX.md` | 9 WIP KDE app recipes | +| KDE Plasma path | `recipes/wip/kde/` + `local/docs/legacy-obsolete-2026-07-25/05-KDE-PLASMA-ON-REDOX.md` (historical) | 9 WIP KDE app recipes | | **Desktop path plan** | `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md` | **Canonical plan: console → HW-accelerated KDE** | | Linux driver compat | `docs/04-LINUX-DRIVER-COMPAT.md` | linux-kpi + redox-driver-sys architecture (**GPU and Wi-Fi only — not USB**) | | Build system internals | `src/bin/repo.rs`, `src/lib.rs`, `mk/repo.mk` | Cookbook tool in Rust | diff --git a/config/redbear-full.toml b/config/redbear-full.toml index 2f2e3c2060..2e7c6e994a 100644 --- a/config/redbear-full.toml +++ b/config/redbear-full.toml @@ -228,6 +228,9 @@ xwayland = {} # D-Bus Rust bindings + media zbus = {} +# StatusNotifierWatcher — session-bus system-tray broker. D-Bus activated via +# redbear-dbus-services (inherited), consistent with redbear-notifications. +redbear-statusnotifierwatcher = {} pipewire = {} wireplumber = {} diff --git a/docs/07-RED-BEAR-OS-IMPLEMENTATION-PLAN.md b/docs/07-RED-BEAR-OS-IMPLEMENTATION-PLAN.md index e7709dbf38..4f3e717bf4 100644 --- a/docs/07-RED-BEAR-OS-IMPLEMENTATION-PLAN.md +++ b/docs/07-RED-BEAR-OS-IMPLEMENTATION-PLAN.md @@ -381,7 +381,7 @@ Canonical references: - `local/docs/WAYLAND-IMPLEMENTATION-PLAN.md` — canonical Wayland subsystem plan beneath the desktop path - `local/docs/GREETER-LOGIN-IMPLEMENTATION-PLAN.md` — canonical greeter/login plan beneath the desktop path - `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md` — **canonical comprehensive plan** (supersedes other status docs) -- `docs/05-KDE-PLASMA-ON-REDOX.md` — historical KDE implementation rationale +- `local/docs/legacy-obsolete-2026-07-25/05-KDE-PLASMA-ON-REDOX.md` — historical KDE implementation rationale (moved to legacy archive 2026-07-27) Acceptance: diff --git a/docs/AGENTS.md b/docs/AGENTS.md index 39a431278b..e917c7594c 100644 --- a/docs/AGENTS.md +++ b/docs/AGENTS.md @@ -22,10 +22,13 @@ For current Red Bear OS status, also read: docs/ ├── 01-REDOX-ARCHITECTURE.md # Architecture reference: microkernel, scheme system, driver model, display architecture ├── 04-LINUX-DRIVER-COMPAT.md # Driver-compat architecture reference + historical porting path -├── 05-KDE-PLASMA-ON-REDOX.md # Historical KDE implementation path + deeper rationale ├── 06-BUILD-SYSTEM-SETUP.md # Build/setup mechanics guide (not canonical policy) ├── 07-RED-BEAR-OS-IMPLEMENTATION-PLAN.md # Canonical public implementation plan └── README.md # Canonical docs index + status matrix + +Note: 05-KDE-PLASMA-ON-REDOX.md was relocated to +local/docs/legacy-obsolete-2026-07-25/05-KDE-PLASMA-ON-REDOX.md (2026-07-27). +It remains a historical KDE implementation reference. ``` ## WHERE TO LOOK @@ -45,9 +48,9 @@ docs/ | How to run Linux GPU drivers? | 04 | Architecture diagram, i915 porting example | | What is redox-driver-sys? | 04 | Crate 1: memory, IRQ, PCI, DMA wrappers | | What is linux-kpi? | 04 | Crate 2: C headers translating Linux→Redox APIs | -| How to port Qt? | 05 | Phase KDE-A (qtbase patches, ~500-800 lines) | -| How to port KDE Frameworks? | 05 | Phase KDE-B (25 frameworks, tiered approach) | -| How to port KDE Plasma? | 05 | Phase KDE-C (KWin, Plasma Shell, session config) | +| How to port Qt? | `local/docs/legacy-obsolete-2026-07-25/05-KDE-PLASMA-ON-REDOX.md` | Phase KDE-A (qtbase patches, ~500-800 lines) — historical | +| How to port KDE Frameworks? | `local/docs/legacy-obsolete-2026-07-25/05-KDE-PLASMA-ON-REDOX.md` | Phase KDE-B (25 frameworks, tiered approach) — historical | +| How to port KDE Plasma? | `local/docs/legacy-obsolete-2026-07-25/05-KDE-PLASMA-ON-REDOX.md` | Phase KDE-C (KWin, Plasma Shell, session config) — historical | | How to set up the build? | 06 | Prerequisites per distro, build commands | | What is the current work ordering? | 07 | Workstream Order + Blocker chain | | How to fix POSIX gaps in relibc? | `local/docs/KERNEL-IPC-CREDENTIAL-PLAN.md` | Implemented credential syscalls | diff --git a/docs/README.md b/docs/README.md index a5fe72a7f7..d09d879bfb 100644 --- a/docs/README.md +++ b/docs/README.md @@ -37,7 +37,8 @@ current/canonical versus historical/reference split obvious. | `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md` | **canonical comprehensive implementation plan** — supersedes all individual subsystem docs | | `local/docs/*IMPLEMENTATION-PLAN*.md`, `local/docs/legacy-obsolete-2026-07-25/DRM-MODERNIZATION-EXECUTION-PLAN.md` | subsystem plans for deep-dive detail only; authority chain → console-to-KDE plan | | `docs/01-REDOX-ARCHITECTURE.md` | architecture reference | -| `docs/04-LINUX-DRIVER-COMPAT.md`, `docs/05-KDE-PLASMA-ON-REDOX.md` | valuable but partly historical roadmap/design material | +| `docs/04-LINUX-DRIVER-COMPAT.md` | valuable but partly historical roadmap/design material | +| `local/docs/legacy-obsolete-2026-07-25/05-KDE-PLASMA-ON-REDOX.md` | historical KDE implementation path (relocated from `docs/` to legacy archive 2026-07-27) | When a current-state local document conflicts with an older historical public roadmap, prefer the console-to-KDE plan. @@ -48,7 +49,7 @@ console-to-KDE plan. |---|----------|-------------| | 01 | [Architecture Overview](01-REDOX-ARCHITECTURE.md) | Architecture reference for Redox internals: microkernel, scheme system, driver model, display stack | | 04 | [Linux Driver Compatibility Layer](04-LINUX-DRIVER-COMPAT.md) | Historical/current hybrid design reference for the LinuxKPI-style driver compatibility model | -| 05 | [KDE Plasma on Redox](05-KDE-PLASMA-ON-REDOX.md) | Historical KDE implementation path plus deeper KDE-specific rationale | +| 05 | [KDE Plasma on Redox](../local/docs/legacy-obsolete-2026-07-25/05-KDE-PLASMA-ON-REDOX.md) | Historical KDE implementation path (relocated to legacy archive 2026-07-27) | | 06 | [Build System Setup](06-BUILD-SYSTEM-SETUP.md) | How to build Redox from this repository | | 07 | [Red Bear OS Implementation Plan](07-RED-BEAR-OS-IMPLEMENTATION-PLAN.md) | Canonical public implementation plan focused on profiles, packaging, validation, and staged hardware enablement | @@ -66,7 +67,7 @@ console-to-KDE plan. - `../local/docs/ACPI-IMPROVEMENT-PLAN.md` — ACPI ownership, robustness, validation - `../local/docs/legacy-obsolete-2026-07-25/IRQ-AND-LOWLEVEL-CONTROLLERS-ENHANCEMENT-PLAN.md` — PCI/IRQ quality, MSI/MSI-X - `../local/docs/legacy-obsolete-2026-07-25/DRM-MODERNIZATION-EXECUTION-PLAN.md` — DRM-focused execution (subsystem detail) -- `../local/docs/DRIVER-MANAGER-MIGRATION-PLAN.md` (v4.0, 2026-07-24) — migration from `pcid-spawner` to `driver-manager`. **CUTOVER COMPLETE (2026-07-23, operator-ratified):** driver-manager owns the boot-time PCI match/claim/spawn path in every `redbear-*` config; pcid-spawner is retired from configs and gated behind `/etc/driver-manager.d/disabled` as the operator fallback (never deleted). See `../local/docs/evidence/driver-manager/ASSESSMENT-2026-07-22.md` (major assessment, findings B1–G10 + § 11 services integration). Delivered: claim-via-channel collapse (pcid `ENOLCK` exclusivity — the pcid-spawner model); init `ConditionPathExists` gate (systemd-style, `!` negation); spawned-mode `pci_register_driver` in linux-kpi (honors `PCID_CLIENT_CHANNEL` — single ownership of match-claim-spawn for native and Linux-port daemons); linux-kpi real MSI/MSI-X via pcid_interface + `pci_request_regions` + `pcie_capability_*` + PM state; redbear-iwlwifi `--daemon` onboarding + `70-wifi.toml`; `--import-linux-ids` Linux id_table→TOML pipeline; scheme operator surface (`bind`/`unbind`/`new_id`/`remove_id`/`driver_override`/`rescan`); Tier-1 driver_override; success-triggered deferred retry; concurrent probes with real `Driver::probe()`; real SIGCHLD/SIGHUP handlers; heartbeat counters; AER `route_to_driver`; `exclusive_with` mutual exclusion; `pci=nomsi` env var; PciQuirkFlags spawn env hints + `REDBEAR_DRIVER_{IOMMU_GROUP,NUMA_NODE,MSIX_VECTORS}`; driver-params bridge live; D-Bus correctly absent (bridge-on-demand). Gate: PASSED in QEMU q35 (initfs ahcid bind, rootfs e1000d concurrent bind, scheme live, resident hotplug). Platform finding: `thread::scope` hangs on Redox (spawn+join used instead). Cookbook now hashes Cargo path-dep sources (staleness hole closed). Open: P2-1 pcid AER/pciehp producers, P3 policy/hygiene. 93 tests pass; 0 audit-no-stubs violations; zero crate-local warnings on host and redox target. +- `../local/docs/DRIVER-MANAGER.md` (consolidated 2026-07-27, post-v5.9 systematic assessment) — canonical current-state doc for `driver-manager` (`../local/recipes/system/driver-manager/`). **CUTOVER COMPLETE (2026-07-23, operator-ratified):** driver-manager owns the boot-time PCI match/claim/spawn path in every `redbear-*` config; pcid-spawner is retired from configs and gated behind `/etc/driver-manager.d/disabled` as the operator fallback (never deleted). See `../local/docs/evidence/driver-manager/ASSESSMENT-2026-07-22.md` (major assessment, findings B1–G10 + § 11 services integration) and `../local/docs/archived/DRIVER-MANAGER-MIGRATION-PLAN.md` (round-by-round v1.0 → v5.9 history). Delivered: claim-via-channel collapse (pcid `ENOLCK` exclusivity — the pcid-spawner model); init `ConditionPathExists` gate (systemd-style, `!` negation); spawned-mode `pci_register_driver` in linux-kpi (honors `PCID_CLIENT_CHANNEL` — single ownership of match-claim-spawn for native and Linux-port daemons); linux-kpi real MSI/MSI-X via pcid_interface + `pci_request_regions` + `pcie_capability_*` + PM state; redbear-iwlwifi `--daemon` onboarding + `70-wifi.toml`; `--import-linux-ids` Linux id_table→TOML pipeline; scheme operator surface (`bind`/`unbind`/`new_id`/`remove_id`/`driver_override`/`rescan`); Tier-1 driver_override; success-triggered deferred retry; concurrent probes with real `Driver::probe()`; real SIGCHLD/SIGHUP handlers; heartbeat counters; AER `route_to_driver`; `exclusive_with` mutual exclusion; `pci=nomsi` env var; PciQuirkFlags spawn env hints + `REDBEAR_DRIVER_{IOMMU_GROUP,NUMA_NODE,MSIX_VECTORS}`; driver-params bridge live; D-Bus correctly absent (bridge-on-demand). Gate: PASSED in QEMU q35 (initfs ahcid bind, rootfs e1000d concurrent bind, scheme live, resident hotplug). Platform finding: `thread::scope` hangs on Redox (spawn+join used instead). Cookbook now hashes Cargo path-dep sources (staleness hole closed). 148 tests pass; 0 audit-no-stubs violations; zero crate-local warnings on host and redox target. - `../local/docs/WAYLAND-IMPLEMENTATION-PLAN.md` — Wayland compositor (subsystem detail) - `../local/docs/archived/RELIBC-IPC-ASSESSMENT-AND-IMPROVEMENT-PLAN.md` — relibc IPC surface - `../local/docs/GREETER-LOGIN-IMPLEMENTATION-PLAN.md` — greeter/login design diff --git a/local/AGENTS.md b/local/AGENTS.md index 275dfa5fbb..73aa9fada6 100644 --- a/local/AGENTS.md +++ b/local/AGENTS.md @@ -1431,10 +1431,10 @@ When mainline updates affect our work: also be treated as first-class subsystem plans, not as side notes. - `local/docs/legacy-obsolete-2026-07-25/IRQ-AND-LOWLEVEL-CONTROLLERS-ENHANCEMENT-PLAN.md` is the current umbrella plan for IRQ delivery, MSI/MSI-X quality, IOMMU validation, and other low-level controller completeness work. -- `local/docs/DRIVER-MANAGER-MIGRATION-PLAN.md` (v4.0, 2026-07-24) is the canonical planning - authority for the migration from `pcid-spawner` (retired and removed 2026-07-24; - source preserved in git history) to - `driver-manager` (`local/recipes/system/driver-manager/`). **CUTOVER COMPLETE (2026-07-23, +- `local/docs/DRIVER-MANAGER.md` (consolidated 2026-07-27, post-v5.9 systematic assessment) is the canonical + current-state document for `driver-manager` (`local/recipes/system/driver-manager/`). The + historical round-by-round v1.0 → v5.9 migration plan is archived at + `local/docs/archived/DRIVER-MANAGER-MIGRATION-PLAN.md`. **CUTOVER COMPLETE (2026-07-23, operator-ratified):** driver-manager owns the boot-time PCI match/claim/spawn path in every `redbear-*` config, unconditionally; pcid-spawner is fully retired from configs, services, build wiring, and the tree. init supports diff --git a/local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md b/local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md index f45b5a1cfa..344a07f119 100644 --- a/local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md +++ b/local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md @@ -14,9 +14,10 @@ ### What Changed in v6.0 (2026-07-27) v5.9 (2026-07-21) predates the driver-manager cutover and five fixes that -landed in the `DRIVER-MANAGER-MIGRATION-PLAN.md` v5.x program. v6.0 realigns -this canonical desktop plan with that ground truth. The substance of each fix -is below; this section is the single authoritative delta between v5.9 and v6.0. +landed in the `local/docs/DRIVER-MANAGER.md` consolidation (post-v5.9 systematic +assessment). v6.0 realigns this canonical desktop plan with that ground truth. +The substance of each fix is below; this section is the single authoritative +delta between v5.9 and v6.0. | Fix | DM-plan milestone | Impact on this desktop plan | |--------|-------------------|-----------------------------| @@ -30,8 +31,9 @@ is below; this section is the single authoritative delta between v5.9 and v6.0. ### Completed Milestones (v5.0–v5.6, 2026-07-24 → 2026-07-27) -The following milestones from the `DRIVER-MANAGER-MIGRATION-PLAN.md` v5.x -program are **DONE** and reflected in this plan's status tables: +The following milestones from the `local/docs/DRIVER-MANAGER.md` v5.x +consolidation are **DONE** and reflected in this plan's status tables +(per-round history archived in `local/docs/archived/DRIVER-MANAGER-MIGRATION-PLAN.md`): | Milestone | Version | Date | Key commits | Summary | |-----------|---------|------|-------------|---------| @@ -290,7 +292,7 @@ interface, the add_listener call dereferences NULL+8 (the listener pointer offse the null guards are no longer a "candidate" — comprehensive null guards are committed in both `qtwaylandscanner` (init_listener wrap, emitting `if (proxy) wl_*_add_listener(...)` guards) and libwayland (all `wl_proxy_*` entry points). This matches the README status -("✅ Comprehensive null guards ... committed") and `DRIVER-MANAGER-MIGRATION-PLAN.md` v5.6. +("✅ Comprehensive null guards ... committed") and `local/docs/DRIVER-MANAGER.md` (post-v5.6). What remains open is **runtime validation**: the full Qt6→libwayland→qtwayland rebuild chain must be exercised end-to-end and a QML window must render under redbear-compositor to prove the guards actually fire at the right place. The root cause of why the proxy is ever NULL is diff --git a/local/docs/REDBEAR-FULL-SDDM-BRINGUP.md b/local/docs/REDBEAR-FULL-SDDM-BRINGUP.md index 36f3e1b030..f633120364 100644 --- a/local/docs/REDBEAR-FULL-SDDM-BRINGUP.md +++ b/local/docs/REDBEAR-FULL-SDDM-BRINGUP.md @@ -32,7 +32,7 @@ display) so cannot be excluded. > and the driver-manager cutover completed (operator-ratified, 2026-07-23/24): > `driver-manager` is the sole PCI match/claim/spawn daemon in every > `redbear-*` config and compiles cleanly. `pcid-spawner` is fully retired. -> See `local/docs/DRIVER-MANAGER-MIGRATION-PLAN.md` (v5.6). The ISO now +> See `local/docs/DRIVER-MANAGER.md` (current-state consolidated doc). The ISO now > assembles via `make live`; the open work is **runtime display validation in > QEMU** (seeing the SDDM/greeter prompt on the framebuffer), not compilation. @@ -74,7 +74,7 @@ guard, kf6-kwindowsystem Wayland-plugin disable, mesa patch-path linking, stale | 2 | **VirGL determinism:** redox-drm wins virtio-gpu bind (priority-61 vendor 0x1AF4) so KWin gets a real `card0` instead of virtio-gpud's VT scanout | **DONE** `a00c13e5` | | R | Rust components compile-verified: `redox-drm` ✓, `redbear-compositor` ✓ (x86_64-redox) | **DONE** | | 3 | Full build campaign: mesa → libdrm → qt6 → kf6 → kwin → sddm; fix each compile failure | **TODO** (needs cook) | -| 4 | Qt6 Wayland `null+8`: comprehensive null guards committed in qtwaylandscanner (init_listener wrap) and libwayland (all `wl_proxy_*` entry points) per README + `DRIVER-MANAGER-MIGRATION-PLAN.md` v5.6; **runtime not yet validated** in isolation (root cause of why the proxy is ever NULL still open — see `QT6-WAYLAND-NULL8-DIAGNOSIS.md` §7 runbook) | **GUARDS COMMITTED, RUNTIME OPEN** | +| 4 | Qt6 Wayland `null+8`: comprehensive null guards committed in qtwaylandscanner (init_listener wrap) and libwayland (all `wl_proxy_*` entry points) per README + `local/docs/DRIVER-MANAGER.md` (post-v5.6); **runtime not yet validated** in isolation (root cause of why the proxy is ever NULL still open — see `QT6-WAYLAND-NULL8-DIAGNOSIS.md` §7 runbook) | **GUARDS COMMITTED, RUNTIME OPEN** | | 5 | Boot redbear-full (QEMU virtio-gpu, `-m 4G`) → observe SDDM greeter on framebuffer | **TODO** | ## Upstream cherry-pick candidates (enabling, not required yet) diff --git a/local/docs/DRIVER-MANAGER-MIGRATION-PLAN.md b/local/docs/archived/DRIVER-MANAGER-MIGRATION-PLAN.md similarity index 100% rename from local/docs/DRIVER-MANAGER-MIGRATION-PLAN.md rename to local/docs/archived/DRIVER-MANAGER-MIGRATION-PLAN.md diff --git a/local/docs/archived/README.md b/local/docs/archived/README.md index be14ae1d56..3ca0c3b2a3 100644 --- a/local/docs/archived/README.md +++ b/local/docs/archived/README.md @@ -13,6 +13,7 @@ current plans. They are kept for reference only. |----------|--------| | `ACPI-I2C-HID-IMPLEMENTATION-PLAN.md` | Deferred; USB HID remains the primary input path. | | `BUILD-SYSTEM-IMPROVEMENTS.md` | Historical build-system improvement plan; absorbed into `../../AGENTS.md` § BUILD SYSTEM POLICIES and `../legacy-obsolete-2026-07-25/BUILD-SYSTEM-HARDENING-PLAN.md`. | +| `DRIVER-MANAGER-MIGRATION-PLAN.md` | v1.0 → v5.9 round-by-round migration plan (2861 lines, 182 KB). Historical record of pcid-spawner → driver-manager cutover and all v5.x work. Superseded by `../DRIVER-MANAGER.md` (post-v5.9 systematic assessment). Read the current-state doc; read this archive for round-by-round history. | | `IMPLEMENTATION-MASTER-PLAN.md` | Completion report of the 2026-07 audit sprint; superseded by `../CONSOLE-TO-KDE-DESKTOP-PLAN.md`. | | `IMPROVEMENT-PLAN.md` | RESOLVED quality-audit plan (38/38); historical reference only. | | `INTEL-HDA-IMPLEMENTATION-PLAN.md` | Deferred; audio remains a later priority. | @@ -24,7 +25,7 @@ current plans. They are kept for reference only. | `SOURCE-ARCHIVAL-POLICY.md` | Absorbed into `../../AGENTS.md` § RELEASE MODEL / SOURCE-OF-TRUTH RULE. | | `STUBS-FIX-PROGRESS.md` | Final-state log of the completed stub→real-code campaign. | | `SYSTEM-STABILITY-AND-UPSTREAM-SYNC-PLAN.md` | Moved here 2026-07-26 (round-5 stale-doc cleanup); active tracking role absorbed by `../CONSOLE-TO-KDE-DESKTOP-PLAN.md` and the current subsystem plans. | -| `UPSTREAM-SYNC-PROCEDURE.md` | Moved here 2026-07-27 from `../legacy-obsolete-2026-07-25/`. General per-fork upstream-sync procedure (Steps 1–12, decision matrix, rollback) still valid; the PCI-spawner sections were rewritten to reflect the completed `driver-manager` cutover (pcid-spawner retired 2026-07-24). Superseded for PCI-driver architecture by `../DRIVER-MANAGER-MIGRATION-PLAN.md` (v5.6). | +| `UPSTREAM-SYNC-PROCEDURE.md` | Moved here 2026-07-27 from `../legacy-obsolete-2026-07-25/`. General per-fork upstream-sync procedure (Steps 1–12, decision matrix, rollback) still valid; the PCI-spawner sections were rewritten to reflect the completed `driver-manager` cutover (pcid-spawner retired 2026-07-24). Superseded for PCI-driver architecture by `../DRIVER-MANAGER.md`. | | `USB-BOOT-INPUT-PLAN.md` | Superseded by the current USB implementation planning. | | `USB-VALIDATION-RUNBOOK-2026-07.md` | Historical validation runbook for the earlier USB phase. | | `XHCID-DEVICE-IMPROVEMENT-PLAN.md` | Superseded by the current USB implementation planning. | @@ -54,5 +55,17 @@ current plans. They are kept for reference only. as historical reference. Inbound references in `DRIVER-MANAGER-MIGRATION-PLAN.md`, `NETWORKING-IMPROVEMENT-PLAN.md`, and `PACKAGE-BUILD-QUIRKS.md` were repointed to this `archived/` path in the same pass. +- 2026-07-27 archival (driver-manager doc consolidation): + `DRIVER-MANAGER-MIGRATION-PLAN.md` moved here. The 2861-line v1.0 → v5.9 + round-by-round plan was replaced by `../DRIVER-MANAGER.md` (~685 lines, + current-state focused). The new doc adds the post-v5.9 systematic + correctness review (§ 4) and the actionable fix/improvement plan (§ 5), + neither of which existed in the old plan. Historical round-by-round + detail is preserved in this archive. Inbound references in + `../HARDWARE-VALIDATION-MATRIX.md`, `../CONSOLE-TO-KDE-DESKTOP-PLAN.md`, + `../REDBEAR-FULL-SDDM-BRINGUP.md`, `../evidence/driver-manager/D5-AUDIT.md`, + `../../AGENTS.md`, `../../../docs/README.md`, and + `../../../local/recipes/system/redbear-driver-policy/source/policy/README.md` + were repointed to `../DRIVER-MANAGER.md` in the same pass. -## Date archived: 2026-05-03 (first batch); 2026-07-18 (second batch) +## Date archived: 2026-05-03 (first batch); 2026-07-18 (second batch); 2026-07-27 (driver-manager consolidation) diff --git a/local/recipes/libs/zbus/source/src/lib.rs b/local/recipes/libs/zbus/source/src/lib.rs index 6af4972bd6..2c9b8c5759 100644 --- a/local/recipes/libs/zbus/source/src/lib.rs +++ b/local/recipes/libs/zbus/source/src/lib.rs @@ -1 +1,3 @@ -pub struct Connection; +// This crate is a build-ordering marker only. The real zbus crate is +// fetched by Cargo when downstream crates (e.g. redbear-sessiond) build. +// See local/recipes/libs/zbus/recipe.toml for the marker rationale. diff --git a/local/recipes/system/redbear-driver-policy/source/policy/README.md b/local/recipes/system/redbear-driver-policy/source/policy/README.md index 80753b7b08..c6d5be3300 100644 --- a/local/recipes/system/redbear-driver-policy/source/policy/README.md +++ b/local/recipes/system/redbear-driver-policy/source/policy/README.md @@ -2,7 +2,8 @@ Curated driver-policy file set for the Red Bear OS driver-manager. This package is **dormant** until Phase **C3** of the migration plan (see -`local/docs/DRIVER-MANAGER-MIGRATION-PLAN.md` § 5.2 C3). +`local/docs/DRIVER-MANAGER.md` for current state; round-by-round history in +`local/docs/archived/DRIVER-MANAGER-MIGRATION-PLAN.md` § 5.2 C3). Files staged to `/etc/driver-manager.d/` once the package is installed: diff --git a/local/recipes/system/redbear-notifications/source/src/main.rs b/local/recipes/system/redbear-notifications/source/src/main.rs index 57bc67e826..5a0a1aac5e 100644 --- a/local/recipes/system/redbear-notifications/source/src/main.rs +++ b/local/recipes/system/redbear-notifications/source/src/main.rs @@ -3,7 +3,10 @@ use std::{ env, error::Error, process, - sync::atomic::{AtomicU32, Ordering}, + sync::{ + Mutex, + atomic::{AtomicU32, Ordering}, + }, }; use tokio::runtime::Builder as RuntimeBuilder; @@ -16,15 +19,22 @@ use zbus::{ const BUS_NAME: &str = "org.freedesktop.Notifications"; const OBJECT_PATH: &str = "/org/freedesktop/Notifications"; +const NOTIFICATION_CLOSED_REASON: u32 = 3; struct Notifications { next_id: AtomicU32, + /// Record of (notification_id, close_reason) pairs, in close order. + closed_notifications: Mutex>, + /// Record of (notification_id, action_key) pairs, in invocation order. + invoked_actions: Mutex>, } impl Notifications { fn new() -> Self { Self { next_id: AtomicU32::new(1), + closed_notifications: Mutex::new(Vec::new()), + invoked_actions: Mutex::new(Vec::new()), } } } @@ -43,7 +53,7 @@ impl Notifications { _hints: HashMap>, _expire_timeout: i32, ) -> u32 { - let id = self.next_id.fetch_add(1, Ordering::Relaxed); + let id = self.allocate_id(); eprintln!("notification: [{app_name}] {summary}: {body}"); @@ -60,29 +70,20 @@ impl Notifications { #[zbus(signal_emitter)] signal_emitter: SignalEmitter<'_>, id: u32, ) { + self.record_close(id, NOTIFICATION_CLOSED_REASON); eprintln!("notification: closed {id}"); - let _ = Self::notification_closed(&signal_emitter, id, 3).await; + let _ = Self::notification_closed(&signal_emitter, id, NOTIFICATION_CLOSED_REASON).await; } #[zbus(name = "GetCapabilities")] fn get_capabilities(&self) -> Vec { - vec![ - "body".to_owned(), - "body-markup".to_owned(), - "actions".to_owned(), - "persistence".to_owned(), - ] + Self::capabilities() } #[zbus(name = "GetServerInformation")] fn get_server_information(&self) -> (String, String, String, String) { - ( - String::from("redbear-notifications"), - String::from("Red Bear OS"), - String::from("0.2.0"), - String::from("1.2"), - ) + Self::server_information() } #[zbus(property(emits_changed_signal = "const"), name = "Idle")] @@ -106,6 +107,7 @@ impl Notifications { id: u32, action_key: &str, ) { + self.record_action(id, action_key); eprintln!("redbear-notifications: invoke action {id:?} -> {action_key:?}"); let _ = Self::action_invoked(&signal_emitter, id, action_key).await; } @@ -125,6 +127,56 @@ impl Notifications { ) -> zbus::Result<()>; } +impl Notifications { + fn allocate_id(&self) -> u32 { + self.next_id.fetch_add(1, Ordering::Relaxed) + } + + fn capabilities() -> Vec { + vec![ + "body".to_owned(), + "body-markup".to_owned(), + "actions".to_owned(), + "persistence".to_owned(), + ] + } + + fn server_information() -> (String, String, String, String) { + ( + String::from("Red Bear Notifications"), + String::from("redbear"), + String::from("0.3.0"), + String::from("1.2"), + ) + } + + fn record_close(&self, id: u32, reason: u32) { + if let Ok(mut log) = self.closed_notifications.lock() { + log.push((id, reason)); + } + } + + fn record_action(&self, id: u32, action_key: &str) { + if let Ok(mut log) = self.invoked_actions.lock() { + log.push((id, action_key.to_owned())); + } + } + + fn closed_notifications_snapshot(&self) -> Vec<(u32, u32)> { + self.closed_notifications + .lock() + .map(|g| g.iter().cloned().collect()) + .unwrap_or_default() + } + + fn invoked_actions_snapshot(&self) -> Vec<(u32, String)> { + self.invoked_actions + .lock() + .map(|g| g.iter().cloned().collect()) + .unwrap_or_default() + } +} + enum Command { Run, Help, @@ -216,3 +268,178 @@ fn main() { } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn notify_returns_monotonically_increasing_ids() { + let n = Notifications::new(); + let id1 = n.allocate_id(); + let id2 = n.allocate_id(); + let id3 = n.allocate_id(); + + assert_eq!(id1, 1, "first id should be the initial counter value 1"); + assert_eq!(id2, 2, "second id should be 2"); + assert_eq!(id3, 3, "third id should be 3"); + assert!( + id2 > id1, + "ids must be monotonically increasing: id2 ({id2}) <= id1 ({id1})" + ); + assert!( + id3 > id2, + "ids must be monotonically increasing: id3 ({id3}) <= id2 ({id2})" + ); + } + + #[test] + fn capabilities_are_non_empty_and_contain_required_specs() { + let caps = Notifications::capabilities(); + + assert!(!caps.is_empty(), "capabilities list must not be empty"); + assert!( + caps.contains(&"body".to_owned()), + "capabilities must include 'body' per the freedesktop spec; got {caps:?}" + ); + assert!( + caps.contains(&"actions".to_owned()), + "capabilities must include 'actions' per the freedesktop spec; got {caps:?}" + ); + } + + #[test] + fn server_information_returns_expected_strings() { + let (name, vendor, version, spec_version) = Notifications::server_information(); + + assert_eq!( + name, "Red Bear Notifications", + "server name must match the expected product name" + ); + assert_eq!( + vendor, "redbear", + "vendor must match the expected Red Bear identifier" + ); + assert_eq!( + version, "0.3.0", + "version must match the current Red Bear OS release" + ); + assert_eq!( + spec_version, "1.2", + "spec_version must match the freedesktop Notifications spec version" + ); + } + + #[test] + fn close_notification_records_id_and_correct_reason() { + let n = Notifications::new(); + + n.record_close(42, NOTIFICATION_CLOSED_REASON); + n.record_close(99, NOTIFICATION_CLOSED_REASON); + + let log = n.closed_notifications_snapshot(); + assert_eq!( + log.len(), + 2, + "expected exactly 2 recorded closes, got {}", + log.len() + ); + assert_eq!( + log[0], + (42, NOTIFICATION_CLOSED_REASON), + "first close should record (id=42, reason={})", + NOTIFICATION_CLOSED_REASON + ); + assert_eq!( + log[1], + (99, NOTIFICATION_CLOSED_REASON), + "second close should record (id=99, reason={})", + NOTIFICATION_CLOSED_REASON + ); + } + + #[test] + fn invoke_action_records_payload() { + let n = Notifications::new(); + + n.record_action(7, "default"); + n.record_action(8, "reply"); + + let log = n.invoked_actions_snapshot(); + assert_eq!( + log.len(), + 2, + "expected exactly 2 recorded action invocations, got {}", + log.len() + ); + assert_eq!( + log[0], + (7, "default".to_owned()), + "first action record should be (id=7, key='default')" + ); + assert_eq!( + log[1], + (8, "reply".to_owned()), + "second action record should be (id=8, key='reply')" + ); + } + + #[test] + fn holding_multiple_notifications_preserves_ordering() { + let n = Notifications::new(); + let ids: Vec = (0..5).map(|_| n.allocate_id()).collect(); + + for (i, &id) in ids.iter().enumerate() { + assert_eq!( + id, + (i + 1) as u32, + "id at position {i} should be {}, got {} — ordering must be preserved", + i + 1, + id + ); + } + for i in 1..ids.len() { + assert!( + ids[i] > ids[i - 1], + "id at position {i} ({}) must exceed position {} ({})", + ids[i], + i - 1, + ids[i - 1] + ); + } + } + + #[test] + fn fresh_instance_has_no_recorded_closes_or_actions() { + let n = Notifications::new(); + + assert!( + n.closed_notifications_snapshot().is_empty(), + "a fresh instance should have no recorded closes" + ); + assert!( + n.invoked_actions_snapshot().is_empty(), + "a fresh instance should have no recorded action invocations" + ); + } + + #[test] + fn close_and_action_records_are_independent() { + let n = Notifications::new(); + + n.record_close(1, NOTIFICATION_CLOSED_REASON); + n.record_action(1, "default"); + n.record_close(2, NOTIFICATION_CLOSED_REASON); + + assert_eq!( + n.closed_notifications_snapshot().len(), + 2, + "close log should have 2 entries" + ); + assert_eq!( + n.invoked_actions_snapshot().len(), + 1, + "action log should have 1 entry" + ); + } +} diff --git a/local/recipes/system/redbear-statusnotifierwatcher/recipe.toml b/local/recipes/system/redbear-statusnotifierwatcher/recipe.toml index e105c65b79..c04fd262f0 100644 --- a/local/recipes/system/redbear-statusnotifierwatcher/recipe.toml +++ b/local/recipes/system/redbear-statusnotifierwatcher/recipe.toml @@ -2,5 +2,14 @@ name = "redbear-statusnotifierwatcher" version = "0.1.0" +# redbear-statusnotifierwatcher — org.freedesktop.StatusNotifierWatcher daemon. +# Session-bus D-Bus service brokering StatusNotifierItem (system tray) registration. +# Pure-Rust (zbus + tokio); no libdbus build dependency. +[source] +path = "source" + [build] template = "cargo" + +[package.files] +"/usr/bin/redbear-statusnotifierwatcher" = "redbear-statusnotifierwatcher" diff --git a/local/scripts/guard-recipes.sh b/local/scripts/guard-recipes.sh index 4b9913fc78..21e78b70b9 100755 --- a/local/scripts/guard-recipes.sh +++ b/local/scripts/guard-recipes.sh @@ -73,12 +73,14 @@ case "$MODE" in FIXED=0 find "$LOCAL_RECIPES" -name "recipe.toml" -type f | while read -r local_recipe; do rel="${local_recipe#$LOCAL_RECIPES/}" - # Compute relative symlink path - depth=$(echo "$rel" | tr -cd '/' | wc -c) - up="" - for ((i=0; i