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:
@@ -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
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user