Files
fruix/docs/reports/phase5-checkout-runtime-freebsd.md

3.6 KiB

Phase 5.1: Unblocked the checkout command path on FreeBSD and established a first fruix frontend boundary

Date: 2026-04-01

Summary

This step moves the FreeBSD port from “the checkout configures and builds generated scripts” to “the checkout actually runs useful commands”.

Added files:

  • tests/guix/patches/phase5-checkout-runtime.patch
  • tests/guix/patches/phase5-guix-daemon-freebsd.patch
  • tests/guix/setup-phase5-checkout.sh
  • tests/guix/run-phase5-checkout-runtime.sh

Root cause of the leave-on-EPIPE failure

The earlier failure:

  • ./pre-inst-env guix --version
  • Wrong type to apply: #<syntax-transformer leave-on-EPIPE>

was traced to the ordering of top-level definitions in guix/ui.scm.

More specifically:

  • show-version-and-exit called leave-on-EPIPE
  • leave-on-EPIPE was defined later in the file as a syntax transformer
  • on this FreeBSD path, the earlier call site was compiled as a value application rather than as a macro expansion site
  • when invoked at runtime, Guile attempted to apply the syntax transformer as a procedure

This produced the observed error:

  • Wrong type to apply: #<syntax-transformer leave-on-EPIPE>

Runtime patch strategy

The runtime patch takes a deliberately small approach:

  1. make (guix ui) explicitly non-declarative for this command-path use case
  2. rewrite show-version-and-exit to use a direct catch 'system-error block instead of relying on the later syntax binding
  3. parameterize program-name in guix-main
  4. derive the version-banner command name from program-name
  5. make (guix scripts repl) explicitly non-declarative as well, since it also uses load

This resolves the FreeBSD checkout runtime failure without forcing a broad internal rename.

FreeBSD/Fruix frontend policy implemented

The step also establishes the first user-facing fruix checkout boundary.

Current policy implemented by the harness:

  • retain upstream-derived internal guix module and script structure
  • generate a scripts/fruix symlink next to scripts/guix
  • rely on the new program-name handling so:
    • ./pre-inst-env guix --version reports guix ...
    • ./pre-inst-env fruix --version reports fruix ...

This is intentionally a front-end boundary, not a whole-tree rename.

Validation command

Run command:

METADATA_OUT=/tmp/phase5-runtime-metadata.txt \
./tests/guix/run-phase5-checkout-runtime.sh

Observed results

The runtime harness validated all of the following successfully:

  1. ./pre-inst-env guix --version
  2. ./pre-inst-env guix repl --help
  3. ./pre-inst-env guix build --help
  4. ./pre-inst-env fruix --version

Observed metadata included:

  • first_guix_version_line=guix (GNU Guix) ...
  • first_fruix_version_line=fruix (GNU Guix) ...
  • repl_usage_line=Usage: guix repl [OPTIONS...] [-- FILE ARGS...]
  • build_usage_line=Usage: guix build [OPTION]... PACKAGE-OR-DERIVATION...

Important notes

  • the first-step fruix boundary currently changes the top-level version banner correctly
  • subcommand help output still exposes upstream-derived guix wording internally
  • this is acceptable for the current transition stage and matches the agreed naming policy:
    • Fruix at the user-facing boundary
    • stable upstream-derived internals unless there is strong reason to rename them

Conclusion

Phase 5.1 is satisfied on the current FreeBSD prototype track:

  • the checkout command path now runs on FreeBSD
  • the leave-on-EPIPE blocker is resolved in the checkout patch queue
  • at least one additional non-trivial checkout subcommand works
  • a first user-facing fruix checkout frontend boundary now exists without a destabilizing blanket rename