From f3269b414c8cc4e5dba80ebbd1708cc96d1eeeff Mon Sep 17 00:00:00 2001 From: vasilito Date: Fri, 10 Jul 2026 16:08:50 +0300 Subject: [PATCH] docs: add LOCAL-FORK-SUPREMACY-POLICY MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Documents the project-wide rule that Red Bear OS local forks are the complete, authoritative source of truth for every component they cover. Key points: - A fork that delegates to upstream/crates.io is not a fork — it's a wrapper. - Missing fork functionality is implemented in the fork, not papered over. - Path deps + [patch.crates-io] everywhere; no version strings for forks. - Adapt to upstream at the same pace — never pin back. Adds a cross-reference from local/AGENTS.md DESIGN PRINCIPLE section. --- local/AGENTS.md | 28 +++ local/docs/LOCAL-FORK-SUPREMACY-POLICY.md | 244 ++++++++++++++++++++++ 2 files changed, 272 insertions(+) create mode 100644 local/docs/LOCAL-FORK-SUPREMACY-POLICY.md diff --git a/local/AGENTS.md b/local/AGENTS.md index c670471f3d..d18e5df1df 100644 --- a/local/AGENTS.md +++ b/local/AGENTS.md @@ -40,6 +40,34 @@ Red Bear OS is a **full fork** based on frozen Redox OS snapshots: - 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 +## LOCAL FORK SUPREMACY POLICY (ABSOLUTE) + +**Red Bear OS local forks are the COMPLETE, AUTHORITATIVE source of truth.** + +If a component has a local fork (in `local/sources/` as a submodule or tracked +tree, or in `local/recipes/` as an original Red Bear project), the fork MUST: + +1. **Be complete** — every function/type/syscall Red Bear uses is implemented + in the fork. No "we'll wait for upstream" or "let's just call crates.io". +2. **Be the only implementation** — path deps + `[patch.crates-io]` everywhere, + never version strings for fork crates. +3. **Adapt to upstream** — when upstream changes, the fork tracks. We never + pin back to avoid adaptation work. +4. **Be the single source of truth** — no duplicate copies, no stubs that + shadow real implementations, no "wrapper" forks that delegate. +5. **Be documented** — fork divergence from upstream is explained in the + commit message and (when architecturally significant) in `local/docs/`. + +The full policy with concrete checklist, anti-patterns, and enforcement +mechanisms lives at **`local/docs/LOCAL-FORK-SUPREMACY-POLICY.md`**. Every +agent MUST read and follow it. + +**Worked example (2026-07-10):** init's `setrens(0, 0)` panicked at +`main.rs:192` because `SYS_MKNS`/`SYS_SETNS`/`SYS_SETRENS` were missing from +the kernel fork. Per this policy, the fix is to implement those syscalls in +the kernel fork — NOT to make init tolerate the failure with `.unwrap_or(())` +or to remove the `setrens` call. The fork must be complete. + ## FREE/LIBRE SOFTWARE POLICY Red Bear OS must remain a free/libre project. diff --git a/local/docs/LOCAL-FORK-SUPREMACY-POLICY.md b/local/docs/LOCAL-FORK-SUPREMACY-POLICY.md new file mode 100644 index 0000000000..2a42061b7f --- /dev/null +++ b/local/docs/LOCAL-FORK-SUPREMACY-POLICY.md @@ -0,0 +1,244 @@ +# Local Fork Supremacy Policy + +**Status:** ABSOLUTE — Do not violate. +**Established:** 2026-07-10 (reinforced during `setrens` namespace debug session) +**Scope:** All Red Bear OS components, all agents, all operators. + +--- + +## Core Principle + +**Red Bear OS local forks are the COMPLETE, AUTHORITATIVE source of truth.** + +Everything else — upstream Redox, crates.io, third-party registries — exists ONLY +as reference material and raw material that flows INTO our local forks. Our local +forks are NOT thin wrappers, NOT compatibility shims, and NOT delegators that +"just call upstream". + +If a component is forked, it is forked COMPLETELY. Our fork contains every piece +of functionality our system needs, implemented in our tree, maintained by us. + +## The Fork Model + +### What Red Bear OS Is + +Red Bear OS is a **full fork** of Redox OS, based on frozen Redox snapshots +(currently 0.1.0 at build-system commit `f55acba68`). We are NOT a downstream +distributor of Redox. We are NOT a configuration overlay on top of Redox. + +We took Redox as a starting point and are building our own complete operating +system on top of it. The fork boundary is real: every component we depend on +lives in our tree. + +### The 9 Declared Submodules + +| Submodule | Branch | Path | +|------------------|-----------------------|-------------------------------| +| base | `submodule/base` | `local/sources/base` | +| bootloader | `submodule/bootloader`| `local/sources/bootloader` | +| installer | `submodule/installer` | `local/sources/installer` | +| kernel | `submodule/kernel` | `local/sources/kernel` | +| libredox | `submodule/libredox` | `local/sources/libredox` | +| redoxfs | `submodule/redoxfs` | `local/sources/redoxfs` | +| relibc | `submodule/relibc` | `local/sources/relibc` | +| syscall | `submodule/syscall` | `local/sources/syscall` | +| userutils | `submodule/userutils` | `local/sources/userutils` | + +**9 submodules. No more, no less.** The fork inventory is closed by policy. +Adding a new submodule requires explicit operator justification (see +`local/AGENTS.md` § BRANCH AND SUBMODULE POLICY). + +### Tracked Trees (Not Submodules) + +Some components live as full tracked trees under `local/sources//` instead +of as submodules. They have the same fork-supremacy guarantee — the local tree is +the source of truth. Examples include `libredox`, `redox-scheme`, and other +smaller but critical components that don't have upstream worth tracking on a +dedicated branch. + +### Local Recipes (Original Red Bear Code) + +Components with NO upstream origin (e.g. `tlc`, `redbear-sessiond`, +`redbear-authd`, `redbear-greeter`, `cub`) live as local recipes under +`local/recipes///source/`. These are 100% Red Bear original code +and are the only authoritative implementation. + +--- + +## The Five Rules of Local Fork Supremacy + +### Rule 1: Local Fork First, Always + +**If a component has a local fork, EVERY dependency on that component MUST route +through the local fork. Period.** + +- ✅ `path = "../../../../local/sources/"` in any Cargo.toml +- ✅ `[patch.crates-io]` entry pointing at the local fork +- ❌ Version-string dependency (`redox_syscall = "0.9"`) +- ❌ Exact-pin dependency (`redox_syscall = "=0.9.0"`) +- ❌ "Let's just use crates.io for now, we'll fix it later" +- ❌ "Upstream has a newer version, let's skip our fork this once" + +**Crates.io may resolve the SAME crate independently of our fork, creating two +copies in the build graph and producing silent ABI mismatches.** This is not a +hypothetical risk — it has caused real, hard-to-debug build failures in Red Bear +history. The path dependency eliminates the ambiguity entirely. + +### Rule 2: Local Fork Complete, Not Partial + +**A local fork must implement everything Red Bear OS needs from that +component. If the fork is missing functionality, implement it IN THE FORK.** + +There is no acceptable shortcut where our fork "defers to upstream" or "passes +through to crates.io" or "re-exports from the system version". A fork that +delegates is not a fork — it is a wrapper. + +When the kernel needs a syscall (`SYS_SETRENS`, `SYS_SETNS`, `SYS_MKNS`) and the +upstream Redox kernel does not implement it, the Red Bear kernel fork MUST +implement it. The relibc fork MUST route through it. The syscall crate fork +MUST define the number. No layer says "we don't support this, use a different +API". We adapt our entire stack to be complete. + +Concrete example from this very session: the `setrens(0, 0)` call in +`local/sources/base/init/src/main.rs:192` panicked on bare metal because the +`SYS_SETRENS`/`SYS_SETNS`/`SYS_MKNS` namespace syscalls were not implemented in +the kernel fork. The fix is not to make init tolerate the failure (a workaround) +— the fix is to implement the missing functionality in the kernel fork properly. + +### Rule 3: Adapt to Upstream, Never Pin Back + +**When upstream Redox changes a dependency version, API, or ABI, Red Bear +adapts — fully.** + +- Upstream bumps `redox_syscall` to `0.9` → every Red Bear crate that touches + `redox_syscall` moves to `0.9` — we fix our code, not theirs. +- Upstream renames a type → our fork renames it too (or wraps it with a compat + layer inside the fork). +- Upstream drops a function we depended on → we either reimplement it or + re-architect around it. We never pin back. + +This is not just convenience. It is the long-term maintenance contract that +keeps the fork healthy: as upstream evolves, our local forks track and adapt +**at the same pace**. Pinning back creates "dead branches" of the fork that +accumulate divergence and become impossible to rebase. + +### Rule 4: Single Source of Truth Per Concept + +**If two places in Red Bear OS can answer the same question, we have a bug.** + +The local fork is the single source of truth for how Redox syscalls work, how +relibc functions behave, how the kernel allocates memory. There is exactly one +implementation, in exactly one tree, and every other tree imports from it. + +This is why we use path dependencies and `[patch.crates-io]`. This is why we +ban "stub" implementations that pretend to provide an interface. This is why +we remove duplicate files (e.g. the `redox.patch` symlinks from before we +switched to local forks — see `local/AGENTS.md` § LOCAL FORK MODEL). + +If a feature appears in both the local fork and in some "in-tree copy", the +"in-tree copy" is dead code and must be removed. + +### Rule 5: Document the Fork Boundary + +**Every local fork commit that diverges from upstream MUST include:** + +1. A clear commit message explaining what changed and why. +2. The upstream commit/tag the fork is based on (in the commit body). +3. If the divergence is significant, an entry in `local/docs/` or + `local/AGENTS.md` describing the architectural choice. + +This is what makes the fork auditable. An operator looking at the fork history +six months from now needs to be able to understand: what did we take from +upstream, what did we change, and why. + +--- + +## What "Complete" Looks Like (Concrete Checklist) + +For every local fork at `local/sources//`: + +- [ ] `Cargo.toml` (or `Makefile`) exists and declares all dependencies as + path deps to other local forks, with `[patch.crates-io]` if needed. +- [ ] `Cargo.toml` `version` field follows the fork versioning convention: + `+rb` (e.g. `0.6.0+rb0.3.0`). +- [ ] `authors` field credits both upstream maintainers AND every Red Bear + contributor who has commits on the fork. +- [ ] All functions/types/syscalls that Red Bear OS uses are implemented in the + fork — none fall through to "unimplemented" stubs. +- [ ] No `unimplemented!()`, `todo!()`, or `unreachable!()` in code paths Red + Bear exercises (warnings policy from `local/AGENTS.md` applies). +- [ ] All cross-fork references use relative `path = "..."` dependencies, not + absolute paths or crates.io versions. +- [ ] Source tree is tracked in git and pushed to the `submodule/` branch + on `gitea.redbearos.org/vasilito/RedBear-OS`. + +For the syscall crate specifically: + +- [ ] Every syscall number used by relibc MUST be defined in + `local/sources/syscall/src/number.rs`. +- [ ] If relibc calls a syscall that is not yet defined, ADD the syscall number + to the syscall crate AND implement it in the kernel fork. Both edits go + in the same work session. + +For the kernel fork specifically: + +- [ ] Every syscall called from relibc/redox-rt MUST have a handler in + `local/sources/kernel/src/syscall/mod.rs` (or a sub-module it dispatches + to). Unhandled syscalls return `ENOSYS` — which is the correct behavior, + not a bug. But if relibc ACTUALLY uses the syscall in its startup path, + the kernel MUST implement it. +- [ ] No panic/abort paths in kernel code. Errors propagate via `Result`. + +For relibc/redox-rt specifically: + +- [ ] Every public function used by Red Bear binaries (init, bootstrap, base + daemons, libredox wrappers) MUST be implemented. If upstream removed or + renamed a function, we reimplement or wrap — we do not delete the + function from the API surface. + +--- + +## Anti-Patterns (Strictly Forbidden) + +| Anti-Pattern | Why It's Forbidden | +|-----------------------------------------------|------------------------------------------------------------------| +| `redox_syscall = "0.9"` (version string) | Pulls from crates.io, creates dual-copy ABI mismatches | +| `as any` / `@ts-ignore` / `unwrap()` on fork APIs | Hides real bugs; kernel fork must not have panic paths | +| Commenting out a fork function to fix a build | Deletes functionality; the function exists for a reason | +| "Let's wait for upstream to add this" | We are a fork. We adapt or reimplement, we don't wait | +| Delegating fork work to crates.io | Two implementations of the same concept = guaranteed divergence | +| Skipping a fork submodule because "it's not used" | Every declared submodule is used somewhere in the build graph | +| Adding an `unimplemented!()` with `#[allow(dead_code)]` | This is a stub. Stubs are forbidden (see local/AGENTS.md) | + +--- + +## Enforcement + +1. **Build preflight** (`local/scripts/build-preflight.sh` + `verify-fork-versions.sh`): + - Rejects builds that use version-string deps for any Cat 2 fork crate. + - Rejects builds where fork version labels don't match upstream base + branch. +2. **CI gates**: + - `sync-versions.sh --check` verifies Cat 1/Cat 2 version compliance. + - Fork version drift is a build-blocking error. +3. **Operator review**: + - Any new submodule addition requires operator sign-off and a documented + necessity case (see `local/AGENTS.md` § BRANCH AND SUBMODULE POLICY). + - Any removal of fork functionality requires explicit user request. + +--- + +## When This Policy Was Last Verified + +- **2026-07-10**: Reinforced during bare-metal boot debugging. The `setrens(0, 0)` + panic in init's `main.rs:192` was traced to missing kernel-side namespace + syscall implementations (`SYS_MKNS`, `SYS_SETNS`, `SYS_SETRENS`). The Red + Bear fork policy requires implementing these in the kernel fork — not + papering over them with `.expect()` → panic bypass. + +## Related Documents + +- `local/AGENTS.md` — full Red Bear agent guidance (branches, submodules, durability) +- `local/docs/SOURCE-ARCHIVAL-POLICY.md` — how sources are frozen and archived +- `local/docs/PATCH-GOVERNANCE.md` (referenced in `local/AGENTS.md`) — how patches + are rebased and applied +- `README.md` (project root) — high-level description including the fork model \ No newline at end of file