docs: amend NO OVERLAY-STYLE PATCHES policy — Red Bear forks allowed for big external projects (mesa, wayland, qt, KF6, KWin, SDDM, llvm, libdrm)

The blanket reading from commit 5396e6c3c would have forced every direct
edit to mesa, wayland, qt, KF6, KWin, SDDM, llvm, libdrm, redox-drm,
libepoxy, and similar multi-million-line external projects to live
inside recipes/<pkg>/source/, where a 'make clean' or upstream sync
would silently clobber our work. That is not a full fork, that is a
liability.

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

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

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

Both AGENTS.md (top-level) and local/AGENTS.md updated. Cross-references
to the section name in the anti-pattern tables at the bottom of the
policy remain valid.
This commit is contained in:
2026-06-09 16:56:22 +03:00
parent 54f4796ddd
commit 2b72f61e41
2 changed files with 278 additions and 18 deletions
+141 -9
View File
@@ -41,12 +41,40 @@ This means:
- If a Cargo dependency breaks, we fork the dependency crate to `local/sources/` and pin our Cargo.toml to our fork.
- The Linux kernel in `local/reference/` is read-only reference — never a dependency.
### NO OVERLAY-STYLE PATCHES — DIRECT EDITS ONLY
### NO OVERLAY-STYLE PATCHES — SCOPED POLICY (AMENDED 2026)
**Hard policy. No exceptions. No "just this once." No "temporary until we fork."**
**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.
The Red Bear build is a **full fork**, not an overlay on top of Redox. The
correct workflow for any change is:
---
#### 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) |
|---|---|
@@ -56,7 +84,7 @@ correct workflow for any change is:
| Change a build script | Edit `local/scripts/<script>.sh` directly. |
| Change a config TOML | Edit `config/redbear-<name>.toml` directly. |
**What is FORBIDDEN:**
**What is FORBIDDEN for in-tree components:**
| Anti-pattern | Why it's wrong |
|---|---|
@@ -67,7 +95,7 @@ correct workflow for any change is:
| `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 a Redox package correctly (no overlay):**
**How to fork an in-tree Redox package correctly (no overlay):**
```bash
# 1. Copy the upstream recipe to local/recipes/ (the fork)
@@ -88,7 +116,7 @@ git rm recipes/<category>/<name>
git commit -m "remove upstream <name> in favor of local fork"
```
**Verification (audit) — every recipe in the build must have exactly one source:**
**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
@@ -98,7 +126,7 @@ find recipes/ -name "recipe.toml" -path "*/local/*" -o -lname "*/local/*" 2>/dev
# Fix by forking the recipe properly per the steps above.
```
**Why this matters:**
**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.
@@ -122,7 +150,111 @@ what overlay state the tree is in; fix the offending recipes by forking
them properly.
If you find yourself adding to `apply-patches.sh` or creating a new entry
in `local/patches/`, STOP. Fork the recipe instead.
in `local/patches/` for an in-tree component, STOP. Fork the recipe instead.
---
#### Rule 2 — Big external projects: Red Bear fork at `local/sources/<component>/`
These projects are too large, too fast-moving, and too far from
Red Bear's direct ownership to live as direct edits inside
`recipes/<pkg>/source/`. A `make clean` of an upstream sync would
silently destroy our work; every `git pull` from upstream becomes a
merge conflict resolution exercise. **The Red Bear fork at
`local/sources/<component>/` is the durable, audit-friendly location
for these components**, and the mainline `recipes/<pkg>/recipe.toml`
points at the fork via `git = "..."` or a `Local` source type. This
is the full-fork model applied to a project of meaningful size:
**we own the source, the recipe just builds it**.
| Component class | Examples | Why a Red Bear fork is mandatory |
|---|---|---|
| Mesa (OpenGL/Vulkan/EGL/GBM) | `local/recipes/libs/mesa/`, `local/sources/mesa/` | Multi-million-line external codebase; virgl disk cache, GBM dumb prime export, hardware driver work — every change must persist across upstream syncs |
| Wayland (protocol + compositors) | `local/sources/wayland/`, `local/sources/wayland-protocols/` | Protocol changes, KMS integration, libwayland for our platform — all need durable storage |
| Qt 6 stack (qtbase, qtdeclarative, qtwayland, qt5compat, …) | `local/sources/qtbase/`, `local/sources/qtdeclarative/`, `local/sources/qtwayland/`, … | KDE Plasma foundation; futex redox support, wayland guards, OpenGL/EGL fixes — these are dozens of patches per component, all must be durable |
| KF6 Frameworks (32 packages) | `local/sources/kf6-*/` (one fork per framework) | KConfig, KWayland, KCMUtils, Kirigami, etc. — each has Red Bear-specific platform integration that must not be clobbered |
| KWin (Wayland compositor + window manager) | `local/sources/kwin/` | The compositor. EGL/GBM integration, KWayland glue, hardware backend wiring — must be a fork |
| SDDM (display manager / greeter host) | `local/sources/sddm/` | Login screen, session launcher, PAM/elogind bridge — must be a fork |
| LLVM/Clang (compiler stack) | `local/sources/llvm-project/` | Patches for Redox target, libc++ relibc glue, linker driver tweaks — all must persist |
| libdrm (DRM userspace library) | `local/sources/libdrm/`, `local/recipes/libs/libdrm/` | ioctl bridge, PCI info, device enumeration — must be a fork |
| redox-drm (DRM/KMS scheme daemon) | `local/sources/redox-drm/`, `local/recipes/gpu/redox-drm/` | Intel + AMD display drivers; consumes quirk flags, MSI/MSI-X fallback, DISABLE_ACCEL — must be a fork |
| libepoxy (OpenGL function pointer manager) | `local/sources/libepoxy/` | EGL/GLX dispatch, dlsym workarounds for Mesa/Redox — must be a fork |
| Other big externals (fontconfig, freetype, xkeyboard-config, libinput, …) | `local/sources/<component>/` as needed | Same rule: any direct edit must live as a Red Bear fork |
**Where the fork lives:**
```
local/sources/<component>/ ← Red Bear fork (durable, git-tracked, commits here)
└── ... full source tree, Red Bear's edits committed here ...
recipes/<category>/<name>/recipe.toml ← mainline recipe pointing at the fork:
[source]
path = "../../../local/sources/<component>" # Local source type
# OR
git = "https://gitea.redbearos.org/redbear/<component>.git" # Our git remote
rev = "<pinned-redbear-revision>"
```
**What this rule prohibits for big external projects:**
| Anti-pattern | Why it's wrong |
|---|---|
| Direct edits inside `recipes/<pkg>/source/` for mesa, wayland, qt, KF6, KWin, SDDM, llvm, libdrm, redox-drm, libepoxy | `recipes/<pkg>/source/` is ephemeral — `make clean` and upstream syncs both destroy it. Edits there are guaranteed to be lost. |
| Patch files in `local/patches/<pkg>/*.patch` for these components | Patches are an upstream-merging anti-pattern. A `git apply` rebase against millions of lines of upstream code is fragile and unauditable. |
| `recipes/wip/<pkg>/source/` symlinks to `local/sources/<pkg>/` for these components | WIP is a transitional tool, not a durable fork. Move the fork to `local/sources/<component>/` and point the recipe at it. |
| Mixing a `local/sources/<component>/` fork with a `recipes/<pkg>/source/` overlay | The fork must own the source entirely. Two sources of truth is a half-forked, half-overlay state — pick one. |
**Why this rule is mandatory for big external projects:**
1. **Survival across `make clean` and upstream syncs**`recipes/<pkg>/source/` is regenerated on every fetch. A Red Bear fork at `local/sources/<component>/` survives because it is a separate git repo, owned by Red Bear, never touched by the build system.
2. **Auditability**`git -C local/sources/<component> log` shows every Red Bear edit, in order, attributed to the right author. No mixing with upstream Mesa/Wayland/Qt/KF6/KWin/SDDM/LLVM/libdrm commits.
3. **No merge conflicts on upstream pull** — When we eventually sync with a newer upstream Mesa/Wayland/Qt release, the Red Bear fork's branch is the only place where our edits live. The mainline recipe's `rev = "..."` advances; our fork rebases forward; no in-place merge conflict in `recipes/<pkg>/source/`.
4. **CI/CD reproducibility** — A test build on CI clones the fork from `gitea.redbearos.org` at a pinned revision, builds it, and the result is bit-identical. No overlay fixup script required.
5. **Ownership of critical surface** — Mesa, Wayland, Qt, KF6, KWin, SDDM, LLVM, libdrm, redox-drm, libepoxy are the GPU and desktop stack. We cannot afford to have our edits silently clobbered by `make clean` or a WIP refactor. These components must be forks.
**How to fork a big external project correctly:**
```bash
# 1. Create a Red Bear git repo at local/sources/<component>/
# (initialize or import from a frozen upstream snapshot)
mkdir -p local/sources/<component>
cd local/sources/<component>
git init
# ... import upstream source tree, make initial commit ...
# 2. Apply Red Bear's edits as commits in this repo
$EDITOR some/file.c
git add some/file.c
git commit -m "<component>: <change description>"
# 3. Point the mainline recipe at the fork
cat > recipes/<category>/<name>/recipe.toml <<EOF
[source]
path = "../../../local/sources/<component>"
[build]
template = "..."
EOF
# 4. Build via the standard pipeline
./target/release/repo cook recipes/<category>/<name>
```
**Rule-of-thumb decision matrix:**
| Is the component … | Then … |
|---|---|
| An in-tree Red Bear core (kernel, relibc, base, installer, bootloader) | **Rule 1** — direct edits in `recipes/<pkg>/source/` and `recipes/<pkg>/recipe.toml`. No fork. |
| A small Red Bear-initiated new package (cub, redbear-info, redbear-netctl, redbear-sessiond, redbear-authd, …) | **Rule 1**`local/recipes/<category>/<name>/` fork replaces the upstream recipe. No symlinks. |
| A big external project (mesa, wayland, qt, KF6, KWin, SDDM, llvm, libdrm, redox-drm, libepoxy, …) | **Rule 2** — Red Bear fork at `local/sources/<component>/`. Recipe points at the fork. |
| An upstream Redox system-internal that we don't modify (core/pkgar, core/ion, core/dash, core/coreutils, gui/orbital, …) | No action needed. Pull from upstream at pinned revision. See "Safe to Pull from Upstream" below. |
| A pure Cargo dep that we don't fork (redox_syscall, libredox, redox-scheme, pkgar, …) | Pulled via Cargo from upstream crates.io. No recipe. |
If a component is on the boundary (e.g., a small but actively-edited
external project), the decision is: **will the edits survive a
`make clean` and an upstream sync if they live in
`recipes/<pkg>/source/`?** If yes, Rule 1. If no, Rule 2. The
default for anything multi-thousand-line external is Rule 2.
### Safe to Pull from Upstream (Redox System Internals)
+137 -9
View File
@@ -4,12 +4,38 @@
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 — DIRECT EDITS ONLY
## NO OVERLAY-STYLE PATCHES — SCOPED POLICY (AMENDED 2026)
**Hard policy. No exceptions. No "just this once." No "temporary until we fork."**
**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.
The Red Bear build is a **full fork**, not an overlay on top of Redox. The correct
workflow for any change is:
### 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) |
|---|---|
@@ -19,7 +45,7 @@ workflow for any change is:
| Change a build script | Edit `local/scripts/<script>.sh` directly. |
| Change a config TOML | Edit `config/redbear-<name>.toml` directly. |
**What is FORBIDDEN:**
**What is FORBIDDEN for in-tree components:**
| Anti-pattern | Why it's wrong |
|---|---|
@@ -30,7 +56,7 @@ workflow for any change is:
| `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 a Redox package correctly (no overlay):**
**How to fork an in-tree Redox package correctly (no overlay):**
```bash
# 1. Copy the upstream recipe to local/recipes/ (the fork)
@@ -51,7 +77,7 @@ git rm recipes/<category>/<name>
git commit -m "remove upstream <name> in favor of local fork"
```
**Verification (audit) — every recipe in the build must have exactly one source:**
**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
@@ -61,7 +87,7 @@ find recipes/ -name "recipe.toml" -path "*/local/*" -o -lname "*/local/*" 2>/dev
# Fix by forking the recipe properly per the steps above.
```
**Why this matters:**
**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.
@@ -81,7 +107,109 @@ 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/`, STOP. Fork the recipe instead.
in `local/patches/` for an in-tree component, STOP. Fork the recipe instead.
### Rule 2 — Big external projects: Red Bear fork at `local/sources/<component>/`
These projects are too large, too fast-moving, and too far from
Red Bear's direct ownership to live as direct edits inside
`recipes/<pkg>/source/`. A `make clean` of an upstream sync would
silently destroy our work; every `git pull` from upstream becomes a
merge conflict resolution exercise. **The Red Bear fork at
`local/sources/<component>/` is the durable, audit-friendly location
for these components**, and the mainline `recipes/<pkg>/recipe.toml`
points at the fork via `git = "..."` or a `Local` source type. This
is the full-fork model applied to a project of meaningful size:
**we own the source, the recipe just builds it**.
| Component class | Examples | Why a Red Bear fork is mandatory |
|---|---|---|
| Mesa (OpenGL/Vulkan/EGL/GBM) | `local/recipes/libs/mesa/`, `local/sources/mesa/` | Multi-million-line external codebase; virgl disk cache, GBM dumb prime export, hardware driver work — every change must persist across upstream syncs |
| Wayland (protocol + compositors) | `local/sources/wayland/`, `local/sources/wayland-protocols/` | Protocol changes, KMS integration, libwayland for our platform — all need durable storage |
| Qt 6 stack (qtbase, qtdeclarative, qtwayland, qt5compat, …) | `local/sources/qtbase/`, `local/sources/qtdeclarative/`, `local/sources/qtwayland/`, … | KDE Plasma foundation; futex redox support, wayland guards, OpenGL/EGL fixes — these are dozens of patches per component, all must be durable |
| KF6 Frameworks (32 packages) | `local/sources/kf6-*/` (one fork per framework) | KConfig, KWayland, KCMUtils, Kirigami, etc. — each has Red Bear-specific platform integration that must not be clobbered |
| KWin (Wayland compositor + window manager) | `local/sources/kwin/` | The compositor. EGL/GBM integration, KWayland glue, hardware backend wiring — must be a fork |
| SDDM (display manager / greeter host) | `local/sources/sddm/` | Login screen, session launcher, PAM/elogind bridge — must be a fork |
| LLVM/Clang (compiler stack) | `local/sources/llvm-project/` | Patches for Redox target, libc++ relibc glue, linker driver tweaks — all must persist |
| libdrm (DRM userspace library) | `local/sources/libdrm/`, `local/recipes/libs/libdrm/` | ioctl bridge, PCI info, device enumeration — must be a fork |
| redox-drm (DRM/KMS scheme daemon) | `local/sources/redox-drm/`, `local/recipes/gpu/redox-drm/` | Intel + AMD display drivers; consumes quirk flags, MSI/MSI-X fallback, DISABLE_ACCEL — must be a fork |
| libepoxy (OpenGL function pointer manager) | `local/sources/libepoxy/` | EGL/GLX dispatch, dlsym workarounds for Mesa/Redox — must be a fork |
| Other big externals (fontconfig, freetype, xkeyboard-config, libinput, …) | `local/sources/<component>/` as needed | Same rule: any direct edit must live as a Red Bear fork |
**Where the fork lives:**
```
local/sources/<component>/ ← Red Bear fork (durable, git-tracked, commits here)
└── ... full source tree, Red Bear's edits committed here ...
recipes/<category>/<name>/recipe.toml ← mainline recipe pointing at the fork:
[source]
path = "../../../local/sources/<component>" # Local source type
# OR
git = "https://gitea.redbearos.org/redbear/<component>.git" # Our git remote
rev = "<pinned-redbear-revision>"
```
**What this rule prohibits for big external projects:**
| Anti-pattern | Why it's wrong |
|---|---|
| Direct edits inside `recipes/<pkg>/source/` for mesa, wayland, qt, KF6, KWin, SDDM, llvm, libdrm, redox-drm, libepoxy | `recipes/<pkg>/source/` is ephemeral — `make clean` and upstream syncs both destroy it. Edits there are guaranteed to be lost. |
| Patch files in `local/patches/<pkg>/*.patch` for these components | Patches are an upstream-merging anti-pattern. A `git apply` rebase against millions of lines of upstream code is fragile and unauditable. |
| `recipes/wip/<pkg>/source/` symlinks to `local/sources/<pkg>/` for these components | WIP is a transitional tool, not a durable fork. Move the fork to `local/sources/<component>/` and point the recipe at it. |
| Mixing a `local/sources/<component>/` fork with a `recipes/<pkg>/source/` overlay | The fork must own the source entirely. Two sources of truth is a half-forked, half-overlay state — pick one. |
**Why this rule is mandatory for big external projects:**
1. **Survival across `make clean` and upstream syncs**`recipes/<pkg>/source/` is regenerated on every fetch. A Red Bear fork at `local/sources/<component>/` survives because it is a separate git repo, owned by Red Bear, never touched by the build system.
2. **Auditability**`git -C local/sources/<component> log` shows every Red Bear edit, in order, attributed to the right author. No mixing with upstream Mesa/Wayland/Qt/KF6/KWin/SDDM/LLVM/libdrm commits.
3. **No merge conflicts on upstream pull** — When we eventually sync with a newer upstream Mesa/Wayland/Qt release, the Red Bear fork's branch is the only place where our edits live. The mainline recipe's `rev = "..."` advances; our fork rebases forward; no in-place merge conflict in `recipes/<pkg>/source/`.
4. **CI/CD reproducibility** — A test build on CI clones the fork from `gitea.redbearos.org` at a pinned revision, builds it, and the result is bit-identical. No overlay fixup script required.
5. **Ownership of critical surface** — Mesa, Wayland, Qt, KF6, KWin, SDDM, LLVM, libdrm, redox-drm, libepoxy are the GPU and desktop stack. We cannot afford to have our edits silently clobbered by `make clean` or a WIP refactor. These components must be forks.
**How to fork a big external project correctly:**
```bash
# 1. Create a Red Bear git repo at local/sources/<component>/
# (initialize or import from a frozen upstream snapshot)
mkdir -p local/sources/<component>
cd local/sources/<component>
git init
# ... import upstream source tree, make initial commit ...
# 2. Apply Red Bear's edits as commits in this repo
$EDITOR some/file.c
git add some/file.c
git commit -m "<component>: <change description>"
# 3. Point the mainline recipe at the fork
cat > recipes/<category>/<name>/recipe.toml <<EOF
[source]
path = "../../../local/sources/<component>"
[build]
template = "..."
EOF
# 4. Build via the standard pipeline
./target/release/repo cook recipes/<category>/<name>
```
**Rule-of-thumb decision matrix:**
| Is the component … | Then … |
|---|---|
| An in-tree Red Bear core (kernel, relibc, base, installer, bootloader) | **Rule 1** — direct edits in `recipes/<pkg>/source/` and `recipes/<pkg>/recipe.toml`. No fork. |
| A small Red Bear-initiated new package (cub, redbear-info, redbear-netctl, redbear-sessiond, redbear-authd, …) | **Rule 1**`local/recipes/<category>/<name>/` fork replaces the upstream recipe. No symlinks. |
| A big external project (mesa, wayland, qt, KF6, KWin, SDDM, llvm, libdrm, redox-drm, libepoxy, …) | **Rule 2** — Red Bear fork at `local/sources/<component>/`. Recipe points at the fork. |
| An upstream Redox system-internal that we don't modify (core/pkgar, core/ion, core/dash, core/coreutils, gui/orbital, …) | No action needed. Pull from upstream at pinned revision. See "Safe to Pull from Upstream" below. |
| A pure Cargo dep that we don't fork (redox_syscall, libredox, redox-scheme, pkgar, …) | Pulled via Cargo from upstream crates.io. No recipe. |
If a component is on the boundary (e.g., a small but actively-edited
external project), the decision is: **will the edits survive a
`make clean` and an upstream sync if they live in
`recipes/<pkg>/source/`?** If yes, Rule 1. If no, Rule 2. The
default for anything multi-thousand-line external is Rule 2.
## TUI CONVENTION — `-i` INTERACTIVE SWITCH