Files
RedBear-OS/local/AGENTS.md
T
vasilito 579f45e65b diskd aggregator, /scheme/ plan, driver-manager fixes, build hardening
- Add diskd: Rust disk aggregator daemon (local/recipes/system/diskd/)
- Add SCHEME-NAMESPACE-POPULATION-PLAN.md: comprehensive /scheme/ design
- driver-manager: thread+timeout scheme check, always-wait, sync probe
- redoxfs: two-path disk discovery (diskd first, legacy fallback)
- prefix.mk: C++ header symlink durability fix
- pcid: fallback cleanup
- config/redbear-mini.toml: add diskd, remove tc/evdevd
- Docs: AGENTS.md, local/AGENTS.md, local/recipes/AGENTS.md updated
2026-06-12 23:59:19 +03:00

65 KiB
Raw Blame History

RED BEAR OS — FULL FORK OF REDOX OS

Red Bear OS is a FULL FORK. Upstream Redox is a reference, not a live dependency. Sources are NEVER auto-pulled from upstream. The recipes/ tree is a frozen snapshot that we will eventually delete entirely; all Red Bear work lives in local/.

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

Hard policy for in-tree Red Bear components. Explicit allowance for Red Bear forks of big external projects. The blanket "no patches anywhere" reading from commit 5396e6c3c was too broad — it would have forced every direct edit to mesa, wayland, qt, KF6, KWin, SDDM, llvm, libdrm, redox-drm, libepoxy, and similar multi-million-line external projects to live inside recipes/<pkg>/source/, where a make clean or upstream sync would clobber it. That is not a full fork, that is a liability. This section sets the two-rule model Red Bear OS actually follows.

Rule 1 — In-tree Red Bear components: NO overlay, NO local fork of mainline

These are Red Bear's own core components. They are small, fast-moving, and tightly coupled to the rest of the system. Direct edits go into the mainline recipes/<pkg>/recipe.toml and recipes/<pkg>/source/. There is no Red Bear fork in local/, no symlink layer, no patch file.

Component Why in-tree, not a fork
kernel (recipes/core/kernel) Red Bear's microkernel fork; ACPI, x2APIC, MSI/MSI-X, scheduling, branding — all live in recipes/core/kernel/source/ directly
relibc (recipes/core/relibc) Red Bear's C library fork; eventfd, signalfd, timerfd, waitid, SysV IPC, credential syscalls — all live in recipes/core/relibc/source/ directly
base (drivers) (recipes/core/base) Red Bear's userspace drivers fork; acpid, pcid, inputd, ps2d, xhcid migrations — all live in recipes/core/base/source/ directly
installer (recipes/core/installer) Red Bear's installer fork; ext4 + GRUB support — all lives in recipes/core/installer/source/ directly
bootloader (recipes/core/bootloader) Red Bear's UEFI bootloader fork; UEFI alloc fix, branding, GPT offset — all lives in recipes/core/bootloader/source/ directly

For these components, the mainline recipe IS the Red Bear fork. We own it. There is no upstream to sync with — it is our code, full stop. The same rule applies to Red Bear-initiated new packages in local/recipes/<category>/<name>/.

Want to change Where to do it (DIRECT EDIT)
Change a recipe's build config Edit local/recipes/<category>/<name>/recipe.toml directly. If the recipe is in upstream recipes/<category>/<name>/recipe.toml, fork it: copy to local/recipes/<category>/<name>/recipe.toml and edit there.
Change a source file Edit local/sources/<component>/<file>.rs directly.
Add a new package Create local/recipes/<category>/<name>/recipe.toml directly.
Change a build script Edit local/scripts/<script>.sh directly.
Change a config TOML Edit config/redbear-<name>.toml directly.

What is FORBIDDEN for in-tree components:

