Files
RedBear-OS/AGENTS.md
T
vasilito 2b72f61e41 docs: amend NO OVERLAY-STYLE PATCHES policy — Red Bear forks allowed for big external projects (mesa, wayland, qt, KF6, KWin, SDDM, llvm, libdrm)
The blanket reading from commit 5396e6c3c 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 silently clobber our work. That is not a full fork, that is a
liability.

Replace the single hard prohibition with a two-rule model:

  Rule 1 — In-tree Red Bear components (kernel, relibc, base, installer,
  bootloader) and small Red Bear-initiated packages: NO overlay, NO
  local fork of mainline. Direct edits in recipes/<pkg>/source/ and
  recipes/<pkg>/recipe.toml. No symlinks, no patch files.

  Rule 2 — Big external projects (mesa, wayland, qt, KF6, KWin, SDDM,
  llvm, libdrm, redox-drm, libepoxy, etc.): Red Bear fork at
  local/sources/<component>/ is mandatory. The mainline recipe points
  at the fork via 'git = ...' or a 'Local' source type. We own the
  source, the recipe just builds it.

Both AGENTS.md (top-level) and local/AGENTS.md updated. Cross-references
to the section name in the anti-pattern tables at the bottom of the
policy remain valid.
2026-06-09 16:56:22 +03:00

