Files
RedBear-OS/AGENTS.md
T
vasilito 2b1e1788de libdrm + Rule 2 migration: recipe upgrade, doc updates, manifest entry (v6.0 2026)
This is the final cleanup batch for the Rule 2 big-project migration
work (pipewire, wireplumber, mesa, libdrm all migrated to upstream git
+ external patches in local/patches/<component>/).

Changes:

  * local/recipes/libs/libdrm/recipe.toml: upgrade from
    template = 'meson' + mesonflags to template = 'custom' +
    DYNAMIC_INIT + cookbook_apply_patches + cookbook_meson. This
    matches the structural pattern used by the other 3 Rule 2
    migration recipes (mesa, pipewire, wireplumber) and gives libdrm
    the same flexible shell-script build context for future
    cross-compilation tweaks. Adds build dependencies expat,
    libpciaccess, meson, ninja-build, pkgconf (the meson template
    had these implicit; the custom template requires them explicit).
    Patch application still goes through cookbook_apply_patches
    (4 dots from local/recipes/libs/libdrm/ to project root).

  * local/recipes/AGENTS.md: catalog update reflecting the libdrm
    template change (now 'custom' instead of 'meson') and adding
    catalog entries for 4 recipes that were created during this
    migration round but were missing from the catalog: libxkbcommon,
    pam-redbear, pipewire, wireplumber.

  * sources/redbear-0.1.0/manifest.json: add a new manifest entry
    for 'libs/libdrm' (the historical 0.1.0 archive entry for libdrm,
    which uses the patched tarball). This mirrors the existing
    'lib/libdrm' entry and gives 'repo restore' a consistent way to
    recover the libdrm source from the 0.1.0 release archive.

  * Doc updates: AGENTS.md, README.md, local/AGENTS.md,
    local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md, local/docs/GPU-MESA-
    KDE-CHAIN-ASSESSMENT.md, local/recipes/AGENTS.md: bring the
    docs in line with the Rule 2 policy and the 4-migration set
    (pipewire, wireplumber, mesa, libdrm). Most are catalog or
    cross-reference updates.

  * local/docs/STUBS-FIX-PROGRESS.md: heavily trimmed (-303 net).
    The old document was tracking 346+ stub fixes from earlier
    sessions; most of those are now closed and the document has
    been condensed to the current state.

  * local/docs/SOURCE-OWNERSHIP-MODEL.md: deleted (-89 lines).
    This old doc described a 'source ownership' concept that has
    been superseded by the amended AGENTS.md Rule 2 (NO OVERLAY-
    STYLE PATCHES — SCOPED POLICY) section, which is the canonical
    source-ownership model going forward.
2026-06-10 08:24:02 +03:00

72 KiB
Raw Blame History

RED BEAR OS BUILD SYSTEM — PROJECT KNOWLEDGE BASE

Generated: 2026-04-12 (P1/P2 complete) · Updated: 2026-06 (source ownership migration) Toolchain: Rust nightly (edition 2024) Architecture: Microkernel OS in Rust, ~38k files, ~294k LoC Rust Target Hardware: AMD64 bare metal, with AMD and Intel machines treated as equal-priority Red Bear OS targets

OVERVIEW

Red Bear OS build system orchestrator — builds and packages ~100+ Git repositories into a bootable Redox image. Uses a Makefile + Rust "cookbook" tool + TOML configs. Languages: Rust (core), C (ported packages), TOML (config), Make (build orchestration).

RedBearOS is a full fork of Redox OS with direct source ownership. Red Bear edits live in two durable locations, depending on the component (see "NO OVERLAY-STYLE PATCHES" below for the full policy):

  • In-tree Red Bear components — direct edits in local/sources/<component>/ (kernel, relibc, base, installer, bootloader, redox-drm).
  • Big external projects — external patches in local/patches/<component>/*.patch applied on top of upstream git/tar source (mesa, libdrm, wayland, qt, KF6, KWin, SDDM, llvm, libepoxy, pipewire, wireplumber).

Durable Red Bear state belongs in local/sources/, local/recipes/, local/patches/, local/docs/, and tracked Red Bear configs.

The current development branch is 0.2.3, and the current Red Bear OS version is 0.2.3 — same as the branch name. The 0.1.0 baseline (Redox snapshot at build-system commit f55acba68) is preserved as the historical frozen archive at sources/redbear-0.1.0/; the release branches 0.2.0, 0.2.1, 0.2.2 carry intermediate work and are also frozen. Active development is on 0.2.3.

FULL FORK PRINCIPLE

Red Bear OS is a FULL FORK. We do not depend on Redox. We reuse Redox code only when needed — and when we do, we fork it into our own repos.

This means:

Rule Explanation
Own your dependencies Every crate and library Red Bear uses must have its source accessible in local/sources/ (in-tree Red Bear forks) or local/patches/<component>/*.patch (big external projects) or local/recipes/. No depending on upstream crates that we cannot fix ourselves.
No waiting for upstream If a dependency breaks, we fix it in our fork (in-tree) or via external patch (big externals). We do not file issues and wait.
Frozen snapshots only Upstream Redox is a reference, not a live dependency. We baseline on frozen snapshots and never auto-pull.
Upstream gitlab URLs are temporary Any recipe pointing at gitlab.redox-os.org (91 currently) must eventually be: (a) forked to local/sources/<component>/ (in-tree Red Bear code), (b) tracked via local/patches/<component>/ (big external projects — the established pattern for pipewire, wireplumber, and upcoming mesa/libdrm), or (c) pinned to a frozen archive (unmodified upstream). Exceptions: unmodified upstream packages with pinned revisions.
Our code, our fixes When crate APIs change (e.g., libredox 0.1.00.1.17 broke call_ro/call_wo signatures), we update OUR fork's code. We don't revert our code to match old APIs — we fix forward.
Durable state All source modifications are committed to local/sources/<component>/ (in-tree Red Bear forks) or local/patches/<component>/*.patch (big external projects). No edits in recipes/*/source/ survive a rebuild.

Concretely:

  • local/recipes/drivers/redox-driver-sys/ is OUR fork. We fix compilation errors there.
  • local/sources/kernel/ is OUR kernel. We don't pull from gitlab.redox-os.org/redox-oskernel.
  • If a Cargo dependency breaks, we fork the dependency crate to local/sources/ and pin our Cargo.toml to our fork.
  • The Linux kernel in local/reference/ is read-only reference — never a dependency.

NO OVERLAY-STYLE PATCHES — SCOPED POLICY (AMENDED 2026)