Anti-pattern Why it's wrong
local/patches/<pkg>/*.patch overlay files We are a full fork. Patches are an upstream-merging anti-pattern. If we need to change a Redox source, we fork the source into local/sources/<pkg>/ and commit the change there. Patches have no place in a full fork.
apply-patches.sh symlinks (recipes/ → local/recipes/) This is an overlay pattern, not a fork. Symlinks hide the fact that we're editing a Redox package in-place, breaking the "every package is a fork" guarantee. A full fork has no overlay layer.
Editing recipes/<pkg>/recipe.toml directly without a corresponding local/recipes/<pkg>/recipe.toml This makes our changes invisible to a full-fork audit. A git log on the upstream recipe shows our commits mixed with Redox's, and local/recipes/ becomes stale.
Creating a local/recipes/<pkg>/ fork but then symlinking recipes/<pkg>/ to it Same as the apply-patches.sh symlink. Hides the fork.
local/patches/redox-sessiond/P4-signal-implementations.patch style files in recipes/ pointing at ../../../local/patches/ The entire local/patches/ directory is historical-only and exists only because deleting it would invalidate git history. New patches go as git commits in local/sources/<component>/.
recipes/wip/<pkg>/source/ symlinks to local/sources/<pkg>/ Same as the apply-patches.sh symlinks. The WIP overlay is a transitional tool for upstream WIP packages; we should fork them into local/recipes/ and not rely on WIP at all.

How to fork an in-tree Redox package correctly (no overlay):

# 1. Copy the upstream recipe to local/recipes/ (the fork)
mkdir -p local/recipes/<category>/<name>
cp recipes/<category>/<name>/recipe.toml local/recipes/<category>/<name>/recipe.toml
cp -r recipes/<category>/<name>/source local/recipes/<category>/<name>/

# 2. Edit local/recipes/<category>/<name>/recipe.toml directly
$EDITOR local/recipes/<category>/<name>/recipe.toml

# 3. Commit the change in the main repo
git add local/recipes/<category>/<name>/
git commit -m "<category>/<name>: <change description>"

# 4. To make this fork override the upstream recipe, DELETE the upstream
#    recipe entirely (this is the fork model — we own it now, not an overlay)
git rm recipes/<category>/<name>
git commit -m "remove upstream <name> in favor of local fork"

Verification (audit) — every in-tree recipe must have exactly one source:

# A well-forked build has no recipes/<pkg>/ symlinks or duplicate recipe.toml
find recipes/ -name "recipe.toml" -path "*/local/*" -o -lname "*/local/*" 2>/dev/null

# If this command returns ANY results, the build is in an overlay state.
# Fix by forking the recipe properly per the steps above.

Why this matters for in-tree components:

  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>/.

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.

TUI CONVENTION — SINGLE BINARY, -i INTERACTIVE SWITCH

All Red Bear desktop applications that offer both a TUI and a CLI mode MUST be a single binary. The TUI code lives behind a tui feature inside the same crate; there is no separate -tui sub-crate, no cub-tui-style split. This applies to every program with a TUI in the Red Bear surface — cub, redbear-info, redbear-netctl, redbear-wifictl, redbear-btctl, and any future app.

App TUI -i flag Description
cub ratatui AUR package manager (search/info/install/build/query tabs)
redbear-info ratatui System dashboard (System/Hardware/Network/Integrations/Health tabs)
redbear-netctl ratatui Network profile manager console

Pattern (enforced for every program):

  • One binary (app), one Cargo.toml, one set of [[bin]] entries.
  • TUI module lives at src/tui/ (or similar) and is gated by a tui Cargo feature so headless --no-default-features builds still work.
  • app (no args) → launches TUI if stdin/stdout is a terminal, else prints help.
  • app -i / app --interactive → forces TUI launch (use this when piping through script(1) or when you want TUI even if stdout is redirected).
  • app <command> → CLI mode; subcommands are unchanged whether the TUI feature is enabled or not.
  • Use ratatui 0.30 + termion 4.0.6 (no crossterm).

Anti-patterns (forbidden):

  • A separate <app>-tui crate that the main binary depends on.
  • A separate <app>-gui binary that wraps a TUI launch.
  • A build flag that produces a different binary name for the TUI mode.

The TUI feature flag is for build-time size / dependency slimming (drop ratatui+termion when the target doesn't have a display, or when running strictly headless), not for splitting the binary. The recipe must build with default features (TUI on) unless the program is intentionally non-interactive (e.g. redbear-firmware, redbear-acmd are CLI-only by design and have no TUI).

This directory contains ALL custom work on top of mainline Redox. When mainline Redox updates (git pull on the build system repo), this directory is untouched.

STUB AND WORKAROUND POLICY — ZERO TOLERANCE

Red Bear OS has zero tolerance for stubs, workarounds, #ifdef-guarded no-ops, fake headers, sed/awk hacks, LD_PRELOAD tricks, rename-to-.disabled wrappers, or any other "make it compile" shortcut.

If something doesn't build because of a missing implementation, the ONLY acceptable response is to implement the missing functionality in the correct component:

Problem Correct Fix
eventfd() not found Implement eventfd() in relibc, generate sys/eventfd.h via cbindgen
signalfd() not found Implement signalfd() in relibc, generate sys/signalfd.h via cbindgen
Missing POSIX type Add it to the relibc header it belongs to, with proper stdint.h include chain
Compiler can't find header Fix the include path in the recipe's sysroot/cookbook, NOT by adding -I hacks
CMake can't find dependency Implement the dependency or fix pkg-config, NOT with -DFEATURE_x=OFF
Qt needs open_memstream Implement it in relibc — never add a static stub in Qt or libwayland source

Any stub found in the tree is a bug to be fixed, not a precedent to follow.

When relibc gains a function or type that obsoletes a previously-needed local stub, the stub MUST be removed and the dependency switched to relibc's implementation. Coexistence of stubs with real implementations causes header conflicts, linker errors, and silent ABI mismatches.

This applies to: relibc functions, kernel syscalls, C headers, CMake modules, pkg-config .pc files, Wayland protocol stubs, D-Bus service stubs, and any other layer of the stack.

No exceptions. No "temporary." No "until we fix it properly."

BUILD DURABILITY AND CASCADE POLICY

Every Build Lands in the Repo

Every successful repo cook <package> MUST produce durable artifacts:

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

A build is not complete until the repo artifacts exist. Verify after every cook:

./target/release/repo find <package>           # Must find the package
ls repo/x86_64-unknown-redox/<package>.toml     # Manifest must exist
ls repo/x86_64-unknown-redox/<package>.pkgar    # Archive must exist

If a package was built but the repo artifacts are missing, the build did not complete. If source changes were made but not committed to local/sources/<component>/, commit them there.

Cascade Rebuild Rule

When a low-level package changes, all packages that transitively depend on it must be rebuilt. A stale dependent silently produces link errors, ABI mismatches, or runtime crashes.

# Rebuild relibc and everything that depends on it
./local/scripts/rebuild-cascade.sh relibc

# Dry run: show what would be rebuilt without building
./local/scripts/rebuild-cascade.sh --dry-run relibc

# Multiple root packages
./local/scripts/rebuild-cascade.sh relibc ncurses

The script performs BFS over reverse dependencies: it finds all packages whose recipe.toml lists the target in dependencies, transitively expands, then builds root-first followed by dependents.

Always use cascade rebuilds after changing:

  • relibc (headers, ABI, any patches)
  • Kernel (syscall ABI changes)
  • Shared libraries (ncurses, zlib, openssl, etc.)
  • Any package listed in other packages' dependencies

Example: Changing relibc's sys/types/internal.h header requires rebuilding bison, m4, flex, and every other gnulib-based package that includes system headers through the relibc include chain.

DESIGN PRINCIPLE

Red Bear OS is a full fork based on frozen Redox OS snapshots:

  • We baseline on a specific Redox OS state and work from immutable, archived sources
  • The local/ directory contains our custom work — untouched by any source immutable archived
  • First-class configs use redbear-* naming (not my-*, which is gitignored)
  • Sources are NEVER auto-immutable archived from upstream — all changes are explicit, human-initiated

FREE/LIBRE SOFTWARE POLICY

Red Bear OS must remain a free/libre project.

  • Prefer components that are open-source, freely available to all users, or built in-tree by Red Bear.
  • Do not introduce proprietary, source-unavailable, paywalled, or redistributability-restricted dependencies into the tracked system surface.
  • When a dependency is dual-licensed under multiple free/open licenses, choose and document the option that is compatible with the Red Bear project surface.
  • For the greeter/login stack specifically, the current SHA-crypt verifier path is the pure-Rust sha-crypt crate, licensed MIT OR Apache-2.0; Red Bear treats it under the MIT option for compatibility with the project's free-software policy.

Build flow:

make all CONFIG_NAME=redbear-full
  → mk/config.mk resolves to the active desktop/graphics compile target
  → Desktop/graphics are available only on redbear-full
  → repo cook builds all packages from local sources (offline by default)
  → Each successful cook produces repo/<arch>/<name>.pkgar + <name>.toml
  → mk/disk.mk creates harddrive.img with Red Bear branding
  → REDBEAR_RELEASE=0.2.3 ensures immutable, archived sources

Cascade rebuild flow (when a low-level package changes):

./local/scripts/rebuild-cascade.sh <package>
  → Finds all packages whose recipe.toml lists <package> in dependencies
  → BFS expands the reverse dependency graph
  → Builds root package first, then dependents in dependency order
  → Pushes all rebuilt packages to sysroot
  → Every rebuilt package lands in repo/ (.pkgar + .toml)

Release flow:

# Sources are immutable — build from archives, never from network
./local/scripts/build-redbear.sh redbear-full

# Check for newer Redox snapshots (read-only, no side effects):
./local/scripts/check-upstream-releases.sh

# Provision a new release (explicit, human-initiated only):
./local/scripts/provision-release.sh --ref=<redox-tag> --release=0.2.0

ACTIVE COMPILE TARGETS

The supported compile targets are exactly three. All three work for both make all (harddrive.img) and make live (ISO):

  • redbear-full — Desktop/graphics-enabled target (Wayland + KDE + GPU drivers)
  • redbear-mini — Text-only console/recovery/install target
  • redbear-grub — Text-only target with GRUB boot manager

Desktop/graphics are available only on redbear-full.

RELEASE MODEL (FORK — NOT OVERLAY)

Red Bear OS releases are versioned by branch name. Active development is on the 0.2.3 branch, and the current Red Bear OS version is 0.2.3 — same as the branch name.

The release branches (with their corresponding sources/redbear-<ver>/ archive directories) are:

Branch Archive directory Status
0.1.0 sources/redbear-0.1.0/ Historical. Frozen. The original Redox snapshot at build-system commit f55acba68.
0.2.0 (next archive) Historical. Frozen.
0.2.1 (next archive) Historical. Frozen.
0.2.2 (next archive) Historical. Frozen.
0.2.3 (next archive) Current. Active development.
0.2.4 (future) Will be created by provision-release.sh --release=0.2.4

The archive directories are immutable. Each new release gets a fresh archive directory alongside the previous ones. Old releases are NEVER deleted.

How releases work:

  • Current development: 0.2.3 (the 0.2.3 branch — same name as the version)
  • All recipe sources are pinned with rev = "..." in recipe.toml
  • Archives are stored in sources/redbear-<ver>/ with a manifest and BLAKE3 checksums
  • Builds are offline by defaultREPO_OFFLINE=1 COOKBOOK_OFFLINE=true
  • NO silent upstream pulls — see AGENTS.md "NO SILENT UPSTREAM PULLS" section for the full policy. Any script or build target that silently pulls from upstream is a bug.
  • New releases are provisioned explicitly via provision-release.sh, never automatically
  • Old releases are NEVER deleted — each new release is added alongside existing ones

Checking for new Redox snapshots:

./local/scripts/check-upstream-releases.sh    # Read-only, zero side effects

Provisioning a new release:

./local/scripts/provision-release.sh --ref=<redox-tag> --release=0.2.0 [--dry-run]

Restoring sources from archives:

./local/scripts/restore-sources.sh --release=0.1.0

SOURCE-OF-TRUTH RULE (VERY IMPORTANT)

Treat the repository as two different layers with different durability guarantees:

1. Source archive layer — immutable per release

These paths are expected to be replaced, refetched, or regenerated when upstream changes:

  • recipes/*/source/
  • most of recipes/ outside our symlinked local/recipes/* release fork
  • config/desktop.toml, config/minimal.toml, and other mainline configs
  • generated build outputs under target/, build/, repo/, and recipe-local target/*

For relibc specifically, recipes/core/relibc/source/ is upstream-owned working source, not Red Bears durable storage location. We may build and validate there, but we must not rely on that tree alone to preserve Red Bear work.

2. Red Bear-owned layer — durable, must survive release provisioning

These paths are our actual long-term source of truth:

  • local/sources/ — Red Bear source forks (git repos, directly editable)
  • local/recipes/ — Red Bear recipe release fork and new packages
  • local/docs/ — Red Bear planning, validation, and integration documentation
  • tracked Red Bear configs such as config/redbear-*.toml

If we can fetch fresh upstream sources tomorrow, provision sources from sources/redbear-<release>/, verify local/recipes/*, and rebuild successfully, then the work is in the right place.

If a change exists only inside an upstream-owned recipes/*/source/ tree, then it is not yet preserved, even if the current build happens to pass.