1186 lines
67 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 maintains its own git forks of every patched component under `local/sources/`.
Sources are directly editable — no patches, no indirection. Changes are committed
to the appropriate fork repo. Durable Red Bear state belongs in `local/sources/`,
`local/recipes/`, `local/docs/`, and tracked Red Bear configs.
The current baseline is **Red Bear OS 0.1.0** (Redox snapshot at build-system commit `f55acba68`).
## 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/` or `local/recipes/`. No dependiendo on upstream crates that we cannot fix ourselves. |
| **No waiting for upstream** | If a dependency breaks, we fix it in our fork. 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 forked to `local/sources/` or pinned to a frozen archive. Exceptions: unmodified upstream packages with pinned revisions. |
| **Our code, our fixes** | When crate APIs change (e.g., `libredox 0.1.0``0.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>/`. 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)
**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):**
```bash
# 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:**
```bash
# 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. **Auditability**`git 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: Red Bear fork at `local/sources/<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` of an upstream sync would
silently destroy our work; every `git pull` from upstream becomes a
merge conflict resolution exercise. **The Red Bear fork at
`local/sources/<component>/` is the durable, audit-friendly location
for these components**, and the mainline `recipes/<pkg>/recipe.toml`
points at the fork via `git = "..."` or a `Local` source type. This
is the full-fork model applied to a project of meaningful size:
**we own the source, the recipe just builds it**.
| Component class | Examples | Why a Red Bear fork is mandatory |
|---|---|---|
| Mesa (OpenGL/Vulkan/EGL/GBM) | `local/recipes/libs/mesa/`, `local/sources/mesa/` | Multi-million-line external codebase; virgl disk cache, GBM dumb prime export, hardware driver work — every change must persist across upstream syncs |
| Wayland (protocol + compositors) | `local/sources/wayland/`, `local/sources/wayland-protocols/` | Protocol changes, KMS integration, libwayland for our platform — all need durable storage |
| Qt 6 stack (qtbase, qtdeclarative, qtwayland, qt5compat, …) | `local/sources/qtbase/`, `local/sources/qtdeclarative/`, `local/sources/qtwayland/`, … | KDE Plasma foundation; futex redox support, wayland guards, OpenGL/EGL fixes — these are dozens of patches per component, all must be durable |
| KF6 Frameworks (32 packages) | `local/sources/kf6-*/` (one fork per framework) | KConfig, KWayland, KCMUtils, Kirigami, etc. — each has Red Bear-specific platform integration that must not be clobbered |
| KWin (Wayland compositor + window manager) | `local/sources/kwin/` | The compositor. EGL/GBM integration, KWayland glue, hardware backend wiring — must be a fork |
| SDDM (display manager / greeter host) | `local/sources/sddm/` | Login screen, session launcher, PAM/elogind bridge — must be a fork |
| LLVM/Clang (compiler stack) | `local/sources/llvm-project/` | Patches for Redox target, libc++ relibc glue, linker driver tweaks — all must persist |
| libdrm (DRM userspace library) | `local/sources/libdrm/`, `local/recipes/libs/libdrm/` | ioctl bridge, PCI info, device enumeration — must be a fork |
| redox-drm (DRM/KMS scheme daemon) | `local/sources/redox-drm/`, `local/recipes/gpu/redox-drm/` | Intel + AMD display drivers; consumes quirk flags, MSI/MSI-X fallback, DISABLE_ACCEL — must be a fork |
| libepoxy (OpenGL function pointer manager) | `local/sources/libepoxy/` | EGL/GLX dispatch, dlsym workarounds for Mesa/Redox — must be a fork |
| Other big externals (fontconfig, freetype, xkeyboard-config, libinput, …) | `local/sources/<component>/` as needed | Same rule: any direct edit must live as a Red Bear fork |
**Where the fork lives:**
```
local/sources/<component>/ ← Red Bear fork (durable, git-tracked, commits here)
└── ... full source tree, Red Bear's edits committed here ...
recipes/<category>/<name>/recipe.toml ← mainline recipe pointing at the fork:
[source]
path = "../../../local/sources/<component>" # Local source type
# OR
git = "https://gitea.redbearos.org/redbear/<component>.git" # Our git remote
rev = "<pinned-redbear-revision>"
```
**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, redox-drm, libepoxy | `recipes/<pkg>/source/` is ephemeral — `make clean` and upstream syncs both destroy it. Edits there are guaranteed to be lost. |
| Patch files in `local/patches/<pkg>/*.patch` for these components | Patches are an upstream-merging anti-pattern. A `git apply` rebase against millions of lines of upstream code is fragile and unauditable. |
| `recipes/wip/<pkg>/source/` symlinks to `local/sources/<pkg>/` for these components | WIP is a transitional tool, not a durable fork. Move the fork to `local/sources/<component>/` and point the recipe at it. |
| Mixing a `local/sources/<component>/` fork with a `recipes/<pkg>/source/` overlay | The fork must own the source entirely. Two sources of truth is a half-forked, half-overlay state — pick one. |
**Why this rule is mandatory for big external projects:**
1. **Survival across `make clean` and upstream syncs**`recipes/<pkg>/source/` is regenerated on every fetch. A Red Bear fork at `local/sources/<component>/` survives because it is a separate git repo, owned by Red Bear, never touched by the build system.
2. **Auditability**`git -C local/sources/<component> log` shows every Red Bear edit, in order, attributed to the right author. No mixing with upstream Mesa/Wayland/Qt/KF6/KWin/SDDM/LLVM/libdrm commits.
3. **No merge conflicts on upstream pull** — When we eventually sync with a newer upstream Mesa/Wayland/Qt release, the Red Bear fork's branch is the only place where our edits live. The mainline recipe's `rev = "..."` advances; our fork rebases forward; no in-place merge conflict in `recipes/<pkg>/source/`.
4. **CI/CD reproducibility** — A test build on CI clones the fork from `gitea.redbearos.org` at a pinned revision, builds it, and the result is bit-identical. No overlay fixup script required.
5. **Ownership of critical surface** — Mesa, Wayland, Qt, KF6, KWin, SDDM, LLVM, libdrm, redox-drm, libepoxy are the GPU and desktop stack. We cannot afford to have our edits silently clobbered by `make clean` or a WIP refactor. These components must be forks.
**How to fork a big external project correctly:**
```bash
# 1. Create a Red Bear git repo at local/sources/<component>/
# (initialize or import from a frozen upstream snapshot)
mkdir -p local/sources/<component>
cd local/sources/<component>
git init
# ... import upstream source tree, make initial commit ...
# 2. Apply Red Bear's edits as commits in this repo
$EDITOR some/file.c
git add some/file.c
git commit -m "<component>: <change description>"
# 3. Point the mainline recipe at the fork
cat > recipes/<category>/<name>/recipe.toml <<EOF
[source]
path = "../../../local/sources/<component>"
[build]
template = "..."
EOF
# 4. Build via the standard pipeline
./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 `recipes/<pkg>/source/` and `recipes/<pkg>/recipe.toml`. No fork. |
| 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, redox-drm, libepoxy, …) | **Rule 2** — Red Bear fork at `local/sources/<component>/`. Recipe points at the fork. |
| 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. The
default for anything multi-thousand-line external is Rule 2.
### 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 (things we modify)
| 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 |
| Mesa | `local/recipes/libs/mesa/` | virgl disk cache, GBM dumb prime export |
| libdrm | `local/recipes/libs/libdrm/` | ioctl bridge, PCI info, device enumeration |
| QtBase | `local/recipes/qt/qtbase/` | futex redox support, wayland guards |
| redox-driver-sys | `local/recipes/drivers/redox-driver-sys/` | Hardware quirks system |
| linux-kpi | `local/recipes/drivers/linux-kpi/` | GPU + Wi-Fi compatibility headers |
| redox-drm | `local/recipes/gpu/redox-drm/` | Intel + AMD display drivers |
## BUILD SYSTEM DURABILITY — THE CARDINAL RULE
**SOURCE LIVES IN `local/sources/<component>/`. EDIT THERE. `recipes/*/source/` IS A SYMLINK
TO `local/sources/` — DO NOT EDIT THROUGH THE SYMLINK (git operations won't work). DO NOT
EDIT FILES IN `recipes/*/source/` DIRECTLY — GO TO `local/sources/<component>/` INSTEAD.**
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>/`** | The `source` symlink is for kernel/base, not for recipes. Recipes are either fully in `local/recipes/` (fork) or fully in `recipes/` (mainline). 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
Red Bear-owned recipes use the `Local` source type, pointing at the fork repo:
```toml
[source]
path = "../../../local/sources/base"
```
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
### Recommended Workflow (use the build script)
The canonical way to build Red Bear OS ISOs is through `local/scripts/build-redbear.sh`.
It enforces all project policies automatically:
```bash
# 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:
```bash
./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
```bash
# 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/`, 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:
```bash
# 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:
```bash
# 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-sys``local/recipes/drivers/redox-driver-sys/source/` — Safe Rust wrappers for scheme:memory, scheme:irq, scheme:pci + hardware quirks system (`src/quirks/`)
2. `linux-kpi``local/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-drm``local/recipes/gpu/redox-drm/source/` — DRM scheme daemon (AMD + Intel drivers); consumes quirk flags for MSI/MSI-X fallback and DISABLE_ACCEL
4. `firmware-loader``local/recipes/system/firmware-loader/source/` — scheme:firmware for GPU blobs
5. `amdgpu``local/recipes/gpu/amdgpu/source/` — AMD DC C port with linux-kpi compat; can query quirks via `pci_has_quirk()` FFI
6. `redbear-sessiond``local/recipes/system/redbear-sessiond/source/` — Rust D-Bus session broker exposing `org.freedesktop.login1` subset for KWin (uses `zbus`)
7. `redbear-dbus-services``local/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