docs: add NO OVERLAY-STYLE PATCHES policy to both AGENTS.md files

Red Bear is a full fork, not an overlay. Document explicitly:
- What the policy is
- What the forbidden anti-patterns are (apply-patches.sh symlinks,
  recipes/*/source/ symlinks, mixing local/recipes/ edits with
  recipes/ patches, etc.)
- How to fork a Redox package correctly (copy to local/recipes/,
  edit there, delete the upstream recipe)
- Why this matters (auditability, build determinism, no stolen
  upstream changes, CI reproducibility)
- Historical context of why apply-patches.sh and local/patches/
  still exist (transitional remnants, historical-only)

Also update the 'How the build system works' diagram to clarify
that the source/ symlink is for core Red Bear forks (kernel,
base, relibc, bootloader, installer) — NOT for recipes. Recipes
have a different model: either fork entirely in local/recipes/ or
coexist in mainline. No symlinks, no overlay.

Also add a row to the 'Common anti-patterns' table listing the four
specific overlay-style mistakes (apply-patches.sh, recipes/ symlinks,
local/recipes/ + recipes/ mix, etc.) so future agents see them
flagged next to the existing 'don't edit source/' and 'don't add
patches' rules.

The user's 'IF YOU DID PATCHES, REDO ALL' was triggered by my adding
mesa to apply-patches.sh. The 450k line deletion was the cost of
the overlay approach breaking. This commit prevents recurrence.
This commit is contained in:
2026-06-09 16:27:09 +03:00
parent 92ed6daf91
commit 5396e6c3cc
2 changed files with 181 additions and 24 deletions
+102 -4
View File
@@ -28,7 +28,7 @@ This means:
| Rule | Explanation |
|---|---|
| **Own your dependencies** | Every crate and library Red Bear uses must have its source accessible in `local/sources/` or `local/recipes/`. No depending on upstream crates that we cannot fix ourselves. |
| **Own your dependencies** | Every crate and library Red Bear uses must have its source accessible in `local/sources/` or `local/recipes/`. No dependiendo on upstream crates that we cannot fix ourselves. |
| **No waiting for upstream** | If a dependency breaks, we fix it in our fork. We do not file issues and wait. |
| **Frozen snapshots only** | Upstream Redox is a reference, not a live dependency. We baseline on frozen snapshots and never auto-pull. |
| **Upstream gitlab URLs are temporary** | Any recipe pointing at `gitlab.redox-os.org` (91 currently) must eventually be forked to `local/sources/` or pinned to a frozen archive. Exceptions: unmodified upstream packages with pinned revisions. |
@@ -37,10 +37,93 @@ This means:
**Concretely:**
- `local/recipes/drivers/redox-driver-sys/` is OUR fork. We fix compilation errors there.
- `local/sources/kernel/` is OUR kernel. We don't pull from `gitlab.redox-os.org/redox-os/kernel`.
- `local/sources/kernel/` is OUR kernel. We don't pull from `gitlab.redox-os.org/redox-oskernel`.
- If a Cargo dependency breaks, we fork the dependency crate to `local/sources/` and pin our Cargo.toml to our fork.
- The Linux kernel in `local/reference/` is read-only reference — never a dependency.
### NO OVERLAY-STYLE PATCHES — DIRECT EDITS ONLY
**Hard policy. No exceptions. No "just this once." No "temporary until we fork."**
The Red Bear build is a **full fork**, not an overlay on top of Redox. The
correct workflow for any change is:
| 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:**
| 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 a 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 recipe in the build 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:**
1. **Auditability**`git log local/recipes/<pkg>/recipe.toml` shows ALL
our changes to that package, not a subset mixed with Redox commits.
2. **Build determinism** — A `make clean && make all` always produces the
same result. Overlay symlinks can break this (the symlink target
moves out from under the build).
3. **No "stolen" upstream changes** — When we edit `recipes/`, we're
competing with Redox's own commits on the same file. A `git pull`
from upstream can silently revert our changes. In `local/recipes/`,
upstream has no write access.
4. **CI/CD reproducibility** — A test build on CI shouldn't have to
re-run an overlay fixup script. The recipes/ and local/recipes/
trees should be consistent at HEAD.
**Historical context:** the `apply-patches.sh` script and `local/patches/`
directory are remnants from when Red Bear was an overlay on Redox. They
exist only because deleting them would invalidate git history. **New
changes go as direct edits to `local/recipes/<pkg>/recipe.toml` or
`local/sources/<component>/`.** Run `apply-patches.sh --dry-run` to see
what overlay state the tree is in; fix the offending recipes by forking
them properly.
If you find yourself adding to `apply-patches.sh` or creating a new entry
in `local/patches/`, STOP. Fork the recipe instead.
### Safe to Pull from Upstream (Redox System Internals)
These are Redox-specific libraries, tools, and protocols that form the stable ABI
@@ -127,15 +210,26 @@ in this project. The rule is:
repo cook <package>
├── repo fetch <package>
│ ├── For local sources: symlink local/sources/<pkg>/ → recipes/<pkg>/source/
│ │ (kernel, base, relibc, bootloader, installer — Red Bear forks)
│ ├── For git sources: clone/fetch from git URL → recipes/<pkg>/source/
│ │ (upstream packages, frozen at pinned revisions)
│ └── Source tree is ready for build (no patch step)
├── Cargo/cmake/configure build
└── Stage artifacts into sysroot
```
**Note:** the `source/` symlink to `local/sources/` applies to the
**core Red Bear forks** (kernel, base, relibc, bootloader, installer).
For **recipes**, the model is different — a Red Bear fork lives
entirely under `local/recipes/<category>/<pkg>/` and either
*replaces* the upstream `recipes/<category>/<pkg>/` (delete it) or
*coexists* with the mainline recipe (just edit `local/recipes/`).
There are no symlinks, no overlay layer, no patch files. See
"NO OVERLAY-STYLE PATCHES" above.
The `source/` directory is a symlink to `local/sources/` for Red Bear-owned
components, or a git clone for upstream packages. There are no patches —
the source IS the source.
**component** forks (kernel, base, relibc, etc.), or a git clone for upstream
packages. There are no patches — the source IS the source.
### Two-layer architecture
@@ -168,6 +262,10 @@ Layer 2: Durable (survives clean/fetch/rebuild/release provisioning)
| Hand-writing patches | No patches exist. Use standard git workflow. |
| Expecting `source/` changes to survive `make clean` | `make clean` deletes `source/` directories |
| Running `repo cook` without `--allow-protected` for core packages | Protected recipes (kernel, relibc, base) are offline-only by default |
| **Adding to `apply-patches.sh` to make a recipe point at `local/recipes/`** | Overlay pattern, not a fork. See "NO OVERLAY-STYLE PATCHES" above. |
| **Creating `recipes/<pkg>/source` as a symlink to `local/sources/<pkg>/`** | The `source` symlink is for kernel/base, not for recipes. Recipes are either fully in `local/recipes/` (fork) or fully in `recipes/` (mainline). See "NO OVERLAY-STYLE PATCHES". |
| **Creating a `local/recipes/<pkg>/` fork but symlinking `recipes/<pkg>/` to it** | Same as apply-patches.sh. Hides the fork. See "NO OVERLAY-STYLE PATCHES". |
| **Mixing `local/recipes/<pkg>/` edits with `recipes/<pkg>/` patches** | The fork should own the recipe entirely. Mixing creates a half-forked, half-overlay state. See "NO OVERLAY-STYLE PATCHES". |
### Recipe source configuration
+79 -20
View File
@@ -1,28 +1,87 @@
# RED BEAR OS — DERIVATIVE OF REDOX OS
# RED BEAR OS — FULL FORK OF REDOX OS
## INTERNAL-FIRST POLICY
**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/.
When building packages, resolving dependencies, or choosing between implementations,
**always prefer internal Red Bear source forks and recipes** over upstream or
third-party alternatives. This applies at every decision point:
## NO OVERLAY-STYLE PATCHES — DIRECT EDITS ONLY
| Decision | Always prefer |
|----------|--------------|
| Recipe location | `local/recipes/` over `recipes/` (upstream) |
| Source code | `local/sources/` (git forks, directly editable) over upstream clones |
| Source archive | Frozen archive in `sources/redbear-0.1.0/tarballs/` over re-download |
| Implementation | Red Bear Rust implementation over upstream C port |
| Config | `config/redbear-*.toml` over mainline `config/*.toml` |
| Scripts | `local/scripts/` over ad-hoc shell commands |
**Hard policy. No exceptions. No "just this once." No "temporary until we fork."**
**Concretely:** if `local/recipes/<category>/<name>/` exists and is symlinked into the
recipe tree, that is the authoritative recipe — never fall back to the upstream
`recipes/` version. Source changes go as git commits in `local/sources/<component>/`,
never as ad-hoc edits to recipe source trees.
The Red Bear build is a **full fork**, not an overlay on top of Redox. The correct
workflow for any change is:
**Rationale:** the local overlay is the durable, version-controlled, release-safe layer.
Upstream recipes are disposable and may be overwritten by `make distclean` or release
provisioning. Only `local/` survives across rebuilds and releases.
| 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:**
| 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 a 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 recipe in the build 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:**
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/`, STOP. Fork the recipe instead.
## TUI CONVENTION — `-i` INTERACTIVE SWITCH