# Fruix on FreeBSD, Path C: Short Hardening Pass, Then Native FreeBSD Base Builds This document extends `docs/PLAN_2.md` after the completion of Phases 1 through 10 and the post-Phase-10 Shepherd/PID-1 and runtime-prefix cleanup work. The project has already crossed the main feasibility threshold: - Fruix can build declarative FreeBSD system artifacts - those artifacts boot on the real XCP-ng VM - the guest reaches DHCP and SSH - both `freebsd-init+rc.d-shepherd` and `shepherd-pid1` have been validated - the guest no longer depends on `/tmp/*-validate-install` runtime-compatibility shims The next architectural question is about the **FreeBSD base itself**. Today, Fruix still assembles the kernel, bootloader, libraries, rc assets, and userland largely by **copying curated artifacts from the build host** into `/frx/store`. That was the right bootstrap move, but it is now the largest remaining non-native part of the system. Long-term, the desired direction is clear: - build FreeBSD kernel/world as Fruix-managed artifacts - keep them in `/frx/store` - make system upgrades a declarative rebuild/redeploy story instead of a host-copy refresh However, this plan does **not** recommend jumping directly into full self-hosted FreeBSD base builds inside the guest. Instead, it takes a narrower and safer sequence: 1. do a **short hardening pass** on the current working system 2. then begin **Option B** immediately as the next major architecture phase 3. start Option B on the **builder side** from `/usr/src`, not with guest self-hosting This keeps momentum while avoiding two failure modes: - over-polishing the current host-copy pipeline as if it were the end state - mixing base-system build mechanics, runtime polish, boot debugging, and self-hosting into one oversized step Throughout this plan, the canonical Fruix roots remain: - `/frx/store` - `/frx/var` - `/frx/etc` The user-facing system remains **Fruix**, with CLI `fruix`, while internal upstream-derived names continue to be renamed selectively rather than mechanically. --- ## Current State at the Start of Plan 3 Fruix on FreeBSD already has: - a functioning content-addressed store and derivation path - daemon-mediated builds with FreeBSD-aware isolation prototypes - real package outputs in `/frx/store` - a declarative FreeBSD operating-system model - rootfs and image generation driven by `fruix system ...` - real XCP-ng validation using the approved VM/VDI path - a working FreeBSD guest with DHCP, SSH, activation, Shepherd, and ready markers - validated `shepherd-pid1` boot on both local QEMU/TCG and the real XCP-ng VM - removal of the guest runtime's dependence on `/tmp` compatibility-prefix symlinks The main remaining architectural compromise is that the FreeBSD base layer is still defined mostly as a set of curated host copies: - kernel from `/boot/kernel` - bootloader and boot assets from `/boot` - userland/runtime pieces from `/bin`, `/sbin`, `/usr/bin`, `/usr/sbin`, `/lib`, `/usr/lib`, and `/etc` - headers from `/usr/src` That means Fruix can currently rebuild and redeploy a working system, but it does **not** yet have a truly native upgrade story for the FreeBSD base itself. --- ## Guiding Decision for the Next Milestone The next milestone should be: - **just enough hardening** to make the current system a reliable platform for deeper work, - followed immediately by the first **host-built FreeBSD base artifacts** in `/frx/store`. This means the next work should optimize for: - debuggability - provenance - repeatable deployment/validation - clean separation between host-staged base artifacts and Fruix-built artifacts - incremental replacement of the copy-based base layer It should **not** optimize for: - turning the current host-copy path into a heavily polished long-term abstraction - immediate self-hosted `buildworld`/`buildkernel` inside the Fruix guest - solving every usability concern before starting native base work --- ## Phase 12: Short Hardening Pass on the Existing Working Pipeline The purpose of this phase is not to beautify the bootstrap path. It is to make the existing validated system reliable enough that FreeBSD base-build work can proceed without avoidable confusion. ### Intermediate Goal 12.1: Improve Deployment Provenance and Failure Diagnosis **Verification Goal 12.1:** Make the current pipeline record exactly what FreeBSD base inputs and deployment artifacts were used for each generated system/image. This should include at least: - host `freebsd-version` / `uname` provenance - `/usr/src` revision or identifying metadata when available - the exact staged base-package store paths used in the system closure - image metadata that clearly distinguishes: - host-copied FreeBSD base artifacts - Fruix-built Guile/Shepherd/system artifacts - better collection of boot/runtime logs where possible from the existing QEMU and XCP-ng harnesses **Success Criteria:** a generated Fruix system/image can be traced back to its host-side FreeBSD base inputs and runtime validation logs without ad hoc investigation. ### Intermediate Goal 12.2: Tighten Basic Runtime Completeness and Operator Diagnostics **Verification Goal 12.2:** Close the most important remaining “prototype rough edges” in the current guest so it remains a dependable validation target while Option B begins. This should focus on small, high-value improvements such as: - clearer boot/service logs - fewer known noisy runtime warnings where reasonably fixable - more explicit validation of essential services and files - better failure surfacing from activation and service startup This phase should avoid broad feature creep. The target is not a polished distribution; it is a sharper debugging and validation baseline. **Success Criteria:** the current FreeBSD guest remains reproducibly bootable and easier to debug, with fewer ambiguous failures during rebuild/redeploy cycles. ### Intermediate Goal 12.3: Make the Host-Staged FreeBSD Base Boundary Explicit **Verification Goal 12.3:** Refine the current package/model layer so the “host-staged FreeBSD base” is treated as an explicit transitional boundary rather than an implicit permanent design. This should include: - clearer grouping or manifesting of host-staged base packages - documentation of which components are currently copied from the host - explicit notes on which ones are planned to be replaced first by native base builds **Success Criteria:** the repo documents and code clearly separate transitional host-copy FreeBSD base handling from genuine Fruix-built artifacts. --- ## Phase 13: Option B Begins — Host-Built FreeBSD Kernel and World Artifacts in `/frx/store` This is the real architectural pivot. The goal is **not** yet to self-host FreeBSD base builds inside a Fruix guest. The goal is to teach Fruix to produce FreeBSD base artifacts as build outputs under `/frx/store`, using the builder host and `/usr/src` as the source of truth. ### Intermediate Goal 13.1: Model FreeBSD World and Kernel as Fruix Build Artifacts **Verification Goal 13.1:** Introduce Fruix build descriptions for the FreeBSD base that can represent at least: - a `freebsd-world` artifact - a `freebsd-kernel` artifact - required boot assets associated with the selected kernel/world build The first version may still be specialized and FreeBSD-specific rather than fully generalized. This step should determine and document: - how `/usr/src` is treated as an input - what build parameters affect output identity - how kernel/world configuration is hashed into the output model - how these outputs are split or grouped in `/frx/store` **Success Criteria:** Fruix can describe native FreeBSD world/kernel build outputs as real store artifacts rather than only host-copy packages. ### Intermediate Goal 13.2: Build and Stage Minimal FreeBSD World/Kernel Outputs From `/usr/src` **Verification Goal 13.2:** Produce the first concrete world/kernel build outputs from `/usr/src` and stage them into `/frx/store`. The first target should be intentionally narrow: - build a kernel matching the validated VM target - build a minimal world sufficient for the current Fruix guest to boot - stage install trees under content-addressed store paths This phase should prefer correctness and repeatability over completeness. A minimal successful output split is acceptable if it is documented. **Success Criteria:** `/frx/store` contains native Fruix-managed FreeBSD world/kernel outputs built from `/usr/src`, and their contents can be inspected as build results rather than copied host snapshots. ### Intermediate Goal 13.3: Boot a Fruix System Using Store-Built FreeBSD Base Artifacts **Verification Goal 13.3:** Wire the operating-system/image pipeline so a generated system can boot using the newly built world/kernel outputs instead of the corresponding host-copy packages. This should preserve the existing validation strategy: - local QEMU/TCG + UEFI where useful - real XCP-ng validation on the approved VM and existing VDI The first boot target may still leave some secondary base components on the older copy path if necessary, as long as the transition boundary is explicit. **Success Criteria:** a Fruix system/image boots successfully using native store-built FreeBSD base artifacts for at least the kernel and core world runtime. --- ## Phase 14: Incrementally Replace the Host-Copy FreeBSD Base Layer Once a minimal native world/kernel path works, the rest of the host-copy base layer should be retired incrementally rather than in one giant switch. ### Intermediate Goal 14.1: Replace Kernel and Boot Assets First **Verification Goal 14.1:** Move the system closure and image generator to prefer native store-built kernel and boot assets over host-copied `/boot/...` material. This should include: - kernel - loader/boot assets as appropriate - any required linker or boot metadata **Success Criteria:** the image no longer relies on host-copied kernel/boot components for the validated boot path. ### Intermediate Goal 14.2: Replace the Core Runtime World Slice **Verification Goal 14.2:** Move the essential userland/runtime components to the native world outputs, including the files required for: - boot - activation - networking - SSH - service startup - basic operator access **Success Criteria:** the booted Fruix system reaches ready state using a native store-built core FreeBSD runtime rather than a hand-curated host copy set. ### Intermediate Goal 14.3: Revisit Headers, Toolchain, and Development Splits **Verification Goal 14.3:** Define cleaner boundaries between: - runtime world outputs - development headers - toolchain artifacts - optional build/developer profiles This step should reduce accidental coupling between “what the guest needs to boot” and “what the host needs to build software”. **Success Criteria:** Fruix has a clearer and more maintainable model for FreeBSD runtime vs. development artifacts in `/frx/store`. --- ## Phase 15: Establish a Real Fruix Upgrade Story for the FreeBSD Base After native base artifacts exist and are used by the system closure, Fruix can move from “rebuild from current host copies” toward a more honest upgrade story. ### Intermediate Goal 15.1: Make the FreeBSD Base Version a Declarative Input **Verification Goal 15.1:** Define how a Fruix system declares which FreeBSD base/kernel source version it targets. This may initially remain tied to locally available `/usr/src`, but it should move the model toward a declarative notion of: - target FreeBSD branch/release - kernel configuration - world configuration - boot/runtime variant **Success Criteria:** FreeBSD base versioning becomes an explicit part of the Fruix system model rather than an implicit property of the builder host. ### Intermediate Goal 15.2: Support Rebuild/Redeploy/Rollback Across Base Versions **Verification Goal 15.2:** Demonstrate that at least two distinct FreeBSD base builds can coexist in `/frx/store` and that the generated system can switch between them through the normal rebuild/redeploy flow. This should preserve the Guix-inspired strengths: - content-addressed outputs - side-by-side versions - rollback-friendly system closures **Success Criteria:** Fruix can rebuild and redeploy a system against a newer FreeBSD base without mutating the old one in place. ### Intermediate Goal 15.3: Decide When to Pursue Self-Hosted Base Builds **Verification Goal 15.3:** Reassess whether the next step should be: - building FreeBSD base artifacts inside a Fruix-managed environment, or - continuing to use the host builder while improving reproducibility and source acquisition This decision should be made only after native world/kernel artifacts are already working in `/frx/store`. **Success Criteria:** the project has a documented, evidence-based decision on whether and when to pursue self-hosted FreeBSD base builds. --- ## Strategic Notes ### Why this order? This sequence is intended to preserve momentum and architectural clarity. The short hardening pass prevents the next phase from being undermined by avoidable debugging ambiguity. But the hardening phase is intentionally short so the project does not over-invest in the transitional host-copy design. Then Option B begins immediately in a way that is ambitious but still controlled: - build FreeBSD base artifacts on the host - store them in `/frx/store` - boot from them - replace the host-copy model incrementally ### What this plan does **not** require yet This plan does **not** require, in its first native-base stages: - guest self-hosting - in-place `freebsd-update` integration - complete replacement of every base file in one step - abandoning the validated XCP-ng/QEMU test harnesses - immediate adoption of `shepherd-pid1` as the only supported boot path ### What success will mean Success under this plan means the project moves from: - “Fruix assembles a FreeBSD system by copying a curated slice of the host” into: - “Fruix builds and stores FreeBSD base artifacts itself, then assembles and deploys systems from those declared outputs.” That is the real bridge from the current prototype to a more genuinely native Fruix system on FreeBSD.