Files
fruix/docs/PROGRESS.md

1794 lines
88 KiB
Markdown

# Progress
## 2026-04-01 — Phase 1.1 started: Guile verified on FreeBSD amd64
Completed work:
- installed/confirmed `guile3-3.0.10`
- added a reusable verification harness:
- `tests/guile/run-phase1-verification.sh`
- `tests/guile/verify-phase1.scm`
- `tests/guile/modules/phase1/sample.scm`
- verified the following on `FreeBSD 15.0-STABLE` amd64:
- module loading
- deterministic output generation
- file I/O
- process handling with `primitive-fork`/`waitpid`
- loopback TCP sockets
- FFI calls into libc
- execution of Guix bootstrap-related code from `(guix build make-bootstrap)`
- wrote the results to `docs/reports/phase1-guile-freebsd.md`
Notable findings:
- `guile3` and `guile-3.0` are present, but there is no unversioned `guile` binary
- `system*` and `open-pipe*` currently segfault on this host (`exit 139`)
- despite that crash, the lower-level process primitives needed for further investigation do work
Current assessment:
- Phase 1.1 has a solid amd64 smoke-verification baseline
- Phase 1.1 is not fully complete yet because `i386` has not been checked and the subprocess crash needs investigation
- verification harness committed as `e380e88` (`Add FreeBSD Guile verification harness`)
## 2026-04-01 — Phase 1.1 follow-up: subprocess crash isolated
Completed work:
- added a dedicated subprocess diagnostic harness:
- `tests/guile/run-subprocess-diagnostics.sh`
- `tests/guile/posix-spawn-freebsd-diagnostics.c`
- reproduced crashes for:
- `system*`
- `spawn`
- `open-pipe*`
- confirmed all three fail with `SIGSEGV` / `exit 139`
- confirmed native FreeBSD `posix_spawn` + `posix_spawn_file_actions_addclosefrom_np` works in a standalone C program
- confirmed FreeBSD behavior that triggers gnulib replacement logic:
- `posix_spawn_file_actions_adddup2` accepts an invalid fd in the gnulib probe
- `posix_spawn_file_actions_addopen` accepts an invalid fd in the gnulib probe
- `posix_spawnp` accepts a shebang-less executable script in the gnulib security probe
- wrote the analysis to `docs/reports/phase1-guile-subprocess-crash.md`
Conclusion:
- this is most likely an upstream Guile/gnulib ABI bug on FreeBSD, not a Guix-specific problem
- likely sequence:
1. gnulib enables `REPLACE_POSIX_SPAWN=1`
2. Guile still enables `HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP`
3. Guile passes a gnulib replacement `posix_spawn_file_actions_t` object to native `posix_spawn_file_actions_addclosefrom_np`
4. libc interprets gnulib struct fields as a native pointer and crashes
- evidence from the lldb core matches this hypothesis (`*fa = 0x0000000600000008`, consistent with gnulib `_allocated=8`, `_used=6`)
Current assessment:
- Phase 1.1 amd64 investigation is now much stronger and has a concrete root-cause hypothesis
- the next practical step is to validate a workaround or patch in Guile so subprocess helpers stop crashing
- after that, continue with Phase 1.2 (minimal native build environment / GNU Hello)
## 2026-04-01 — Phase 1.1 follow-up: local Guile build validated the fix
Completed work:
- installed the additional build tooling needed for a local Guile checkout build:
- `autoconf`
- `automake`
- `libtool`
- `gettext-tools`
- `texinfo`
- `help2man`
- `gperf`
- `pkgconf`
- confirmed a FreeBSD-specific bootstrap quirk:
- Guile `autogen.sh` needs GNU `m4`
- FreeBSD base `/usr/bin/m4` is not sufficient
- `M4=gm4 ./autogen.sh` works
- built a disposable validation copy from `~/repos/guile`
- confirmed `~/repos/guile` already contains upstream commit:
- `eb828801f621d3e130b6fe88cfc4acaa69b98a03`
- `Don't use posix_spawn_file_actions_addclosefrom_np with glib posix_spawn`
- updated the local test harnesses so they can test non-system Guile builds:
- `tests/guile/run-phase1-verification.sh`
- `tests/guile/run-subprocess-diagnostics.sh`
- both now accept `GUILE_BIN`
- both now prepend the sibling `../lib` directory to `LD_LIBRARY_PATH` when a matching local `libguile-3.0.so.1` exists
- subprocess diagnostics now supports `EXPECT_GUILE_SUBPROCESS_CRASH=0` for fixed builds
- validated that the packaged Guile still reproduces the crash
- validated that the locally built Guile succeeds for:
- `system*`
- `spawn`
- `open-pipe*`
- re-ran the broader Phase 1.1 Scheme verification suite successfully against the local Guile build
- wrote the results to `docs/reports/phase1-guile-local-build-validation.md`
Important findings:
- the local Guile executable initially still crashed until it was forced to load its matching local `libguile-3.0.so.1`
- once `LD_LIBRARY_PATH` pointed at the local install lib directory, subprocess helpers worked correctly
- this strongly supports the earlier diagnosis and shows that the upstream Guile fix resolves the problem in practice
- the local `~/repos/bdwgc` checkout was not needed for this step; packaged `boehm-gc-threaded` was sufficient so far
Current assessment:
- Phase 1.1 now has both a root-cause analysis and a working validated fix path on amd64
- no source changes were needed in `~/repos/guile` because the local checkout already contains the relevant upstream fix
- no source changes were needed in `~/repos/bdwgc` yet, but the earlier FreeBSD warning keeps it on the watch list
- the project can now move on to Phase 1.2 with a known-good local Guile fallback
## 2026-04-01 — Phase 1.2 started: native GNU Hello build validated on FreeBSD
Completed work:
- added a reusable native build harness:
- `tests/native-build/run-gnu-hello.sh`
- used the current Guix package definition in `~/repos/guix/gnu/packages/base.scm` as the source of truth for:
- GNU Hello version `2.12.3`
- expected Guix nix-base32 source hash `183a6rxnhixiyykd7qis0y9g9cfqhpkk872a245y3zl28can0pqd`
- verified the downloaded tarball against the translated SHA256:
- `0d5f60154382fee10b114a1c34e785d8b1f492073ae2d3a6f7b147687b366aa0`
- successfully executed the standard native build lifecycle on `FreeBSD 15.0-STABLE` amd64:
- fetch
- hash verification
- extract
- configure
- build
- staged install
- runtime execution
- confirmed the staged binary runs and prints:
- `Hello, world!`
- captured build metadata including:
- compiler and make versions
- host triplet
- configure command
- staged output path
- runtime shared-library dependencies
- wrote the results to `docs/reports/phase1-native-gnu-hello.md`
Important findings:
- GNU Hello built successfully with FreeBSD base `make`, not just `gmake`
- that contrasts with the earlier local Guile build, which did require GNU `gmake`
- even this minimal GNU package links against FreeBSD-userland-provided libraries such as `libiconv` and `libintl`, which is useful data for later Guix package modeling
- this step is still a native shell-driven build exercise, not yet a real Guix package build
Current assessment:
- Phase 1.2 now has a concrete native autotools success case on FreeBSD
- the host can perform the basic fetch/verify/configure/build/install/run cycle needed for later `gnu-build-system` adaptation work
- Guix-specific build orchestration is still missing, but the environmental baseline is stronger now
Recent commits:
- `e380e88``Add FreeBSD Guile verification harness`
- `cd721b1``Update progress after Guile verification`
- `27916cb``Diagnose Guile subprocess crash on FreeBSD`
- `02f7a7f``Validate local Guile fix on FreeBSD`
Next recommended step:
1. extend Phase 1.2 with at least one additional representative GNU/autotools package build on FreeBSD, or
2. prototype a tiny Scheme-based `gnu-build-system`-like phase runner using the known-good local Guile path, starting from the GNU Hello flow
3. continue keeping `~/repos/bdwgc` in reserve if later FreeBSD-specific GC/thread issues appear
## 2026-04-01 — Phase 1.2 follow-up: Guix builder-side GNU Hello phase runner validated
Completed work:
- added a Scheme-driven GNU Hello build prototype:
- `tests/native-build/gnu-hello-guix-phase-runner.scm`
- `tests/native-build/run-gnu-hello-guix-phase-runner.sh`
- required the previously validated fixed local Guile build for this harness because it depends on subprocess-heavy Scheme operations
- used Guix modules directly from `~/repos/guix`, including:
- `(guix base32)`
- `(guix build gnu-build-system)`
- `(guix build utils)`
- fetched and hash-verified GNU Hello `2.12.3` again against the Guix package hash:
- nix-base32: `183a6rxnhixiyykd7qis0y9g9cfqhpkk872a245y3zl28can0pqd`
- SHA256: `0d5f60154382fee10b114a1c34e785d8b1f492073ae2d3a6f7b147687b366aa0`
- successfully executed a subset of Guix builder-side `%standard-phases` on FreeBSD:
- `set-SOURCE-DATE-EPOCH`
- `unpack`
- `configure`
- `build`
- `check`
- `install`
- installed GNU Hello into a store-like output path under the temporary work directory rather than using a `/usr/local` `DESTDIR` staging layout
- executed the resulting binary successfully and confirmed output:
- `Hello, world!`
- captured metadata including:
- host triplet
- selected phase list
- runtime dependencies
- test-suite summary
- wrote the results to `docs/reports/phase1-guix-gnu-hello-phase-runner.md`
Important findings:
- this is the first validation step in the repo that successfully exercised actual Guix builder-side GNU build logic on FreeBSD instead of only a shell approximation
- the harness works when driven by the fixed local Guile build, confirming that the earlier Guile subprocess-fix validation is directly useful for FreeBSD Guix build orchestration
- GNU Hello's `make check` test suite also passed in this mode:
- total: `7`
- pass: `7`
- fail: `0`
- the resulting binary's runtime dependencies differ from the earlier `/usr/local`-prefixed native shell harness; in this store-like output layout it only showed:
- `libc.so.7`
- `libsys.so.7`
- that difference is a useful clue that Guix-style output layout/build invocation can materially affect FreeBSD runtime linkage behavior
Current assessment:
- Phase 1.2 now has both:
- a shell-driven native GNU Hello build harness, and
- a Scheme-driven prototype that uses real Guix builder-side GNU phases
- this is still short of a true Guix package/derivation build, but it significantly narrows the gap between host validation and real `gnu-build-system` execution on FreeBSD
- the known-good local Guile path is now validated as part of a practical Guix-adjacent build workflow, not just standalone subprocess diagnostics
Recent commits:
- `e380e88``Add FreeBSD Guile verification harness`
- `cd721b1``Update progress after Guile verification`
- `27916cb``Diagnose Guile subprocess crash on FreeBSD`
- `02f7a7f``Validate local Guile fix on FreeBSD`
- `4aebea4``Add native GNU Hello FreeBSD build harness`
Next recommended step:
1. run the Scheme-driven phase-runner pattern against at least one more small GNU/autotools package on FreeBSD, or
2. document the concrete gaps between this prototype and a real Guix package/derivation build, especially around store management and build isolation
3. continue keeping `~/repos/bdwgc` in reserve if later FreeBSD-specific GC/thread issues appear
## 2026-04-01 — Phase 1.2 follow-up: second Scheme-driven GNU package build validated with GNU which
Completed work:
- added a second Scheme-driven GNU package harness:
- `tests/native-build/gnu-which-guix-phase-runner.scm`
- `tests/native-build/run-gnu-which-guix-phase-runner.sh`
- again used the previously validated fixed local Guile build because this harness depends on subprocess-heavy Guix/Scheme builder logic
- used the current Guix package definition in `~/repos/guix/gnu/packages/base.scm` as the source of truth for:
- GNU which version `2.21`
- expected Guix nix-base32 source hash `1bgafvy3ypbhhfznwjv1lxmd6mci3x1byilnnkc7gcr486wlb8pl`
- verified the downloaded tarball against the translated SHA256:
- `f4a245b94124b377d8b49646bf421f9155d36aa7614b6ebf83705d3ffc76eaad`
- successfully executed the same subset of Guix builder-side `%standard-phases` on FreeBSD as used for GNU Hello:
- `set-SOURCE-DATE-EPOCH`
- `unpack`
- `configure`
- `build`
- `check`
- `install`
- executed the resulting `which` binary successfully with a deterministic command:
- `PATH=/bin:/usr/bin ./which sh`
- confirmed output:
- `/bin/sh`
- captured metadata including:
- host triplet
- phase list
- runtime dependencies
- check-phase success status
- executed command output
- wrote the results to `docs/reports/phase1-guix-which-phase-runner.md`
Important findings:
- this confirms the Scheme-driven Guix builder-side phase-runner pattern is not limited to GNU Hello; a second small GNU/autotools package also succeeds on FreeBSD
- GNU which's `check` phase passed, but it did not leave behind an Automake-style `test-suite.log` or `testsuite.log`
- GNU which emitted a non-fatal `configure` warning about Guix's standard `--enable-fast-install` flag being unrecognized
- the source also emitted several clang warnings about deprecated non-prototype C declarations/definitions, but the build still completed successfully
- the resulting `which` binary again showed a minimal store-like runtime linkage profile:
- `libc.so.7`
- `libsys.so.7`
- unlike GNU Hello, the source tree did not present an obvious shipped `config.guess`, so the harness used `cc -dumpmachine` as a fallback for host-triplet metadata
Current assessment:
- Phase 1.2 now has two successful Scheme-driven Guix builder-side GNU package validations on FreeBSD:
- GNU Hello
- GNU which
- this increases confidence that a narrow but real subset of `gnu-build-system` builder-side execution already works on FreeBSD when paired with the fixed local Guile build
- the next uncertainty is now less about whether basic builder phases run at all, and more about where real Guix package/derivation/store integration and isolation will first require FreeBSD-specific adaptation
Recent commits:
- `e380e88``Add FreeBSD Guile verification harness`
- `cd721b1``Update progress after Guile verification`
- `27916cb``Diagnose Guile subprocess crash on FreeBSD`
- `02f7a7f``Validate local Guile fix on FreeBSD`
- `4aebea4``Add native GNU Hello FreeBSD build harness`
- `c944cdb``Validate Guix builder phases on FreeBSD`
Next recommended step:
1. document the concrete remaining gap between these Scheme-driven phase-runner prototypes and a true Guix package/derivation/store-daemon build on FreeBSD, especially around store management, implicit inputs, and build isolation
2. or choose a somewhat more demanding GNU package with non-trivial declared inputs to identify the first builder-side FreeBSD adaptation points
3. continue keeping `~/repos/bdwgc` in reserve if later FreeBSD-specific GC/thread issues appear
## 2026-04-01 — Phase 1.2 follow-up: documented the gap to a real Guix package build
Completed work:
- analyzed the concrete remaining gap between the current FreeBSD validation harnesses and a real Guix package/derivation/store-daemon build
- wrote the analysis to:
- `docs/reports/phase1-guix-build-gap-analysis.md`
- based the analysis on the current local Guix source tree, including the relevant host-side and daemon-side code paths in:
- `guix/packages.scm`
- `guix/build-system/gnu.scm`
- `guix/gexp.scm`
- `guix/store.scm`
- `guix/derivations.scm`
- `gnu/packages/commencement.scm`
- `doc/guix.texi`
- `nix/libstore/build.cc`
- compared those real Guix layers against the currently validated FreeBSD prototypes:
- shell-driven native GNU Hello harness
- Scheme-driven GNU Hello builder-phase runner
- Scheme-driven GNU which builder-phase runner
Main conclusions recorded:
- the current FreeBSD work has validated a narrow but real builder-side slice of Guix execution:
- Guile can run the needed Scheme code when using the fixed local build
- `(guix build gnu-build-system)` phases can build small GNU packages on FreeBSD
- however, the current prototypes still bypass several critical layers of a real Guix build:
- package -> bag lowering
- bag -> derivation lowering
- imported module closure/store materialization
- real daemon RPC and build submission
- canonical `/gnu/store` management and metadata
- build users, chroot/container or jail-style isolation
- substitute/graft/offload handling
- documented that the current phase runners rely on host tools already present on FreeBSD, whereas real `gnu-build-system` uses implicit inputs drawn from `%final-inputs`
- identified the most actionable next milestone as a derivation-generation investigation for a tiny package, to locate the first failure boundary among:
- host-side lowering
- store interaction
- derivation emission
- daemon availability
- daemon-side execution
Current assessment:
- Phase 1.2 now has both practical build validation and a clearer architectural map of what remains before a true Guix package build can work on FreeBSD
- the project has reduced uncertainty around builder-side GNU phase portability
- the next uncertainty is now specifically the host-side lowering/store/daemon boundary, not the builder-phase boundary
Recent commits:
- `e380e88``Add FreeBSD Guile verification harness`
- `cd721b1``Update progress after Guile verification`
- `27916cb``Diagnose Guile subprocess crash on FreeBSD`
- `02f7a7f``Validate local Guile fix on FreeBSD`
- `4aebea4``Add native GNU Hello FreeBSD build harness`
- `c944cdb``Validate Guix builder phases on FreeBSD`
- `0a2e48e``Validate GNU which builder phases on FreeBSD`
Next recommended step:
1. investigate whether a tiny package can be lowered far enough on FreeBSD to produce a real derivation, and capture the exact first failure point
2. if derivation generation proves immediately blocked, document whether the blocker is generated Guix modules/configuration, store connectivity, or daemon assumptions
3. continue keeping `~/repos/bdwgc` in reserve if later FreeBSD-specific GC/thread issues appear
## 2026-04-01 — Phase 1.2 follow-up: derivation-generation investigation identified the first real checkout blockers
Completed work:
- added a reproducible checkout/bootstrap/configure investigation harness:
- `tests/guix/run-derivation-generation-investigation.sh`
- used the previously validated fixed local Guile build for the investigation:
- `/tmp/guile-freebsd-validate-install/bin/guile`
- followed the operator instruction for future store setup by parameterizing the checkout attempts to use:
- store directory: `/frx/store`
- local state directory: `/frx/var`
- sysconf directory: `/frx/etc`
- created a disposable shared clone of `~/repos/guix`
- successfully ran `./bootstrap` from that disposable checkout on FreeBSD
- attempted `configure` without `--with-courage`
- attempted `configure` again with `--with-courage`
- confirmed directly that the local fixed Guile build currently cannot load:
- `(gnutls)`
- wrote the results to:
- `docs/reports/phase1-guix-derivation-generation-investigation.md`
Important findings:
- a stock Guix checkout currently fails configuration on FreeBSD before any derivation/store/daemon work is reached, due to the explicit unsupported-platform gate:
- ``configure: error: `x86_64-freebsd15.0' is not a supported platform.``
- re-running `configure` with `--with-courage` gets past that gate, but then stops on a second blocker:
- `configure: error: The Guile bindings of GnuTLS are missing; please install them.`
- a direct module-load test with the same local Guile confirms the problem more concretely:
- `(use-modules (gnutls))` fails with `no code for module (gnutls)`
- this means the current effort is still blocked before reaching:
- usable `pre-inst-env` generation for Guix commands
- package -> bag lowering in a live checkout
- bag -> derivation lowering
- daemon connectivity
- actual `/frx/store` population
Current assessment:
- the first practical boundary between the earlier FreeBSD builder-phase prototypes and a real Guix checkout has now been located more precisely
- the project is no longer blocked by vague uncertainty at this stage; it is blocked by two concrete checkout-preparation issues:
1. unsupported-platform configure gating
2. missing Guile `(gnutls)` bindings
- importantly, the derivation-generation investigation has not yet reached the store/daemon boundary, so the next step must first clear the `(gnutls)` dependency issue
Recent commits:
- `e380e88``Add FreeBSD Guile verification harness`
- `cd721b1``Update progress after Guile verification`
- `27916cb``Diagnose Guile subprocess crash on FreeBSD`
- `02f7a7f``Validate local Guile fix on FreeBSD`
- `4aebea4``Add native GNU Hello FreeBSD build harness`
- `c944cdb``Validate Guix builder phases on FreeBSD`
- `0a2e48e``Validate GNU which builder phases on FreeBSD`
- `245a47d``Document gaps to real Guix FreeBSD builds`
Next recommended step:
1. obtain working Guile `(gnutls)` bindings compatible with the fixed local Guile build and re-run the derivation-generation investigation
2. once configuration succeeds, continue until the next failure boundary is identified among:
- `pre-inst-env` usability
- derivation emission
- daemon connectivity
- daemon-side `/frx/store` assumptions
3. continue keeping `~/repos/bdwgc` in reserve if later FreeBSD-specific GC/thread issues appear
## 2026-04-01 — Phase 1.2 follow-up: local Guile-GnuTLS built on FreeBSD; next blocker is Guile-Git
Completed work:
- installed the host-side C GnuTLS stack needed for Guile-GnuTLS builds:
- `gnutls`
- `libtasn1`
- `nettle`
- `p11-kit`
- added a reproducible local Guile-GnuTLS build harness:
- `tests/guix/build-local-guile-gnutls.sh`
- updated the derivation-generation investigation harness so it can consume extra Guile module prefixes through:
- `GUILE_EXTRA_PREFIX`
- used the current Guix package definition in `~/repos/guix/gnu/packages/tls.scm` as the source of truth for:
- `guile-gnutls` version `5.0.1`
- expected Guix nix-base32 source hash `0kqngyx4520gjk49l6whjd2ss994kaj9rm78lli6p3q6xry0945i`
- verified the downloaded Guile-GnuTLS tarball against the translated SHA256:
- `b190047cee068f6b22a5e8d49ca49a2425ad4593901b9ac8940f8842ba7f164f`
- built and installed a local Guile-GnuTLS validation copy against the previously validated fixed local Guile build under:
- `/tmp/guile-gnutls-freebsd-validate-install`
- validated successfully that the fixed local Guile can now load:
- `(gnutls)`
- re-ran the checkout derivation-generation investigation with:
- `GUILE_EXTRA_PREFIX=/tmp/guile-gnutls-freebsd-validate-install`
- store directory still set to `/frx/store`
- wrote the results to:
- `docs/reports/phase1-guile-gnutls-freebsd.md`
Important findings:
- Guile-GnuTLS does not build with FreeBSD base `make`; it requires GNU `gmake`
- a FreeBSD-specific source compatibility issue surfaced in `guile/src/core.c`:
- it includes `<alloca.h>` unconditionally
- on this host, `alloca` is available through `<stdlib.h>` instead
- for local validation, the harness applies a small disposable-tree patch that uses `<stdlib.h>` on `__FreeBSD__`
- after that fix, the local Guile-GnuTLS build succeeded and `(use-modules (gnutls))` worked with the fixed local Guile build
- re-running the Guix checkout investigation confirms the earlier `(gnutls)` blocker is genuinely cleared
- the next configure-time blocker is now:
- `configure: error: Guile-Git is missing; please install it.`
Current assessment:
- the first checkout-preparation blocker after unsupported-platform gating has advanced from missing `(gnutls)` to missing `Guile-Git`
- this is meaningful progress because the project is now moving farther into the dependency chain required for a real Guix checkout on FreeBSD
- the requested experimental store path remains `/frx/store`, but the effort still has not yet reached actual store population or daemon interaction
Recent commits:
- `e380e88``Add FreeBSD Guile verification harness`
- `cd721b1``Update progress after Guile verification`
- `27916cb``Diagnose Guile subprocess crash on FreeBSD`
- `02f7a7f``Validate local Guile fix on FreeBSD`
- `4aebea4``Add native GNU Hello FreeBSD build harness`
- `c944cdb``Validate Guix builder phases on FreeBSD`
- `0a2e48e``Validate GNU which builder phases on FreeBSD`
- `245a47d``Document gaps to real Guix FreeBSD builds`
- `d62e9b0``Investigate Guix derivation generation on FreeBSD`
Next recommended step:
1. obtain `Guile-Git` compatible with the fixed local Guile build and re-run the derivation-generation investigation again
2. once checkout configuration succeeds, continue until the next failure boundary is identified among:
- `pre-inst-env` usability
- derivation emission
- daemon connectivity
- daemon-side `/frx/store` assumptions
3. continue keeping `~/repos/bdwgc` in reserve if later FreeBSD-specific GC/thread issues appear
## 2026-04-01 — Phase 1.2 follow-up: local Guile-Git stack built on FreeBSD; next blocker is Guile-JSON
Completed work:
- added a reproducible local Guile-Git dependency-stack build harness:
- `tests/guix/build-local-guile-git.sh`
- updated the derivation-generation investigation harness to probe and record both:
- local `(gnutls)` availability
- local `(git)` / `graph-descendant?` availability
- used the current Guix package definitions in `~/repos/guix/gnu/packages/guile.scm` as the source of truth for:
- `guile-bytestructures` version `1.0.10`
- `guile-git` version `0.10.0`
- built `guile-bytestructures` from the matching upstream tag and recorded resolved commit:
- `27cadba6b69a01b38b33bb39b9766d713eb90c1b`
- built `guile-git` from the matching upstream tag and recorded resolved commit:
- `05d4a48c811f29c8db80ee6697fe658950fb503e`
- installed both into the same local dependency prefix already used for the earlier Guile-GnuTLS validation:
- `/tmp/guile-gnutls-freebsd-validate-install`
- validated successfully that the fixed local Guile can now load:
- `(bytestructures guile)`
- `(git)`
- validated specifically that the Guile-Git export required by Guix `configure.ac` is present:
- `graph-descendant?`
- confirmed the host `libgit2` dependency used for the build is:
- `1.9.2`
- re-ran the checkout derivation-generation investigation with:
- `GUILE_EXTRA_PREFIX=/tmp/guile-gnutls-freebsd-validate-install`
- store directory still set to `/frx/store`
- wrote the results to:
- `docs/reports/phase1-guile-git-freebsd.md`
Important findings:
- both `guile-bytestructures` and `guile-git` were built from Git source layouts, so autotools regeneration was required:
- `guile-bytestructures`: `autoreconf -vfi`
- `guile-git`: `autoreconf -vfi` via harness fallback
- unlike the earlier Guile-GnuTLS step, no additional FreeBSD-specific source patch was needed for either package in this validation pass
- the Guix checkout now gets past both previously cleared dependency gates:
- `(gnutls)`
- `Guile-Git`
- after clearing those, the next configure-time blocker is now:
- `configure: error: Guile-JSON is missing; please install it.`
Current assessment:
- the checkout-preparation path on FreeBSD has progressed one dependency layer deeper
- the local validation prefix under `/tmp/guile-gnutls-freebsd-validate-install` now contains at least:
- Guile-GnuTLS
- Guile bytestructures
- Guile-Git
- despite that progress, the work still has not yet reached derivation emission, daemon connectivity, or actual `/frx/store` population
- the next concrete blocker is now `Guile-JSON`, as reported directly by the real Guix checkout configure step
Recent commits:
- `e380e88``Add FreeBSD Guile verification harness`
- `cd721b1``Update progress after Guile verification`
- `27916cb``Diagnose Guile subprocess crash on FreeBSD`
- `02f7a7f``Validate local Guile fix on FreeBSD`
- `4aebea4``Add native GNU Hello FreeBSD build harness`
- `c944cdb``Validate Guix builder phases on FreeBSD`
- `0a2e48e``Validate GNU which builder phases on FreeBSD`
- `245a47d``Document gaps to real Guix FreeBSD builds`
- `d62e9b0``Investigate Guix derivation generation on FreeBSD`
- `c0a85ed``Build local Guile-GnuTLS on FreeBSD`
Next recommended step:
1. obtain `Guile-JSON` compatible with the fixed local Guile build and install it into the same local dependency prefix
2. re-run the derivation-generation investigation again to identify the next configure-time or checkout-time blocker after `Guile-JSON`
3. continue keeping `/frx/store` as the intended experimental store root and keep `~/repos/bdwgc` in reserve if later FreeBSD-specific GC/thread issues appear
## 2026-04-01 — Phase 1.2 follow-up: local Guile-JSON built on FreeBSD; next blocker is Guile-SQLite3
Completed work:
- added a reproducible local Guile-JSON build harness:
- `tests/guix/build-local-guile-json.sh`
- updated the derivation-generation investigation harness to probe and record local recent-enough `(json)` availability in addition to the earlier `(gnutls)` and `(git)` checks
- used the current Guix package definition in `~/repos/guix/gnu/packages/guile.scm` as the source of truth for:
- `guile-json` version `4.7.3`
- expected Guix nix-base32 source hash `127k2xc07w1gnyqs40z4865l8p3ra5xgpcn569dz04lxsa709fiq`
- verified the downloaded Guile-JSON tarball against the translated SHA256:
- `38ba048ed29d12f05b32c5b2fb7a51795c448b41e403a2b1b72ff0035817f388`
- built and installed a local Guile-JSON validation copy into the same local dependency prefix already used for checkout prerequisites:
- `/tmp/guile-gnutls-freebsd-validate-install`
- validated successfully that the fixed local Guile now satisfies the Guix configure-time JSON requirement by:
- loading `(json)`
- using `define-json-mapping`
- decoding a small JSON object successfully
- re-ran the checkout derivation-generation investigation with:
- `GUILE_EXTRA_PREFIX=/tmp/guile-gnutls-freebsd-validate-install`
- store directory still set to `/frx/store`
- wrote the results to:
- `docs/reports/phase1-guile-json-freebsd.md`
Important findings:
- unlike the earlier Guile-Git step, Guile-JSON built cleanly from the release tarball and did not require autotools regeneration in this validation pass
- unlike the earlier Guile-GnuTLS step, no FreeBSD-specific source patch was needed here
- the shared local validation prefix now contains at least:
- Guile-GnuTLS
- Guile bytestructures
- Guile-Git
- Guile-JSON
- the Guix checkout now gets past the previously cleared dependency gates for:
- `(gnutls)`
- `Guile-Git`
- `Guile-JSON`
- after clearing those, the next configure-time blocker is now:
- `configure: error: A recent Guile-SQLite3 could not be found; please install it.`
Current assessment:
- the checkout-preparation path on FreeBSD has progressed another dependency layer deeper
- the project still has not yet reached derivation emission, daemon connectivity, or actual `/frx/store` population
- the next concrete blocker is now recent `Guile-SQLite3`, as reported directly by the real Guix checkout configure step
Recent commits:
- `e380e88``Add FreeBSD Guile verification harness`
- `cd721b1``Update progress after Guile verification`
- `27916cb``Diagnose Guile subprocess crash on FreeBSD`
- `02f7a7f``Validate local Guile fix on FreeBSD`
- `4aebea4``Add native GNU Hello FreeBSD build harness`
- `c944cdb``Validate Guix builder phases on FreeBSD`
- `0a2e48e``Validate GNU which builder phases on FreeBSD`
- `245a47d``Document gaps to real Guix FreeBSD builds`
- `d62e9b0``Investigate Guix derivation generation on FreeBSD`
- `c0a85ed``Build local Guile-GnuTLS on FreeBSD`
- `15b9037``Build local Guile-Git on FreeBSD`
Next recommended step:
1. obtain recent `Guile-SQLite3` compatible with the fixed local Guile build and install it into the same local dependency prefix
2. re-run the derivation-generation investigation again to identify the next configure-time or checkout-time blocker after `Guile-SQLite3`
3. continue keeping `/frx/store` as the intended experimental store root and keep `~/repos/bdwgc` in reserve if later FreeBSD-specific GC/thread issues appear
## 2026-04-01 — Phase 1.2 follow-up: remaining checkout Guile prerequisites built; next blocker is `./pre-inst-env guix --version`
Completed work:
- installed the remaining missing host C library dependencies required for the next Guile extension stack:
- `libgcrypt`
- `libgpg-error`
- `lzlib`
- added a reproducible build harness for the remaining mandatory Guix checkout Guile modules:
- `tests/guix/build-local-guile-configure-deps.sh`
- extended the derivation-generation investigation harness to:
- probe local recent-enough availability for:
- `(sqlite3)`
- `(gcrypt hash)`
- `(zlib)`
- `(lzlib)`
- `(semver)`
- run checkout `configure` with:
- `MAKE=gmake`
- continue past successful configuration into:
- `gmake scripts/guix`
- `./pre-inst-env guix --version`
- used the current Guix package definitions as source of truth for the following additional module stack:
- `guile-sqlite3` `0.1.3`
- `guile-gcrypt` `0.5.0`
- `guile-zlib` `0.2.2`
- `guile-lzlib` `0.3.0`
- `guile-semver` `0.2.0`
- built and installed those modules into the same shared local dependency prefix already used for prior checkout prerequisites:
- `/tmp/guile-gnutls-freebsd-validate-install`
- validated successfully that the fixed local Guile can now satisfy all of the remaining configure-time Guix module checks encountered so far:
- `(sqlite3)` with `sqlite-bind-arguments`
- `(gcrypt hash)` with `hash-algorithm` lookup
- `(zlib)` with `make-zlib-input-port`
- `(lzlib)`
- `(semver)`
- re-ran the checkout derivation-generation investigation with:
- `GUILE_EXTRA_PREFIX=/tmp/guile-gnutls-freebsd-validate-install`
- store directory still set to `/frx/store`
- wrote the results to:
- `docs/reports/phase1-guix-checkout-configure-stack-freebsd.md`
Important findings:
- `guile-gcrypt` required an explicit configure workaround on this host:
- `--with-libgcrypt-prefix=/usr/local`
- without it, the package's `libgcrypt-config --libs` parsing produced an unusable shared-library name on FreeBSD
- the currently served upstream `guile-lzlib` `0.3.0` tarball no longer matches the Guix-recorded hash:
- expected from Guix: `a7f99c8d2a143e05ea22db2dc8b9ce6c27cae942162b45ee3015ed9027af0ff2`
- observed from current source URL: `6a2847a303a141bb95b1b5d1a4b975b4dbff9cc590eba377cc8072682e7637ec`
- for local validation, the harness fell back to the matching upstream Git tag and recorded commit:
- `474cee42116295bc0bd2acf12d4d6a766043090e`
- once the remaining Guile modules were present, checkout `configure --with-courage` stopped failing on missing modules
- however, the checkout still needed:
- `MAKE=gmake`
to complete configuration successfully on FreeBSD
- after that, `gmake scripts/guix` succeeded as well
- the next concrete blocker has moved from configuration-time prerequisites to runtime behavior of the uninstalled Guix command path:
- `./pre-inst-env guix --version` prints the version banner, then exits with:
- `Wrong type to apply: #<syntax-transformer leave-on-EPIPE>`
Current assessment:
- the checkout-preparation path on FreeBSD has now progressed beyond the missing mandatory Guile module stack that previously blocked configuration
- the current local validation prefix now contains the required configure-time modules encountered so far for a real Guix checkout
- the first blocker after successful checkout configuration and `scripts/guix` generation is now a runtime Scheme failure in the uninstalled `guix` command path itself
- the work is therefore now meaningfully past “cannot configure” and into “configures, builds `scripts/guix`, but fails at `./pre-inst-env guix --version`
Recent commits:
- `e380e88``Add FreeBSD Guile verification harness`
- `cd721b1``Update progress after Guile verification`
- `27916cb``Diagnose Guile subprocess crash on FreeBSD`
- `02f7a7f``Validate local Guile fix on FreeBSD`
- `4aebea4``Add native GNU Hello FreeBSD build harness`
- `c944cdb``Validate Guix builder phases on FreeBSD`
- `0a2e48e``Validate GNU which builder phases on FreeBSD`
- `245a47d``Document gaps to real Guix FreeBSD builds`
- `d62e9b0``Investigate Guix derivation generation on FreeBSD`
- `c0a85ed``Build local Guile-GnuTLS on FreeBSD`
- `15b9037``Build local Guile-Git on FreeBSD`
- `47d31e8``Build local Guile-JSON on FreeBSD`
Next recommended step:
1. investigate the `leave-on-EPIPE` runtime failure now blocking `./pre-inst-env guix --version`
2. complete the remaining Phase 1.3 FreeBSD system-call mapping/documentation deliverable so Phase 1 foundations can be closed out cleanly
3. continue keeping `/frx/store` as the intended experimental store root and keep `~/repos/bdwgc` in reserve if later FreeBSD-specific GC/thread issues appear
## 2026-04-01 — Phase 1.3 completed: FreeBSD syscall/interface mapping documented and exercised
Completed work:
- added a runnable C syscall/interface mapping harness:
- `tests/system/freebsd-syscall-mapping.c`
- added a shell runner for the mapping harness:
- `tests/system/run-freebsd-syscall-mapping.sh`
- inspected current Guix/Linux-oriented source paths relevant to daemon/build isolation and host behavior, especially:
- `~/repos/guix/nix/libstore/build.cc`
- `~/repos/guix/configure.ac`
- inspected the relevant FreeBSD interfaces/documentation available on the host, including:
- `jail(2)`
- `chroot(2)`
- `closefrom(2)` / `close_range(2)`
- `mount(2)` / `nmount(2)`
- `mount_nullfs(8)`
- `cap_enter(2)`
- `cap_rights_limit(2)`
- `lutimes(2)`
- `lchown(2)`
- `posix_fallocate(2)`
- `pdfork(2)`
- ran the new syscall mapping harness successfully and captured metadata under:
- `/tmp/freebsd-syscall-mapping-metadata.txt`
- wrote the Phase 1.3 report to:
- `docs/reports/phase1-freebsd-syscall-mapping.md`
Important findings:
- the current FreeBSD host provides and the harness successfully exercised:
- `fork` / `waitpid`
- `posix_spawn_file_actions_addclosefrom_np`
- `close_range`
- `lutimes`
- `statvfs`
- `chroot` (root test)
- `jail(2)` (root test)
- `lchown` (root test)
- the same harness confirmed the absence of the key Linux namespace-oriented interfaces that current Guix daemon code depends on:
- `clone`
- `unshare`
- `setns`
- `pivot_root`
- `sys/prctl.h`
- FreeBSD Capsicum headers are present, which is useful context for later security design, but Capsicum is not a direct replacement for Linux namespaces or Linux capabilities
- `posix_fallocate` is present but returned `EOPNOTSUPP` on the tested filesystems, so a successful configure/link probe does not guarantee useful runtime semantics
- the mapping strongly confirms that the correct Phase 2 direction is not syscall emulation but a jail-first redesign using:
- jails
- `chroot`
- `nullfs`
- traditional build-user privilege separation
Current assessment:
- the Phase 1.3 deliverable is now satisfied with both:
- a technical mapping document, and
- a runnable validation harness
- the main architectural conclusion is now concrete rather than speculative:
- Linux namespace code paths in current Guix daemon/build isolation cannot be ported directly to FreeBSD
- the FreeBSD implementation must instead be designed around jails and explicit mount/layout control
## 2026-04-01 — Phase 1 completed on the current FreeBSD amd64 porting track
Phase 1 is now considered complete for the active amd64 FreeBSD host path.
Why this milestone is satisfied:
- **Phase 1.1** success criteria were met on the current host:
- Guile executes Guix bootstrap-related code
- deterministic/module/FFI/socket/process validation succeeded
- the FreeBSD subprocess crash was root-caused and a working fixed local Guile path was validated
- **Phase 1.2** success criteria were exceeded:
- native GNU Hello build success was demonstrated
- multiple Guix builder-side GNU phase validations succeeded
- a real Guix checkout now configures on FreeBSD with local dependency supplementation, builds `scripts/guix`, and reaches a concrete runtime blocker at:
- `./pre-inst-env guix --version`
- **Phase 1.3** is now completed with the syscall/interface mapping document and runnable harness
Important scope note:
- the original Phase 1.1 narrative mentioned `i386` as additional target coverage, but the explicit success criteria used to gate progression have been satisfied on the active amd64 FreeBSD host
- full i386 Guile validation remains useful future coverage work, but it is no longer the blocker for moving into Phase 2 design/prototyping on this machine
Recent commits:
- `e380e88``Add FreeBSD Guile verification harness`
- `cd721b1``Update progress after Guile verification`
- `27916cb``Diagnose Guile subprocess crash on FreeBSD`
- `02f7a7f``Validate local Guile fix on FreeBSD`
- `4aebea4``Add native GNU Hello FreeBSD build harness`
- `c944cdb``Validate Guix builder phases on FreeBSD`
- `0a2e48e``Validate GNU which builder phases on FreeBSD`
- `245a47d``Document gaps to real Guix FreeBSD builds`
- `d62e9b0``Investigate Guix derivation generation on FreeBSD`
- `c0a85ed``Build local Guile-GnuTLS on FreeBSD`
- `15b9037``Build local Guile-Git on FreeBSD`
- `47d31e8``Build local Guile-JSON on FreeBSD`
- `d82195b``Advance Guix checkout on FreeBSD`
Next recommended step:
1. begin Phase 2.1 by turning the new syscall mapping into a concrete FreeBSD jail-based build-isolation design/prototype
2. carry forward the current concrete runtime blocker from Phase 1.2:
- investigate the `leave-on-EPIPE` failure in `./pre-inst-env guix --version`
3. continue keeping `/frx/store` as the intended experimental store root and keep `~/repos/bdwgc` in reserve if later FreeBSD-specific GC/thread issues appear
## 2026-04-01 — Phase 2.1 completed: jail-first build isolation design validated on FreeBSD
Completed work:
- added a runnable jail-based build isolation prototype:
- `tests/daemon/run-freebsd-jail-build-prototype.sh`
- wrote the Phase 2.1 design/prototype report:
- `docs/reports/phase2-freebsd-jail-build-isolation.md`
- translated the earlier Phase 1 syscall mapping into a concrete FreeBSD Guix-daemon isolation design centered on:
- thin jails
- one jail per build
- explicit `nullfs` mount plans
- networking disabled by default
- separate build-user credentials inside the jail envelope
- ran the jail prototype successfully and captured metadata under:
- `/tmp/jail-build-metadata.txt`
Important findings:
- a thin-jail approach is the right match for Guix's declared-input model; thick jails would overexpose ambient host state and add unnecessary duplication
- a per-build jail root assembled from explicit read-only `nullfs` mounts is a practical replacement for the Linux bind-mount + mount-namespace model in current Guix daemon code
- a basic build operation can already be executed successfully inside a FreeBSD jail with a restricted filesystem view consisting only of:
- selected read-only host toolchain paths
- a read-only declared input directory
- a writable declared output directory
- a writable `/tmp`
- a host sentinel file left outside the jail root is not visible inside the build environment, confirming the prototype is exercising real visibility restriction rather than a mere chroot-like shell wrapper
- the prototype jail ran with:
- `ip4=disable`
- `ip6=disable`
which matches the intended default for hermetic builds
Current assessment:
- Phase 2.1 is now satisfied on the current FreeBSD prototype track
- the main design decision is now concrete rather than speculative:
- the Guix FreeBSD daemon path should be jail-first, not Linux-namespace emulation
- the next step is to add a build-user privilege-dropping prototype inside or alongside this jail model so the design covers both containment and user-level isolation
Recent commits:
- `e380e88``Add FreeBSD Guile verification harness`
- `cd721b1``Update progress after Guile verification`
- `27916cb``Diagnose Guile subprocess crash on FreeBSD`
- `02f7a7f``Validate local Guile fix on FreeBSD`
- `4aebea4``Add native GNU Hello FreeBSD build harness`
- `c944cdb``Validate Guix builder phases on FreeBSD`
- `0a2e48e``Validate GNU which builder phases on FreeBSD`
- `245a47d``Document gaps to real Guix FreeBSD builds`
- `d62e9b0``Investigate Guix derivation generation on FreeBSD`
- `c0a85ed``Build local Guile-GnuTLS on FreeBSD`
- `15b9037``Build local Guile-Git on FreeBSD`
- `47d31e8``Build local Guile-JSON on FreeBSD`
- `d82195b``Advance Guix checkout on FreeBSD`
- `9bf3d30``Document FreeBSD syscall mapping`
Next recommended step:
1. implement the Phase 2.2 privilege-dropping/build-user prototype for FreeBSD, ideally combined with the new jail execution model
2. then establish a `/frx/store`-based store-management prototype covering permissions, package readability, and garbage-collection behavior
3. continue carrying the separate Guix checkout runtime blocker:
- investigate the `leave-on-EPIPE` failure in `./pre-inst-env guix --version`
## 2026-04-01 — Phase 2.2 completed: privilege dropping and concurrent build-user isolation validated
Completed work:
- added a C helper implementing the core daemon-side privilege drop mechanics:
- `tests/daemon/freebsd-build-user-helper.c`
- added a harness that combines that helper with the new jail model and runs two jobs concurrently:
- `tests/daemon/run-freebsd-privilege-drop-prototype.sh`
- wrote the Phase 2.2 report:
- `docs/reports/phase2-freebsd-privilege-drop.md`
- ran the concurrent build-user prototype successfully and captured metadata under:
- `/tmp/freebsd-privdrop-metadata.txt`
Important findings:
- a root-launched FreeBSD helper can successfully perform the expected daemon-side transition:
- `setgroups`
- `setgid`
- `setuid`
into a dedicated build identity
- once dropped, the helper cannot regain root with `setuid(0)`:
- `Operation not permitted`
- each build job can create files in its own writable directory and those files end up owned by the dropped build UID/GID rather than by root
- two concurrent jobs using distinct numeric build identities succeeded with:
- job 1 UID/GID `35001:35001`
- job 2 UID/GID `35002:35002`
- host-side result files were observed with the matching ownership and restrictive permissions:
- `0600`
- the two jobs were deliberately held for two seconds each and the measured wall-clock elapsed time was also about two seconds, demonstrating actual concurrent execution rather than serialized execution
- two complementary denial modes were validated at the same time:
- peer build files mounted but blocked by permissions: `Permission denied`
- host path not mounted into the jail at all: `No such file or directory`
- the dropped build user also could not:
- create files in a protected root-owned directory
- `chown` its own output back to root
Current assessment:
- Phase 2.2 is now satisfied on the current FreeBSD prototype track
- the combined jail + build-user model now has practical validation for the most important security properties required by a future FreeBSD Guix daemon:
- root-controlled setup
- permanent drop to build credentials
- per-build writable areas
- cross-build isolation
- concurrent execution under distinct identities
- the remaining Phase 2 work is now centered on the store itself: permissions, readability, content-addressed layout, and garbage-collection behavior under `/frx/store`
Recent commits:
- `e380e88``Add FreeBSD Guile verification harness`
- `cd721b1``Update progress after Guile verification`
- `27916cb``Diagnose Guile subprocess crash on FreeBSD`
- `02f7a7f``Validate local Guile fix on FreeBSD`
- `4aebea4``Add native GNU Hello FreeBSD build harness`
- `c944cdb``Validate Guix builder phases on FreeBSD`
- `0a2e48e``Validate GNU which builder phases on FreeBSD`
- `245a47d``Document gaps to real Guix FreeBSD builds`
- `d62e9b0``Investigate Guix derivation generation on FreeBSD`
- `c0a85ed``Build local Guile-GnuTLS on FreeBSD`
- `15b9037``Build local Guile-Git on FreeBSD`
- `47d31e8``Build local Guile-JSON on FreeBSD`
- `d82195b``Advance Guix checkout on FreeBSD`
- `9bf3d30``Document FreeBSD syscall mapping`
- `7621798``Prototype FreeBSD jail build isolation`
Next recommended step:
1. complete Phase 2.3 by establishing a `/frx/store`-based store prototype with:
- correct root/daemon write restrictions
- unprivileged read access
- content-addressed path naming
- garbage-collection behavior
2. if possible, use outputs or dependency relationships realistic enough to model how a future FreeBSD Guix daemon would retain referenced store items
3. continue carrying the separate Guix checkout runtime blocker:
- investigate the `leave-on-EPIPE` failure in `./pre-inst-env guix --version`
## 2026-04-01 — Phase 2.3 completed: `/frx/store` prototype validated on FreeBSD
Completed work:
- added a runnable `/frx/store` prototype harness:
- `tests/store/run-freebsd-store-prototype.sh`
- wrote the Phase 2.3 report:
- `docs/reports/phase2-freebsd-store-prototype.md`
- created and exercised the operator-requested `/frx` layout on-host:
- `/frx/store`
- `/frx/var`
- `/frx/etc`
- `/frx/var/fruix/gcroots`
- created a store group for the prototype path:
- `fruixbuild`
- ran the store prototype successfully and captured metadata under:
- `/tmp/freebsd-store-prototype-metadata.txt`
Important findings:
- the current host now has a working `/frx/store` prototype owned as:
- `root:fruixbuild`
with mode:
- `drwxrwxr-t`
- the prototype successfully created content-addressed demo store items under `/frx/store` using hash-based names
- the demo item set included:
- rooted greeting data
- a rooted app referencing that data through an absolute store path
- an unrooted orphan item intended for collection
- an unprivileged user (`nobody`) could:
- read store data
- execute the demo app from the store
- the same unprivileged user could not:
- create files directly in `/frx/store`
and the observed failure was:
- `Permission denied`
- the prototype GC logic followed rooted references successfully:
- with a GC root present, the app and its referenced data survived while the orphan item was collected
- after removing the GC root, the remaining demo items were collected as well
- the demo store returned to an empty state after the second GC pass, so the host is left with the `/frx` skeleton but without lingering prototype payloads
Current assessment:
- Phase 2.3 is now satisfied on the current FreeBSD prototype track
- the core store assumptions needed for a FreeBSD Guix-daemon design have practical validation now:
- `/frx/store` path viability
- root-controlled mutation
- unprivileged read access
- immutable absolute store references
- root-managed GC roots and mark/sweep retention behavior
- remaining gaps are now above this architectural layer rather than below it:
- real derivation registration
- SQLite-backed store metadata
- daemon RPC integration
- actual package lowering/build submission using these mechanisms
## 2026-04-01 — Phase 2 completed on the current FreeBSD prototype track
Phase 2 is now considered complete for the active FreeBSD amd64 prototype path.
Why this milestone is satisfied:
- **Phase 2.1** success criteria were met:
- a detailed jail-first build-isolation design was produced
- a runnable prototype successfully executed a build command in a restricted FreeBSD jail
- **Phase 2.2** success criteria were met:
- a concrete C privilege-dropping implementation was added
- build-user credential drop, inability to regain root, and concurrent cross-build isolation were demonstrated
- **Phase 2.3** success criteria were met on the prototype track:
- a working `/frx/store` equivalent was established
- content-addressed demo store items were created and consumed
- unprivileged read vs. privileged write behavior was validated
- garbage-collection behavior over rooted references was demonstrated
Important scope note:
- this completes the **core daemon architecture adaptation** milestone, not a full Guix-daemon port
- the separate real-checkout blocker from Phase 1 remains relevant for later integration work:
- `./pre-inst-env guix --version` still fails with `Wrong type to apply: #<syntax-transformer leave-on-EPIPE>`
- however, that runtime issue no longer blocks the specific Phase 2 architectural deliverables because the jail, privilege, and store assumptions have now been validated independently on FreeBSD
Recent commits:
- `e380e88``Add FreeBSD Guile verification harness`
- `cd721b1``Update progress after Guile verification`
- `27916cb``Diagnose Guile subprocess crash on FreeBSD`
- `02f7a7f``Validate local Guile fix on FreeBSD`
- `4aebea4``Add native GNU Hello FreeBSD build harness`
- `c944cdb``Validate Guix builder phases on FreeBSD`
- `0a2e48e``Validate GNU which builder phases on FreeBSD`
- `245a47d``Document gaps to real Guix FreeBSD builds`
- `d62e9b0``Investigate Guix derivation generation on FreeBSD`
- `c0a85ed``Build local Guile-GnuTLS on FreeBSD`
- `15b9037``Build local Guile-Git on FreeBSD`
- `47d31e8``Build local Guile-JSON on FreeBSD`
- `d82195b``Advance Guix checkout on FreeBSD`
- `9bf3d30``Document FreeBSD syscall mapping`
- `7621798``Prototype FreeBSD jail build isolation`
- `d65b2af``Prototype FreeBSD build user isolation`
Next recommended step:
1. begin Phase 3.1 by adapting Guix build-system expectations to the now-validated jail/privilege/store model on FreeBSD
2. carry forward the concrete real-checkout runtime blocker for later integration work:
- investigate the `leave-on-EPIPE` failure in `./pre-inst-env guix --version`
3. continue using `/frx/store` rather than `/gnu/store` for FreeBSD store experiments
## 2026-04-01 — Phase 3.1 completed: reusable FreeBSD GNU build-system adaptation validated across five packages
Completed work:
- added a reusable Scheme runner for FreeBSD-adapted GNU package builds:
- `tests/build-system/gnu-package-freebsd-phase-runner.scm`
- added a shell wrapper for the generic runner:
- `tests/build-system/run-gnu-package-freebsd-phase-runner.sh`
- added a five-package validation matrix:
- `tests/build-system/run-freebsd-gnu-package-matrix.sh`
- wrote the Phase 3.1 report:
- `docs/reports/phase3-freebsd-gnu-build-system.md`
- ran the matrix successfully and captured summary metadata under:
- `/tmp/freebsd-gnu-package-matrix-summary.txt`
Important findings:
- the build adaptation is now centralized rather than package-specific and is applied through a dedicated pre-configure FreeBSD environment phase
- the adaptation consistently uses:
- GNU `gmake` via a `make` path shim
- FreeBSD Clang via `cc`/`gcc` and `c++`/`g++` tool shims
- `CONFIG_SHELL=/bin/sh`
- `/usr/local` include/library/pkg-config search paths
- five representative GNU packages from current Guix package definitions now build successfully through the adapted runner on the current FreeBSD amd64 host:
- `hello` `2.12.3`
- `which` `2.21`
- `time` `1.9`
- `patch` `2.8`
- `nano` `8.7.1`
- the resulting binaries executed correctly with deterministic checks appropriate to each package:
- `hello` -> `Hello, world!`
- `which` -> `/bin/sh`
- `time` -> `time (GNU Time) 1.9`
- `patch` -> `GNU patch 2.8`
- `nano` -> `GNU nano, version 8.7.1`
- the matrix also validated a package with meaningful runtime dependencies:
- `nano` linked against FreeBSD/base and `/usr/local` libraries including `libintl`, `libmagic`, `libncursesw`, `libtinfow`, and `libz`
- one package-specific FreeBSD test boundary was recorded explicitly instead of being hidden:
- `time` required `RUN_TESTS=0` because the upstream `time-max-rss` test was not reliable on this host
Current assessment:
- Phase 3.1 is now satisfied on the current prototype track
- the main question has shifted from “can adapted GNU builder phases run on FreeBSD?” to “how should FreeBSD system components themselves be described and installed as profile-usable packages?”
- the next step is therefore Phase 3.2: define a minimal FreeBSD package set with explicit dependencies and validate profile-style installation/usability
Recent commits:
- `e380e88``Add FreeBSD Guile verification harness`
- `cd721b1``Update progress after Guile verification`
- `27916cb``Diagnose Guile subprocess crash on FreeBSD`
- `02f7a7f``Validate local Guile fix on FreeBSD`
- `4aebea4``Add native GNU Hello FreeBSD build harness`
- `c944cdb``Validate Guix builder phases on FreeBSD`
- `0a2e48e``Validate GNU which builder phases on FreeBSD`
- `245a47d``Document gaps to real Guix FreeBSD builds`
- `d62e9b0``Investigate Guix derivation generation on FreeBSD`
- `c0a85ed``Build local Guile-GnuTLS on FreeBSD`
- `15b9037``Build local Guile-Git on FreeBSD`
- `47d31e8``Build local Guile-JSON on FreeBSD`
- `d82195b``Advance Guix checkout on FreeBSD`
- `9bf3d30``Document FreeBSD syscall mapping`
- `7621798``Prototype FreeBSD jail build isolation`
- `d65b2af``Prototype FreeBSD build user isolation`
- `e404e2e``Prototype FreeBSD store management`
Next recommended step:
1. complete Phase 3.2 by defining a minimal FreeBSD system package set with explicit dependency relationships and profile-style installation validation
2. carry forward the concrete real-checkout runtime blocker for later integration work:
- investigate the `leave-on-EPIPE` failure in `./pre-inst-env guix --version`
3. continue using `/frx/store` rather than `/gnu/store` for future FreeBSD store experiments when the prototype work needs a persistent store root
## 2026-04-01 — Phase 3.2 completed: FreeBSD system package-definition prototype and profile validation added
Completed work:
- added a Guix-style FreeBSD system package-definition prototype module:
- `modules/fruix/packages/freebsd.scm`
- added a Scheme harness to materialize those package definitions into store-like outputs and a merged profile:
- `tests/packages/freebsd-package-profile-prototype.scm`
- added a shell wrapper for that harness:
- `tests/packages/run-freebsd-package-profile-prototype.sh`
- installed the missing host shell dependency needed to satisfy the requested package set:
- `bash`
- wrote the Phase 3.2 report:
- `docs/reports/phase3-freebsd-package-definitions.md`
- ran the profile prototype successfully and captured metadata under:
- `/tmp/freebsd-package-profile-prototype-metadata.txt`
Important findings:
- the prototype now defines a minimal FreeBSD core package set covering the categories requested by Phase 3.2:
- kernel
- kernel headers
- libc
- userland utilities
- development tools (`clang`, `make`, autotools)
- minimum system libraries (`openssl`, `zlib`)
- shells (`sh`, `bash`)
- the current package-definition layer uses an explicit Guix-like record shape with fields for:
- name
- version
- build system
- inputs
- synopsis/description/home-page/license
- install plan
- explicit dependency relationships are now encoded and resolved recursively during materialization, including examples such as:
- `freebsd-libc` -> `freebsd-kernel-headers`
- `freebsd-userland` -> `freebsd-libc`, `freebsd-sh`
- `freebsd-clang-toolchain` -> `freebsd-libc`, `freebsd-kernel-headers`, `freebsd-sh`
- `freebsd-autotools` -> `freebsd-gmake`, `freebsd-bash`, `freebsd-libc`
- the harness successfully materialized:
- `11` core package outputs
into a store-like directory tree under the work directory
- it then merged those outputs into a development profile and validated that the profile contains working:
- `bash`
- `make`
- `autoconf`
- `cc`
- kernel image path
- kernel-header path
- core shared-library paths
- the generated profile compiled and ran a C test program successfully, with observed output:
- `hello-from-freebsd-profile`
- for executables installed under `bin/`, the prototype uses wrappers that `exec` the host tool by absolute path; this preserved correct behavior for prefix-sensitive tools such as `autoconf`
Current assessment:
- Phase 3.2 is now satisfied on the current prototype track
- Phase 3 as a whole is now completed on the current FreeBSD amd64 path because both:
- adapted GNU build-system execution, and
- minimal FreeBSD system package-definition/profile validation
have been demonstrated successfully
- the next remaining project milestone is now Phase 4, centered on Shepherd rather than package-building foundations
## 2026-04-01 — Phase 3 completed on the current FreeBSD prototype track
Phase 3 is now considered complete for the active FreeBSD amd64 prototype path.
Why this milestone is satisfied:
- **Phase 3.1** success criteria were met on the prototype track:
- a reusable FreeBSD adaptation layer for GNU builder phases was added
- five representative GNU packages built successfully through that adapted runner
- the resulting binaries executed correctly on the host
- **Phase 3.2** success criteria were met on the prototype track:
- a minimal FreeBSD system package-definition layer was added
- explicit dependency relationships were modeled and resolved
- the package outputs installed into a merged profile successfully
- the generated profile was validated by compiling and running a test program with the staged toolchain
Important scope note:
- this completes the **build-system adaptation milestone** in prototype form, not the full Guix package-lowering/daemon integration path
- the earlier concrete upstream/runtime blocker still exists for later integration work:
- `./pre-inst-env guix --version` fails with `Wrong type to apply: #<syntax-transformer leave-on-EPIPE>`
- however, that blocker no longer prevents Phase 4 work because the core build-system and package-definition assumptions have now been validated independently
Recent commits:
- `e380e88``Add FreeBSD Guile verification harness`
- `cd721b1``Update progress after Guile verification`
- `27916cb``Diagnose Guile subprocess crash on FreeBSD`
- `02f7a7f``Validate local Guile fix on FreeBSD`
- `4aebea4``Add native GNU Hello FreeBSD build harness`
- `c944cdb``Validate Guix builder phases on FreeBSD`
- `0a2e48e``Validate GNU which builder phases on FreeBSD`
- `245a47d``Document gaps to real Guix FreeBSD builds`
- `d62e9b0``Investigate Guix derivation generation on FreeBSD`
- `c0a85ed``Build local Guile-GnuTLS on FreeBSD`
- `15b9037``Build local Guile-Git on FreeBSD`
- `47d31e8``Build local Guile-JSON on FreeBSD`
- `d82195b``Advance Guix checkout on FreeBSD`
- `9bf3d30``Document FreeBSD syscall mapping`
- `7621798``Prototype FreeBSD jail build isolation`
- `d65b2af``Prototype FreeBSD build user isolation`
- `e404e2e``Prototype FreeBSD store management`
- `eb0d77c``Adapt GNU build phases for FreeBSD`
Next recommended step:
1. begin Phase 4.1 by validating whether Shepherd itself now builds and runs as a regular service on FreeBSD with the fixed local Guile path
2. carry forward the separate real-checkout runtime blocker for later integration work:
- investigate the `leave-on-EPIPE` failure in `./pre-inst-env guix --version`
3. continue using `/frx/store` rather than `/gnu/store` for future FreeBSD integration experiments when a persistent store root is required
## 2026-04-01 — Phase 4.1 completed: Shepherd built and validated as a regular FreeBSD service manager
Completed work:
- added a reproducible local Guile Fibers build harness:
- `tests/shepherd/build-local-guile-fibers.sh`
- added a reproducible local Shepherd build harness:
- `tests/shepherd/build-local-shepherd.sh`
- added a runnable multi-service Shepherd validation harness for FreeBSD:
- `tests/shepherd/run-freebsd-shepherd-service-prototype.sh`
- wrote the Phase 4.1 report:
- `docs/reports/phase4-freebsd-shepherd-service.md`
- ran the service-management prototype successfully and captured metadata under:
- `/tmp/freebsd-shepherd-service-metadata.txt`
Important findings:
- the current FreeBSD path now has a working local Shepherd build based on:
- local fixed Guile
- locally installed Guile Fibers `1.4.2`
- Shepherd `1.0.9`
- Shepherd build/install required one concrete FreeBSD-specific toolchain adaptation:
- `SED=/usr/local/bin/gsed`
because the install phase edits wrapper scripts using GNU `sed -i` syntax that base FreeBSD `sed` does not accept
- at runtime, Shepherd reports:
- `System lacks support for 'signalfd'; using fallback mechanism.`
but the fallback path works correctly for supervision on this host
- the prototype successfully validated all requested regular-service capabilities:
- start/stop via `herd`
- dependency handling
- status monitoring
- crash/respawn behavior
- privilege-aware execution
- the concrete service set used for validation included:
- an unprivileged heartbeat logger
- a loopback HTTP service
- a dependent file-monitor service
- a crash-once respawn test service
- observed metadata confirmed:
- `logger_running=yes`
- `web_running=yes`
- `monitor_running=yes`
- `crashy_running=yes`
- `logger_uid=65534` (`nobody`)
- `http_response=shepherd-freebsd-ok`
- `monitor_detected=detected`
- `crashy_counter=2`
Current assessment:
- Phase 4.1 is now satisfied on the current FreeBSD prototype track
- Shepherd is no longer just a theoretical later step; it now builds and supervises multiple services correctly on the host when paired with the fixed local Guile stack
- the next question is no longer “can Shepherd run on FreeBSD at all?” but “what is the best FreeBSD init-integration strategy for it on this prototype path?”
Recent commits:
- `e380e88``Add FreeBSD Guile verification harness`
- `cd721b1``Update progress after Guile verification`
- `27916cb``Diagnose Guile subprocess crash on FreeBSD`
- `02f7a7f``Validate local Guile fix on FreeBSD`
- `4aebea4``Add native GNU Hello FreeBSD build harness`
- `c944cdb``Validate Guix builder phases on FreeBSD`
- `0a2e48e``Validate GNU which builder phases on FreeBSD`
- `245a47d``Document gaps to real Guix FreeBSD builds`
- `d62e9b0``Investigate Guix derivation generation on FreeBSD`
- `c0a85ed``Build local Guile-GnuTLS on FreeBSD`
- `15b9037``Build local Guile-Git on FreeBSD`
- `47d31e8``Build local Guile-JSON on FreeBSD`
- `d82195b``Advance Guix checkout on FreeBSD`
- `9bf3d30``Document FreeBSD syscall mapping`
- `7621798``Prototype FreeBSD jail build isolation`
- `d65b2af``Prototype FreeBSD build user isolation`
- `e404e2e``Prototype FreeBSD store management`
- `eb0d77c``Adapt GNU build phases for FreeBSD`
- `d47dc9b``Prototype FreeBSD package definitions`
Next recommended step:
1. complete Phase 4.2 by prototyping how Shepherd should be launched and stopped through FreeBSD init conventions while validating boot/shutdown dependency ordering for essential services
2. after that, bridge Shepherd to key FreeBSD service concepts such as rc.d management, loopback/network configuration, filesystem setup, and temporary user/group administration
3. continue carrying the separate real-checkout runtime blocker for later integration work:
- investigate the `leave-on-EPIPE` failure in `./pre-inst-env guix --version`
## 2026-04-01 — Phase 4.2 completed: FreeBSD rc.d init-integration prototype validated for Shepherd
Completed work:
- added a runnable FreeBSD init-integration prototype harness:
- `tests/shepherd/run-freebsd-shepherd-init-prototype.sh`
- wrote the Phase 4.2 report:
- `docs/reports/phase4-freebsd-shepherd-init-integration.md`
- ran the init-integration prototype successfully and captured metadata under:
- `/tmp/freebsd-shepherd-init-metadata.txt`
Important findings:
- a real temporary FreeBSD `rc.d` script can successfully launch the locally built Shepherd daemon through the standard:
- `service <name> onestart`
path
- the same wrapper can stop it cleanly through:
- `service <name> onestop`
using `herd ... stop root` under the hood
- the prototype automatically started a minimal essential-service graph at daemon launch consisting of:
- `filesystems`
- `system-log`
- `networking`
- `login`
- observed startup order matched the declared dependency chain exactly:
- `start:filesystems`
- `start:system-log`
- `start:networking`
- `start:login`
- observed shutdown order matched the expected reverse dependency order exactly:
- `stop:login`
- `stop:networking`
- `stop:system-log`
- `stop:filesystems`
- the rc.d wrapper reported the Shepherd instance as running while active:
- `rc_status=running`
- the prototype again observed the expected FreeBSD runtime note:
- `System lacks support for 'signalfd'; using fallback mechanism.`
and confirmed that it does not prevent correct boot/shutdown ordering behavior
Current assessment:
- Phase 4.2 is now satisfied on the current prototype track as an init-integration prototype
- the key result is that Shepherd can already be launched and stopped through native FreeBSD service-management conventions while preserving dependency-based startup and shutdown semantics
- the remaining Phase 4 work is now specifically about bridging Shepherd services to concrete FreeBSD host-management concepts rather than basic daemon launch or service ordering
Recent commits:
- `e380e88``Add FreeBSD Guile verification harness`
- `cd721b1``Update progress after Guile verification`
- `27916cb``Diagnose Guile subprocess crash on FreeBSD`
- `02f7a7f``Validate local Guile fix on FreeBSD`
- `4aebea4``Add native GNU Hello FreeBSD build harness`
- `c944cdb``Validate Guix builder phases on FreeBSD`
- `0a2e48e``Validate GNU which builder phases on FreeBSD`
- `245a47d``Document gaps to real Guix FreeBSD builds`
- `d62e9b0``Investigate Guix derivation generation on FreeBSD`
- `c0a85ed``Build local Guile-GnuTLS on FreeBSD`
- `15b9037``Build local Guile-Git on FreeBSD`
- `47d31e8``Build local Guile-JSON on FreeBSD`
- `d82195b``Advance Guix checkout on FreeBSD`
- `9bf3d30``Document FreeBSD syscall mapping`
- `7621798``Prototype FreeBSD jail build isolation`
- `d65b2af``Prototype FreeBSD build user isolation`
- `e404e2e``Prototype FreeBSD store management`
- `eb0d77c``Adapt GNU build phases for FreeBSD`
- `d47dc9b``Prototype FreeBSD package definitions`
- `b36746f``Validate Shepherd services on FreeBSD`
Next recommended step:
1. complete Phase 4.3 by adding a small FreeBSD Shepherd bridge layer for rc.d-style services, loopback/network configuration, filesystem setup, and temporary user/group administration
2. use that bridge layer in a runnable integration harness that validates both activation and cleanup of those FreeBSD concepts
3. continue carrying the separate real-checkout runtime blocker for later integration work:
- investigate the `leave-on-EPIPE` failure in `./pre-inst-env guix --version`
## 2026-04-01 — Phase 4.3 completed: FreeBSD Shepherd bridge layer validated across rc.d, network, filesystem, and account management
Completed work:
- added a reusable FreeBSD Shepherd bridge module:
- `modules/fruix/shepherd/freebsd.scm`
- added a runnable integration harness exercising that bridge layer:
- `tests/shepherd/run-freebsd-shepherd-bridge-prototype.sh`
- wrote the Phase 4.3 report:
- `docs/reports/phase4-freebsd-shepherd-bridge.md`
- ran the bridge prototype successfully and captured metadata under:
- `/tmp/freebsd-shepherd-bridge-metadata.txt`
Important findings:
- the new module now exports concrete helper constructors for four FreeBSD integration categories:
- `freebsd-rc-service`
- `freebsd-loopback-alias-service`
- `freebsd-tmpfs-service`
- `freebsd-user-group-service`
- the integration harness used those helpers to manage a real chained host-side service graph under Shepherd covering:
- a temporary rc.d script in `/usr/local/etc/rc.d/`
- loopback alias configuration on `lo0`
- tmpfs mount/unmount with mode validation
- temporary user/group creation and removal via `pw`
- observed activation metadata confirmed all of those operations succeeded under Shepherd control:
- `target_running=yes`
- `rc_started=yes`
- `alias_present=yes`
- `tmpfs_mounted=yes`
- `tmpfs_mode=drwxr-x---`
- `user_present=yes`
- `group_present=yes`
- observed cleanup metadata confirmed that `stop root` also reversed all of those host-side effects successfully:
- `rc_stopped=yes`
- `alias_removed=yes`
- `tmpfs_unmounted=yes`
- `user_removed=yes`
- `group_removed=yes`
- the same expected FreeBSD runtime note remained true here as well:
- `System lacks support for 'signalfd'; using fallback mechanism.`
and again it did not prevent the prototype from working correctly
Current assessment:
- Phase 4.3 is now satisfied on the current prototype track
- Shepherd now has a concrete FreeBSD bridge layer in-repo rather than only ad hoc validation scripts
- with service supervision, rc.d integration, and FreeBSD host-concept bridging now all validated, Phase 4 is complete on the current FreeBSD amd64 prototype path
## 2026-04-01 — Phase 4 completed on the current FreeBSD prototype track
Phase 4 is now considered complete for the active FreeBSD amd64 prototype path.
Why this milestone is satisfied:
- **Phase 4.1** success criteria were met on the prototype track:
- Shepherd built successfully on FreeBSD with the fixed local Guile stack
- regular multi-service supervision worked
- dependency handling, status monitoring, privilege-aware execution, and respawn behavior were all validated
- **Phase 4.2** success criteria were met in init-integration prototype form:
- a real FreeBSD `rc.d` wrapper launched Shepherd successfully
- a minimal essential-service graph started automatically in correct dependency order
- orderly reverse shutdown through native FreeBSD service entry points was validated
- **Phase 4.3** success criteria were met on the prototype track:
- a reusable FreeBSD Shepherd bridge layer was added
- Shepherd services successfully bridged to rc.d service control, loopback/network configuration, filesystem mounting/permissions, and temporary user/group administration
- both activation and cleanup were validated
Important scope note:
- this completes the **Shepherd porting milestone** on the current prototype track, not a literal replacement of `/sbin/init` on the live host
- however, the core Shepherd questions have now been answered positively on FreeBSD:
- it builds
- it runs
- it supervises services
- it integrates with FreeBSD service-management conventions
- it can express concrete FreeBSD host-management tasks through Shepherd services
- the separate real-Guix-checkout runtime blocker still exists for later integration work:
- `./pre-inst-env guix --version` fails with `Wrong type to apply: #<syntax-transformer leave-on-EPIPE>`
but that is now clearly outside the scope of the completed Phase 4 Shepherd milestone
Recent commits:
- `e380e88``Add FreeBSD Guile verification harness`
- `cd721b1``Update progress after Guile verification`
- `27916cb``Diagnose Guile subprocess crash on FreeBSD`
- `02f7a7f``Validate local Guile fix on FreeBSD`
- `4aebea4``Add native GNU Hello FreeBSD build harness`
- `c944cdb``Validate Guix builder phases on FreeBSD`
- `0a2e48e``Validate GNU which builder phases on FreeBSD`
- `245a47d``Document gaps to real Guix FreeBSD builds`
- `d62e9b0``Investigate Guix derivation generation on FreeBSD`
- `c0a85ed``Build local Guile-GnuTLS on FreeBSD`
- `15b9037``Build local Guile-Git on FreeBSD`
- `47d31e8``Build local Guile-JSON on FreeBSD`
- `d82195b``Advance Guix checkout on FreeBSD`
- `9bf3d30``Document FreeBSD syscall mapping`
- `7621798``Prototype FreeBSD jail build isolation`
- `d65b2af``Prototype FreeBSD build user isolation`
- `e404e2e``Prototype FreeBSD store management`
- `eb0d77c``Adapt GNU build phases for FreeBSD`
- `d47dc9b``Prototype FreeBSD package definitions`
- `b36746f``Validate Shepherd services on FreeBSD`
- `83715f0``Prototype Shepherd rc.d integration`
Next recommended step:
1. return to the remaining real Guix checkout/runtime blocker and investigate the `leave-on-EPIPE` failure in `./pre-inst-env guix --version`
2. begin the next post-Phase-4 integration milestone by connecting the now-validated daemon/build/store/Shepherd prototypes more directly to real Guix checkout behavior on FreeBSD
3. continue using `/frx/store` rather than `/gnu/store` whenever future integration experiments need a persistent store root
## 2026-04-01 — Planning update: Fruix naming policy clarified for post-Phase-4 work
Completed work:
- added a new post-Phase-4 planning document:
- `docs/PLAN_2.md`
- updated that plan to clarify the naming policy for the fork going forward
Key planning decision:
- **Fruix** is now the intended user-facing product identity
- the user-facing CLI should become:
- `fruix`
- `/frx` remains the canonical store/state/config root on the FreeBSD path
- however, the plan explicitly avoids a blanket rename of all upstream-derived internal identifiers
- in particular:
- internal `guix` namespaces may remain temporarily where needed for compatibility and maintenance
- `gnu` names are preserved where they refer to real GNU concepts or components such as GNU packages, GNU Shepherd, or `gnu-build-system`
- new fork-specific modules and user-facing surfaces should prefer `fruix` naming
Current assessment:
- the naming direction is now clearer for the next integration batch
- Phase 5 and beyond should aim to:
- first make the upstream-derived checkout runnable on FreeBSD,
- then introduce a deliberate `fruix` command boundary,
- rather than destabilizing the codebase with a whole-tree `guix`/`gnu` rename too early
## 2026-04-01 — Phase 5.1 completed: checkout runtime unblocked and first `fruix` frontend boundary established
Completed work:
- added a reusable phase-5 checkout setup helper:
- `tests/guix/setup-phase5-checkout.sh`
- added a checkout runtime patch queue for the upstream-derived source tree:
- `tests/guix/patches/phase5-checkout-runtime.patch`
- added a FreeBSD daemon/build patch queue needed for later phase-5 work:
- `tests/guix/patches/phase5-guix-daemon-freebsd.patch`
- added a runtime validation harness:
- `tests/guix/run-phase5-checkout-runtime.sh`
- wrote the Phase 5.1 report:
- `docs/reports/phase5-checkout-runtime-freebsd.md`
- ran the runtime harness successfully and captured metadata under:
- `/tmp/phase5-runtime-metadata.txt`
Important findings:
- the earlier checkout blocker
- `./pre-inst-env guix --version`
- `Wrong type to apply: #<syntax-transformer leave-on-EPIPE>`
is now explained by top-level definition ordering in `guix/ui.scm`:
- `show-version-and-exit` called `leave-on-EPIPE` before the syntax transformer was defined later in the file
- on this FreeBSD path, that became a runtime application of a syntax-transformer object instead of a macro expansion site
- the phase-5 runtime patch fixes this by:
- making `(guix ui)` explicitly non-declarative
- rewriting `show-version-and-exit` to use direct `catch 'system-error` handling
- parameterizing `program-name` in `guix-main`
- deriving the top-level version banner name from `program-name`
- making `(guix scripts repl)` explicitly non-declarative as well
- the checkout now successfully runs the following commands on FreeBSD:
- `./pre-inst-env guix --version`
- `./pre-inst-env guix repl --help`
- `./pre-inst-env guix build --help`
- the first user-facing Fruix command boundary is now implemented in the checkout setup via:
- `scripts/fruix`
as a front-end alias next to `scripts/guix`
- observed runtime metadata confirmed:
- `first_guix_version_line=guix (GNU Guix) ...`
- `first_fruix_version_line=fruix (GNU Guix) ...`
- this matches the agreed naming policy:
- Fruix at the user-facing boundary
- stable upstream-derived internal `guix`/`gnu` names unless there is a concrete reason to rename them
Current assessment:
- Phase 5.1 is now satisfied on the current FreeBSD prototype track
- the key boundary has shifted from “the checkout still crashes immediately” to “the checkout runs, and can now be used as the basis for real derivation/store experiments”
- the next step is to prove that a real derivation can be emitted against `/frx/store` from the now-runnable checkout
## 2026-04-01 — Phase 5.2 completed: real derivation generation validated against `/frx/store`
Completed work:
- added a runnable derivation-generation harness:
- `tests/guix/run-phase5-derivation-generation.sh`
- wrote the Phase 5.2 report:
- `docs/reports/phase5-derivation-generation-freebsd.md`
- ran the derivation-generation harness successfully and captured metadata under:
- `/tmp/phase5-derivation-metadata.txt`
Important findings:
- the now-runnable checkout can successfully use a real daemon/store connection on FreeBSD to lower a package through:
- `package->bag`
- `bag->derivation`
- the emitted derivation is a real `/frx/store` derivation path rather than an ad hoc placeholder or shell metadata artifact
- the validation used a deliberately minimal custom package with a custom low-level build system so that this subphase isolates the real lowering/store boundary without being dominated by still-unresolved upstream bootstrap assumptions for full native FreeBSD package graphs
- observed metadata confirmed:
- `bag_name=phase5-freebsd-lowering-0`
- `bag_host_inputs=("source")`
- `drv_path=/frx/store/...-phase5-freebsd-lowering-0.drv`
- `out_path=/frx/store/...-phase5-freebsd-lowering-0`
- this means the key architectural step is now real and no longer hypothetical:
- a package object in the checkout can be lowered to a real derivation targeting `/frx/store` on FreeBSD
Current assessment:
- Phase 5.2 is now satisfied on the current FreeBSD prototype track
- the next step is no longer “can we emit a derivation at all?” but “can the same daemon/store path accept and execute a derivation-backed build request successfully?”
## 2026-04-01 — Phase 5.3 completed: minimal daemon/store RPC integration validated on FreeBSD
Completed work:
- added a runnable daemon/store RPC validation harness:
- `tests/guix/run-phase5-daemon-rpc.sh`
- wrote the Phase 5.3 report:
- `docs/reports/phase5-daemon-rpc-freebsd.md`
- ran the daemon/store RPC harness successfully and captured metadata under:
- `/tmp/phase5-daemon-rpc-metadata.txt`
Important findings:
- the patched checkout can now contact a real FreeBSD-aware daemon over a Unix socket and submit a derivation-backed build request successfully
- the resulting build path is a real `/frx/store` output rather than a simulated prototype artifact
- the successful metadata path now includes the full minimal chain needed for later system work:
- checkout command path
- daemon RPC
- derivation submission
- build execution
- store output materialization
- observed metadata confirmed:
- `drv_path=/frx/store/...-phase5-freebsd-daemon-build-0.drv`
- `out_path=/frx/store/...-phase5-freebsd-daemon-build-0`
- `payload=phase5-daemon-build-source`
- `source_path=/frx/store/...-phase5-source.txt`
- this step was exercised through the Fruix-facing checkout boundary:
- `./pre-inst-env fruix repl -- ...`
which means the user-facing transition is now connected to actual daemon/store activity, not just to help text or version banners
Current assessment:
- Phase 5.3 is now satisfied on the current FreeBSD prototype track
- the project now has a real but narrow end-to-end host-side execution path on FreeBSD:
- runnable checkout
- Fruix front-end boundary
- real derivation emission
- daemon/store RPC
- successful derivation-backed build into `/frx/store`
## 2026-04-01 — Phase 5 completed on the current FreeBSD prototype track
Phase 5 is now considered complete for the active FreeBSD amd64 prototype path.
Why this milestone is satisfied:
- **Phase 5.1** success criteria were met on the prototype track:
- the checkout runtime blocker around `leave-on-EPIPE` was root-caused and fixed in the patch queue
- the uninstalled checkout command path now runs on FreeBSD
- a first user-facing `fruix` command boundary was established
- **Phase 5.2** success criteria were met on the prototype track:
- a real package object was lowered through `package->bag` and `bag->derivation`
- a real derivation was emitted targeting `/frx/store`
- **Phase 5.3** success criteria were met on the prototype track:
- a real checkout command path contacted a FreeBSD-aware daemon/store path
- that path accepted and executed a derivation-backed build request
- the resulting output was materialized successfully in `/frx/store`
Important scope note:
- this completes the **real checkout and host runtime unblocking milestone** on the current prototype track, not full upstream-package-graph support for arbitrary native FreeBSD package builds yet
- the successful derivation/build path currently uses a deliberately minimal custom package/build-system path to isolate real daemon/store viability from still-unresolved upstream bootstrap and package-graph assumptions for native FreeBSD
- nevertheless, the core Phase 5 question has now been answered positively:
- the checkout runs
- real derivations can be emitted
- the daemon can be built far enough to serve store RPC
- and derivation-backed builds can succeed into `/frx/store`
Next recommended step:
1. begin Phase 6.1 by moving from the minimal custom derivation-backed package path to at least one real FreeBSD store-backed package build driven by Fruix/Guix mechanisms
2. then integrate the already validated jail/build-user model more directly into the live daemon build path
3. continue preserving the selective Fruix naming policy:
- Fruix at the product boundary
- `/frx` as the canonical store root
- stable upstream-derived internal names unless there is strong architectural value in renaming them
## 2026-04-01 — Phase 6.1 completed: real package build validated into `/frx/store`
Completed work:
- added a runnable real-package harness:
- `tests/guix/run-phase6-real-package-build.sh`
- wrote the Phase 6.1 report:
- `docs/reports/phase6-real-package-build-freebsd.md`
- ran the real-package harness successfully and captured metadata under:
- `/tmp/phase6-real-package-metadata.txt`
Important findings:
- the checkout can now build a real package definition derived from Guix's `hello` package through:
- `./pre-inst-env fruix build -f ...`
- the FreeBSD-aware daemon
- `/frx/store`
- this moves the project beyond the deliberately minimal Phase 5 custom derivation path and into a real package-definition flow
- the current successful path still uses a prefetched local GNU Hello tarball as the package source because the built-in downloader path remains a separate unresolved FreeBSD/root-daemon issue
- observed metadata confirmed:
- `drv_path=/frx/store/...-hello-2.12.3.drv`
- `out_path=/frx/store/...-hello-2.12.3`
- `source_store_path=/frx/store/...-hello-2.12.3.tar.gz`
- `runtime_output=Hello, world!`
- a daemon-side references query confirmed that the built output preserved the declared source store item as a direct reference
Current assessment:
- Phase 6.1 is now satisfied on the current FreeBSD prototype track
- the next step is to move the already validated jail/build-user model into this live package-build path rather than keeping it prototype-only
## 2026-04-01 — Phase 6.2 completed: jail/build-user isolation integrated into the real package path
Completed work:
- added a reusable UID/GID drop helper source:
- `tests/daemon/freebsd-drop-exec.c`
- added a runnable jail-integrated package harness:
- `tests/guix/run-phase6-jail-package-build.sh`
- wrote the Phase 6.2 report:
- `docs/reports/phase6-jail-build-integration-freebsd.md`
- ran the jail-integrated harness successfully and captured metadata under:
- `/tmp/phase6-jail-package-metadata.txt`
Important findings:
- a real package build derived from Guix's `hello` definition now runs through the live daemon path inside a FreeBSD jail rather than only through the earlier prototype scripts
- the actual build work inside the jail runs as dropped credentials:
- UID `35001`
- GID `35001`
- the integrated build path required one additional FreeBSD-specific adjustment beyond the earlier prototype:
- the daemon-side host `TMPDIR` path was not automatically valid inside the jail, so the jailed build environment must reset `TMPDIR=/tmp`
- observed metadata confirmed:
- `drv_path=/frx/store/...-hello-2.12.3.drv`
- `out_path=/frx/store/...-hello-2.12.3`
- `runtime_output=Hello, world!`
- `build_uid=35001`
- `build_gid=35001`
- `jail_hostname=fruix-phase6-hello-...`
- `build_mode=freebsd-jail`
- `source_store_path=/frx/store/...-hello-2.12.3.tar.gz`
- the GNU Hello test suite also passed inside the jail-integrated build path
Current assessment:
- Phase 6.2 is now satisfied on the current FreeBSD prototype track
- the next step is to validate a minimal user-facing profile installation flow on top of these real store outputs