Two-rule model: in-tree Red Bear components get direct edits; big external projects get external patches in local/patches/<component>/*.patch applied on top of the upstream git source. We DO NOT maintain a Red Bear source fork of big external projects — that would diverge from upstream and accumulate upstream history as "Red Bear commits". The patches model keeps us close to upstream and gives a clean audit trail (one mbox-style patch per Red Bear change).

The migration of mesa, libdrm, pipewire, and wireplumber to the patches model happened in June 2026 (v6.0). The previous "fork model" was found to be a liability: it diverged from upstream and made every upstream sync a Red Bear rebase exercise.


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:

  1. Auditabilitygit log local/recipes/<pkg>/recipe.toml shows ALL our changes to that package, not a subset mixed with Redox commits.
  2. Build determinism — A make clean && make all always produces the same result. Overlay symlinks can break this (the symlink target moves out from under the build).
  3. No "stolen" upstream changes — When we edit recipes/, we're competing with Redox's own commits on the same file. A git pull from upstream can silently revert our changes. In local/recipes/, upstream has no write access.
  4. 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>/. Run apply-patches.sh --dry-run to see what overlay state the tree is in; fix the offending recipes by forking them properly.

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:

  1. Survival across make clean and upstream syncsrecipes/<pkg>/source/ is regenerated on every fetch. Patches in local/patches/<component>/ survive because they live in the main repo, never touched by the build system, and the cookbook re-applies them every build.
  2. Auditabilitygit 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.
  3. 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.
  4. 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.
  5. 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.
  6. 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 clean or 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 1local/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.

Safe to Pull from Upstream (Redox System Internals)

These are Redox-specific libraries, tools, and protocols that form the stable ABI between the kernel and userspace. We do NOT modify these — we pull them from upstream with pinned revisions. Forking them would create divergence from the Redox ABI and cause silent breakage.

Crates (pulled via Cargo, NOT via recipe git URLs):

Crate Why safe Notes
redox_syscall Syscall numbers, types, flags — must match kernel ABI Maintained by Redox; we never modify syscall numbers
redox-scheme Scheme protocol (SchemeSync, SchemeAsync traits) Stable protocol; our daemons implement it
libredox High-level syscall wrappers (call_ro, call_wo) Thin wrapper; if it breaks we fork it
pkgar / pkgar-core / pkgar-keys Package format (archive, signing, manifest) Stable ABI; used by installer and repo tool
redox-pkg Package dependency resolution Used by cookbook; we don't modify
redox_installer Filesystem image creation We forked this — ext4 + GRUB support
redoxer Cross-compilation wrapper Build tool; we use it as-is

Recipes (gitlab URLs — safe to pull from upstream):

Recipe Why safe Notes
core/pkgar Package format tools Matches pkgar crate ABI
core/ion Shell We don't modify shells
core/dash POSIX shell Redox port, we don't modify
core/coreutils Core utilities From uutils; we don't modify
core/extrautils Extra utilities Redox-specific; we don't modify
core/findutils File search We don't modify
core/netdb Network database Redox-specific
core/netutils Network utilities Redox-specific
core/pkgutils Package utilities Redox-specific
core/profiled Profiler daemon Redox-specific
core/strace Syscall tracer Redox-specific
core/contain Container runtime Redox-specific
gui/orbital Legacy display server We use Wayland; not modified
gui/orbdata Legacy display data Not modified
gui/orbterm Legacy terminal Not modified
gui/orbutils Legacy display utils Not modified
dev/redoxer Cross-compilation wrapper Build tool
kernel/kernel Sub-recipe Main kernel is OUR fork in local/sources/kernel/

Rule of thumb: If it defines the Redox ABI (syscall numbers, scheme protocol, package format), we pull from upstream. If we add features to it, we fork it.

What We MUST Fork (in-tree Red Bear code we own)

Component Our fork Why forked
Kernel local/sources/kernel/ ACPI, x2APIC, MSI/MSI-X, scheduling, branding
relibc local/sources/relibc/ eventfd, signalfd, timerfd, waitid, SysV IPC
Base (drivers) local/sources/base/ acpid, pcid, inputd, ps2d, xhcid migrations
Bootloader local/sources/bootloader/ UEFI alloc fix, branding, GPT offset
Installer local/sources/installer/ ext4 + GRUB bootloader integration
redoxfs local/sources/redoxfs/ RedoxFS daemon — minor changes
userutils local/sources/userutils/ User utilities — login shell tweaks
redox-drm local/sources/redox-drm/ Intel + AMD display drivers (Red Bear-internal Rust scheme daemon)
redox-driver-sys local/recipes/drivers/redox-driver-sys/ Hardware quirks system (Red Bear-internal Rust crate)
linux-kpi local/recipes/drivers/linux-kpi/ GPU + Wi-Fi compatibility headers (Red Bear-internal C-header crate)

What We Patch (big upstream projects we modify, NOT fork)

Per AGENTS.md "NO OVERLAY-STYLE PATCHES" Rule 2, big external projects are NOT forked. We carry Red Bear changes as external patches in local/patches/<component>/*.patch, applied on top of the upstream git source at build time. The mainline recipe pulls upstream at a pinned revision and the build script applies the patches.

Component Recipe Patches directory Why patched
PipeWire local/recipes/libs/pipewire/ local/patches/pipewire/*.patch redox_compat/ shim headers, audiod scheme backend
WirePlumber local/recipes/libs/wireplumber/ local/patches/wireplumber/*.patch redox_compat/ shim headers, README-redbear port status
Mesa (migration in progress) recipes/libs/mesa/ local/patches/mesa/*.patch (TBD) EGL/GBM/virgl Redox fixes, include/sys/ioccom.h stub
libdrm (migration in progress) local/recipes/libs/libdrm/ local/patches/libdrm/*.patch (TBD) xf86drm dispatch through scheme:drm paths, mode probing shim, xf86drm_redox.h helper
Qt 6 stack (qtbase, qtdeclarative, qtwayland, qt5compat, …) local/recipes/qt/<name>/ local/patches/qtbase/*.patch, local/patches/qtdeclarative/*.patch, … futex redox support, wayland guards, OpenGL/EGL fixes
KF6 Frameworks (32 packages) local/recipes/kde/kf6-<name>/ local/patches/kf6-*/ KConfig, KWayland, KCMUtils, Kirigami, …
KWin (Wayland compositor) local/recipes/kde/kwin/ local/patches/kwin/*.patch EGL/GBM integration, KWayland glue
SDDM (display manager) local/recipes/kde/sddm/ local/patches/sddm/*.patch Login screen, session launcher
LLVM/Clang (compiler stack) (upstream) local/patches/llvm-project/*.patch Redox target, libc++ relibc glue
libepoxy (OpenGL function pointer manager) (upstream) local/patches/libepoxy/*.patch EGL/GLX dispatch, dlsym workarounds for Mesa/Redox

BUILD SYSTEM DURABILITY — THE CARDINAL RULE

For in-tree Red Bear components (Rule 1): source lives in local/sources/<component>/. recipes/<pkg>/source/ is a symlink to local/sources/<component>/ — do NOT edit through the symlink (git operations won't work). Do NOT edit files in recipes/<pkg>/source/ directly — go to local/sources/<component>/ instead.

For big external projects (Rule 2): source comes from upstream git/tar at a pinned revision, and Red Bear patches in local/patches/<component>/*.patch are applied on top of the upstream tree at build time. The patches are the durable artifact, not the upstream source.

This is the #1 mistake AI agents and new contributors make. It has caused repeated work loss in this project. The rule is:

What you want to do Where to do it
Change a kernel source file Edit local/sources/kernel/ and commit
Change an init or daemon source file Edit local/sources/base/ and commit
Change relibc Edit local/sources/relibc/ and commit
Change a driver Edit local/sources/<component>/ and commit
Add a new package Create a recipe in local/recipes/<category>/<name>/
Change build config Edit config/redbear-*.toml
Add documentation Write to local/docs/

How the build system works

repo cook <package>
  ├── repo fetch <package>
  │   ├── For local sources: symlink local/sources/<pkg>/ → recipes/<pkg>/source/
  │   │   (kernel, base, relibc, bootloader, installer — Red Bear forks)
  │   ├── For git sources: clone/fetch from git URL → recipes/<pkg>/source/
  │   │   (upstream packages, frozen at pinned revisions)
  │   └── Source tree is ready for build (no patch step)
  ├── Cargo/cmake/configure build
  └── Stage artifacts into sysroot

Note: the source/ symlink to local/sources/ applies to the core Red Bear forks (kernel, base, relibc, bootloader, installer). For recipes, the model is different — a Red Bear fork lives entirely under local/recipes/<category>/<pkg>/ and either replaces the upstream recipes/<category>/<pkg>/ (delete it) or coexists with the mainline recipe (just edit local/recipes/). There are no symlinks, no overlay layer, no patch files. See "NO OVERLAY-STYLE PATCHES" above.

The source/ directory is a symlink to local/sources/ for Red Bear-owned component forks (kernel, base, relibc, etc.), or a git clone for upstream packages. There are no patches — the source IS the source.

Two-layer architecture

Layer 1: Ephemeral (destroyed on clean/fetch/rebuild)
  recipes/<pkg>/source/       ← symlink to local/sources/ or git clone
  build/                      ← build outputs
  target/                     ← cargo target dir

Layer 2: Durable (survives clean/fetch/rebuild/release provisioning)
  local/sources/<pkg>/        ← Red Bear source forks (git repos, directly editable)
  local/recipes/<pkg>/        ← custom recipe directories
  config/redbear-*.toml       ← Red Bear OS build configs
  local/docs/                 ← planning and integration docs

The correct workflow for any source change

  1. Edit the source in local/sources/<component>/
  2. Build: ./target/release/repo cook <package>
  3. Test: make qemu CONFIG_NAME=redbear-mini
  4. Commit: git -C local/sources/<component>/ commit -m "..."

Common anti-patterns

Anti-pattern Why it fails
Editing files in recipes/<pkg>/source/ Those are symlinks to local/sources/. Git operations must happen in the actual repo.
Creating new patch files in local/patches/ local/patches/ is historical only. Changes go as git commits in local/sources/<component>/.
Hand-writing patches No patches exist. Use standard git workflow.
Expecting source/ changes to survive make clean make clean deletes source/ directories
Running repo cook without --allow-protected for core packages Protected recipes (kernel, relibc, base) are offline-only by default
Adding to apply-patches.sh to make a recipe point at local/recipes/ Overlay pattern, not a fork. See "NO OVERLAY-STYLE PATCHES" above.
Creating recipes/<pkg>/source as a symlink to local/sources/<pkg>/ for a big external project Big external projects use upstream git/tar + external patches in local/patches/<component>/, not a local/sources/<component>/ Red Bear fork. See "NO OVERLAY-STYLE PATCHES".
Creating a local/recipes/<pkg>/ fork but symlinking recipes/<pkg>/ to it Same as apply-patches.sh. Hides the fork. See "NO OVERLAY-STYLE PATCHES".
Mixing local/recipes/<pkg>/ edits with recipes/<pkg>/ patches The fork should own the recipe entirely. Mixing creates a half-forked, half-overlay state. See "NO OVERLAY-STYLE PATCHES".

Recipe source configuration

For in-tree Red Bear components (Rule 1) — kernel, relibc, base, bootloader, installer, redox-drm — recipes use the Local source type, pointing at the Red Bear fork repo:

[source]
path = "../../../local/sources/base"

For big external projects (Rule 2) — mesa, libdrm, wayland, qt, KF6, KWin, SDDM, llvm, libepoxy, pipewire, wireplumber — recipes keep their upstream git or tar source at a pinned revision, and the recipe's [build].script applies Red Bear patches on top:

[source]
git = "https://gitlab.redox-os.org/redox-os/mesa.git"
rev = "0ecd6b66c"

[build]
script = """
# The cookbook runs the build script with cwd = the build dir, but
# `git apply` needs the upstream source tree, so cd there first.
REDBEAR_PATCHES_DIR="$(cd "$(dirname "${COOKBOOK_RECIPE}")/../.." && pwd)/local/patches/mesa"
cd "${COOKBOOK_SOURCE}"
for p in "${REDBEAR_PATCHES_DIR}"/[0-9]*.patch; do
    [ -f "$p" ] || continue
    git apply "$p" || { echo "Failed to apply $p"; exit 1; }
done
# Return to the build dir for the rest of the build
cd "${COOKBOOK_BUILD}"
# ... actual build ...
"""

Important: The REDBEAR_PATCHES_DIR path is relative to the recipe file. For recipes under recipes/<category>/<name>/ (e.g. mesa), the recipe is 2 levels deep from the project root (../../../), so REDBEAR_PATCHES_DIR=../../../local/patches/<component> resolves correctly. For recipes under local/recipes/<category>/<name>/ (e.g. libdrm, wireplumber, pipewire), the recipe is 3 levels deep (../../../../), so REDBEAR_PATCHES_DIR=../../../../local/patches/<component> resolves correctly. Adjust the ../../../ count to match your recipe's depth in the tree.

Non-forked recipes use standard git or tar sources — no patches needed.

Rules

  1. REPO_OFFLINE defaults to 1 (offline). Set REPO_OFFLINE=0 to explicitly allow online fetching for non-protected development recipes only.
  2. REDBEAR_RELEASE unconditionally forces offline mode — no network access during release builds, even with REPO_OFFLINE=0.
  3. Protected recipes (kernel, relibc, base, bootloader, all Red Bear custom recipes) are always offline — they use archived sources from sources/redbear-<release>/.
  4. GNU_CONFIG_GET (wget for config.sub) is gated by COOKBOOK_OFFLINE — no download when offline.
  5. Manual scripts (fetch-firmware.sh, fetch-all-sources.sh, provision-release.sh) may pull from upstream but MUST be explicitly invoked by the user. They are never called by make all or make live.
  6. Toolchain downloads (mk/prefix.mk) are the only ungated network access — they download the cross-compiler toolchain from static.redox-os.org. These are one-time prerequisites, not per-recipe source fetches.

What Counts as a Silent Upstream Pull

Any of the following that runs without the user explicitly requesting it:

  • git clone, git fetch, git pull against any remote
  • wget or curl downloading source code or build artifacts
  • Any HTTP request to gitlab.redox-os.org, github.com, static.redox-os.org, or any other upstream hosting service (note: Red Bear OS does not use GitHub — see Repository Hosting below)

What Does NOT Count

  • Toolchain setup (make prefix) — one-time cross-compiler download
  • QEMU firmware for non-x86 targets (mk/qemu.mk ARM/Raspberry Pi U-Boot) — not used in standard x86_64 builds
  • make fetch — explicit user action, gated by REDBEAR_RELEASE

Enforcement

  • Violations are bugs. If you find a script or build target that silently pulls from upstream, fix it immediately: add an offline gate, or move the fetch to a manual-only script.
  • The cookbook tool (src/cook/fetch.rs) enforces offline mode for protected recipes regardless of COOKBOOK_OFFLINE.
  • COOKBOOK_OFFLINE=true is the default in the Rust cookbook config parser when the environment variable is not set.

STRUCTURE

redox-master/
├── config/          # Build configs (TOML): tracked redbear-* targets plus mainline references
├── mk/              # Makefile fragments: config.mk, repo.mk, prefix.mk, disk.mk, qemu.mk
├── recipes/         # Package recipes (TOML + source). 26 categories. See recipes/AGENTS.md
│   ├── core/        # kernel, bootloader, relibc, base drivers — See recipes/core/AGENTS.md
│   ├── wip/         # Wayland, KDE, driver WIP ports — See recipes/wip/AGENTS.md
│   ├── libs/        # Libraries: mesa, cairo, SDL, zlib, openssl, etc.
│   ├── gui/         # Legacy GUI stack packages
│   └── ...          # 21 other categories (net, dev, games, shells, etc.)
├── src/             # Cookbook Rust tooling (repo binary, cook logic)
├── docs/            # Architecture docs (6 detailed integration guides) — See docs/AGENTS.md
├── local/           # OUR CUSTOM WORK — survives mainline updates — See local/AGENTS.md
│   ├── config/      # Custom configs (my-amd-desktop.toml)
│   ├── 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
│   │   └── ...        #   Additional component forks
│   ├── recipes/     # Custom recipes (AMD drivers, GPU stack, Wayland)
│   ├── patches/     # HISTORICAL — old patch files (not used by build system)
│   ├── Assets/      # Branding assets (icon, loading background)
│   ├── firmware/    # AMD GPU firmware blobs (fetched, not committed)
│   ├── scripts/     # Build/deploy scripts (fetch-firmware.sh, build-redbear.sh)
│   ├── docs/        # Red Bear integration docs (AMD roadmap, Wi-Fi/Bluetooth plans, status notes)
│   └── reference/   # External reference sources (gitignored, never deleted, always kept)
├── prefix/          # Cross-compiler toolchain (Clang/LLVM for x86_64-unknown-redox)
├── build/           # Build outputs, logs, fstools, per-arch directories
├── repo/            # Package manifests and PKGAR artifacts per architecture
├── bin/             # Cross-tool wrappers (pkg-config, llvm-config per target)
├── scripts/         # Helper scripts (backtrace, category, changelog, etc.)
├── podman/          # Podman container build support
├── .cargo/          # Cargo config: linker per target (aarch64, x86_64, i586, i686, riscv64gc)
├── Makefile         # Root orchestrator (all, live, image, rebuild, clean, qemu, gdb)
├── Cargo.toml       # Cookbook crate: binaries (repo, repo_builder), lib (cookbook)
├── rust-toolchain.toml  # nightly-2025-10-03 + rust-src + rustfmt + clippy
└── .config          # PODMAN_BUILD=0 (set to 1 for container builds)

WHERE TO LOOK

Task Location Notes
Add a package recipes/<category>/<name>/recipe.toml Use template = "cargo|cmake|meson|custom"
Change build config config/<name>.toml Include chain: wayland→desktop→desktop-minimal→minimal→base
Fix kernel local/sources/kernel/ Kernel is a recipe, not top-level
Fix a driver local/sources/base/src/drivers/ All drivers are userspace daemons
Fix relibc (POSIX) local/sources/relibc/ 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
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
Cross-toolchain setup mk/prefix.mk, prefix/x86_64-unknown-redox/ Downloads Clang/LLVM toolchain
Display/session surface config/redbear-full.toml Active desktop/graphics compile surface
GPU/graphics stack recipes/libs/mesa/ OSMesa + LLVMpipe (software only)
GPU hardware drivers local/recipes/gpu/redox-drm/source/ AMD + Intel DRM/KMS via redox-driver-sys
D-Bus integration local/docs/DBUS-INTEGRATION-PLAN.md Architecture, gap analysis, phased implementation for KDE Plasma D-Bus
Boot config config/*.toml TOML hierarchy, include-based
Hardware quirks local/recipes/drivers/redox-driver-sys/source/src/quirks/ Data-driven quirk tables: compiled-in + TOML + DMI; see local/docs/QUIRKS-SYSTEM.md

BUILD COMMANDS

The canonical way to build Red Bear OS ISOs is through local/scripts/build-redbear.sh. It enforces all project policies automatically:

# Build redbear-mini (text-only, recovery) — ~30 min
./local/scripts/build-redbear.sh redbear-mini

# Build redbear-full (3D desktop + SDDM + KDE) — ~90 min first build
./local/scripts/build-redbear.sh redbear-full

# Clean rebuild (discard caches, force recompile)
./local/scripts/build-redbear.sh redbear-full --no-cache

What build-redbear.sh does automatically:

  1. Enforces local-over-WIP: Any recipes/wip/ package shadowing a local/recipes/ package is replaced with a symlink to the local version (per local/recipes/ priority policy)
  2. Verifies overlay integrity: Checks that all recipe symlinks resolve correctly
  3. Stashes dirty submodules: Prevents accidental commits from contaminating the build
  4. Checks firmware: Warns if AMD GPU firmware is missing for redbear-full

When to use --no-cache:

  • After changing local/sources/{relibc,kernel,base} (low-level packages)
  • After make clean or make distclean
  • When stale cached packages cause build failures

Cascade rebuild rule: When a low-level package changes (relibc, kernel, base), ALL packages that transitively depend on it must be rebuilt. Use:

./local/scripts/rebuild-cascade.sh relibc    # Rebuild relibc + all dependents
./local/scripts/rebuild-cascade.sh --dry-run relibc  # Preview without rebuilding

Legacy Manual Build Commands

# Prerequisites (Linux x86_64 host)
#   rustup + nightly-2025-10-03, cargo install just cbedgen, nasm, qemu-system-x86
#   See docs/06-BUILD-SYSTEM-SETUP.md for distro-specific packages

# Configuration
echo 'PODMAN_BUILD?=0' > .config          # Native build (no container)
echo 'PODMAN_BUILD?=1' > .config          # Podman container build

# Build Red Bear OS
# Supported compile targets:
#   redbear-full         desktop/graphics target (harddrive.img or live ISO)
#   redbear-mini         text-only console/recovery target (harddrive.img or live ISO)
#   redbear-grub         text-only with GRUB boot manager (live ISO)
# Desktop/graphics target: redbear-full
# Text-only targets: redbear-mini, redbear-grub
make all CONFIG_NAME=redbear-full         # Desktop/graphics target → harddrive.img
make all CONFIG_NAME=redbear-mini         # Text-only target → harddrive.img
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
CI=1 make all CONFIG_NAME=redbear-mini    # CI mode (disables TUI, for non-interactive)

# Run
make qemu                                 # Boot in QEMU
make qemu QEMUFLAGS="-m 4G"              # With more RAM
make live                                 # Build live ISO for real bare metal

# Single recipe
./target/release/repo cook recipes/libs/mesa     # Build one recipe
./target/release/repo fetch recipes/core/kernel   # Fetch source only
make r.mesa                                      # Make shorthand for cook
make cr.mesa                                     # Clean + rebuild

# Clean
make clean                                # Remove build artifacts
make distclean                            # Remove sources + artifacts

BUILD FLOW

make all
  → mk/config.mk (ARCH, CONFIG_NAME, FILESYSTEM_CONFIG)
  → mk/depends.mk (check host tools: rustup, cbedgen, nasm, just)
  → mk/prefix.mk (download/setup cross-toolchain if needed)
  → mk/fstools.mk (build cookbook repo binary + fstools)
  → mk/repo.mk (repo cook --filesystem=config/*.toml)
    → For each recipe: fetch source → build → stage into sysroot
    → Each successful build produces repo/<arch>/<name>.pkgar + <name>.toml
  → mk/disk.mk (create filesystem.img, harddrive.img, redbear-live.iso or harddrive.img)
    → redoxfs-mkfs → redox_installer → bootloader embedding

Build Outputs

Every successful repo cook <package> produces:

Artifact Location Purpose
Package archive repo/x86_64-unknown-redox/<name>.pkgar Binary package for image assembly
Package manifest repo/x86_64-unknown-redox/<name>.toml Metadata, version, deps, hashes
Staged sysroot recipes/*/<name>/target/.../stage/ Files for repo push
Source tree recipes/*/<name>/source/ Symlink to local/sources/ or git clone

A build is not complete until the .pkgar and .toml exist in repo/.

CONVENTIONS

  • Rust edition 2024, nightly channel
  • rustfmt.toml: max_width=100, brace_style=SameLineWhere
  • clippy.toml: cognitive-complexity-threshold=100, type-complexity-threshold=1000
  • Recipe format: TOML with [source] + [build] + optional [package]
  • Build templates: cargo, meson, cmake, make, configure, custom
  • WIP recipes: Must start with #TODO comment explaining what's missing
  • Custom configs: Name with my- prefix (git-ignored by convention)
  • CI: GitLab CI (.gitlab-ci.yml) at root + per-recipe
  • Repository Hosting: Gitea at gitea.redbearos.org — the ONLY git server. No GitHub.
  • Syscall ABI: Unstable intentionally. Stability via libredox and relibc
  • Drivers: ALL userspace daemons via scheme system. No kernel-space drivers (except serio)

SYSTEM-CRITICAL INFRASTRUCTURE MUST BE RUST

All Red Bear OS system-critical infrastructure must be written in Rust. C and C++ are acceptable only for ported upstream applications (KDE Plasma, Qt, games, third-party tools) where the original source is not Rust.

What counts as system-critical

Layer Component Language Status
Kernel microkernel Rust
C library relibc Rust
Init service manager Rust
Filesystems redoxfs, ext4d, fatd Rust
Driver infrastructure redox-driver-sys, linux-kpi headers Rust + C headers
Display/compositor Wayland compositor Rust required
Session/auth redbear-sessiond, redbear-authd Rust
D-Bus broker session/system bus Rust
Network stack TCP/IP, Wi-Fi control plane Rust required
Bluetooth stack host/controller path Rust required
USB stack controller drivers, hub driver Rust required
Input stack evdev, libinput adapter Rust required
Firmware loading scheme:firmware daemon Rust
Core utilities shell, fileutils, process tools Rust required
Bootloader UEFI bootloader Rust
Installer redox_installer Rust
Build tooling cookbook, repo binary Rust

What does NOT need to be Rust

  • Ported desktop applications: KDE Plasma, Qt apps, KDE Frameworks — these are upstream C++ codebases and remain C++. The boundary is at the platform adapter layer: anything Red Bear writes to integrate them ( Wayland protocol bridges, D-Bus service implementations, platform plugins) must be Rust even if the upstream consumer is C++.
  • Ported libraries: mesa, wayland, libxkbcommon, libinput, fontconfig, etc. — upstream C.
  • Games and end-user applications: upstream code in any language.

Decision rule

When writing new code for Red Bear OS, or when choosing between writing new code vs porting existing code, the rule is:

If the component runs below the application layer — kernel, libc, drivers, filesystems, compositor, session management, networking, input, USB, Bluetooth, core utilities — it must be written in Rust.

If the component is an application or library that users would recognize as a separate upstream project (KDE, Qt, Firefox, etc.), it may remain in its upstream language.

The integration layer between Rust infrastructure and upstream C/C++ code must be Rust. Platform adapters, D-Bus service implementations, Wayland protocol bridges, and plugin shims are infrastructure, not applications.

Enforcement

  • New recipes under local/recipes/ for system-critical components must use template = "cargo".
  • C/C++ build templates (cmake, meson, make, configure) are only for ported upstream packages and their direct dependencies.
  • If a ported C/C++ package needs a companion daemon, helper, or bridge, that companion must be a separate Rust recipe — not embedded C in the ported package.

Conflicting implementations: always prefer Rust

When both a Rust implementation and a C/C++ implementation exist for the same functionality, Red Bear OS always prefers the Rust implementation. This applies even when the C version is from upstream Redox or appears more complete.

The rationale: Rust provides memory safety, type safety, and panic-based error recovery at the language level. For an OS with no ASLR, no stack canaries, and a minimal kernel, the language itself is the primary defense boundary. A C implementation of equivalent functionality is always a strictly weaker choice.

Examples:

Situation Correct choice
relibc (Rust) vs newlib/glibc (C) relibc — always
redoxfs (Rust) vs an imported C filesystem driver redoxfs — always
redbear-sessiond (Rust) vs dbus-daemon (C) redbear-sessiond — always
A Rust crate for a protocol vs the reference C library Rust crate — always
Upstream Redox provides a Rust driver; we also have a C port Rust driver — always

If a Rust implementation is less feature-complete than the C alternative, the correct response is to improve the Rust implementation — not to fall back to C.

INSTALLER FILE LAYERING

The installer creates filesystem images in four layers. Understanding this ordering is critical to avoid silent file overwrites.

Layer Ordering During install_dir()

Layer 1: Config pre-install [[files]]    (postinstall = false)
Layer 2: Package staging                  (install_packages())
Layer 3: Config post-install [[files]]    (postinstall = true)
Layer 4: User/group creation              (passwd, shadow, group)

Collision Implications

  • Layer 2 overwrites Layer 1 silently (same path → last writer wins). This is the bug class that caused the D-Bus regression: config overrides at /usr/lib/init.d/ were overwritten by the base package staging the same paths.
  • Layer 3 overwrites Layer 2 (intentional — postinstall overrides).
  • For init services, config overrides MUST use /etc/init.d/ so they survive Layer 2.

Init Service File Ownership

  • Packages own /usr/lib/init.d/ — default service files installed by recipe staging
  • Config overrides own /etc/init.d/ — override files created by [[files]] entries
  • The init system's config_for_dirs() gives /etc/init.d/ priority via BTreeMap dedup
  • Config [[files]] entries MUST NOT use /usr/lib/init.d/ paths for init services
  • Run make lint-config to detect violations

Collision Detection

The installer now includes a 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).

Validation Gates

After building an image, run make validate to verify:

  • Init service path violations (via lint-config)
  • Override effectiveness and scheme binary existence (via validate-init-services.sh)
  • File ownership conflicts (via validate-file-ownership.sh)

See local/docs/BUILD-SYSTEM-HARDENING-PLAN.md for the full plan.

ANTI-PATTERNS (THIS PROJECT)

  • DO NOT suppress errors with as any / @ts-ignore — use proper Result handling
  • DO NOT use unwrap() / expect() in library/driver code — pervasive anti-pattern (~14k instances)
  • DO NOT modify kernel syscall ABI directly — use libredox or relibc
  • DO NOT put drivers in kernel space — all drivers are userspace daemons
  • DO NOT hardcode /dev/ paths — use scheme paths (/scheme/drm/card0)
  • DO NOT skip required dependencies — document what's missing with #TODO
  • DO NOT skip warnings — investigate, diagnose, and fix the root cause; suppressing or ignoring warnings is not acceptable when a fix is feasible
  • DO NOT suppress build failures by disabling features — fix the root cause instead
  • DO NOT remove BINS entries to fix build failures — fix the source or use EXISTING_BINS filtering
  • DO NOT use the VESA display driver (vesad) as the primary display surface after GPU detection. vesad is only for early-boot framebuffer handoff — after redox-drm loads, the display path is /scheme/drm/card0. See NO VESA POLICY below.

NO VESA POLICY

Red Bear OS does not use the VESA display driver as the primary display surface. All display output goes through the DRM/KMS path via real GPU drivers:

Environment GPU Driver 3D Support
QEMU virtio-gpu (via redox-drm) virgl
Intel hardware Intel i915-like (via redox-drm) Mesa i965/iris
AMD hardware amdgpu (via redox-drm + linux-kpi) Mesa radeonsi
Future nouveau reimplementation (Rust, via redox-drm) Mesa nouveau

vesad is allowed ONLY as an early-boot framebuffer handoff. The bootloader sets up a linear framebuffer before the kernel starts. vesad takes over this framebuffer so the initfs has console output (fbcond, fbbootlogd) before real GPU drivers are available. Once redox-drm initializes and registers scheme:drm/card0, vesad must hand off and NOT register scheme:display.vesa as the primary display surface.

The display path for redbear-full:

Bootloader linear framebuffer
  → vesad (initfs, service 20): temporary FB handoff for text console
  → redox-drm (initfs, service 30): detects GPU hardware, takes over via DRM/KMS
  → redox-drm (rootfs, service 14): full DRM driver with 3D (Mesa)
  → KWin compositor: DRM/KMS master, composites desktop via /scheme/drm/card0

For redbear-mini: vesad handles the bootloader framebuffer for the text-only console. No GPU driver loads — mini is text-only by design.

After GPU detection, any code that opens /scheme/display.vesa/ is incorrect. The correct display path is /scheme/drm/card0 via the DRM scheme.

Rationale: VESA is a legacy BIOS-era standard with no hardware acceleration, no mode setting beyond what the bootloader provides, no 3D, and no future. Red Bear OS targets real GPU hardware with full DRM/KMS and Mesa support. vesad serves only as a bridge between bootloader FB and the real GPU driver — it is never the final display path.

This policy also covers future GPU driver work: any new GPU support (nouveau Rust reimplementation, ARM Mali, etc.) must go through the redox-drm + DRM/KMS path, never through VESA fallback.

FULL 3D DESKTOP — NON-NEGOTIABLE

Red Bear OS must ship with a fully hardware-accelerated 3D desktop on redbear-full. Software rendering fallbacks (LLVMpipe, softpipe) are NOT acceptable as the primary render path. The Mesa build must include hardware GPU drivers and export proper CMake configurations so Qt6/KWin can link against OpenGL/EGL/GBM.

Why This Is Non-Negotiable

Reason Detail
KDE Plasma requires 3D KWin is a hardware-composited window manager. It requires libEGL, libGLESv2, and libgbm from Mesa to composite the desktop. Without these, the greeter (SDDM) and desktop session (Plasma) cannot render.
Qt6 Quick requires OpenGL Qt6Quick/QML rendering is GPU-accelerated. The QML JIT compiles shaders that execute on the GPU via OpenGL ES 2.0. Without hardware OpenGL, QML scenes render as blank or crash.
No compromises on features Disabling OpenGL/EGL/GBM in Qt6 (-DFEATURE_opengl=OFF, -DFEATURE_egl=OFF) is a POLICY VIOLATION. These features are required by the desktop path and must be fixed, not disabled.
Mesa is a hard build dependency mesa, libdrm, libepoxy, redox-drm are required packages in redbear-full. If they fail to build, the root cause must be fixed — never worked around by disabling features or removing packages.

Build Chain Integrity

The GPU stack depends on this build chain:

mesa → libdrm → libepoxy → redox-drm → qtbase → qtdeclarative → qtwayland
  → KF6 Frameworks → KWin → SDDM → KDE Plasma

If MESA fails to build or exports incorrect CMake configurations, the ENTIRE desktop chain is blocked. Every package in this chain must compile and link correctly against the Redox target.

Mesa Build Requirements for Redox

Requirement Why
-Dgallium-drivers=swrast,virgl,iris,crocus Software + VirtIO + Intel GPU drivers
-Dvulkan-drivers=swrast Software Vulkan (for future Vulkan-based compositing)
-Degl=enabled EGL library (required by Qt6, KWin, SDDM)
-Dgbm=enabled Generic Buffer Manager (required by KWin DRM backend)
-Dllvm=enabled LLVMpipe software rasterizer (fallback, NOT primary)
-Dshared-glapi=enabled Shared GL dispatch (required for multi-vendor GPU)
-Dosmesa=true Off-screen Mesa (required by some Qt tests)
Stub headers provided sys/ioccom.h must be available via sysroot or recipe CFLAGS for DRM uapi

Troubleshooting Mesa → Qt6 CMake Chain

When Qt6's CMake reports Feature "opengles2": Forcing to "ON" breaks its condition or Feature "egl": Forcing to "ON" breaks its condition, the root cause is that Mesa's CMake configuration files (installed to the sysroot) enable features that the cross-compilation toolchain cannot satisfy at CMake time. The fix is:

  1. Verify Mesa's .pc files (egl.pc, glesv2.pc, gbm.pc) are in the sysroot
  2. Verify Mesa's CMake config (lib/cmake/mesa/) exports proper include paths
  3. Check that the Redox toolchain has working EGL/GLES headers
  4. If Qt6's CMake feature detection fails on the cross-compiled target, add -DQT_FEATURE_opengles2=ON -DQT_FEATURE_egl=ON explicitly (overriding the auto-detection) AND ensure the sysroot has the required libraries

Never disable OpenGL/EGL as a workaround. If Qt6 can't find mesa's CMake configs, fix Mesa's build or Qt6's CMake detection — do not remove 3D support.

No Package Removal Policy

The following packages are MANDATORY in redbear-full and must never be removed or suppressed (ignored):

Package Reason
mesa OpenGL/EGL/GBM provider — required by Qt6, KWin, SDDM
libdrm DRM userspace library — required by mesa and redox-drm
libepoxy OpenGL function pointer manager — required by Qt6
redox-drm DRM/KMS display driver — required for GPU display output
qtbase Qt6 Core — required by entire KDE stack
qtdeclarative Qt6 QML — required by SDDM greeter and KDE Plasma
qtwayland Qt6 Wayland backend — required for Wayland compositing
kwin KWin compositor — the Wayland compositor/window manager
sddm SDDM display manager — the login screen

If ANY of these packages fails to build, the root cause must be fixed immediately. There is no "ignore" workaround for mandatory desktop packages.

ZERO TOLERANCE FOR STUBS

Red Bear OS has zero tolerance for stubs, placeholders, fake implementations, skeleton code, unimplemented functions, or any other "make it compile" shortcut.

What counts as a stub

Any of the following:

  • A function or method that returns a hardcoded value instead of computing the real result
  • A trait implementation where methods log "not implemented" or return empty/default values
  • A struct that stores fields but never uses them for real work
  • A file that exists to satisfy an import but contains no real logic
  • A // TODO: implement comment followed by a dummy return
  • A driver that creates synthetic data (fake EDID, hardcoded modes) instead of querying the hardware
  • A todo!() or unimplemented!() macro anywhere in non-test code

The rule

As soon as a stub is detected, it must be replaced with real, sophisticated, comprehensive code in the same work session. No exceptions. No "I'll come back to it." No "this is good enough for now."

A stub found in the tree is a bug — not a precedent to follow, not a placeholder to defer, not an acceptable intermediate state. Every stub is technical debt that compounds daily.

Required response to a stub

When you encounter a stub:

  1. Stop what you are doing. The stub takes priority.
  2. Understand the interface. Read the trait, API contract, or specification the stub is supposed to implement.
  3. Implement it comprehensively. Real logic, real hardware communication, real error handling, real edge cases.
  4. Verify it works. Run cargo check, tests, or build verification.
Stub pattern Required fix
fn detect_connectors() -> Vec<ConnectorInfo> { vec![] } Implement real hardware enumeration with proper protocol
fn handle_irq() -> Ok(None) Implement real interrupt handling with event dispatch
synthetic_edid() when hardware can provide real EDID Query the device via the proper protocol
Hardcoded mode "1280x720" Query the display hardware for actual supported modes
_firmware: HashMap<String, Vec<u8>> (unused parameter) Use the firmware data in device initialization
Ok(self.vblank_count.fetch_add(1, Ordering::SeqCst)) in page_flip Submit real buffer to hardware and wait for display
todo!() / unimplemented!() Replace with full implementation

Why this matters

Stubs are worse than missing code because they:

  • Hide missing functionality — the system appears to work but silently does nothing
  • Block real testing — you can't verify behavior against hardware when the code doesn't talk to hardware
  • Create false confidence — "it compiles" becomes a substitute for "it works"
  • Compound over time — one stub leads to another as callers assume the interface is real
  • Waste debugging time — hours spent tracing why something "doesn't display" when the driver never sent a command

Enforcement

  • Code reviews must reject any PR containing stubs
  • Any agent or developer that introduces a stub must replace it before the session ends
  • If a stub cannot be replaced (missing specification, blocked dependency), document it as a known gap in local/docs/ — but never leave it in the code as a stub. Remove the code path entirely and add a clear error message instead.

LINUX REFERENCE SOURCE POLICY

local/reference/linux-7.0/ (or later) contains a full Linux kernel source tree for cross-referencing driver behavior, hardware initialization sequences, register definitions, and error handling patterns.

Rules:

  • NEVER delete the reference tree. It is gitignored but permanent.
  • ALWAYS consult the Linux source when building or fixing drivers, daemons, or any subsystem that has a Linux counterpart (audio/HDA, GPU/DRM, networking, USB, PCI, ACPI, input, storage, filesystems, scheduler, memory management).
  • Update the reference tree when a new stable Linux version is needed: git -C local/reference/linux-7.0 fetch --depth=1 origin tag:v7.x --force
  • The reference tree is read-only for consultation purposes. No modifications.
  • Location: local/reference/ is gitignored. It survives make clean and make distclean.

DURABILITY POLICY

Every change to an upstream-owned source tree (anything under recipes/*/source/) must be mirrored into a durable location in the same work session it was made. A change that exists only inside a fetched source tree is not preserved.