Upstream-first rule for fast-moving components

Some components, especially relibc, are actively evolving upstream. For those areas, Red Bear must prefer the upstream solution whenever upstream already solves the same problem.

That means:

  • if our source fork has a fix that upstream still needs, keep it in the fork
  • if upstream lands an equivalent or better solution, prefer upstream and port our additional changes on top
  • do not keep Red Bear-specific code just because it existed first; keep it only while it still provides unique value

When upstream Redox already provides a package, crate, or subsystem for functionality that also exists in Red Bear local code, prefer the upstream Redox version by default unless the Red Bear implementation is materially better. Do not grow lower-quality in-house duplicates as a steady state.

For quirks and driver support specifically:

  • prefer improving and using the canonical redox-driver-sys path,
  • avoid maintaining separate lower-quality quirk engines when the same functionality belongs in redox-driver-sys,
  • if duplication is temporarily unavoidable, treat it as convergence work to remove, not as a permanent design.

Daily workflow

For any change to Red Bear-owned source:

  1. edit the source in local/sources/<component>/
  2. build: repo cook <component>
  3. test: make qemu
  4. commit: git -C local/sources/<component>/ commit
  5. push: git -C local/sources/<component>/ push

The success criterion is therefore:

We can sources are provisioned via provision-release.sh and archived in sources/redbear-/ build the project successfully.

Local recipe priority vs upstream WIP

When Red Bear maintains a local recipe and upstream contains a package with the same name under recipes/wip/*, Red Bear must prefer the local recipe unconditionally.

  • Use the local release fork symlink in recipes/*/<name> -> ../../local/recipes/...
  • Do not switch back to upstream WIP for active Red Bear builds
  • Re-evaluate only when upstream package exits WIP and becomes a normal maintained package
# Automated sync (preferred):
./local/scripts/check-upstream-releases.sh              # Check for new Redox snapshots (read-only)
./local/scripts/provision-release.sh --ref=<tag> --release=0.2.0 --dry-run   # Preview new release
make all CONFIG_NAME=redbear-full             # Rebuild OS

STRUCTURE

