5.6 KiB
Phase 10 completion: canonical FreeBSD system workflows now use fruix system
Date: 2026-04-02
Goal
Complete the current Optional Phase 10 track by moving the existing FreeBSD system workflows away from phase-specific direct materializer entry points and toward the real Fruix command surface introduced in Phase 10.1.
Concretely, this subphase targeted three things:
- make the existing system validation harnesses call
bin/fruixas their canonical frontend, - keep the deeper static and boot validations intact after that refactor,
- and prove that the real XCP-ng deployment path still works when the image is produced through the
fruix systempath.
Result
This refactor succeeded.
The main static system harnesses no longer invoke the Scheme materializer runners directly as their primary frontend. They now call the real Fruix command and then perform their existing validation logic on the resulting artifacts.
Updated harnesses:
tests/system/run-phase7-system-closure.shtests/system/run-phase7-rootfs.shtests/system/run-phase8-system-image.sh
These harnesses now use:
bin/fruix system buildbin/fruix system rootfsbin/fruix system image
The Phase 9 XCP-ng boot path benefits from this automatically because:
tests/system/run-phase9-xcpng-boot.shstill callstests/system/run-phase8-system-image.sh,- and that Phase 8 harness now builds the image through
bin/fruix.
Code-level changes
scripts/fruix.scm
Extended the fruix system build metadata so callers can recover more of the closure structure without having to re-enter the Scheme materializer directly.
Added emitted fields for:
ready_markerbase_package_store_countbase_package_stores
That made it practical for the refactored shell harnesses to keep their old validation/reporting fidelity while using the new CLI frontend.
tests/system/run-phase7-system-closure.sh
Reworked to:
- call
bin/fruix system buildtwice, - validate closure reproducibility through the command frontend,
- validate closure contents and key symlink targets,
- and record metadata showing
frontend_invocation=/.../bin/fruix system build.
tests/system/run-phase7-rootfs.sh
Reworked to:
- call
bin/fruix system rootfs, - validate the generated rootfs symlink structure and content expectations,
- and record metadata showing
frontend_invocation=/.../bin/fruix system rootfs.
tests/system/run-phase8-system-image.sh
Reworked to:
- call
bin/fruix system image, - preserve the existing GPT/filesystem/mount/static-layout validation logic,
- and record metadata showing
frontend_invocation=/.../bin/fruix system image.
Validation
Static workflow validation
Successful closure validation:
PASS phase7-system-closure- workdir:
/tmp/phase10-canon-closure2-1775119728
Successful rootfs validation:
PASS phase7-rootfs- workdir:
/tmp/phase10-canon-rootfs3-1775120391
Successful image validation:
PASS phase8-system-image- workdir:
/tmp/phase10-canon-image-1775120548
The resulting metadata confirms that all of those paths are now driven by bin/fruix.
Real XCP-ng regression validation
To ensure this was not merely a static refactor, the full real-VM path was rerun after the harness changes.
Successful real boot validation:
PASS phase9-xcpng-boot- workdir:
/tmp/phase10-canon-xcpng-1775120869
That successful rerun confirmed that the fruix system image-driven path still produces an image that can:
- be converted to dynamic VHD,
- be imported into the existing XCP-ng VDI,
- boot on VM
90490f2e-e8fc-4b7a-388e-5c26f0157289, - reach DHCP and SSH,
- keep Shepherd running,
- and reach the ready marker.
Representative final guest state from that pass:
ready_marker=ready
shepherd_status=running
sshd_status=running
run_current_system_target=/frx/store/0fe459ea22156510e64cea794b7a001151b59625bd5f12a488d6851e1c6d2198-fruix-system-fruix-freebsd
boot_backend=xcp-ng-xo-cli
Why this completes Phase 10 on the current track
By the end of Phase 9, Fruix already had:
- a declarative system model,
- real closure and image outputs in
/frx/store, - and a booted FreeBSD VM with Shepherd and SSH.
What was still transitional was the operator/tooling layer: too much of the system workflow was still centered on phase-specific scripts invoking internal materializers directly.
After Phase 10.1 and this completion step, the current track now has:
- a user-facing Fruix command:
bin/fruix - real system actions under that command:
system buildsystem rootfssystem image
- existing validation/deployment workflows using that command as their canonical frontend
- and successful regression validation on the real XCP-ng guest path
That is enough to treat Optional Phase 10 as complete for the current FreeBSD prototype track.
Remaining follow-up work beyond Phase 10
There is still good follow-up work available, but it is no longer required to say that Fruix has crossed from “prototype scripts only” into a real OS-tooling shape.
Useful future cleanup includes:
- replacing the current Guile/Shepherd compatibility-prefix shims with a more native runtime arrangement,
- polishing residual boot noise and base-service rough edges,
- and extending
fruixwith richer deploy/vm-oriented commands.
Conclusion
Optional Phase 10 is now complete on the current track.
Fruix no longer just has a declarative FreeBSD system implementation internally; it now has a real Fruix command surface that is used by the canonical closure/rootfs/image workflows, and that command path has been validated all the way through a successful real XCP-ng boot.