Files
fruix/docs/reports/phase10-canonical-system-workflows-freebsd.md

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/fruix as 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 system path.

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.sh
  • tests/system/run-phase7-rootfs.sh
  • tests/system/run-phase8-system-image.sh

These harnesses now use:

  • bin/fruix system build
  • bin/fruix system rootfs
  • bin/fruix system image

The Phase 9 XCP-ng boot path benefits from this automatically because:

  • tests/system/run-phase9-xcpng-boot.sh still calls tests/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_marker
  • base_package_store_count
  • base_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 build twice,
  • 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 build
    • system rootfs
    • system 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 fruix with 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.