redox-master/                  ← git pull updates mainline Redox
├── config/
│   ├── desktop.toml           ← mainline configs (untouched)
│   ├── minimal.toml
│   ├── redbear-full.toml      ← Desktop/graphics target
│   ├── redbear-mini.toml      ← Text-only console/recovery target
│   ├── redbear-grub.toml      ← Text-only with GRUB boot manager
│   ├── redbear-grub-policy.toml ← GRUB policy fragment (bootloader = "grub", efi_partition_size = 16)
│   └── redbear-greeter-services.toml ← Greeter/auth/session-launch wiring fragment
├── recipes/                   ← mainline package recipes (untouched)
├── mk/                        ← mainline build system (untouched)
├── local/                     ← RED BEAR OS custom work
│   ├── AGENTS.md              ← This file
│   ├── config/                ← Legacy configs (my-*, gitignored)
│   ├── recipes/
│   │   ├── core/              ← ext4d (ext4 filesystem scheme daemon + mkfs tool), grub (GRUB 2.12 UEFI bootloader)
│   │   ├── branding/          ← redbear-release (os-release, hostname, motd)
│   │   ├── drivers/           ← redox-driver-sys, linux-kpi (DRM/GPU + Wi-Fi only — NOT USB — NOT input subsystem)
│   │   ├── gpu/               ← redox-drm (AMD + Intel display drivers), amdgpu (C port)
│   │   ├── system/            ← cub, diskd, evdevd, udev-shim, redbear-firmware, firmware-loader, redbear-hwutils, redbear-info, redbear-netctl, redbear-quirks, redbear-meta
│   │   │   ├── redbear-sessiond       ← org.freedesktop.login1 D-Bus session broker (zbus-based Rust daemon)
│   │   │   ├── redbear-authd          ← local-user authentication daemon (`/etc/passwd` + `/etc/shadow` + `/etc/group`)
│   │   │   ├── redbear-session-launch ← session bootstrap helper (uid/gid/env/runtime-dir handoff)
│   │   │   ├── redbear-greeter        ← greeter orchestrator package (`redbear-greeterd`, UI, compositor wrapper, staged assets)
│   │   │   ├── redbear-dbus-services  ← D-Bus .service activation files + XML policies
│   │   ├── wayland/           ← Wayland compositor (Phase 2)
│   │   └── kde/               ← KDE Plasma (Phases 34)
│   ├── sources/      ← Red Bear source forks (git repos, directly editable)
│   │   ├── kernel/    ←   Red Bear's kernel fork
│   │   ├── relibc/    ←   Red Bear's C library fork
│   │   ├── base/      ←   Red Bear's userspace drivers fork
│   │   ├── bootloader/←   Red Bear's bootloader fork
│   │   └── installer/ ←   Red Bear's installer fork
│   ├── Assets/                ← Branding assets (icon, loading background)
│   │   └── images/            ← Red Bear OS icon (1254x1254) + loading bg (1536x1024)
│   ├── firmware/              ← GPU firmware blobs (gitignored, fetched)
│   ├── scripts/
│   │   ├── rebuild-cascade.sh  ← Rebuild package + all dependents (BFS reverse-dep graph)
│   │   ├── provision-release.sh   ← Provision new release from Redox ref
│   │   ├── build-redbear.sh   ← Unified Red Bear OS build script
│   │   ├── fetch-firmware.sh  ← Download bounded AMD or Intel firmware subsets from linux-firmware
│   │   ├── test-drm-display-runtime.sh ← Shared bounded DRM/KMS display validation harness
│   │   ├── test-amd-gpu.sh    ← AMD wrapper for the DRM display validation harness
│   │   ├── test-intel-gpu.sh  ← Intel wrapper for the DRM display validation harness
│   │   ├── test-baremetal.sh  ← Bare metal test script
│   │   ├── build-redbear-wifictl-redox.sh ← Build redbear-wifictl for the Redox target with the repo toolchain
│   │   ├── test-iwlwifi-driver-runtime.sh ← Bounded Intel driver lifecycle check inside a target runtime
│   │   ├── test-wifi-control-runtime.sh ← Bounded Wi-Fi control/profile runtime check inside a target runtime
│   │   ├── test-wifi-baremetal-runtime.sh ← Strongest in-repo Wi-Fi runtime check on a real Red Bear target
│   │   ├── validate-wifi-vfio-host.sh ← Host-side VFIO passthrough readiness check for Intel Wi-Fi validation
│   │   ├── prepare-wifi-vfio.sh ← Bind/unbind Intel Wi-Fi PCI function for VFIO validation
│   │   ├── test-wifi-passthrough-qemu.sh ← QEMU/VFIO Wi-Fi validation harness with in-guest checks
│   │   ├── run-wifi-passthrough-validation.sh ← One-shot host wrapper for the full Wi-Fi passthrough validation flow
│   │   ├── package-wifi-validation-artifacts.sh ← Package Wi-Fi validation artifacts into one host-side tarball
│   │   ├── summarize-wifi-validation-artifacts.sh ← Summarize captured Wi-Fi validation artifacts for quick triage
│   │   ├── finalize-wifi-validation-run.sh ← Analyze a Wi-Fi capture bundle and package the final evidence set
│   │   ├── validate-vm-network-baseline.sh ← Static repo-level VM networking baseline check
│   │   ├── test-vm-network-qemu.sh ← QEMU launcher for the VirtIO VM networking baseline
│   │   ├── test-vm-network-runtime.sh ← In-guest runtime check for the VM networking baseline
│   │   ├── test-ps2-qemu.sh ← QEMU launcher for the bounded PS/2 + serio runtime proof
│   │   ├── test-timer-qemu.sh ← QEMU launcher for the bounded monotonic timer runtime proof
│   │   ├── test-lowlevel-controllers-qemu.sh ← Sequential wrapper for bounded low-level controller proofs
│   │   ├── test-usb-maturity-qemu.sh ← Sequential wrapper for bounded USB maturity proofs
│   │   └── test-greeter-qemu.sh ← Bounded QEMU proof for the Red Bear greeter/auth/session surface
│   └── docs/                  ← Integration docs

HOW TO BUILD RED BEAR OS

# Build targets (all three work for both `make all` and `make live`)
./local/scripts/build-redbear.sh redbear-full     # Desktop/graphics target
./local/scripts/build-redbear.sh redbear-mini     # Text-only console/recovery target
./local/scripts/build-redbear.sh redbear-grub     # Text-only with GRUB boot manager

# Or manually:
make all CONFIG_NAME=redbear-full                 # Desktop/graphics → harddrive.img
make all CONFIG_NAME=redbear-mini                 # Text-only → harddrive.img
make all CONFIG_NAME=redbear-grub                 # Text-only + GRUB → harddrive.img

# Live ISO (for real bare metal)
make live CONFIG_NAME=redbear-full                # Full desktop live ISO
make live CONFIG_NAME=redbear-mini                # Text-only mini live ISO
make live CONFIG_NAME=redbear-grub                # Text-only mini live ISO with GRUB

# Or using the helper:
scripts/build-iso.sh redbear-full                 # Full desktop live ISO
scripts/build-iso.sh redbear-mini                 # Text-only mini (default)
scripts/build-iso.sh redbear-grub                 # Text-only + GRUB

# Rebuild a package and all its dependents (cascade)
./local/scripts/rebuild-cascade.sh relibc         # Rebuild relibc + all dependents
./local/scripts/rebuild-cascade.sh --dry-run ncurses  # Show cascade without building

# VM-network baseline validation helpers
./local/scripts/validate-vm-network-baseline.sh
./local/scripts/test-vm-network-qemu.sh redbear-mini
# Then run inside the guest:
#   ./local/scripts/test-vm-network-runtime.sh

# Phase 1 runtime-substrate validation (canonical plan: CONSOLE-TO-KDE v6.0)
# firmware-loader, DRM/KMS, time — covers acceptance areas + POSIX compat)
./local/scripts/test-phase1-runtime.sh --qemu redbear-full

# Legacy Phase 1 desktop-substrate validation (still works)
./local/scripts/test-phase1-desktop-substrate.sh --qemu redbear-full

# Phase 1 POSIX compatibility tests (inside guest)
# Run inside the guest after boot:
#   cd /home/user/relibc-phase1-tests && ./test_signalfd_wayland && ./test_timerfd_qt6 && ...
# Or use the test harness:
./local/scripts/test-phase1-runtime.sh --guest

# Legacy Phase 3 runtime-substrate validation (historical P0-P6 numbering; script still works)
./local/scripts/test-phase3-runtime-substrate.sh --qemu redbear-full

# Low-level controller validation
./local/scripts/test-xhci-irq-qemu.sh --check
./local/scripts/test-msix-qemu.sh
./local/scripts/test-iommu-qemu.sh
./local/scripts/test-ps2-qemu.sh --check
./local/scripts/test-timer-qemu.sh --check
./local/scripts/test-lowlevel-controllers-qemu.sh
./local/scripts/test-usb-storage-qemu.sh
./local/scripts/test-usb-qemu.sh --check
./local/scripts/test-usb-maturity-qemu.sh

