c2f5bb09fc
Phase 1 remediation of the build-system assessment:
- Makefile: wire 'validate' target into build/live/reimage flows; surface
lint-config and init-service validators as a first-class gate.
- mk/disk.mk: add 'validate' target running lint-config, init-service
validator, and file-ownership validator; suppress noisy unmount warnings
that masked real failures.
- mk/redbear.mk: add source-fingerprint tracking so integrate-redbear.sh
re-runs when local/recipes, local/Assets, or local/firmware change.
- src/cook/cook_build.rs: atomic dep_hashes.toml write (tmp + rename) to
prevent torn-write cache corruption; binary-store restore now checks
dep_hashes before silent restore; fix production bug in
collect_files_recursive that silently dropped subdirectories whose
name matched an exclude pattern.
- src/cook/fetch.rs, src/cook/fetch_repo.rs: harden atomic patch
application and protected-recipe gating.
- AGENTS.md, local/AGENTS.md, local/docs/COLLISION-DETECTION-STATUS.md:
sync collision-detection status to 'implemented (Phase 15.0)' now that
CollisionTracker is wired across all four installer layers
(installer submodule pointer tracked separately in 13cc6fb0c3).
Verified: cargo check (0 errors), cargo test --lib (35/35 passed),
cargo clippy (0 new warnings vs baseline), make -n validate, make -n live.
124 lines
5.7 KiB
Markdown
124 lines
5.7 KiB
Markdown
# Collision Detection — Status (Updated 2026-07-18, Phase 15.0 / Round 16)
|
|
|
|
## History
|
|
|
|
- **2026-07-18 (Phase 15.0 — runtime detection landed)**: Implemented
|
|
the runtime package-vs-config collision tracker in the installer's
|
|
`install_dir()`. Lives at `local/sources/installer/src/collision.rs`
|
|
(module `redox_installer::collision`), wired into all four installer
|
|
layers via `CollisionTracker`. Integration tests at
|
|
`local/sources/installer/tests/collision.rs` (6 tests, public-API
|
|
only). Warn-only by default; strict mode opt-in via
|
|
`REDBEAR_INSTALLER_STRICT_COLLISIONS=1`. Emits `[COLLISION-WARN]` /
|
|
`[COLLISION-ERROR]` markers for `scripts/validate-collision-log.sh`.
|
|
Suppresses Layer 3 (postinstall overrides — intentional) and the
|
|
known-safe override pairs (`/etc/init.d` over `/usr/lib/init.d`,
|
|
`/etc/environment.d` over `/usr/lib/environment.d`). This closes the
|
|
gap item 1 below: runtime Layer 2 overwrites Layer 1 is now caught.
|
|
|
|
- **2026-07-12 (Phase 0)**: AGENTS.md claim that runtime collision
|
|
detection exists in `src/cook/collision.rs` was **disproven** — the
|
|
file does not exist in source code. The init-service variant is
|
|
caught by `scripts/lint-config-paths.sh`; the general
|
|
package-vs-config variant was not implemented. `local/docs/COLLISION-
|
|
DETECTION-STATUS.md` documented this gap.
|
|
|
|
- **2026-07-12 (Phase 4.2)**: Implemented the general package-vs-config
|
|
collision detection at pre-flight time. Located at
|
|
`local/scripts/verify-collision-detection.py`. Wired into
|
|
`local/scripts/build-preflight.sh` with `REDBEAR_SKIP_COLLISION_CHECK=1`
|
|
bypass env var.
|
|
|
|
- **2026-07-12 (Phase 5.1)**: Extended collision detection to also parse
|
|
`[[package]].files` (the TOML inline table of install paths used by
|
|
39 recipes including the Round 3 system drivers like redbear-power,
|
|
redbear-acmd, evdevd). The forward coverage ensures future recipes
|
|
using this pattern are caught.
|
|
|
|
- **2026-07-12 (Phase 5.4)**: Added `--selftest` mode with 8 regression
|
|
test cases that exercise the algorithm's edge cases (exact match,
|
|
parent-dir prefix, /etc/init.d override, /etc/environment.d override,
|
|
non-overlapping, parent-of-subpath, two siblings, different base
|
|
names). The selftest is wired into `pre-push-checks.sh` so future
|
|
algorithm changes must keep these cases passing or the pre-push
|
|
hook fails.
|
|
|
|
## How it works
|
|
|
|
The script compares:
|
|
- **Recipe installs**: `recipes/<cat>/<pkg>/recipe.toml` `[[package]].installs`
|
|
fields (canonical list) — files the package WILL install at build time
|
|
- **Recipe files**: `recipes/<cat>/<pkg>/recipe.toml` `[[package]].files`
|
|
dict (path → source mapping) — also checked (Phase 5.1)
|
|
- **Config [[files]]**: `config/redbear-*.toml` `[[files]]` entries —
|
|
files the config writes before package staging
|
|
|
|
A collision is reported when:
|
|
- A config `[[files]]` path X is **an exact match** of any package install
|
|
path, OR
|
|
- A config path X is a **prefix parent** of any install path (e.g.,
|
|
`/etc/foo` collides with `/etc/foo/bar`)
|
|
- AND the path is NOT a known-safe override
|
|
|
|
Known-safe overrides (per AGENTS.md "Init Service File Ownership"):
|
|
- `/etc/init.d/*` overrides `/usr/lib/init.d/*`
|
|
- `/etc/environment.d/*` overrides `/usr/lib/environment.d/*`
|
|
|
|
## Initial result (2026-07-12, post-Phase-4.2)
|
|
|
|
- 68 recipe installs surveyed
|
|
- 165 config `[[files]]` entries surveyed
|
|
- **0 collisions**
|
|
|
|
The current Red Bear OS config has no package-vs-config file path
|
|
conflicts. The 2026-04-30 D-Bus regression class (per AGENTS.md
|
|
historical) is not present in the active build.
|
|
|
|
## What this does NOT cover
|
|
|
|
1. **Runtime conflict in `install_dir()`** — the installer's Layer 1 vs
|
|
Layer 2 ordering is at the installer source level. The pre-flight
|
|
check catches the BUILD-TIME planning. **COVERED as of Phase 5.1:
|
|
`[[package]].files` paths are now checked alongside `[[package]].installs`
|
|
(39 recipes use this field). 162 total paths surveyed.**
|
|
**COVERED as of Phase 15.0: runtime `CollisionTracker` in
|
|
`install_dir()` now detects Layer 2 (package staging) overwriting
|
|
Layer 1 (config pre-install) at install time. See
|
|
`local/sources/installer/src/collision.rs` and the 6 integration
|
|
tests in `local/sources/installer/tests/collision.rs`.**
|
|
|
|
2. **Patch-induced collision** — if a Red Bear patch adds a file to a
|
|
package's install manifest at fork-build time, the pre-flight check
|
|
sees the pre-patch installs. The pre-flight catches the static
|
|
recipe state, not fork-merge state.
|
|
|
|
3. **Dynamic file generation** — the `base` package's initfs generator
|
|
creates files at build time (`/usr/lib/boot/initfs.img`,
|
|
`/usr/lib/init.d/*`, `/usr/lib/drivers/*`). **PARTIALLY COVERED
|
|
as of Phase 8.2: 18 hardcoded dynamic-build paths from base's
|
|
Makefile are now checked.** Future work: auto-detect these paths
|
|
from the Makefile rather than hardcoding.
|
|
|
|
4. **In-file test cases** — the `--selftest` mode (Phase 5.4) tests
|
|
the algorithm against 8 hard-coded cases. A more comprehensive
|
|
fuzzing test (random paths, deeper prefix trees) would catch more
|
|
edge cases. Future work: add property-based test using
|
|
hypothesis or similar.
|
|
|
|
## Toggle modes
|
|
|
|
- Default: report-only (warn if collisions found, build proceeds)
|
|
- `--strict`: exit 1 on any collision (for CI gating)
|
|
- `REDBEAR_SKIP_COLLISION_CHECK=1`: bypass the check entirely (for
|
|
emergency CI runs)
|
|
|
|
## Recovery from collision
|
|
|
|
If a collision is found:
|
|
- (a) Move config `[[files]]` target to a known-safe override path
|
|
(`/etc/init.d/*`, `/etc/environment.d/*`)
|
|
- (b) Remove the conflicting path from the recipe's
|
|
`[[package]].installs` list
|
|
- (c) Add an explicit `[path.collision.allow]` exception to the
|
|
config (not yet implemented — Phase 4.3+ work)
|