Required actions after any source-tree edit:

  1. Commit your changes in the fork repo: git -C local/sources/<component>/ commit -m "...".
  2. Push if sharing: git -C local/sources/<component>/ push.

Why: make distclean, make clean, and source immutable archivedes all discard or replace recipes/*/source/ trees. Only local/sources/, local/recipes/, tracked configs, local/docs/, local/patches/, and sources/redbear-0.1.0/ survive.

Examples of changes that require immediate committing:

What you edited Where to commit
local/sources/relibc/src/header/sys_select/mod.rs git -C local/sources/relibc commit
local/sources/relibc/src/header/signal/cbindgen.toml same repo as above
local/sources/userutils/res/issue git -C local/sources/userutils commit
local/sources/kernel/src/... git -C local/sources/kernel commit

What does NOT need committing to fork repos: Files that already live in local/recipes/, tracked config/redbear-*.toml, or any path that is already git-tracked in the main repo.

What does NOT need committing to fork repos: Files that already live in local/recipes/, tracked config/redbear-*.toml, or any path that is already git-tracked in the main repo.

BUILD SYSTEM POLICIES

Build Durability Rule — Every Build Lands in the Repo

Every successful repo cook produces two durable artifacts:

  1. Package in the repo: repo/x86_64-unknown-redox/<name>.pkgar + <name>.toml
  2. Committed source: All source modifications are committed in the appropriate local/sources/<component>/ git repo

A build is not complete until the repo artifacts exist:

# After cooking, verify the package is in the repo
./target/release/repo find <package>

# Check the repo manifest exists
ls repo/x86_64-unknown-redox/<package>.toml
ls repo/x86_64-unknown-redox/<package>.pkgar

If a package was built but the repo artifacts are missing, the build did not complete. Re-run repo cook <package> to regenerate them.

If source changes were made but not committed to local/sources/<component>/, commit them there.

Cascade Rebuild Rule

When a low-level package changes (relibc, kernel, base, or any library), all packages that depend on it must be rebuilt. A stale dependent silently produces link errors, ABI mismatches, or runtime crashes.

Use the cascade rebuild script:

# 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:

  1. Finds all packages whose recipe.toml lists the target in dependencies
  2. Transitively expands the reverse dependency graph (BFS)
  3. Builds the root package(s) first, then dependents in order
  4. Pushes all rebuilt packages to the sysroot

When to use cascade rebuilds:

  • After changing relibc headers or ABI
  • After rebuilding a shared library (ncurses, zlib, openssl, etc.)
  • After kernel ABI changes that affect userspace
  • After any change to a package listed in other packages' dependencies

When NOT to use cascade rebuilds:

  • Standalone applications with no dependents (editors, games, utilities)
  • Terminal/leaf packages that nothing depends on

AMD-FIRST INTEGRATION PATH

See local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md for the canonical desktop path plan.

Target: AMD64 bare metal, with AMD and Intel machines treated as equal-priority hardware targets.

amdgpu is 6M+ lines — 18x larger than Intel i915. LinuxKPI compat approach mandatory.

Bare Metal Boot Status

Component Status Detail
UEFI boot x86_64 bootloader functional
AMD CPUs Ryzen Threadripper 128-thread verified
ACPI Boot-baseline complete RSDP/SDT checksums, MADT types 0x4/0x5/0x9/0xA, LVT NMI, FADT shutdown/reboot, explicit RSDP_ADDR forwarding into acpid, x86 BIOS-search AML fallback, and bounded AML-backed power enumeration are present; the explicit AML bootstrap producer contract and broader robustness still remain open — see local/docs/ACPI-IMPROVEMENT-PLAN.md
ACPI shutdown 🚧 PM1a/PM1b S5 via \_S5 AML exists, but shutdown robustness and bounded validation are still open
ACPI reboot 🚧 Reset register + keyboard controller fallback exist, but broader reboot correctness and bounded validation are still open
ACPI power 🚧 \_PS0/\_PS3/\_PPC AML methods are available and the runtime power surface performs bounded AML-backed enumeration, but bootstrap preconditions and validation are still too weak for stronger support claims; see local/docs/ACPI-IMPROVEMENT-PLAN.md
x2APIC/SMP Multi-core works
IOMMU 🚧 QEMU first-use proof now passes; real hardware validation still open
AMD GPU 🚧 MMIO mapped, bounded Red Bear display glue path builds, MSI-X wired; imported Linux AMD DC/TTM/core remain builds and included in redbear-full (2026-04-29); no hardware validation yet

Phased Roadmap (historical P0P6)

Note: The P0P6 numbering below is the historical hardware-enablement sequence. The canonical current desktop path plan uses a new Phase 15 structure documented in local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md (v2.0, 2026-04-16).

Phase Duration Delivers
P0: Fix ACPI for AMD 4-6 weeks Materially complete — boots on modern AMD bare metal; see local/docs/ACPI-IMPROVEMENT-PLAN.md for forward work
P1: Driver infrastructure 8-12 weeks Complete — redox-driver-sys + linux-kpi + firmware-loader + pcid /config + MSI-X (compiles)
P2: AMD GPU display 12-16 weeks 🚧 Partial — redox-drm + bounded Red Bear AMD display glue build; imported Linux AMD DC/TTM/core remain builds and included in redbear-full (2026-04-29); Intel driver compiles, no HW validation
P3: POSIX + input 4-8 weeks 🚧 Build-side work substantially complete — the relibc source fork carries the bounded fd-event, semaphore, and waitid compatibility surface needed by current downstreams, while broader runtime validation and input-stack maturity remain open
P4: Wayland compositor 4-6 weeks 🚧 Partial — libwayland/Qt6 Wayland/Mesa EGL+GBM+GLES2/Qt6 OpenGL now build, but compositor/runtime validation is still incomplete
P5: DML2 enablement partial 🚧 Historical DML2 config work landed, but the current retained AMDGPU build no longer treats imported DML2/TTM as part of the default bounded compile path; libdrm amdgpu , iommu daemon now builds; hardware validation still open
P6: KDE Plasma 12-16 weeks 🚧 In progress — Qt6 , KF6 32/32 , Mesa EGL/GBM/GLES2 , kf6-kcmutils , kf6-kwayland , kdecoration , KWin 🔄 building

Canonical Desktop Path (current plan)

The current execution plan uses a three-track model with new Phase 15 numbering:

  • Phase 1: Runtime Substrate Validation (46 weeks)
  • Phase 2: Wayland Compositor Proof (46 weeks)
  • Phase 3: KWin Desktop Session (610 weeks)
  • Phase 4: KDE Plasma Session (812 weeks)
  • Phase 5: Hardware GPU Enablement (1220 weeks, parallel with 34)

See local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md for full detail.

Total to software-rendered KDE Plasma: 2234 weeks (~68 months) with 2 developers. Total to hardware-accelerated KDE Plasma: 3454 weeks (~813 months) with 2 developers.

Critical Path

Phase 1 (runtime substrate) → Phase 2 (software compositor) → Phase 3 (KWin session) → Phase 4 (KDE Plasma)
                               Phase 5 (hardware GPU, parallel with Phases 34)

Custom Crates (P1/P2)

  1. redox-driver-syslocal/recipes/drivers/redox-driver-sys/source/ — Safe Rust wrappers for scheme:memory, scheme:irq, scheme:pci + hardware quirks system (src/quirks/)
  2. linux-kpilocal/recipes/drivers/linux-kpi/source/ — C headers translating Linux kernel APIs → redox-driver-sys; includes pci_get_quirk_flags() C FFI for quirk queries. GPU and Wi-Fi drivers only — linux-kpi does NOT cover USB. It provides PCI, DMA, IRQ, DRM, networking (ieee80211/nl80211/mac80211), firmware, and related kernel infrastructure headers, but contains zero USB headers, USB device ID tables, or USB driver implementations.
  3. redox-drmlocal/recipes/gpu/redox-drm/source/ — DRM scheme daemon (AMD + Intel drivers); consumes quirk flags for MSI/MSI-X fallback and DISABLE_ACCEL
  4. firmware-loaderlocal/recipes/system/firmware-loader/source/ — scheme:firmware for GPU blobs
  5. amdgpulocal/recipes/gpu/amdgpu/source/ — AMD DC C port with linux-kpi compat; can query quirks via pci_has_quirk() FFI
  6. redbear-sessiondlocal/recipes/system/redbear-sessiond/source/ — Rust D-Bus session broker exposing org.freedesktop.login1 subset for KWin (uses zbus)
  7. redbear-dbus-serviceslocal/recipes/system/redbear-dbus-services/ — D-Bus activation .service files and XML policy files for system and session buses

All custom work goes in local/ — see local/AGENTS.md for fork model usage.

NOTES

  • Build requires Linux x86_64 host, 8GB+ RAM, 20GB+ disk
  • QEMU used for testing (make qemu). VirtualBox also supported
  • The repo binary (cookbook CLI) may crash with TUI in non-interactive environments — use CI=1
  • No git submodules — external repos managed via recipe source URLs and repo manifests
  • Historical integration report removed (2026-04-16); see local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md for current state

WARNING POLICY

When presented with a compiler warning, linker warning, runtime warning, or test warning, the project treats it as a signal requiring action — not as noise to be silenced or deferred.

  • Investigate every warning. Understand what causes it and whether it indicates a real defect.
  • Fix the root cause when feasible. Prefer comprehensive fixes over workarounds.
  • Suppress only as last resort, with a comment explaining why the warning is known-safe and why suppression is the correct choice for that specific case.
  • Never ignore warnings silently. An unexplained warning in the build is a defect in discipline, not just in code.

This applies to all subsystems: kernel, relibc, drivers, userspace daemons, and build tooling.

SUBSYSTEM PRIORITY AND ORDER

Red Bear OS should treat low-level controllers, USB, Wi-Fi, and Bluetooth as first-class subsystem targets.

For PCI interrupt plumbing, IRQ delivery quality, MSI/MSI-X follow-up, low-level controller runtime-proof sequencing, and IOMMU/interrupt-remapping quality, the canonical current plan is:

  • local/docs/IRQ-AND-LOWLEVEL-CONTROLLERS-ENHANCEMENT-PLAN.md

Use that file as the execution authority and current robustness judgment for PCI/IRQ work. Higher- level summaries in README.md, docs/README.md, and this file should stay aligned with its validation language rather than acting as competing rollout plans.

Current execution order:

  1. low-level controllers / IRQ quality / runtime-proof
  2. USB controller and topology maturity
  3. Wi-Fi native control-plane and one bounded driver path
  4. Bluetooth host/controller path
  5. desktop/session compatibility layers on top of those runtime services

Current blocker emphasis:

  • low-level controller quality blocks reliable USB and Wi-Fi validation
  • USB maturity blocks the realistic first Bluetooth transport path
  • Wi-Fi and Bluetooth should not be treated as optional polish; both remain missing subsystem work that must be implemented fully, but in the right order