# The current xHCI proof checks for an interrupt-driven mode in boot logs.
# The current MSI-X proof uses the live virtio-net path in QEMU.
# The current IOMMU proof runs a guest-driven first-use self-test and checks that discovered
# AMD-Vi units initialize and drain events successfully in QEMU.
# The current PS/2 proof checks serio node visibility and then hands off to the existing Phase 3
# input-path checker inside the guest.
# The current timer proof checks that /scheme/time/CLOCK_MONOTONIC advances across two guest reads.
# The aggregate low-level wrapper runs xHCI, IOMMU, PS/2, and timer proofs in sequence.
# The USB storage proof now verifies usbscsid autospawn plus bounded sector-0 readback against a
# host-seeded pattern, while guest-side write verification is still open.
# The aggregate USB wrapper runs xHCI mode, full USB stack, and USB storage readback proofs in sequence.

# Legacy Phase 4 Wayland runtime validation (historical P0-P6 numbering; script still works)
./local/scripts/build-redbear.sh redbear-full
./local/scripts/test-phase4-wayland-qemu.sh
# Then run inside the guest:
#   redbear-phase4-wayland-check

# Legacy Phase 5 desktop/network plumbing validation (historical P0-P6 numbering; script still works)
./local/scripts/build-redbear.sh redbear-full
./local/scripts/test-phase5-network-qemu.sh --check
# Then run inside the guest:
#   redbear-phase5-network-check

# Experimental Red Bear greeter/login validation
./local/scripts/build-redbear.sh redbear-full
./local/scripts/test-greeter-qemu.sh --check
# Then run inside the guest:
#   redbear-greeter-check
#   redbear-greeter-check --invalid root wrong

# Bounded Intel Wi-Fi runtime validation (real target or passthrough guest)
# Host preparation for VFIO-backed guests:
#   sudo ./local/scripts/validate-wifi-vfio-host.sh --host-pci 0000:xx:yy.z --expect-driver iwlwifi
#   sudo ./local/scripts/prepare-wifi-vfio.sh bind 0000:xx:yy.z
# Guest/target packaged checks:
#   redbear-phase5-wifi-check
#   redbear-phase5-wifi-link-check
#   redbear-phase5-wifi-run wifi-open-bounded wlan0 /tmp/redbear-phase5-wifi-capture.json
#   redbear-phase5-wifi-capture wifi-open-bounded wlan0 /tmp/redbear-phase5-wifi-capture.json
#   redbear-phase5-wifi-analyze /tmp/redbear-phase5-wifi-capture.json
# Helper scripts:
#   ./local/scripts/test-wifi-baremetal-runtime.sh
#   ./local/scripts/test-wifi-passthrough-qemu.sh --host-pci 0000:xx:yy.z --check --capture-output ./wifi-passthrough-capture.json
#   ./local/scripts/finalize-wifi-validation-run.sh ./wifi-passthrough-capture.json ./wifi-passthrough-artifacts.tar.gz

# Legacy Phase 6 KDE session-surface validation (historical P0-P6 numbering; script still works)
./local/scripts/build-redbear.sh redbear-full
./local/scripts/test-phase6-kde-qemu.sh --check
# Then run inside the guest:
#   redbear-phase6-kde-check

# redbear-netctl user-facing alias
redbear-netctl --help

# Single custom recipe:
./target/release/repo cook local/recipes/branding/redbear-release
./target/release/repo cook local/recipes/system/redbear-meta
./target/release/repo cook local/recipes/core/ext4d
./target/release/repo cook local/recipes/core/grub  # GRUB bootloader (host build, produces EFI binary)

# GRUB boot manager (installer-native):
make r.grub                                                   # Build GRUB recipe
make all CONFIG_NAME=redbear-grub                             # Build text-only target with GRUB
# Linux-compatible CLI (add local/scripts to PATH):
grub-install --target=x86_64-efi --disk-image=build/x86_64/harddrive.img
grub-mkconfig -o local/recipes/core/grub/grub.cfg
# Or legacy post-build script:
./local/scripts/install-grub.sh build/x86_64/harddrive.img    # Modify existing image

TRACKING MAINLINE CHANGES

When mainline updates affect our work:

Component What to check Where
Kernel ACPI, scheme, memory API changes recipes/core/kernel/source/src/
relibc New POSIX functions added upstream recipes/core/relibc/source/src/header/
Base drivers Driver API changes recipes/core/base/source/drivers/
libdrm DRM API updates recipes/libs/libdrm/ or the current in-tree libdrm location
Mesa OpenGL/Vulkan backend changes recipes/libs/mesa/
Build system Makefile/config changes mk/, src/
rsext4 ext4 crate API changes local/recipes/core/ext4d/source/ Cargo.toml
Installer ext4 dispatch, filesystem selection, GRUB bootloader local/sources/installer/ (git fork)
Quirks New Linux quirk entries to port local/recipes/drivers/redox-driver-sys/source/src/quirks/

PLANNING NOTES

  • docs/07-RED-BEAR-OS-IMPLEMENTATION-PLAN.md is the canonical public execution plan.
  • local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md (v6.0) is the canonical comprehensive plan — supersedes all individual subsystem docs. See it for current state, blockers, and roadmap.
  • local/docs/WAYLAND-IMPLEMENTATION-PLAN.md is the canonical Wayland subsystem plan beneath the desktop path. Use it for Wayland-specific stability, completeness, ownership, and runtime-proof sequencing.
  • local/docs/DRM-MODERNIZATION-EXECUTION-PLAN.md is the current DRM-focused execution plan beneath the canonical desktop path. It keeps Intel and AMD at the same evidence bar while separating display/KMS maturity from render/3D maturity.
  • Older GPU-specific docs (AMD-FIRST-INTEGRATION.md, HARDWARE-3D-ASSESSMENT.md, DMA-BUF-IMPROVEMENT-PLAN.md) have been retired and removed from the tree. Their content is subsumed by CONSOLE-TO-KDE-DESKTOP-PLAN.md and DRM-MODERNIZATION-EXECUTION-PLAN.md.
  • DESKTOP-STACK-CURRENT-STATUS.md has been retired — its content merged into CONSOLE-TO-KDE-DESKTOP-PLAN.md.
  • AMD and Intel machines are now equal-priority Red Bear OS targets; the older AMD-first path is preserved only in the canonical DRM plan and the desktop path plan.
  • local/docs/WIFI-IMPLEMENTATION-PLAN.md is the current Wi-Fi architecture and rollout plan, including the bounded role of linux-kpi and the native wireless control-plane direction.
  • local/docs/USB-IMPLEMENTATION-PLAN.md and local/docs/BLUETOOTH-IMPLEMENTATION-PLAN.md should also be treated as first-class subsystem plans, not as side notes.
  • local/docs/IRQ-AND-LOWLEVEL-CONTROLLERS-ENHANCEMENT-PLAN.md is the current umbrella plan for IRQ delivery, MSI/MSI-X quality, IOMMU validation, and other low-level controller completeness work.
  • local/docs/QUIRKS-SYSTEM.md documents the hardware quirks infrastructure: compiled-in tables, TOML runtime files, DMI matching, driver integration, and the linux-kpi C FFI bridge.
  • The historical QUIRKS-IMPROVEMENT-PLAN.md has been retired — quirks convergence is tracked in local/docs/QUIRKS-SYSTEM.md and the canonical desktop path plan.
  • local/docs/DBUS-INTEGRATION-PLAN.md is the canonical D-Bus architecture and implementation plan for KDE Plasma 6 on Wayland. It defines the phased approach to D-Bus service integration, the redbear-sessiond login1-compatible session broker, and the gap analysis for desktop-facing D-Bus services.
  • local/docs/GREETER-LOGIN-IMPLEMENTATION-PLAN.md is the canonical Red Bear-native greeter/login design and current implementation plan for the redbear-full desktop path. It defines the redbear-authd / redbear-session-launch / redbear-greeter split, service wiring, validation surface, and the current boundary between the active greeter path and the older redbear-validation-session helper flows.
  • local/docs/SCHEME-NAMESPACE-POPULATION-PLAN.md is the canonical /scheme/ namespace design document. It covers the diskd disk aggregator daemon, the /scheme/ completeness matrix, boot ordering (lived → diskd → rootfs), the two-path redoxfs disk discovery strategy (diskd first, legacy fallback), and future enhancements (hotplug, devfs-style aggregation, per-process namespaces). Cross-referenced with Linux (kobject/uevent), Fuchsia (Zircon/Component Manager), seL4 (CSpace), Plan 9 (per-process namespace), Genode (Platform session), and MINIX 3 (driver model).

