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

Changes:

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

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

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

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

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

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

1141 lines
64 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 — 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):**
```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>/`.**
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 syncs**`recipes/<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. **Auditability**`git log local/patches/<component>/` shows every Red Bear patch, in order, with a clear message. No mixing with upstream Mesa/Wayland/Qt/KF6/KWin/SDDM/LLVM/libdrm history.
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:**
```bash
# 1. Make the change in the fetched upstream tree (e.g. in a scratch clone or after a build)
$EDITOR some/file.c
# 2. Generate a patch from the change
git diff > local/patches/<component>/NN-short-description.patch
# (NN = next number; use leading zeros so order is stable when sorted)
# 3. Commit the patch in the main repo
git add local/patches/<component>/NN-*.patch
git commit -m "<component>: <short description> (external patch)"
# 4. The cookbook's cookbook_apply_patches loop picks up NN-prefixed patches
# in lexical order automatically. No recipe edit needed for step (4) — the
# loop in [build].script iterates REDBEAR_PATCHES_DIR/[0-9]*.patch.
# 5. Build via the standard pipeline (recipe fetches upstream, applies patches, builds)
./target/release/repo cook recipes/<category>/<name>
```
**Rule-of-thumb decision matrix:**
| Is the component … | Then … |
|---|---|
| An in-tree Red Bear core (kernel, relibc, base, installer, bootloader) | **Rule 1** — direct edits in `local/sources/<component>/` and `local/recipes/<category>/<name>/recipe.toml`. No fork. No patches. |
| A Red Bear-internal Rust scheme daemon (redox-drm, audiod, pcid, inputd, …) | **Rule 1** — direct edits in `local/sources/<component>/` and `local/recipes/<category>/<name>/recipe.toml`. No fork. No patches. |
| A small Red Bear-initiated new package (cub, redbear-info, redbear-netctl, redbear-sessiond, redbear-authd, …) | **Rule 1**`local/recipes/<category>/<name>/` fork replaces the upstream recipe. No symlinks. |
| A big external project (mesa, wayland, qt, KF6, KWin, SDDM, llvm, libdrm, libepoxy, pipewire, wireplumber, …) | **Rule 2** — external patches in `local/patches/<component>/*.patch`. Recipe has upstream git/tar source + `[build].script` calls `cookbook_apply_patches`. |
| An upstream Redox system-internal that we don't modify (core/pkgar, core/ion, core/dash, core/coreutils, gui/orbital, …) | No action needed. Pull from upstream at pinned revision. See "Safe to Pull from Upstream" below. |
| A pure Cargo dep that we don't fork (redox_syscall, libredox, redox-scheme, pkgar, …) | Pulled via Cargo from upstream crates.io. No recipe. |
If a component is on the boundary (e.g., a small but actively-edited
external project), the decision is: **will the edits survive a
`make clean` and an upstream sync if they live in
`recipes/<pkg>/source/`?** If yes, Rule 1. If no, Rule 2 — and
Rule 2 means **external patches, not a Red Bear source fork**.
## TUI CONVENTION — `-i` INTERACTIVE SWITCH
All Red Bear desktop applications that offer a TUI mode MUST use `-i`/`--interactive`
as the standard switch. Applications without a subcommand default to launching their TUI.
| 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:**
- `app` (no args) → launches TUI if terminal available, else help
- `app -i` → launches TUI regardless
- `app <command>` → CLI mode
- Feature-gate TUI behind `tui` feature in Cargo.toml for minimal builds
- Use `ratatui 0.30 + termion` (same stack as cub-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:
```bash
./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.
```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 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 default** — `REPO_OFFLINE=1 COOKBOOK_OFFLINE=true`
- **NO silent upstream pulls** — see `AGENTS.md` "NO SILENT UPSTREAM PULLS" section for the full policy. Any script or build target that silently pulls from upstream is a bug.
- **New releases are provisioned explicitly** via `provision-release.sh`, never automatically
- **Old releases are NEVER deleted** — each new release is added alongside existing ones
### Checking for new Redox snapshots:
```bash
./local/scripts/check-upstream-releases.sh # Read-only, zero side effects
```
### Provisioning a new release:
```bash
./local/scripts/provision-release.sh --ref=<redox-tag> --release=0.2.0 [--dry-run]
```
### Restoring sources from archives:
```bash
./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-<release>/
> 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
```bash
# 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, 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
```bash
# 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 v4.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` (v4.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`.
- `local/docs/AMD-FIRST-INTEGRATION.md` remains the deeper AMD-specific technical roadmap, but AMD
and Intel machines are now equal-priority Red Bear OS targets.
- `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.
- `local/docs/QUIRKS-IMPROVEMENT-PLAN.md` has been retired — quirks convergence is tracked in `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.
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:
```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
```bash
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
```bash
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:
```rust
_ => 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.