docs: define build invariants and fix-before-disable policy

This commit is contained in:
2026-05-02 22:09:19 +01:00
parent 91cb8bb369
commit a15d79209c
2 changed files with 440 additions and 1 deletions
+56 -1
View File
@@ -191,7 +191,7 @@ redox-master/ ← git pull updates mainline Redox
│ ├── 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 (GPU/Wi-Fi compat only — NOT USB)
│ │ ├── 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)
@@ -426,6 +426,41 @@ The current execution order for these subsystem plans is:
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:
@@ -599,6 +634,26 @@ When a package fails to build due to missing functionality:
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 |
+384
View File
@@ -0,0 +1,384 @@
# Build System Invariants
## Purpose
This document defines the non-negotiable build-system invariants for Red Bear OS.
Its job is to answer four questions unambiguously:
1. **What build surface is authoritative?**
2. **How must build surfaces propagate to consumers?**
3. **What state is durable vs disposable?**
4. **What must preflight verify before expensive builds begin?**
This file is the execution authority for:
- build preflight design
- sysroot synchronization logic
- release/archive orchestration
- patch/source durability checks
---
## Core rule
The Red Bear build must prefer **explicit, authoritative, reproducible state** over implicit, stale, or opportunistic state.
If a successful build depends on hidden state, stale copied headers, or untracked nested-source edits, the build system is considered incorrect even if the image happens to complete once.
When a build blocker is caused by a missing dependency surface, missing producer artifact, or invalid integration boundary, the default policy is:
> **Always do your best to fix before disabling.**
That means:
- prefer restoring the missing producer surface over disabling the consumer
- prefer repairing dependency visibility over commenting out downstream features
- treat disabling as a last resort, not a convenience path
If disabling is temporarily unavoidable, it must be:
- explicit
- narrowly scoped
- documented with the real upstream/producer-side blocker
- treated as temporary debt to remove, not as the desired final state
---
## Surface ownership model
### 1. relibc staged surface
**Authoritative location**
- `recipes/core/relibc/target/<target>/stage/usr/include`
- `recipes/core/relibc/target/<target>/stage/usr/lib`
**Authority level**
This is the authoritative build output for libc headers and libc-adjacent runtime libraries.
**Why**
- relibc is the canonical producer of the libc header/runtime surface used by downstream packages
- downstream recipes must not invent or preserve stale copies of relibc-provided interfaces when the staged surface has changed
**Invariant R1**
If relibc headers or exports change, the staged relibc surface is the only source of truth for those changes.
**Invariant R2**
No downstream package may rely on older copies of relibc-provided headers or libs once relibc has been refreshed.
---
### 2. Recipe consumer sysroot
**Authoritative location**
- per-recipe `target/<target>/sysroot`
**Authority level**
Derived surface, not root authority.
**Why**
- recipe sysroots are dependency assemblies for consumers
- they may contain additional recipe-local compatibility shims, but they do not supersede the canonical producer of those surfaces
**Invariant S1**
Recipe sysroots are derived from authoritative producers and may only diverge intentionally, minimally, and visibly.
**Invariant S2**
Recipe-local shims or injected compatibility headers must be treated as temporary exceptions, not silent permanent state.
**Invariant S3**
If a recipe sysroot needs manual copying or compatibility injection, that work must be explicit in the recipe and considered a candidate for future centralization.
---
### 3. Prefix toolchain sysroot
**Authoritative location**
- `prefix/x86_64-unknown-redox/sysroot`
**Authority level**
Derived toolchain-consumer surface.
**Why**
- GCC/Clang and their bundled target include resolution may consult the prefix sysroot directly
- some downstream packages, especially C++ consumers, may see this surface before or instead of a recipe-local sysroot
**Invariant T1**
If the compiler toolchain resolves target headers or libs from the prefix sysroot, critical relibc-provided interfaces must be synchronized there after relibc refresh.
**Invariant T2**
The prefix sysroot is not allowed to remain silently stale relative to the relibc staged surface for critical libc headers/libs.
**Invariant T3**
Sync into the prefix sysroot must be explicit, repeatable, and owned by shared build logic rather than scattered one-off package repairs where possible.
---
### 4. Release/archive source surface
**Authoritative location**
- `sources/redbear-<release>/...`
**Authority level**
Authoritative source origin in release mode.
**Why**
- release mode must be offline and reproducible
- release builds must not depend on network fetch or accidental live working-tree state
**Invariant A1**
When `REDBEAR_RELEASE` is set, archived release sources are the authoritative source surface.
**Invariant A2**
Release-mode builds must not require opportunistic upstream fetches.
**Invariant A3**
Before a release-mode build begins, required source trees must either already exist or be ensured from archived release sources.
---
### 5. Durable patch/source surface
**Authoritative location for persistence**
- `local/patches/...`
- `local/recipes/...`
- tracked Red Bear configs and docs
**Not authoritative for persistence**
- `recipes/*/source/`
**Why**
- upstream-owned source trees are disposable working trees
- successful compilation alone does not make a live source edit durable
**Invariant P1**
Any intended Red Bear change to an upstream-owned source tree must be mirrored into a durable patch carrier or Red Bear-owned location.
**Invariant P2**
An upstream-owned working tree with uncarried edits is an invalid end state, even if the current build succeeds.
**Invariant P3**
Patch wiring in recipe metadata is part of the durable source of truth.
---
## Propagation order
The expected propagation order for critical libc/runtime surfaces is:
1. upstream-owned source tree is patched or refreshed
2. authoritative recipe stage is rebuilt
3. recipe consumer sysroots are refreshed from authoritative producers
4. toolchain prefix sysroot is refreshed if compiler resolution depends on it
5. downstream package feature visibility is revalidated
If step 4 or 5 is skipped, the build may observe stale success/failure behavior and is considered unstable.
---
## Config-to-feature honesty rules
### Rule F1
If a config enables a package, the build system must verify that all required metadata exists before heavy compilation:
- source metadata
- hash metadata where required
- patch files
- dependency wiring
### Rule F2
If a recipe claims a feature is enabled, downstream discovery must also succeed.
Examples:
- CMake package visibility
- pkg-config metadata visibility
- required headers visible to consumers
- required shared/static libraries visible to linkers
### Rule F3
A feature is not considered present merely because a build flag says it is on.
It is only considered present if downstream consumers can discover and use it successfully.
---
## Patch-state classification rules
Any patch application outcome should be classified as one of the following:
1. **Applies cleanly**
- source is missing the change and patch applies normally
2. **Already applied**
- source already contains the intended delta
3. **Drifted/conflicting**
- source changed enough that the patch no longer applies mechanically, and equivalence is not yet proven
4. **Obsolete**
- the patchs intent is now satisfied by upstream, relibc, toolchain, or another authoritative producer
**Invariant C1**
Build logic must not treat all non-applying patches as the same condition.
**Invariant C2**
Obsolete patches should be shrinkable or removable once equivalence is verified.
---
## Release-mode behavior rules
### Rule A4
Release-mode checks must happen before expensive build execution:
- archive existence
- archive mapping completeness
- required source trees present or ensure-able
- critical manifests consistent with build expectations
### Rule A5
If release-mode recovery is possible, the build system must say exactly what recovery path to use.
### Rule A6
Release-mode flow must be explainable through one coherent orchestration path, not many partial helpers with overlapping responsibility.
---
## Preflight-required checks
The preflight stage must catch cheap, known failures before deep compilation.
### Metadata checks
- tar-based recipes missing required `blake3`
- declared patch files missing from disk
- broken local overlay symlinks
- release archive/source mapping gaps in release mode
### Critical libc/runtime surface checks
- relibc staged headers exist for required known surfaces:
- `sys/signalfd.h`
- `sys/timerfd.h`
- `sys/eventfd.h`
- `threads.h`
- relibc export/header visibility exists for known problematic interfaces:
- `strtold`
- `thrd_exit`
### Toolchain coherence checks
- prefix toolchain sysroot reflects current relibc critical surface
- known critical headers are not stale relative to authoritative relibc stage
### Feature-surface checks
- QtNetwork is discoverable when enabled
- known Wayland prerequisite headers/macros are visible to configure probes
- package-family feature claims are not contradicted by missing downstream CMake/pkg-config surfaces
---
## Known anti-patterns
The following are explicitly disallowed or should be treated as defects:
1. **Late discovery of cheap metadata errors**
- e.g. missing `blake3` found after long build progress
2. **Silent stale sysroot dependence**
- build result depends on old copied relibc headers/libs remaining in the toolchain or recipe sysroot
3. **Uncarried upstream-owned source edits**
- live source changes not mirrored into `local/patches/`
4. **Feature dishonesty**
- a feature is marked enabled but downstream consumers cannot actually find or use it
5. **Indistinguishable patch skip behavior**
- already-applied, drifted, and obsolete patches all looking like the same “skip” outcome
6. **Top-level orchestration script absorbing permanent package-specific hacks**
- `build-redbear.sh` should coordinate, not become the only place build correctness lives
---
## Acceptance checklist
This invariants document is usable when all of the following are true:
- [ ] It names the authoritative owner of relibc stage, recipe sysroot, prefix toolchain sysroot, release archives, and durable patch state
- [ ] It defines the required propagation order for critical runtime surfaces
- [ ] It defines what counts as a valid durable upstream-owned source edit
- [ ] It defines the patch-state classes needed by the build system
- [ ] It gives preflight a concrete required check set
- [ ] It gives downstream tasks enough specificity to implement without guessing intent
---
## Downstream task consumers
This file is intended to directly unblock:
- **Build preflight command**
- consumes the preflight-required check list
- **Sysroot sync helper**
- consumes the ownership and propagation rules for relibc/recipe/toolchain surfaces
- **Patch-state classifier**
- consumes the patch-state and durability rules
- **Release-mode orchestration**
- consumes the archive/source authority and release-mode rules
---
## First implementation implications
Based on these invariants, the first practical implementation slice should do all of the following:
1. add preflight checks for hashes, patch presence, and critical relibc surfaces
2. formalize relibc-to-toolchain sysroot refresh as shared logic
3. classify patch outcomes instead of generic skip behavior
4. ensure release-mode source trees before deep build execution
If those four changes land cleanly, the build system will already move from reactive deep-build debugging toward proactive build-state validation.