The current execution order for these subsystem plans is:

  1. IRQ / low-level controller quality
  2. USB maturity
  3. Wi-Fi native control plane and first driver family
  4. Bluetooth controller + host path
  5. desktop/session compatibility on top of those runtime services

Do not present USB, Wi-Fi, Bluetooth, or low-level controller work as optional or secondary.

LINUX KERNEL SOURCE POLICY (CRITICAL)

Linux kernel source is REFERENCE ONLY — never a dependency.

If Red Bear OS needs something from the Linux kernel, it MUST be implemented in the project tree, using Linux source as reference only.

Policy (VERBATIM)

"If we need something from Linux kernel, it MUST be implemented in our tree, having Linux source as reference only" "If we need linux-input-headers than we must code redbear-input-headers"

linux-kpi Scope

local/recipes/drivers/linux-kpi/ covers ONLY:

  • DRM/GPU headers (drm/) — AMD + Intel display drivers
  • Wi-Fi headers (net/) — mac80211, cfg80211, nl80211
  • General kernel headers (linux/) — mm, device, irq, dma-mapping, firmware, etc.

Does NOT cover: USB, input subsystem, or any other Linux kernel subsystem.

Implementing New Linux-Compatibility Headers

When Red Bear needs Linux kernel headers for a new subsystem:

  1. Create local/recipes/drivers/redbear-<subsystem>-headers/
  2. Implement headers using Linux source as reference only
  3. Do NOT pull Linux source tarballs directly
  4. Do NOT use third-party tarballs that bundle Linux headers as a proxy
  5. Examples:
    • redbear-input-headers/ → linux/input.h, input-event-codes.h, uinput.h
    • redbear-usb-headers/ → linux/usb/ch9.h, etc. (NOT linux-kpi's purpose)

linux-input-headers — Policy Violation

recipes/wip/libs/linux-input-headers/ extracts Linux kernel input headers from the libevdev tarball. This is a policy violation — it pulls Linux headers via a third-party tarball. The correct implementation is redbear-input-headers in local/recipes/drivers/.

FILESYSTEMS

Red Bear OS supports three filesystems:

Filesystem Implementation Package Status
RedoxFS Mainline Redox (default) recipes/core/redoxfs Stable
ext4 rsext4 0.3 crate + ext4d scheme daemon local/recipes/core/ext4d Compiles + Installer wired
FAT (VFAT) fatfs 0.3.6 crate + fatd scheme daemon local/recipes/core/fatd Compiles + Tools tested + label write verified

ext4 Workspace (local/recipes/core/ext4d/source/)

ext4d/source/
├── Cargo.toml              ← Workspace: ext4-blockdev, ext4d, ext4-mkfs
├── ext4-blockdev/           ← BlockDevice trait impls for rsext4
│   ├── Cargo.toml           ← Features: default=["redox"], redox=[libredox,syscall]
│   └── src/
│       ├── lib.rs           ← Re-exports: FileDisk, RedoxDisk, Ext4Error, Ext4Result
│       ├── file_disk.rs     ← FileDisk: std::fs backed, builds on host Linux + Redox
│       └── redox_disk.rs    ← RedoxDisk: syscall/libredox backed, Redox-only (feature-gated)
├── ext4d/                   ← ext4 filesystem scheme daemon (Redox userspace)
│   ├── Cargo.toml           ← Features: default=["redox"], redox deps
│   └── src/
│       ├── main.rs          ← Daemon: fork, SIGTERM, scheme registration
│       ├── mount.rs         ← Scheme event loop (redox_scheme::SchemeSync)
│       ├── scheme.rs        ← Full ext4 FSScheme: open, read, write, mkdir, unlink, stat...
│       └── handle.rs        ← FileHandle, DirectoryHandle, Handle types
└── ext4-mkfs/               ← ext4 mkfs tool (host-side utility)
    ├── Cargo.toml
    └── src/main.rs          ← Creates ext4 images via FileDisk + rsext4::mkfs

Architecture:

  • ext4d is a Redox scheme daemon — it serves ext4 filesystems via scheme:ext4d
  • Uses rsext4 crate (pure Rust ext4 implementation) for all filesystem operations
  • FileDisk allows building/testing on the Linux host machine
  • RedoxDisk uses libredox + redox_syscall for actual Redox bare-metal I/O
  • Both impls are behind the redox feature flag — --no-default-features gives Linux-only

Recipe: Symlinked into mainline search path:

recipes/core/ext4d → local/recipes/core/ext4d

Config: ext4d is included in config/desktop.toml (mainline), which redbear-full.toml inherits.

Dependencies (from workspace Cargo.toml):

  • rsext4 = "0.3" — Pure Rust ext4 filesystem implementation
  • redox_syscall = "0.7.3" — Redox syscall wrappers (scheme, data types, flags)
  • redox-scheme = "0.11.0" — Scheme server framework
  • libredox = "0.1.13" — High-level Redox syscalls (open, read, write, fstat)
  • redox-path = "0.3.0" — Redox path utilities

Installer ext4 + GRUB Integration

The mainline installer is patched to support ext4 as an install target filesystem and GRUB as an alternative boot manager:

  • GeneralConfig.filesystem: Option<String> — TOML field, accepts "redoxfs" (default) or "ext4"
  • GeneralConfig.bootloader: Option<String> — TOML field, accepts "redox" (default) or "grub"
  • FilesystemType enum — dispatch tag used by install_inner
  • with_whole_disk_ext4() — GPT partition layout + ext4 mkfs + file sync (mirrors with_whole_disk)
  • Ext4SliceDisk<T> — adapts DiskWrapper to rsext4's BlockDevice trait
  • sync_host_dir_to_ext4() — copies staged sysroot files into ext4 filesystem
  • GRUB chainload: when bootloader = "grub", writes GRUB EFI + grub.cfg to ESP alongside Redox bootloader
  • CLI flags: --filesystem ext4 / --bootloader grub

Usage in config TOML:

[general]
filesystem = "ext4"        # "redoxfs" is default
bootloader = "grub"        # "redox" is default
efi_partition_size = 16    # Required for GRUB (default 1 MiB is too small)
filesystem_size = 10240    # MB

See local/docs/GRUB-INTEGRATION-PLAN.md for the full GRUB architecture and usage guide.

FAT (VFAT) Workspace (local/recipes/core/fatd/source/)

fatd/source/
├── Cargo.toml              ← Workspace: fat-blockdev, fatd, fat-mkfs, fat-label, fat-check
├── fat-blockdev/            ← Block device adapter for fatfs crate
│   ├── src/lib.rs           ← Re-exports: FileDisk (always), RedoxDisk (feature-gated)
│   ├── src/file_disk.rs     ← FileDisk: std::fs::File → Read+Write+Seek
│   └── src/redox_disk.rs    ← RedoxDisk: libredox → Read+Write+Seek (redox feature)
├── fatd/                    ← FAT filesystem scheme daemon (Redox userspace)
│   ├── src/main.rs          ← Daemon: fork, SIGTERM, dispatch to FileDisk/RedoxDisk
│   ├── src/mount.rs         ← Scheme event loop (redox_scheme::SchemeSync)
│   ├── src/scheme.rs        ← FatScheme: full FSScheme (open/read/write/mkdir/unlink/stat...)
│   └── src/handle.rs        ← FileHandle, DirectoryHandle, Handle types
├── fat-mkfs/                ← mkfs.fat equivalent (create FAT12/16/32 filesystems)
│   └── src/main.rs
├── fat-label/               ← fatlabel equivalent (read + write volume labels via BPB)
│   └── src/main.rs          ← `-s "LABEL"` writes label at BPB offset 43/71; verifies round-trip
└── fat-check/               ← fsck.fat equivalent (verify BPB, FAT chains, directory tree + safe repair)
    └── src/main.rs          ← `--repair` clears dirty flag, fixes FSInfo, reclaims lost clusters

Architecture: fatd is a Redox scheme daemon using fatfs v0.3.6 (MIT, no_std capable). FAT is for data volumes and ESP only — NOT for root filesystem. fscommon::BufStream wraps block device for mandatory caching.

Recipe: Symlinked into mainline search path:

recipes/core/fatd → ../../local/recipes/core/fatd

Config: Packages included via config/redbear-device-services.toml (inherited by redbear-full.toml and redbear-mini.toml). Init service at /usr/lib/init.d/15_fatd.service.

Dependencies: fatfs 0.3.6, fscommon 0.1.1, redox_syscall, redox-scheme, libredox, libc

Tool verification status (2026-04-17):

  • fat-mkfs: Creates FAT12/16/32, labels, auto-detection, cluster size option (-c), tested up to 1GB
  • fat-label: Reads labels; writes BPB + creates/updates root-directory volume-label entry; verifies round-trip on all FAT types (including previously unlabeled volumes)
  • fat-check: BPB validation, boot signature check, directory tree walk, cluster stats; safe repair (dirty flag including FAT12, FSInfo, lost clusters, orphaned LFN). Handles 0xFFFFFFFF FSInfo sentinel on fresh images.
  • fatd: Compiles (links on Redox target only — expected). frename + rmdir non-empty check implemented. NOT runtime-tested (requires QEMU/bare metal).
  • Phase 4 (runtime auto-mount): Deferred to runtime validation. Static init service exists.
  • Known limitation: fatfs v0.3.6 strictly requires total_sectors_16 == 0 for FAT32, rejecting some Linux mkfs.fat images
  • cargo test: 60 unit tests (25 scheme + 7 label + 28 check) + 13+ integration edge cases

BRANDING ASSETS

Red Bear OS visual identity files live in local/Assets/.

local/Assets/
└── images/
    ├── Red Bear OS icon.png              ← App icon / logo (1254x1254px)
    │                                        Red bear head, dark background, red border
    │                                        Use: desktop icon, bootloader logo, about dialog
    └── Red Bear OS loading background.png ← Boot / loading screen (1536x1024px)
                                             Cinematic red bear with forest silhouette
                                             Use: bootloader splash, login screen background

Integration points (future):

Asset Target How
icon.png Bootloader logo Convert to BMP, embed via bootloader config
icon.png Desktop icon Install to /usr/share/icons/hicolor/ via redbear-release recipe
icon.png About dialog Install through the active icon/theme surface
loading background.png Boot splash Convert to framebuffer-compatible format, display during startup
loading background.png Login screen Set as the display-session background

Current status: Assets are committed to git. Not yet integrated into the build — requires bootloader and display server integration (P2 hardware validation).

BUILD SYSTEM SAFETY

The build system includes collision detection and validation to prevent the D-Bus regression class (config overrides silently overwritten by package staging).

Validation Targets

make lint-config                       # Check for /usr/lib/init.d/ in config [[files]]
make validate CONFIG_NAME=redbear-mini # Full validation: lint + init services + ownership

Init Service Path Convention

  • Packages own /usr/lib/init.d/ — default service files from recipe staging
  • Config overrides own /etc/init.d/ — override files from [[files]] entries
  • Config [[files]] MUST NOT use /usr/lib/init.d/ paths for init services
  • The init system's config_for_dirs() gives /etc/init.d/ priority via BTreeMap dedup

Collision Detection (installer)

The installer includes CollisionTracker (in collision.rs) that detects when package staging overwrites config pre-install files. Init service collisions always error. Other collisions warn by default, error in strict mode (REDBEAR_STRICT_COLLISION=1).

Recipe Installs Manifest

Recipes can declare installed paths via installs = [...] in [package] section. scripts/validate-file-ownership.sh checks for conflicts. No recipes declare installs yet.

Manifest Generation

scripts/generate-installs-manifest.sh base  # Output suggested installs for base package

See local/docs/BUILD-SYSTEM-HARDENING-PLAN.md for the full 5-phase hardening plan. See local/docs/BUILD-SYSTEM-INVARIANTS.md for invariants I1-I3.

ANTI-PATTERNS

  • DO NOT edit files under mainline recipes/ directly — put patches in local/patches/
  • DO NOT commit firmware blobs to git — use local/scripts/fetch-firmware.sh
  • DO NOT modify mk/ or src/ directly — extend via local/scripts/
  • DO NOT assume mainline recipe names won't conflict — prefix custom ones (e.g., redox-)
  • DO NOT use my-* naming for configs that should be tracked in git — use redbear-* instead
  • DO NOT edit config/base.toml directly — our configs include it and override via TOML merge
  • DO NOT attempt to immutable archived sources from upstream — sources are immutable; use provision-release.sh

COMPREHENSIVE IMPLEMENTATION POLICY

Red Bear OS has zero tolerance for shortcuts, workarounds, and stubs. Every package in the build must be a comprehensive, real implementation. No approximations.

The Rule

When a package fails to build due to missing functionality:

  1. DO NOT mark packages as "ignore" to skip them
  2. DO NOT create stub recipes that provide fake cmake configs without real functionality
  3. DO NOT disable required dependencies via sed/cmake hacks without implementing the dependency

Fix Before Disable

When a build blocker exposes a missing producer surface, missing dependency export, or incomplete integration boundary, the default policy is:

Always do your best to fix before disabling.

This means:

  • prefer restoring the real producer/package surface over commenting out the consumer
  • prefer fixing CMake/pkg-config/header visibility over disabling the dependent feature
  • treat disabling as a last resort, not the normal path

If disabling is temporarily unavoidable, it must be:

  • explicit,
  • narrowly scoped,
  • documented with the real blocker,
  • and treated as temporary debt to remove, not as the desired final state.

Instead, implement the missing functionality properly:

Missing Component Required Action
Missing POSIX function in relibc Implement it in recipes/core/relibc/source/ + create patch in local/patches/relibc/
Missing KF6 package Create full recipe in local/recipes/kde/ with proper cmake build
Disabled Qt feature (e.g., QtNetwork) Implement the feature properly in qtbase recipe
Missing system call Implement in kernel recipe + create patch in local/patches/kernel/

Why This Matters

  • Stubs and workarounds accumulate technical debt
  • They block real functionality from ever being implemented
  • They make the system unreliable and untestable
  • They hide the real work that needs to be done

Current Comprehensive Implementation Gaps

CREDENTIAL SYSCALLS — RESOLVED (2026-04-30): setgroups, getgroups, initgroups, setresuid, setresgid, getrlimit, setrlimit are now implemented. See local/docs/KERNEL-IPC-CREDENTIAL-PLAN.md for the full implementation detail.

Implementation: Kernel: Context.groups: Vec<u32>, CallerCtx.groups, Groups proc scheme handle at auth-{fd}-groups. Relibc: posix_setgroups()/posix_getgroups() in redox-rt, real setgroups()/getgroups() in platform layer, RLIMIT userspace stubs. Durable patches: local/patches/kernel/P4-supplementary-groups.patch, local/patches/relibc/P4-setgroups-getgroups.patch.

Gap Root Cause Status
setgroups ENOSYS on Redox Redox kernel had no supplementary group infrastructure RESOLVED
getgroups returns only egid Redox kernel had no group table concept RESOLVED
setuid/setgid/getuid/getgid No credential syscalls in kernel Already worked via posix_setresugid (proc scheme)
getrlimit/setrlimit ENOSYS RESOLVED — userspace stubs with defaults
CONFIG: KWin is a stub KWin recipe attempts real cmake build with QML/Quick disabled. Blocked by QML gate. Previously had wrapper stubs — removed 2026-04-30. RESOLVED: honest recipe, fails on QML gate
CONFIG: 36/48 KDE packages enabled 12 blocked by QML gate (kirigami → plasma-framework → plasma-workspace → plasma-desktop). See local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md for breakdown. BLOCKED: QML gate requires Qt6Quick/QML engineering
CONFIG: Plasma packages blocked plasma-framework, plasma-workspace, plasma-desktop depend on kirigami (QML gate). Documented in plan. BLOCKED: QML gate
CONFIG: Greeter service 20_greeter.service wired. Greeter QEMU proof passes (GREETER_HELLO=ok, GREETER_VALID=ok). RESOLVED
RUNTIME: Greeter UI Qt Wayland integration: redbear-compositor handles Wayland protocol. Qt6's Wayland plugin reports loading issues due to endianness in compositor wire format. DOCUMENTED in plan
RUNTIME: Greeter UI crash Qt Wayland integration fails (wl-shell deprecated, xdg-shell not working) Fix Qt platform plugin initialization for Wayland
RUNTIME: D-Bus user lookup root and messagebus users not found in passwd database → RESOLVED: user/group config exists in redbear-full.toml; runtime files generated in build Verify in QEMU runtime
RUNTIME: seatd missing seatd binary not in image despite being in config → RESOLVED: seatd builds and is in image Verify in QEMU runtime
RUNTIME: getrlimit(7) relibc getrlimit not implemented → RESOLVED: implemented in relibc patches Verify in QEMU runtime

Kernel Syscall Gap Analysis

The Redox kernel (recipes/core/kernel/source/src/syscall/mod.rs) match statement ends with:

_ => Err(Error::new(ENOSYS)),

All credential syscalls (SYS_SETGROUPS, SYS_GETGROUPS, SYS_SETUID, SYS_SETGID, etc.) fall through to this catch-all and return ENOSYS.

The syscall numbers come from redox_syscall crate (external, versioned) - not defined in the kernel tree.

Fixes Applied (2026-04-29)

  1. relibc/grp/cbindgen.toml: Added group functions to export list
  2. relibc/grp/mod.rs: Implemented getgroups() with egid fallback
  3. Patches created: local/patches/relibc/P3-grp-cbindgen-exports.patch, P3-getgroups-implementation.patch
  4. KERNEL GAP: Cannot fix without upstream redox_syscall + kernel changes

Implementation Locations

  • POSIX functions: recipes/core/relibc/source/src/header/<func>/ + local/patches/relibc/
  • New KF6 recipes: local/recipes/kde/kf6-<name>/
  • Kernel syscalls: recipes/core/kernel/source/ + local/patches/kernel/
  • Qt fixes: recipes/qt/qtbase/source/ + local/patches/qtbase/

RED BEAR OS CONFIG HIERARCHY

Active compile targets (all three work for both make all and make live):

  • redbear-full — Desktop/graphics-enabled target
  • redbear-mini — Text-only console/recovery target
  • redbear-grub — Text-only with GRUB boot manager

Desktop/graphics are available only on redbear-full.

redbear-full.toml
  └── redbear-mini.toml
        ├── minimal.toml (mainline)
        ├── redbear-legacy-base.toml
        └── redbear-netctl.toml
  └── [packages] firmware, GPU, Wayland, Qt6, KF6, KWin, greeter, fonts, icons
  └── [services] D-Bus, seatd, greeter, console
  └── [users] messagebus, greeter
  NOTE: ext4d is inherited from desktop.toml (mainline package).
  NOTE: redbear-meta is explicitly included; keep broader inclusion deliberate.

redbear-mini.toml
  └── minimal.toml (mainline)
  └── redbear-legacy-base.toml
  └── redbear-netctl.toml
  └── [packages] pciids, redbear-hwutils, redbear-netctl, redbear-info, cub, etc.
  └── [services] pcid-spawner, netctl boot, console, debug console

redbear-grub.toml
  └── redbear-mini.toml
  └── redbear-grub-policy.toml (bootloader = "grub", efi_partition_size = 16)
  └── [packages] grub

Config comparison:

Config GPU Stack Desktop Branding ext4d GRUB filesystem_size
redbear-full Full Yes Yes No 4096 MiB
redbear-mini None None Yes No No 1536 MiB
redbear-grub None None Yes No Yes (from mini)

ANTI-PATTERNS (COMMIT POLICY)

  • DO NOT include AI attribution in commit messages — no AI agent footers, co-authored-by lines for automated assistance, or similar markers. Commits belong to the human author only.