- Add diskd: Rust disk aggregator daemon (local/recipes/system/diskd/) - Add SCHEME-NAMESPACE-POPULATION-PLAN.md: comprehensive /scheme/ design - driver-manager: thread+timeout scheme check, always-wait, sync probe - redoxfs: two-path disk discovery (diskd first, legacy fallback) - prefix.mk: C++ header symlink durability fix - pcid: fallback cleanup - config/redbear-mini.toml: add diskd, remove tc/evdevd - Docs: AGENTS.md, local/AGENTS.md, local/recipes/AGENTS.md updated
65 KiB
RED BEAR OS — FULL FORK OF REDOX OS
Red Bear OS is a FULL FORK. Upstream Redox is a reference, not a live dependency. Sources are NEVER auto-pulled from upstream. The recipes/ tree is a frozen snapshot that we will eventually delete entirely; all Red Bear work lives in local/.
NO OVERLAY-STYLE PATCHES — SCOPED POLICY (AMENDED 2026)
Hard policy for in-tree Red Bear components. Explicit allowance for
Red Bear forks of big external projects. The blanket "no patches
anywhere" reading from commit 5396e6c3c was too broad — it would have
forced every direct edit to mesa, wayland, qt, KF6, KWin, SDDM, llvm,
libdrm, redox-drm, libepoxy, and similar multi-million-line external
projects to live inside recipes/<pkg>/source/, where a make clean
or upstream sync would clobber it. That is not a full fork, that is a
liability. This section sets the two-rule model Red Bear OS actually
follows.
Rule 1 — In-tree Red Bear components: NO overlay, NO local fork of mainline
These are Red Bear's own core components. They are small, fast-moving,
and tightly coupled to the rest of the system. Direct edits go into
the mainline recipes/<pkg>/recipe.toml and recipes/<pkg>/source/.
There is no Red Bear fork in local/, no symlink layer,
no patch file.
| Component | Why in-tree, not a fork |
|---|---|
kernel (recipes/core/kernel) |
Red Bear's microkernel fork; ACPI, x2APIC, MSI/MSI-X, scheduling, branding — all live in recipes/core/kernel/source/ directly |
relibc (recipes/core/relibc) |
Red Bear's C library fork; eventfd, signalfd, timerfd, waitid, SysV IPC, credential syscalls — all live in recipes/core/relibc/source/ directly |
base (drivers) (recipes/core/base) |
Red Bear's userspace drivers fork; acpid, pcid, inputd, ps2d, xhcid migrations — all live in recipes/core/base/source/ directly |
installer (recipes/core/installer) |
Red Bear's installer fork; ext4 + GRUB support — all lives in recipes/core/installer/source/ directly |
bootloader (recipes/core/bootloader) |
Red Bear's UEFI bootloader fork; UEFI alloc fix, branding, GPT offset — all lives in recipes/core/bootloader/source/ directly |
For these components, the mainline recipe IS the Red Bear fork. We own
it. There is no upstream to sync with — it is our code, full stop.
The same rule applies to Red Bear-initiated new packages in
local/recipes/<category>/<name>/.
| Want to change | Where to do it (DIRECT EDIT) |
|---|---|
| Change a recipe's build config | Edit local/recipes/<category>/<name>/recipe.toml directly. If the recipe is in upstream recipes/<category>/<name>/recipe.toml, fork it: copy to local/recipes/<category>/<name>/recipe.toml and edit there. |
| Change a source file | Edit local/sources/<component>/<file>.rs directly. |
| Add a new package | Create local/recipes/<category>/<name>/recipe.toml directly. |
| Change a build script | Edit local/scripts/<script>.sh directly. |
| Change a config TOML | Edit config/redbear-<name>.toml directly. |
What is FORBIDDEN for in-tree components:
| Anti-pattern | Why it's wrong |
|---|---|
local/patches/<pkg>/*.patch overlay files |
We are a full fork. Patches are an upstream-merging anti-pattern. If we need to change a Redox source, we fork the source into local/sources/<pkg>/ and commit the change there. Patches have no place in a full fork. |
apply-patches.sh symlinks (recipes/ → local/recipes/) |
This is an overlay pattern, not a fork. Symlinks hide the fact that we're editing a Redox package in-place, breaking the "every package is a fork" guarantee. A full fork has no overlay layer. |
Editing recipes/<pkg>/recipe.toml directly without a corresponding local/recipes/<pkg>/recipe.toml |
This makes our changes invisible to a full-fork audit. A git log on the upstream recipe shows our commits mixed with Redox's, and local/recipes/ becomes stale. |
Creating a local/recipes/<pkg>/ fork but then symlinking recipes/<pkg>/ to it |
Same as the apply-patches.sh symlink. Hides the fork. |
local/patches/redox-sessiond/P4-signal-implementations.patch style files in recipes/ pointing at ../../../local/patches/ |
The entire local/patches/ directory is historical-only and exists only because deleting it would invalidate git history. New patches go as git commits in local/sources/<component>/. |
recipes/wip/<pkg>/source/ symlinks to local/sources/<pkg>/ |
Same as the apply-patches.sh symlinks. The WIP overlay is a transitional tool for upstream WIP packages; we should fork them into local/recipes/ and not rely on WIP at all. |
How to fork an in-tree Redox package correctly (no overlay):
# 1. Copy the upstream recipe to local/recipes/ (the fork)
mkdir -p local/recipes/<category>/<name>
cp recipes/<category>/<name>/recipe.toml local/recipes/<category>/<name>/recipe.toml
cp -r recipes/<category>/<name>/source local/recipes/<category>/<name>/
# 2. Edit local/recipes/<category>/<name>/recipe.toml directly
$EDITOR local/recipes/<category>/<name>/recipe.toml
# 3. Commit the change in the main repo
git add local/recipes/<category>/<name>/
git commit -m "<category>/<name>: <change description>"
# 4. To make this fork override the upstream recipe, DELETE the upstream
# recipe entirely (this is the fork model — we own it now, not an overlay)
git rm recipes/<category>/<name>
git commit -m "remove upstream <name> in favor of local fork"
Verification (audit) — every in-tree recipe must have exactly one source:
# A well-forked build has no recipes/<pkg>/ symlinks or duplicate recipe.toml
find recipes/ -name "recipe.toml" -path "*/local/*" -o -lname "*/local/*" 2>/dev/null
# If this command returns ANY results, the build is in an overlay state.
# Fix by forking the recipe properly per the steps above.
Why this matters for in-tree components:
- Auditability —
git log local/recipes/<pkg>/recipe.tomlshows ALL our changes to that package, not a subset mixed with Redox commits. - Build determinism — A
make clean && make allalways produces the same result. Overlay symlinks can break this (the symlink target moves out from under the build). - No "stolen" upstream changes — When we edit
recipes/, we're competing with Redox's own commits on the same file. Agit pullfrom upstream can silently revert our changes. Inlocal/recipes/, upstream has no write access. - CI/CD reproducibility — A test build on CI shouldn't have to re-run an overlay fixup script. The recipes/ and local/recipes/ trees should be consistent at HEAD.
Historical context: the apply-patches.sh script and local/patches/
directory are remnants from when Red Bear was an overlay on Redox. They
exist only because deleting them would invalidate git history. New
changes go as direct edits to local/recipes/<pkg>/recipe.toml or
local/sources/<component>/.
If you find yourself adding to apply-patches.sh or creating a new entry
in local/patches/ for an in-tree component, STOP. Fork the recipe instead.
Rule 2 — Big external projects: external patches in local/patches/<component>/
These projects are too large, too fast-moving, and too far from
Red Bear's direct ownership to live as direct edits inside
recipes/<pkg>/source/. A make clean or upstream sync would
silently destroy our work. We DO NOT maintain a Red Bear source
fork of these projects (a fork diverges from upstream and
accumulates the full upstream history as "Red Bear commits").
Instead, Red Bear's edits live as external patches under
local/patches/<component>/*.patch, and the cookbook applies
them on top of the upstream tree at fetch time via the
cookbook_apply_patches helper. The patches survive make clean
and upstream syncs because they live in a directory Red Bear owns.
The migration of mesa, libdrm, pipewire, and wireplumber to the patches model happened in June 2026 (v6.0). The previous "fork model" was a liability: it diverged from upstream and made every upstream sync a Red Bear rebase exercise. See the "What We Patch" table below for the current list of patched projects.
Where the patches live:
local/patches/<component>/ ← Red Bear external patches (durable, in main repo)
├── 01-...-patch
├── 02-...-patch
└── ... (numbered, in apply order)
recipes/<category>/<name>/recipe.toml ← mainline recipe keeps upstream git source:
[source]
git = "https://...upstream-url/..."
rev = "<upstream-pinned-revision>"
[build]
script = """
REDBEAR_PATCHES_DIR="$(cd "$(dirname "${COOKBOOK_RECIPE}")/../.." && pwd)/local/patches/<component>"
cookbook_apply_patches "${REDBEAR_PATCHES_DIR}"
# ... actual build (meson / cmake / cargo / make) ...
"""
cookbook_apply_patches helper (defined in src/cook/script.rs,
auto-loaded into every build script): for each [0-9]*.patch in the
dir, checks if it's already applied (git apply --reverse --check)
and skips it if so, otherwise applies it. Returns to the build dir
when done. The helper is idempotent — a partial re-cook after a
previous successful build doesn't fail with "patch already applied".
What this rule prohibits for big external projects:
| Anti-pattern | Why it's wrong |
|---|---|
Direct edits inside recipes/<pkg>/source/ for mesa, wayland, qt, KF6, KWin, SDDM, llvm, libdrm, libepoxy, pipewire, wireplumber |
recipes/<pkg>/source/ is ephemeral — make clean and upstream syncs both destroy it. Edits there are guaranteed to be lost. |
A Red Bear source fork at local/sources/<component>/ for these projects |
A fork accumulates the full upstream history as "Red Bear commits", diverges from upstream, and makes every upstream sync a rebase exercise. We are not the upstream maintainers of these projects. Patches keep us close to upstream. |
recipes/wip/<pkg>/source/ symlinks to local/sources/<pkg>/ for these components |
WIP is a transitional tool. Move the patches to local/patches/<component>/ and have the recipe apply them. |
Mixing a local/sources/<component>/ fork with local/patches/<component>/ patches |
Two sources of truth is a half-forked, half-patched state. Pick one — for big external projects, pick patches. |
Why this rule is mandatory for big external projects:
- Survival across
make cleanand upstream syncs —recipes/<pkg>/source/is regenerated on every fetch. Patches inlocal/patches/<component>/survive because they live in the main repo, never touched by the build system, and the cookbook re-applies them every build. - Auditability —
git log local/patches/<component>/shows every Red Bear patch, in order, with a clear message. No mixing with upstream Mesa/Wayland/Qt/KF6/KWin/SDDM/LLVM/libdrm history. - No rebase debt — A Red Bear source fork would rebase the entire upstream history onto itself every time we sync. With external patches, upstream is upstream; our changes are deltas. Upstream sync is
rev = "<newer-rev>"and a re-apply, not a rebase. - CI/CD reproducibility — A test build on CI clones upstream at a pinned revision, applies the Red Bear patches from
local/patches/<component>/, builds, and the result is bit-identical. No overlay fixup script required. - Closeness to upstream — We are not the upstream maintainers of mesa, wayland, qt, KF6, KWin, SDDM, llvm, libdrm, libepoxy, pipewire, or wireplumber. Patches let us track upstream releases with minimal friction. If we ever want to upstream a fix, the patch is already in mbox format.
- Ownership of critical surface — Mesa, Wayland, Qt, KF6, KWin, SDDM, LLVM, libdrm, libepoxy, PipeWire, WirePlumber are the GPU, desktop, and multimedia stack. We cannot afford to have our edits silently clobbered by
make cleanor a WIP refactor. These components' edits must be external patches.
How to add a Red Bear edit to a big external project correctly:
# 1. Make the change in the fetched upstream tree (e.g. in a scratch clone or after a build)
$EDITOR some/file.c
# 2. Generate a patch from the change
git diff > local/patches/<component>/NN-short-description.patch
# (NN = next number; use leading zeros so order is stable when sorted)
# 3. Commit the patch in the main repo
git add local/patches/<component>/NN-*.patch
git commit -m "<component>: <short description> (external patch)"
# 4. The cookbook's cookbook_apply_patches loop picks up NN-prefixed patches
# in lexical order automatically. No recipe edit needed for step (4) — the
# loop in [build].script iterates REDBEAR_PATCHES_DIR/[0-9]*.patch.
# 5. Build via the standard pipeline (recipe fetches upstream, applies patches, builds)
./target/release/repo cook recipes/<category>/<name>
Rule-of-thumb decision matrix:
| Is the component … | Then … |
|---|---|
| An in-tree Red Bear core (kernel, relibc, base, installer, bootloader) | Rule 1 — direct edits in local/sources/<component>/ and local/recipes/<category>/<name>/recipe.toml. No fork. No patches. |
| A Red Bear-internal Rust scheme daemon (redox-drm, audiod, pcid, inputd, …) | Rule 1 — direct edits in local/sources/<component>/ and local/recipes/<category>/<name>/recipe.toml. No fork. No patches. |
| A small Red Bear-initiated new package (cub, redbear-info, redbear-netctl, redbear-sessiond, redbear-authd, …) | Rule 1 — local/recipes/<category>/<name>/ fork replaces the upstream recipe. No symlinks. |
| A big external project (mesa, wayland, qt, KF6, KWin, SDDM, llvm, libdrm, libepoxy, pipewire, wireplumber, …) | Rule 2 — external patches in local/patches/<component>/*.patch. Recipe has upstream git/tar source + [build].script calls cookbook_apply_patches. |
| An upstream Redox system-internal that we don't modify (core/pkgar, core/ion, core/dash, core/coreutils, gui/orbital, …) | No action needed. Pull from upstream at pinned revision. See "Safe to Pull from Upstream" below. |
| A pure Cargo dep that we don't fork (redox_syscall, libredox, redox-scheme, pkgar, …) | Pulled via Cargo from upstream crates.io. No recipe. |
If a component is on the boundary (e.g., a small but actively-edited
external project), the decision is: will the edits survive a
make clean and an upstream sync if they live in
recipes/<pkg>/source/? If yes, Rule 1. If no, Rule 2 — and
Rule 2 means external patches, not a Red Bear source fork.
TUI CONVENTION — SINGLE BINARY, -i INTERACTIVE SWITCH
All Red Bear desktop applications that offer both a TUI and a CLI mode MUST be
a single binary. The TUI code lives behind a tui feature inside the same
crate; there is no separate -tui sub-crate, no cub-tui-style split. This
applies to every program with a TUI in the Red Bear surface — cub,
redbear-info, redbear-netctl, redbear-wifictl, redbear-btctl, and any
future app.
| App | TUI | -i flag |
Description |
|---|---|---|---|
cub |
ratatui | ✅ | AUR package manager (search/info/install/build/query tabs) |
redbear-info |
ratatui | ✅ | System dashboard (System/Hardware/Network/Integrations/Health tabs) |
redbear-netctl |
ratatui | ✅ | Network profile manager console |
Pattern (enforced for every program):
- One binary (
app), one Cargo.toml, one set of[[bin]]entries. - TUI module lives at
src/tui/(or similar) and is gated by atuiCargo feature so headless--no-default-featuresbuilds still work. app(no args) → launches TUI if stdin/stdout is a terminal, else prints help.app -i/app --interactive→ forces TUI launch (use this when piping throughscript(1)or when you want TUI even if stdout is redirected).app <command>→ CLI mode; subcommands are unchanged whether the TUI feature is enabled or not.- Use
ratatui 0.30 + termion 4.0.6(nocrossterm).
Anti-patterns (forbidden):
- A separate
<app>-tuicrate that the main binary depends on. - A separate
<app>-guibinary that wraps a TUI launch. - A build flag that produces a different binary name for the TUI mode.
The TUI feature flag is for build-time size / dependency slimming (drop
ratatui+termion when the target doesn't have a display, or when running
strictly headless), not for splitting the binary. The recipe must build
with default features (TUI on) unless the program is intentionally
non-interactive (e.g. redbear-firmware, redbear-acmd are CLI-only by
design and have no TUI).
This directory contains ALL custom work on top of mainline Redox. When mainline Redox
updates (git pull on the build system repo), this directory is untouched.
STUB AND WORKAROUND POLICY — ZERO TOLERANCE
Red Bear OS has zero tolerance for stubs, workarounds, #ifdef-guarded no-ops, fake headers,
sed/awk hacks, LD_PRELOAD tricks, rename-to-.disabled wrappers, or any
other "make it compile" shortcut.
If something doesn't build because of a missing implementation, the ONLY acceptable response is to implement the missing functionality in the correct component:
| Problem | Correct Fix |
|---|---|
eventfd() not found |
Implement eventfd() in relibc, generate sys/eventfd.h via cbindgen |
signalfd() not found |
Implement signalfd() in relibc, generate sys/signalfd.h via cbindgen |
| Missing POSIX type | Add it to the relibc header it belongs to, with proper stdint.h include chain |
| Compiler can't find header | Fix the include path in the recipe's sysroot/cookbook, NOT by adding -I hacks |
| CMake can't find dependency | Implement the dependency or fix pkg-config, NOT with -DFEATURE_x=OFF |
Qt needs open_memstream |
Implement it in relibc — never add a static stub in Qt or libwayland source |
Any stub found in the tree is a bug to be fixed, not a precedent to follow.
When relibc gains a function or type that obsoletes a previously-needed local stub, the stub MUST be removed and the dependency switched to relibc's implementation. Coexistence of stubs with real implementations causes header conflicts, linker errors, and silent ABI mismatches.
This applies to: relibc functions, kernel syscalls, C headers, CMake modules, pkg-config .pc
files, Wayland protocol stubs, D-Bus service stubs, and any other layer of the stack.
No exceptions. No "temporary." No "until we fix it properly."
BUILD DURABILITY AND CASCADE POLICY
Every Build Lands in the Repo
Every successful repo cook <package> MUST produce durable artifacts:
- Package in the repo:
repo/x86_64-unknown-redox/<name>.pkgar+<name>.toml - Committed source: All source modifications committed in the appropriate
local/sources/<component>/git repo
A build is not complete until the repo artifacts exist. Verify after every cook:
./target/release/repo find <package> # Must find the package
ls repo/x86_64-unknown-redox/<package>.toml # Manifest must exist
ls repo/x86_64-unknown-redox/<package>.pkgar # Archive must exist
If a package was built but the repo artifacts are missing, the build did not complete.
If source changes were made but not committed to local/sources/<component>/, commit them there.
Cascade Rebuild Rule
When a low-level package changes, all packages that transitively depend on it must be rebuilt. A stale dependent silently produces link errors, ABI mismatches, or runtime crashes.
# Rebuild relibc and everything that depends on it
./local/scripts/rebuild-cascade.sh relibc
# Dry run: show what would be rebuilt without building
./local/scripts/rebuild-cascade.sh --dry-run relibc
# Multiple root packages
./local/scripts/rebuild-cascade.sh relibc ncurses
The script performs BFS over reverse dependencies: it finds all packages whose
recipe.toml lists the target in dependencies, transitively expands, then builds
root-first followed by dependents.
Always use cascade rebuilds after changing:
- relibc (headers, ABI, any patches)
- Kernel (syscall ABI changes)
- Shared libraries (ncurses, zlib, openssl, etc.)
- Any package listed in other packages'
dependencies
Example: Changing relibc's sys/types/internal.h header requires rebuilding
bison, m4, flex, and every other gnulib-based package that includes system headers
through the relibc include chain.
DESIGN PRINCIPLE
Red Bear OS is a full fork based on frozen Redox OS snapshots:
- We baseline on a specific Redox OS state and work from immutable, archived sources
- The
local/directory contains our custom work — untouched by any source immutable archived - First-class configs use
redbear-*naming (notmy-*, which is gitignored) - Sources are NEVER auto-immutable archived from upstream — all changes are explicit, human-initiated
FREE/LIBRE SOFTWARE POLICY
Red Bear OS must remain a free/libre project.
- Prefer components that are open-source, freely available to all users, or built in-tree by Red Bear.
- Do not introduce proprietary, source-unavailable, paywalled, or redistributability-restricted dependencies into the tracked system surface.
- When a dependency is dual-licensed under multiple free/open licenses, choose and document the option that is compatible with the Red Bear project surface.
- For the greeter/login stack specifically, the current SHA-crypt verifier path is the pure-Rust
sha-cryptcrate, licensedMIT OR Apache-2.0; Red Bear treats it under the MIT option for compatibility with the project's free-software policy.
Build flow:
make all CONFIG_NAME=redbear-full
→ mk/config.mk resolves to the active desktop/graphics compile target
→ Desktop/graphics are available only on redbear-full
→ repo cook builds all packages from local sources (offline by default)
→ Each successful cook produces repo/<arch>/<name>.pkgar + <name>.toml
→ mk/disk.mk creates harddrive.img with Red Bear branding
→ REDBEAR_RELEASE=0.2.3 ensures immutable, archived sources
Cascade rebuild flow (when a low-level package changes):
./local/scripts/rebuild-cascade.sh <package>
→ Finds all packages whose recipe.toml lists <package> in dependencies
→ BFS expands the reverse dependency graph
→ Builds root package first, then dependents in dependency order
→ Pushes all rebuilt packages to sysroot
→ Every rebuilt package lands in repo/ (.pkgar + .toml)
Release flow:
# Sources are immutable — build from archives, never from network
./local/scripts/build-redbear.sh redbear-full
# Check for newer Redox snapshots (read-only, no side effects):
./local/scripts/check-upstream-releases.sh
# Provision a new release (explicit, human-initiated only):
./local/scripts/provision-release.sh --ref=<redox-tag> --release=0.2.0
ACTIVE COMPILE TARGETS
The supported compile targets are exactly three. All three work for both make all (harddrive.img)
and make live (ISO):
redbear-full— Desktop/graphics-enabled target (Wayland + KDE + GPU drivers)redbear-mini— Text-only console/recovery/install targetredbear-grub— Text-only target with GRUB boot manager
Desktop/graphics are available only on redbear-full.
RELEASE MODEL (FORK — NOT OVERLAY)
Red Bear OS releases are versioned by branch name. Active development is on
the 0.2.3 branch, and the current Red Bear OS version is 0.2.3 —
same as the branch name.
The release branches (with their corresponding sources/redbear-<ver>/
archive directories) are:
| Branch | Archive directory | Status |
|---|---|---|
0.1.0 |
sources/redbear-0.1.0/ |
Historical. Frozen. The original Redox snapshot at build-system commit f55acba68. |
0.2.0 |
(next archive) | Historical. Frozen. |
0.2.1 |
(next archive) | Historical. Frozen. |
0.2.2 |
(next archive) | Historical. Frozen. |
0.2.3 |
(next archive) | Current. Active development. |
0.2.4 |
(future) | Will be created by provision-release.sh --release=0.2.4 |
The archive directories are immutable. Each new release gets a fresh archive directory alongside the previous ones. Old releases are NEVER deleted.
How releases work:
- Current development: 0.2.3 (the
0.2.3branch — same name as the version) - All recipe sources are pinned with
rev = "..."inrecipe.toml - Archives are stored in
sources/redbear-<ver>/with a manifest and BLAKE3 checksums - Builds are offline by default —
REPO_OFFLINE=1 COOKBOOK_OFFLINE=true - NO silent upstream pulls — see
AGENTS.md"NO SILENT UPSTREAM PULLS" section for the full policy. Any script or build target that silently pulls from upstream is a bug. - New releases are provisioned explicitly via
provision-release.sh, never automatically - Old releases are NEVER deleted — each new release is added alongside existing ones
Checking for new Redox snapshots:
./local/scripts/check-upstream-releases.sh # Read-only, zero side effects
Provisioning a new release:
./local/scripts/provision-release.sh --ref=<redox-tag> --release=0.2.0 [--dry-run]
Restoring sources from archives:
./local/scripts/restore-sources.sh --release=0.1.0
SOURCE-OF-TRUTH RULE (VERY IMPORTANT)
Treat the repository as two different layers with different durability guarantees:
1. Source archive layer — immutable per release
These paths are expected to be replaced, refetched, or regenerated when upstream changes:
recipes/*/source/- most of
recipes/outside our symlinkedlocal/recipes/*release fork config/desktop.toml,config/minimal.toml, and other mainline configs- generated build outputs under
target/,build/,repo/, and recipe-localtarget/*
For relibc specifically, recipes/core/relibc/source/ is upstream-owned working source, not
Red Bear’s durable storage location. We may build and validate there, but we must not rely on that
tree alone to preserve Red Bear work.
2. Red Bear-owned layer — durable, must survive release provisioning
These paths are our actual long-term source of truth:
local/sources/— Red Bear source forks (git repos, directly editable)local/recipes/— Red Bear recipe release fork and new packageslocal/docs/— Red Bear planning, validation, and integration documentation- tracked Red Bear configs such as
config/redbear-*.toml
If we can fetch fresh upstream sources tomorrow, provision sources from sources/redbear-<release>/, verify
local/recipes/*, and rebuild successfully, then the work is in the right place.
If a change exists only inside an upstream-owned recipes/*/source/ tree, then it is not yet
preserved, even if the current build happens to pass.
Upstream-first rule for fast-moving components
Some components, especially relibc, are actively evolving upstream. For those areas, Red Bear must prefer the upstream solution whenever upstream already solves the same problem.
That means:
- if our source fork has a fix that upstream still needs, keep it in the fork
- if upstream lands an equivalent or better solution, prefer upstream and port our additional changes on top
- do not keep Red Bear-specific code just because it existed first; keep it only while it still provides unique value
When upstream Redox already provides a package, crate, or subsystem for functionality that also exists in Red Bear local code, prefer the upstream Redox version by default unless the Red Bear implementation is materially better. Do not grow lower-quality in-house duplicates as a steady state.
For quirks and driver support specifically:
- prefer improving and using the canonical
redox-driver-syspath, - avoid maintaining separate lower-quality quirk engines when the same functionality belongs in
redox-driver-sys, - if duplication is temporarily unavoidable, treat it as convergence work to remove, not as a permanent design.
Daily workflow
For any change to Red Bear-owned source:
- edit the source in
local/sources/<component>/ - build:
repo cook <component> - test:
make qemu - commit:
git -C local/sources/<component>/ commit - push:
git -C local/sources/<component>/ push
The success criterion is therefore:
We can sources are provisioned via provision-release.sh and archived in sources/redbear-/ build the project successfully.
Local recipe priority vs upstream WIP
When Red Bear maintains a local recipe and upstream contains a package with the same name under
recipes/wip/*, Red Bear must prefer the local recipe unconditionally.
- Use the local release fork symlink in
recipes/*/<name> -> ../../local/recipes/... - Do not switch back to upstream WIP for active Red Bear builds
- Re-evaluate only when upstream package exits WIP and becomes a normal maintained package
# Automated sync (preferred):
./local/scripts/check-upstream-releases.sh # Check for new Redox snapshots (read-only)
./local/scripts/provision-release.sh --ref=<tag> --release=0.2.0 --dry-run # Preview new release
make all CONFIG_NAME=redbear-full # Rebuild OS
STRUCTURE
redox-master/ ← git pull updates mainline Redox
├── config/
│ ├── desktop.toml ← mainline configs (untouched)
│ ├── minimal.toml
│ ├── redbear-full.toml ← Desktop/graphics target
│ ├── redbear-mini.toml ← Text-only console/recovery target
│ ├── redbear-grub.toml ← Text-only with GRUB boot manager
│ ├── redbear-grub-policy.toml ← GRUB policy fragment (bootloader = "grub", efi_partition_size = 16)
│ └── redbear-greeter-services.toml ← Greeter/auth/session-launch wiring fragment
├── recipes/ ← mainline package recipes (untouched)
├── mk/ ← mainline build system (untouched)
├── local/ ← RED BEAR OS custom work
│ ├── AGENTS.md ← This file
│ ├── config/ ← Legacy configs (my-*, gitignored)
│ ├── recipes/
│ │ ├── core/ ← ext4d (ext4 filesystem scheme daemon + mkfs tool), grub (GRUB 2.12 UEFI bootloader)
│ │ ├── branding/ ← redbear-release (os-release, hostname, motd)
│ │ ├── drivers/ ← redox-driver-sys, linux-kpi (DRM/GPU + Wi-Fi only — NOT USB — NOT input subsystem)
│ │ ├── gpu/ ← redox-drm (AMD + Intel display drivers), amdgpu (C port)
│ │ ├── system/ ← cub, diskd, evdevd, udev-shim, redbear-firmware, firmware-loader, redbear-hwutils, redbear-info, redbear-netctl, redbear-quirks, redbear-meta
│ │ │ ├── redbear-sessiond ← org.freedesktop.login1 D-Bus session broker (zbus-based Rust daemon)
│ │ │ ├── redbear-authd ← local-user authentication daemon (`/etc/passwd` + `/etc/shadow` + `/etc/group`)
│ │ │ ├── redbear-session-launch ← session bootstrap helper (uid/gid/env/runtime-dir handoff)
│ │ │ ├── redbear-greeter ← greeter orchestrator package (`redbear-greeterd`, UI, compositor wrapper, staged assets)
│ │ │ ├── redbear-dbus-services ← D-Bus .service activation files + XML policies
│ │ ├── wayland/ ← Wayland compositor (Phase 2)
│ │ └── kde/ ← KDE Plasma (Phases 3–4)
│ ├── sources/ ← Red Bear source forks (git repos, directly editable)
│ │ ├── kernel/ ← Red Bear's kernel fork
│ │ ├── relibc/ ← Red Bear's C library fork
│ │ ├── base/ ← Red Bear's userspace drivers fork
│ │ ├── bootloader/← Red Bear's bootloader fork
│ │ └── installer/ ← Red Bear's installer fork
│ ├── Assets/ ← Branding assets (icon, loading background)
│ │ └── images/ ← Red Bear OS icon (1254x1254) + loading bg (1536x1024)
│ ├── firmware/ ← GPU firmware blobs (gitignored, fetched)
│ ├── scripts/
│ │ ├── rebuild-cascade.sh ← Rebuild package + all dependents (BFS reverse-dep graph)
│ │ ├── provision-release.sh ← Provision new release from Redox ref
│ │ ├── build-redbear.sh ← Unified Red Bear OS build script
│ │ ├── fetch-firmware.sh ← Download bounded AMD or Intel firmware subsets from linux-firmware
│ │ ├── test-drm-display-runtime.sh ← Shared bounded DRM/KMS display validation harness
│ │ ├── test-amd-gpu.sh ← AMD wrapper for the DRM display validation harness
│ │ ├── test-intel-gpu.sh ← Intel wrapper for the DRM display validation harness
│ │ ├── test-baremetal.sh ← Bare metal test script
│ │ ├── build-redbear-wifictl-redox.sh ← Build redbear-wifictl for the Redox target with the repo toolchain
│ │ ├── test-iwlwifi-driver-runtime.sh ← Bounded Intel driver lifecycle check inside a target runtime
│ │ ├── test-wifi-control-runtime.sh ← Bounded Wi-Fi control/profile runtime check inside a target runtime
│ │ ├── test-wifi-baremetal-runtime.sh ← Strongest in-repo Wi-Fi runtime check on a real Red Bear target
│ │ ├── validate-wifi-vfio-host.sh ← Host-side VFIO passthrough readiness check for Intel Wi-Fi validation
│ │ ├── prepare-wifi-vfio.sh ← Bind/unbind Intel Wi-Fi PCI function for VFIO validation
│ │ ├── test-wifi-passthrough-qemu.sh ← QEMU/VFIO Wi-Fi validation harness with in-guest checks
│ │ ├── run-wifi-passthrough-validation.sh ← One-shot host wrapper for the full Wi-Fi passthrough validation flow
│ │ ├── package-wifi-validation-artifacts.sh ← Package Wi-Fi validation artifacts into one host-side tarball
│ │ ├── summarize-wifi-validation-artifacts.sh ← Summarize captured Wi-Fi validation artifacts for quick triage
│ │ ├── finalize-wifi-validation-run.sh ← Analyze a Wi-Fi capture bundle and package the final evidence set
│ │ ├── validate-vm-network-baseline.sh ← Static repo-level VM networking baseline check
│ │ ├── test-vm-network-qemu.sh ← QEMU launcher for the VirtIO VM networking baseline
│ │ ├── test-vm-network-runtime.sh ← In-guest runtime check for the VM networking baseline
│ │ ├── test-ps2-qemu.sh ← QEMU launcher for the bounded PS/2 + serio runtime proof
│ │ ├── test-timer-qemu.sh ← QEMU launcher for the bounded monotonic timer runtime proof
│ │ ├── test-lowlevel-controllers-qemu.sh ← Sequential wrapper for bounded low-level controller proofs
│ │ ├── test-usb-maturity-qemu.sh ← Sequential wrapper for bounded USB maturity proofs
│ │ └── test-greeter-qemu.sh ← Bounded QEMU proof for the Red Bear greeter/auth/session surface
│ └── docs/ ← Integration docs
HOW TO BUILD RED BEAR OS
# Build targets (all three work for both `make all` and `make live`)
./local/scripts/build-redbear.sh redbear-full # Desktop/graphics target
./local/scripts/build-redbear.sh redbear-mini # Text-only console/recovery target
./local/scripts/build-redbear.sh redbear-grub # Text-only with GRUB boot manager
# Or manually:
make all CONFIG_NAME=redbear-full # Desktop/graphics → harddrive.img
make all CONFIG_NAME=redbear-mini # Text-only → harddrive.img
make all CONFIG_NAME=redbear-grub # Text-only + GRUB → harddrive.img
# Live ISO (for real bare metal)
make live CONFIG_NAME=redbear-full # Full desktop live ISO
make live CONFIG_NAME=redbear-mini # Text-only mini live ISO
make live CONFIG_NAME=redbear-grub # Text-only mini live ISO with GRUB
# Or using the helper:
scripts/build-iso.sh redbear-full # Full desktop live ISO
scripts/build-iso.sh redbear-mini # Text-only mini (default)
scripts/build-iso.sh redbear-grub # Text-only + GRUB
# Rebuild a package and all its dependents (cascade)
./local/scripts/rebuild-cascade.sh relibc # Rebuild relibc + all dependents
./local/scripts/rebuild-cascade.sh --dry-run ncurses # Show cascade without building
# VM-network baseline validation helpers
./local/scripts/validate-vm-network-baseline.sh
./local/scripts/test-vm-network-qemu.sh redbear-mini
# Then run inside the guest:
# ./local/scripts/test-vm-network-runtime.sh
# Phase 1 runtime-substrate validation (canonical plan: CONSOLE-TO-KDE v6.0)
# firmware-loader, DRM/KMS, time — covers acceptance areas + POSIX compat)
./local/scripts/test-phase1-runtime.sh --qemu redbear-full
# Legacy Phase 1 desktop-substrate validation (still works)
./local/scripts/test-phase1-desktop-substrate.sh --qemu redbear-full
# Phase 1 POSIX compatibility tests (inside guest)
# Run inside the guest after boot:
# cd /home/user/relibc-phase1-tests && ./test_signalfd_wayland && ./test_timerfd_qt6 && ...
# Or use the test harness:
./local/scripts/test-phase1-runtime.sh --guest
# Legacy Phase 3 runtime-substrate validation (historical P0-P6 numbering; script still works)
./local/scripts/test-phase3-runtime-substrate.sh --qemu redbear-full
# Low-level controller validation
./local/scripts/test-xhci-irq-qemu.sh --check
./local/scripts/test-msix-qemu.sh
./local/scripts/test-iommu-qemu.sh
./local/scripts/test-ps2-qemu.sh --check
./local/scripts/test-timer-qemu.sh --check
./local/scripts/test-lowlevel-controllers-qemu.sh
./local/scripts/test-usb-storage-qemu.sh
./local/scripts/test-usb-qemu.sh --check
./local/scripts/test-usb-maturity-qemu.sh
# The current xHCI proof checks for an interrupt-driven mode in boot logs.
# The current MSI-X proof uses the live virtio-net path in QEMU.
# The current IOMMU proof runs a guest-driven first-use self-test and checks that discovered
# AMD-Vi units initialize and drain events successfully in QEMU.
# The current PS/2 proof checks serio node visibility and then hands off to the existing Phase 3
# input-path checker inside the guest.
# The current timer proof checks that /scheme/time/CLOCK_MONOTONIC advances across two guest reads.
# The aggregate low-level wrapper runs xHCI, IOMMU, PS/2, and timer proofs in sequence.
# The USB storage proof now verifies usbscsid autospawn plus bounded sector-0 readback against a
# host-seeded pattern, while guest-side write verification is still open.
# The aggregate USB wrapper runs xHCI mode, full USB stack, and USB storage readback proofs in sequence.
# Legacy Phase 4 Wayland runtime validation (historical P0-P6 numbering; script still works)
./local/scripts/build-redbear.sh redbear-full
./local/scripts/test-phase4-wayland-qemu.sh
# Then run inside the guest:
# redbear-phase4-wayland-check
# Legacy Phase 5 desktop/network plumbing validation (historical P0-P6 numbering; script still works)
./local/scripts/build-redbear.sh redbear-full
./local/scripts/test-phase5-network-qemu.sh --check
# Then run inside the guest:
# redbear-phase5-network-check
# Experimental Red Bear greeter/login validation
./local/scripts/build-redbear.sh redbear-full
./local/scripts/test-greeter-qemu.sh --check
# Then run inside the guest:
# redbear-greeter-check
# redbear-greeter-check --invalid root wrong
# Bounded Intel Wi-Fi runtime validation (real target or passthrough guest)
# Host preparation for VFIO-backed guests:
# sudo ./local/scripts/validate-wifi-vfio-host.sh --host-pci 0000:xx:yy.z --expect-driver iwlwifi
# sudo ./local/scripts/prepare-wifi-vfio.sh bind 0000:xx:yy.z
# Guest/target packaged checks:
# redbear-phase5-wifi-check
# redbear-phase5-wifi-link-check
# redbear-phase5-wifi-run wifi-open-bounded wlan0 /tmp/redbear-phase5-wifi-capture.json
# redbear-phase5-wifi-capture wifi-open-bounded wlan0 /tmp/redbear-phase5-wifi-capture.json
# redbear-phase5-wifi-analyze /tmp/redbear-phase5-wifi-capture.json
# Helper scripts:
# ./local/scripts/test-wifi-baremetal-runtime.sh
# ./local/scripts/test-wifi-passthrough-qemu.sh --host-pci 0000:xx:yy.z --check --capture-output ./wifi-passthrough-capture.json
# ./local/scripts/finalize-wifi-validation-run.sh ./wifi-passthrough-capture.json ./wifi-passthrough-artifacts.tar.gz
# Legacy Phase 6 KDE session-surface validation (historical P0-P6 numbering; script still works)
./local/scripts/build-redbear.sh redbear-full
./local/scripts/test-phase6-kde-qemu.sh --check
# Then run inside the guest:
# redbear-phase6-kde-check
# redbear-netctl user-facing alias
redbear-netctl --help
# Single custom recipe:
./target/release/repo cook local/recipes/branding/redbear-release
./target/release/repo cook local/recipes/system/redbear-meta
./target/release/repo cook local/recipes/core/ext4d
./target/release/repo cook local/recipes/core/grub # GRUB bootloader (host build, produces EFI binary)
# GRUB boot manager (installer-native):
make r.grub # Build GRUB recipe
make all CONFIG_NAME=redbear-grub # Build text-only target with GRUB
# Linux-compatible CLI (add local/scripts to PATH):
grub-install --target=x86_64-efi --disk-image=build/x86_64/harddrive.img
grub-mkconfig -o local/recipes/core/grub/grub.cfg
# Or legacy post-build script:
./local/scripts/install-grub.sh build/x86_64/harddrive.img # Modify existing image
TRACKING MAINLINE CHANGES
When mainline updates affect our work:
| Component | What to check | Where |
|---|---|---|
| Kernel | ACPI, scheme, memory API changes | recipes/core/kernel/source/src/ |
| relibc | New POSIX functions added upstream | recipes/core/relibc/source/src/header/ |
| Base drivers | Driver API changes | recipes/core/base/source/drivers/ |
| libdrm | DRM API updates | recipes/libs/libdrm/ or the current in-tree libdrm location |
| Mesa | OpenGL/Vulkan backend changes | recipes/libs/mesa/ |
| Build system | Makefile/config changes | mk/, src/ |
| rsext4 | ext4 crate API changes | local/recipes/core/ext4d/source/ Cargo.toml |
| Installer | ext4 dispatch, filesystem selection, GRUB bootloader | local/sources/installer/ (git fork) |
| Quirks | New Linux quirk entries to port | local/recipes/drivers/redox-driver-sys/source/src/quirks/ |
PLANNING NOTES
docs/07-RED-BEAR-OS-IMPLEMENTATION-PLAN.mdis the canonical public execution plan.local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md(v6.0) is the canonical comprehensive plan — supersedes all individual subsystem docs. See it for current state, blockers, and roadmap.local/docs/WAYLAND-IMPLEMENTATION-PLAN.mdis the canonical Wayland subsystem plan beneath the desktop path. Use it for Wayland-specific stability, completeness, ownership, and runtime-proof sequencing.local/docs/DRM-MODERNIZATION-EXECUTION-PLAN.mdis the current DRM-focused execution plan beneath the canonical desktop path. It keeps Intel and AMD at the same evidence bar while separating display/KMS maturity from render/3D maturity.- Older GPU-specific docs (
AMD-FIRST-INTEGRATION.md,HARDWARE-3D-ASSESSMENT.md,DMA-BUF-IMPROVEMENT-PLAN.md) have been retired and removed from the tree. Their content is subsumed byCONSOLE-TO-KDE-DESKTOP-PLAN.mdandDRM-MODERNIZATION-EXECUTION-PLAN.md. DESKTOP-STACK-CURRENT-STATUS.mdhas been retired — its content merged intoCONSOLE-TO-KDE-DESKTOP-PLAN.md.- AMD and Intel machines are now equal-priority Red Bear OS targets; the older AMD-first path is preserved only in the canonical DRM plan and the desktop path plan.
local/docs/WIFI-IMPLEMENTATION-PLAN.mdis the current Wi-Fi architecture and rollout plan, including the bounded role oflinux-kpiand the native wireless control-plane direction.local/docs/USB-IMPLEMENTATION-PLAN.mdandlocal/docs/BLUETOOTH-IMPLEMENTATION-PLAN.mdshould also be treated as first-class subsystem plans, not as side notes.local/docs/IRQ-AND-LOWLEVEL-CONTROLLERS-ENHANCEMENT-PLAN.mdis the current umbrella plan for IRQ delivery, MSI/MSI-X quality, IOMMU validation, and other low-level controller completeness work.local/docs/QUIRKS-SYSTEM.mddocuments the hardware quirks infrastructure: compiled-in tables, TOML runtime files, DMI matching, driver integration, and the linux-kpi C FFI bridge.- The historical
QUIRKS-IMPROVEMENT-PLAN.mdhas been retired — quirks convergence is tracked inlocal/docs/QUIRKS-SYSTEM.mdand the canonical desktop path plan. local/docs/DBUS-INTEGRATION-PLAN.mdis the canonical D-Bus architecture and implementation plan for KDE Plasma 6 on Wayland. It defines the phased approach to D-Bus service integration, theredbear-sessiondlogin1-compatible session broker, and the gap analysis for desktop-facing D-Bus services.local/docs/GREETER-LOGIN-IMPLEMENTATION-PLAN.mdis the canonical Red Bear-native greeter/login design and current implementation plan for theredbear-fulldesktop path. It defines theredbear-authd/redbear-session-launch/redbear-greetersplit, service wiring, validation surface, and the current boundary between the active greeter path and the olderredbear-validation-sessionhelper flows.local/docs/SCHEME-NAMESPACE-POPULATION-PLAN.mdis the canonical/scheme/namespace design document. It covers thediskddisk aggregator daemon, the /scheme/ completeness matrix, boot ordering (lived → diskd → rootfs), the two-path redoxfs disk discovery strategy (diskd first, legacy fallback), and future enhancements (hotplug, devfs-style aggregation, per-process namespaces). Cross-referenced with Linux (kobject/uevent), Fuchsia (Zircon/Component Manager), seL4 (CSpace), Plan 9 (per-process namespace), Genode (Platform session), and MINIX 3 (driver model).
The current execution order for these subsystem plans is:
- IRQ / low-level controller quality
- USB maturity
- Wi-Fi native control plane and first driver family
- Bluetooth controller + host path
- desktop/session compatibility on top of those runtime services
Do not present USB, Wi-Fi, Bluetooth, or low-level controller work as optional or secondary.
LINUX KERNEL SOURCE POLICY (CRITICAL)
Linux kernel source is REFERENCE ONLY — never a dependency.
If Red Bear OS needs something from the Linux kernel, it MUST be implemented in the project tree, using Linux source as reference only.
Policy (VERBATIM)
"If we need something from Linux kernel, it MUST be implemented in our tree, having Linux source as reference only" "If we need linux-input-headers than we must code redbear-input-headers"
linux-kpi Scope
local/recipes/drivers/linux-kpi/ covers ONLY:
- DRM/GPU headers (
drm/) — AMD + Intel display drivers - Wi-Fi headers (
net/) — mac80211, cfg80211, nl80211 - General kernel headers (
linux/) — mm, device, irq, dma-mapping, firmware, etc.
Does NOT cover: USB, input subsystem, or any other Linux kernel subsystem.
Implementing New Linux-Compatibility Headers
When Red Bear needs Linux kernel headers for a new subsystem:
- Create
local/recipes/drivers/redbear-<subsystem>-headers/ - Implement headers using Linux source as reference only
- Do NOT pull Linux source tarballs directly
- Do NOT use third-party tarballs that bundle Linux headers as a proxy
- Examples:
redbear-input-headers/→ linux/input.h, input-event-codes.h, uinput.hredbear-usb-headers/→ linux/usb/ch9.h, etc. (NOT linux-kpi's purpose)
linux-input-headers — Policy Violation
recipes/wip/libs/linux-input-headers/ extracts Linux kernel input headers from the
libevdev tarball. This is a policy violation — it pulls Linux headers via a third-party
tarball. The correct implementation is redbear-input-headers in local/recipes/drivers/.
FILESYSTEMS
Red Bear OS supports three filesystems:
| Filesystem | Implementation | Package | Status |
|---|---|---|---|
| RedoxFS | Mainline Redox (default) | recipes/core/redoxfs |
✅ Stable |
| ext4 | rsext4 0.3 crate + ext4d scheme daemon | local/recipes/core/ext4d |
✅ Compiles + Installer wired |
| FAT (VFAT) | fatfs 0.3.6 crate + fatd scheme daemon | local/recipes/core/fatd |
✅ Compiles + Tools tested + label write verified |
ext4 Workspace (local/recipes/core/ext4d/source/)
ext4d/source/
├── Cargo.toml ← Workspace: ext4-blockdev, ext4d, ext4-mkfs
├── ext4-blockdev/ ← BlockDevice trait impls for rsext4
│ ├── Cargo.toml ← Features: default=["redox"], redox=[libredox,syscall]
│ └── src/
│ ├── lib.rs ← Re-exports: FileDisk, RedoxDisk, Ext4Error, Ext4Result
│ ├── file_disk.rs ← FileDisk: std::fs backed, builds on host Linux + Redox
│ └── redox_disk.rs ← RedoxDisk: syscall/libredox backed, Redox-only (feature-gated)
├── ext4d/ ← ext4 filesystem scheme daemon (Redox userspace)
│ ├── Cargo.toml ← Features: default=["redox"], redox deps
│ └── src/
│ ├── main.rs ← Daemon: fork, SIGTERM, scheme registration
│ ├── mount.rs ← Scheme event loop (redox_scheme::SchemeSync)
│ ├── scheme.rs ← Full ext4 FSScheme: open, read, write, mkdir, unlink, stat...
│ └── handle.rs ← FileHandle, DirectoryHandle, Handle types
└── ext4-mkfs/ ← ext4 mkfs tool (host-side utility)
├── Cargo.toml
└── src/main.rs ← Creates ext4 images via FileDisk + rsext4::mkfs
Architecture:
ext4dis a Redox scheme daemon — it serves ext4 filesystems viascheme:ext4d- Uses
rsext4crate (pure Rust ext4 implementation) for all filesystem operations FileDiskallows building/testing on the Linux host machineRedoxDiskuseslibredox+redox_syscallfor actual Redox bare-metal I/O- Both impls are behind the
redoxfeature flag —--no-default-featuresgives Linux-only
Recipe: Symlinked into mainline search path:
recipes/core/ext4d → local/recipes/core/ext4d
Config: ext4d is included in config/desktop.toml (mainline), which redbear-full.toml inherits.
Dependencies (from workspace Cargo.toml):
rsext4 = "0.3"— Pure Rust ext4 filesystem implementationredox_syscall = "0.7.3"— Redox syscall wrappers (scheme, data types, flags)redox-scheme = "0.11.0"— Scheme server frameworklibredox = "0.1.13"— High-level Redox syscalls (open, read, write, fstat)redox-path = "0.3.0"— Redox path utilities
Installer ext4 + GRUB Integration
The mainline installer is patched to support ext4 as an install target filesystem and GRUB as an alternative boot manager:
GeneralConfig.filesystem: Option<String>— TOML field, accepts"redoxfs"(default) or"ext4"GeneralConfig.bootloader: Option<String>— TOML field, accepts"redox"(default) or"grub"FilesystemTypeenum — dispatch tag used byinstall_innerwith_whole_disk_ext4()— GPT partition layout + ext4 mkfs + file sync (mirrorswith_whole_disk)Ext4SliceDisk<T>— adaptsDiskWrapperto rsext4'sBlockDevicetraitsync_host_dir_to_ext4()— copies staged sysroot files into ext4 filesystem- GRUB chainload: when
bootloader = "grub", writes GRUB EFI + grub.cfg to ESP alongside Redox bootloader - CLI flags:
--filesystem ext4/--bootloader grub
Usage in config TOML:
[general]
filesystem = "ext4" # "redoxfs" is default
bootloader = "grub" # "redox" is default
efi_partition_size = 16 # Required for GRUB (default 1 MiB is too small)
filesystem_size = 10240 # MB
See local/docs/GRUB-INTEGRATION-PLAN.md for the full GRUB architecture and usage guide.
FAT (VFAT) Workspace (local/recipes/core/fatd/source/)
fatd/source/
├── Cargo.toml ← Workspace: fat-blockdev, fatd, fat-mkfs, fat-label, fat-check
├── fat-blockdev/ ← Block device adapter for fatfs crate
│ ├── src/lib.rs ← Re-exports: FileDisk (always), RedoxDisk (feature-gated)
│ ├── src/file_disk.rs ← FileDisk: std::fs::File → Read+Write+Seek
│ └── src/redox_disk.rs ← RedoxDisk: libredox → Read+Write+Seek (redox feature)
├── fatd/ ← FAT filesystem scheme daemon (Redox userspace)
│ ├── src/main.rs ← Daemon: fork, SIGTERM, dispatch to FileDisk/RedoxDisk
│ ├── src/mount.rs ← Scheme event loop (redox_scheme::SchemeSync)
│ ├── src/scheme.rs ← FatScheme: full FSScheme (open/read/write/mkdir/unlink/stat...)
│ └── src/handle.rs ← FileHandle, DirectoryHandle, Handle types
├── fat-mkfs/ ← mkfs.fat equivalent (create FAT12/16/32 filesystems)
│ └── src/main.rs
├── fat-label/ ← fatlabel equivalent (read + write volume labels via BPB)
│ └── src/main.rs ← `-s "LABEL"` writes label at BPB offset 43/71; verifies round-trip
└── fat-check/ ← fsck.fat equivalent (verify BPB, FAT chains, directory tree + safe repair)
└── src/main.rs ← `--repair` clears dirty flag, fixes FSInfo, reclaims lost clusters
Architecture: fatd is a Redox scheme daemon using fatfs v0.3.6 (MIT, no_std capable).
FAT is for data volumes and ESP only — NOT for root filesystem.
fscommon::BufStream wraps block device for mandatory caching.
Recipe: Symlinked into mainline search path:
recipes/core/fatd → ../../local/recipes/core/fatd
Config: Packages included via config/redbear-device-services.toml (inherited by
redbear-full.toml and redbear-mini.toml). Init service at
/usr/lib/init.d/15_fatd.service.
Dependencies: fatfs 0.3.6, fscommon 0.1.1, redox_syscall, redox-scheme, libredox, libc
Tool verification status (2026-04-17):
fat-mkfs: ✅ Creates FAT12/16/32, labels, auto-detection, cluster size option (-c), tested up to 1GBfat-label: ✅ Reads labels; writes BPB + creates/updates root-directory volume-label entry; verifies round-trip on all FAT types (including previously unlabeled volumes)fat-check: ✅ BPB validation, boot signature check, directory tree walk, cluster stats; ✅ safe repair (dirty flag including FAT12, FSInfo, lost clusters, orphaned LFN). Handles 0xFFFFFFFF FSInfo sentinel on fresh images.fatd: ✅ Compiles (links on Redox target only — expected). ✅frename+ rmdir non-empty check implemented. NOT runtime-tested (requires QEMU/bare metal).- Phase 4 (runtime auto-mount): Deferred to runtime validation. Static init service exists.
- Known limitation: fatfs v0.3.6 strictly requires
total_sectors_16 == 0for FAT32, rejecting some Linuxmkfs.fatimages cargo test: 60 unit tests (25 scheme + 7 label + 28 check) + 13+ integration edge cases
BRANDING ASSETS
Red Bear OS visual identity files live in local/Assets/.
local/Assets/
└── images/
├── Red Bear OS icon.png ← App icon / logo (1254x1254px)
│ Red bear head, dark background, red border
│ Use: desktop icon, bootloader logo, about dialog
└── Red Bear OS loading background.png ← Boot / loading screen (1536x1024px)
Cinematic red bear with forest silhouette
Use: bootloader splash, login screen background
Integration points (future):
| Asset | Target | How |
|---|---|---|
| icon.png | Bootloader logo | Convert to BMP, embed via bootloader config |
| icon.png | Desktop icon | Install to /usr/share/icons/hicolor/ via redbear-release recipe |
| icon.png | About dialog | Install through the active icon/theme surface |
| loading background.png | Boot splash | Convert to framebuffer-compatible format, display during startup |
| loading background.png | Login screen | Set as the display-session background |
Current status: Assets are committed to git. Not yet integrated into the build — requires bootloader and display server integration (P2 hardware validation).
BUILD SYSTEM SAFETY
The build system includes collision detection and validation to prevent the D-Bus regression class (config overrides silently overwritten by package staging).
Validation Targets
make lint-config # Check for /usr/lib/init.d/ in config [[files]]
make validate CONFIG_NAME=redbear-mini # Full validation: lint + init services + ownership
Init Service Path Convention
- Packages own
/usr/lib/init.d/— default service files from recipe staging - Config overrides own
/etc/init.d/— override files from[[files]]entries - Config
[[files]]MUST NOT use/usr/lib/init.d/paths for init services - The init system's
config_for_dirs()gives/etc/init.d/priority via BTreeMap dedup
Collision Detection (installer)
The installer includes CollisionTracker (in collision.rs) that detects when package
staging overwrites config pre-install files. Init service collisions always error. Other
collisions warn by default, error in strict mode (REDBEAR_STRICT_COLLISION=1).
Recipe Installs Manifest
Recipes can declare installed paths via installs = [...] in [package] section.
scripts/validate-file-ownership.sh checks for conflicts. No recipes declare installs yet.
Manifest Generation
scripts/generate-installs-manifest.sh base # Output suggested installs for base package
See local/docs/BUILD-SYSTEM-HARDENING-PLAN.md for the full 5-phase hardening plan.
See local/docs/BUILD-SYSTEM-INVARIANTS.md for invariants I1-I3.
ANTI-PATTERNS
- DO NOT edit files under mainline
recipes/directly — put patches inlocal/patches/ - DO NOT commit firmware blobs to git — use
local/scripts/fetch-firmware.sh - DO NOT modify
mk/orsrc/directly — extend vialocal/scripts/ - DO NOT assume mainline recipe names won't conflict — prefix custom ones (e.g.,
redox-) - DO NOT use
my-*naming for configs that should be tracked in git — useredbear-*instead - DO NOT edit config/base.toml directly — our configs include it and override via TOML merge
- DO NOT attempt to immutable archived sources from upstream — sources are immutable; use provision-release.sh
COMPREHENSIVE IMPLEMENTATION POLICY
Red Bear OS has zero tolerance for shortcuts, workarounds, and stubs. Every package in the build must be a comprehensive, real implementation. No approximations.
The Rule
When a package fails to build due to missing functionality:
- DO NOT mark packages as
"ignore"to skip them - DO NOT create stub recipes that provide fake cmake configs without real functionality
- DO NOT disable required dependencies via sed/cmake hacks without implementing the dependency
Fix Before Disable
When a build blocker exposes a missing producer surface, missing dependency export, or incomplete integration boundary, the default policy is:
Always do your best to fix before disabling.
This means:
- prefer restoring the real producer/package surface over commenting out the consumer
- prefer fixing CMake/pkg-config/header visibility over disabling the dependent feature
- treat disabling as a last resort, not the normal path
If disabling is temporarily unavoidable, it must be:
- explicit,
- narrowly scoped,
- documented with the real blocker,
- and treated as temporary debt to remove, not as the desired final state.
Instead, implement the missing functionality properly:
| Missing Component | Required Action |
|---|---|
| Missing POSIX function in relibc | Implement it in recipes/core/relibc/source/ + create patch in local/patches/relibc/ |
| Missing KF6 package | Create full recipe in local/recipes/kde/ with proper cmake build |
| Disabled Qt feature (e.g., QtNetwork) | Implement the feature properly in qtbase recipe |
| Missing system call | Implement in kernel recipe + create patch in local/patches/kernel/ |
Why This Matters
- Stubs and workarounds accumulate technical debt
- They block real functionality from ever being implemented
- They make the system unreliable and untestable
- They hide the real work that needs to be done
Current Comprehensive Implementation Gaps
CREDENTIAL SYSCALLS — RESOLVED (2026-04-30): setgroups, getgroups, initgroups, setresuid, setresgid, getrlimit, setrlimit are now implemented. See local/docs/KERNEL-IPC-CREDENTIAL-PLAN.md for the full implementation detail.
Implementation: Kernel: Context.groups: Vec<u32>, CallerCtx.groups, Groups proc scheme handle at auth-{fd}-groups. Relibc: posix_setgroups()/posix_getgroups() in redox-rt, real setgroups()/getgroups() in platform layer, RLIMIT userspace stubs. Durable patches: local/patches/kernel/P4-supplementary-groups.patch, local/patches/relibc/P4-setgroups-getgroups.patch.
| Gap | Root Cause | Status |
|---|---|---|
setgroups ENOSYS on Redox |
Redox kernel had no supplementary group infrastructure | ✅ RESOLVED |
getgroups returns only egid |
Redox kernel had no group table concept | ✅ RESOLVED |
setuid/setgid/getuid/getgid |
No credential syscalls in kernel | ✅ Already worked via posix_setresugid (proc scheme) |
getrlimit/setrlimit |
ENOSYS | ✅ RESOLVED — userspace stubs with defaults |
| CONFIG: KWin is a stub | KWin recipe attempts real cmake build with QML/Quick disabled. Blocked by QML gate. Previously had wrapper stubs — removed 2026-04-30. | ✅ RESOLVED: honest recipe, fails on QML gate |
| CONFIG: 36/48 KDE packages enabled | 12 blocked by QML gate (kirigami → plasma-framework → plasma-workspace → plasma-desktop). See local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md for breakdown. |
BLOCKED: QML gate requires Qt6Quick/QML engineering |
| CONFIG: Plasma packages blocked | plasma-framework, plasma-workspace, plasma-desktop depend on kirigami (QML gate). Documented in plan. | BLOCKED: QML gate |
| CONFIG: Greeter service | 20_greeter.service wired. Greeter QEMU proof passes (GREETER_HELLO=ok, GREETER_VALID=ok). | ✅ RESOLVED |
| RUNTIME: Greeter UI | Qt Wayland integration: redbear-compositor handles Wayland protocol. Qt6's Wayland plugin reports loading issues due to endianness in compositor wire format. | DOCUMENTED in plan |
| RUNTIME: Greeter UI crash | Qt Wayland integration fails (wl-shell deprecated, xdg-shell not working) |
Fix Qt platform plugin initialization for Wayland |
| RUNTIME: D-Bus user lookup | root and messagebus users not found in passwd database → ✅ RESOLVED: user/group config exists in redbear-full.toml; runtime files generated in build |
Verify in QEMU runtime |
| RUNTIME: seatd missing | seatd binary not in image despite being in config → ✅ RESOLVED: seatd builds and is in image |
Verify in QEMU runtime |
| RUNTIME: getrlimit(7) | relibc getrlimit not implemented → ✅ RESOLVED: implemented in relibc patches |
Verify in QEMU runtime |
Kernel Syscall Gap Analysis
The Redox kernel (recipes/core/kernel/source/src/syscall/mod.rs) match statement ends with:
_ => Err(Error::new(ENOSYS)),
All credential syscalls (SYS_SETGROUPS, SYS_GETGROUPS, SYS_SETUID, SYS_SETGID, etc.) fall through to this catch-all and return ENOSYS.
The syscall numbers come from redox_syscall crate (external, versioned) - not defined in the kernel tree.
Fixes Applied (2026-04-29)
- relibc/grp/cbindgen.toml: Added group functions to export list
- relibc/grp/mod.rs: Implemented
getgroups()with egid fallback - Patches created:
local/patches/relibc/P3-grp-cbindgen-exports.patch,P3-getgroups-implementation.patch - KERNEL GAP: Cannot fix without upstream
redox_syscall+ kernel changes
Implementation Locations
- POSIX functions:
recipes/core/relibc/source/src/header/<func>/+local/patches/relibc/ - New KF6 recipes:
local/recipes/kde/kf6-<name>/ - Kernel syscalls:
recipes/core/kernel/source/+local/patches/kernel/ - Qt fixes:
recipes/qt/qtbase/source/+local/patches/qtbase/
RED BEAR OS CONFIG HIERARCHY
Active compile targets (all three work for both make all and make live):
redbear-full— Desktop/graphics-enabled targetredbear-mini— Text-only console/recovery targetredbear-grub— Text-only with GRUB boot manager
Desktop/graphics are available only on redbear-full.
redbear-full.toml
└── redbear-mini.toml
├── minimal.toml (mainline)
├── redbear-legacy-base.toml
└── redbear-netctl.toml
└── [packages] firmware, GPU, Wayland, Qt6, KF6, KWin, greeter, fonts, icons
└── [services] D-Bus, seatd, greeter, console
└── [users] messagebus, greeter
NOTE: ext4d is inherited from desktop.toml (mainline package).
NOTE: redbear-meta is explicitly included; keep broader inclusion deliberate.
redbear-mini.toml
└── minimal.toml (mainline)
└── redbear-legacy-base.toml
└── redbear-netctl.toml
└── [packages] pciids, redbear-hwutils, redbear-netctl, redbear-info, cub, etc.
└── [services] pcid-spawner, netctl boot, console, debug console
redbear-grub.toml
└── redbear-mini.toml
└── redbear-grub-policy.toml (bootloader = "grub", efi_partition_size = 16)
└── [packages] grub
Config comparison:
| Config | GPU Stack | Desktop | Branding | ext4d | GRUB | filesystem_size |
|---|---|---|---|---|---|---|
| redbear-full | Full | Yes | Yes | ✅ | No | 4096 MiB |
| redbear-mini | None | None | Yes | No | No | 1536 MiB |
| redbear-grub | None | None | Yes | No | Yes | (from mini) |
ANTI-PATTERNS (COMMIT POLICY)
- DO NOT include AI attribution in commit messages — no AI agent footers, co-authored-by lines for automated assistance, or similar markers. Commits belong to the human author only.