Files
fruix/docs/reports/phase14-native-splits-freebsd.md

6.1 KiB

Phase 14.3: split native FreeBSD boot, runtime, and development artifacts

Date: 2026-04-03

Goal

Phase 14.3 finished the Phase 14 cleanup work by replacing the temporary broad-world reuse with narrower native artifacts and by making the runtime/development boundary explicit in code.

The target was:

  • no host-staged FreeBSD base stores in the validated path
  • no need to keep the broad freebsd-native-world artifact in the final validated system closure
  • explicit native boot and runtime slices
  • clearer development-profile boundaries

Implementation

New native packages

Added in modules/fruix/packages/freebsd.scm:

  • freebsd-native-bootloader
  • freebsd-native-headers

Also refined:

  • freebsd-native-runtime

Narrower native runtime slice

freebsd-native-runtime now prunes more obviously non-runtime content, including at least:

  • boot
  • rescue
  • usr/include
  • usr/lib/debug
  • usr/lib32
  • usr/obj
  • usr/src
  • usr/share/doc
  • usr/share/examples
  • usr/share/info
  • usr/share/man
  • usr/share/mk
  • usr/tests

This shrank the runtime output substantially and made the runtime/development distinction much cleaner.

Native bootloader slice

freebsd-native-bootloader is now a native world-derived slice that keeps only the validated boot assets Fruix currently needs:

  • boot/loader
  • boot/loader.efi
  • boot/device.hints
  • boot/defaults
  • boot/lua

Native headers slice

freebsd-native-headers now captures the development-facing header/mk boundary explicitly:

  • usr/include
  • usr/share/mk

Build-system support for sliced native outputs

modules/fruix/system/freebsd.scm gained support for keep-paths on native world-derived packages.

That means a native package can now:

  • install full world/distribution into a staging tree
  • keep only selected subtrees/files for its final store output
  • still participate in the same /usr/src-based identity/build-root story

Native output metadata now records both:

  • keep-paths
  • prune-paths

New package-set boundaries

Added explicit package sets:

  • %freebsd-native-system-packages
    • currently centered on freebsd-native-runtime
  • %freebsd-native-development-profile-packages
    • freebsd-native-runtime
    • freebsd-native-headers
    • explicit toolchain/dev helpers that remain separate artifacts

This makes the boundary clearer:

  • runtime world output
  • headers artifact
  • toolchain artifact(s)
  • optional development profile composition

Final validated Phase 14 system model

The final Phase 14 PID1 system template now uses:

  • #:kernel freebsd-native-kernel
  • #:bootloader freebsd-native-bootloader
  • #:base-packages %freebsd-native-system-packages

That means the validated system closure now contains:

  • native kernel
  • native bootloader slice
  • native runtime slice
  • Fruix runtime stores

and no longer needs the broad freebsd-native-world artifact in the final system closure.

New files

Added:

  • tests/system/phase14-native-split-pid1-operating-system.scm.in
  • tests/system/run-phase14-native-split-qemu.sh
  • tests/system/run-phase14-native-split-xcpng.sh
  • tests/system/run-phase14-native-development-split.sh

Validation

Development split validation

Passing run:

  • PASS phase14-native-development-split
  • workdir: /tmp/phase14-3-dev5-1775191195

Confirmed:

bootloader_store=/frx/store/71aa3ba5dd9a02f7d2710bfc3624cbf5e3cd18f1fbff0744c82df36901b10ec0-freebsd-native-bootloader-15.0-STABLE
headers_store=/frx/store/aab09122d37962e6d479c17172ce4b8ea85e5ff33c98aa76424ada2fa1a82617-freebsd-native-headers-15.0-STABLE
native_system_packages=freebsd-native-runtime
native_development_packages=freebsd-native-runtime,freebsd-native-headers,freebsd-clang-toolchain,freebsd-gmake,freebsd-autotools,freebsd-openssl,freebsd-zlib,freebsd-sh,freebsd-bash
runtime_vs_development_split=ok

The harness also confirmed:

  • native bootloader slice contains only expected boot assets
  • native headers slice contains headers/mk files
  • native headers slice does not contain /boot or runtime binaries

Local QEMU / UEFI / TCG

Passing run:

  • PASS phase14-native-split-qemu
  • workdir: /tmp/phase14-3-qemu-1775191337

Confirmed:

disk_capacity=8g
root_size=6g
bootloader_store=/frx/store/71aa3ba5dd9a02f7d2710bfc3624cbf5e3cd18f1fbff0744c82df36901b10ec0-freebsd-native-bootloader-15.0-STABLE
runtime_store=/frx/store/1b4b8774d0df36df2635fe1c35367a2c5fa7790e303f0aaa26eabfe3cce667f2-freebsd-native-runtime-15.0-STABLE
native_base_store_count=3
host_base_store_count=0
shepherd_pid=1
sshd_status=running
native_split_boot=ok

Real XCP-ng VM

Passing run:

  • PASS phase14-native-split-xcpng
  • workdir: /tmp/phase14-3-xcpng-1775191743

Confirmed:

vm_id=90490f2e-e8fc-4b7a-388e-5c26f0157289
vdi_id=0f1f90d3-48ca-4fa2-91d8-fc6339b95743
guest_ip=192.168.213.62
root_size=6g
bootloader_store=/frx/store/71aa3ba5dd9a02f7d2710bfc3624cbf5e3cd18f1fbff0744c82df36901b10ec0-freebsd-native-bootloader-15.0-STABLE
runtime_store=/frx/store/1b4b8774d0df36df2635fe1c35367a2c5fa7790e303f0aaa26eabfe3cce667f2-freebsd-native-runtime-15.0-STABLE
native_base_store_count=3
host_base_store_count=0
shepherd_pid=1
sshd_status=running
compat_prefix_shims=absent
guile_module_smoke=ok
native_split_boot=ok

Notably, after the narrower native split, the XCP-ng upload size dropped back down dramatically:

  • dynamic VHD upload: 1560725504 bytes (~1.45 GiB)

That is much better than the temporary broad-world + runtime duplication in Phase 14.2.

Result

Phase 14 is complete.

Fruix now has a validated, host-base-free FreeBSD system path built from native artifacts in /frx/store:

  • freebsd-native-kernel
  • freebsd-native-bootloader
  • freebsd-native-runtime

with a clearer development boundary via:

  • freebsd-native-headers
  • %freebsd-native-development-profile-packages

This completes the Phase 14 objective of incrementally replacing the host-copy FreeBSD base layer for the validated boot/runtime path.

Next step

Proceed to Phase 15:

  1. make the FreeBSD base version a declarative input
  2. demonstrate side-by-side base versions in /frx/store
  3. establish rebuild/redeploy/rollback across those base versions