# Phase 16.2: materialize declarative FreeBSD source inputs under Fruix control Date: 2026-04-03 ## Goal Phase 16.2 moves from merely *describing* FreeBSD source inputs to actually *materializing* them under Fruix control. The objective in this subphase was not yet to switch the native base build path away from ambient `/usr/src`. Instead, it was to establish the missing fetch/materialization layer that later phases can consume. That means Fruix now knows how to: - fetch a Git-backed FreeBSD source declaration - download and verify a `src.txz` declaration - materialize the resulting source tree into `/frx/store` - cache downloaded source state under `/frx/var/cache/fruix/freebsd-source` - record stable source metadata for later native builds ## Implementation ### New source materializer in `modules/fruix/system/freebsd.scm` Added: - `materialize-freebsd-source` and exported it for use by the Fruix CLI. This materializer now supports all currently modeled source kinds: - `local-tree` - `git` - `src-txz` ### Source artifacts are now first-class store objects Materialized source outputs are now stored in paths of the form: - `/frx/store/-freebsd-source-` Each source output contains: - `tree/` or an auto-detected nested source root beneath it - `.fruix-source` - `.freebsd-source-info.scm` - `.references` The source info file records at least: - declared source - effective/resolved source - materialized store path - effective source root - source tree SHA256 - cache path used to produce it ### Cache layout added under `/frx/var/cache/fruix/freebsd-source` The new materializer caches downloaded source state under: - `/frx/var/cache/fruix/freebsd-source/git/...` - `/frx/var/cache/fruix/freebsd-source/archives/...` Current behavior: - Git sources use a cached bare repository - `src.txz` sources use a cached archive file - repeated materialization of the same resolved source identity reuses the same store output path ### Git source handling Git materialization now: - uses `https://git.FreeBSD.org/src.git` - supports declarations by ref and/or commit - fetches the selected ref/commit into a cached bare repository - resolves refs to a concrete commit - exports that commit into a store materialization This means Fruix can now represent moving refs declaratively while still recording the exact resolved commit used for a given materialized source tree. ### `src.txz` source handling `src.txz` materialization now: - downloads the declared archive URL with `fetch` - requires and verifies SHA256 for materialization - extracts the archive into a store materialization - records both the declared hash and the resulting source tree hash For release archives, the canonical shorter URL form is now used in validation and documentation, for example: - `https://download.freebsd.org/releases/amd64/15.0-RELEASE/src.txz` rather than the longer doubled-architecture variant. ### Auto-detect the effective source root inside materialized trees Git exports place the source tree directly at the materialized root. Official `src.txz` archives instead unpack as: - `usr/src/...` inside the extracted directory tree. To make this usable for later native builds, the materializer now auto-detects the effective source root and records it explicitly. For example: - Git materialization root: - `/frx/store/...-freebsd-source-stable15-git-ref/tree` - `src.txz` materialization root: - `/frx/store/...-freebsd-source-release15-src-txz/tree/usr/src` ### New user-facing CLI command Added a new user-facing command path in `scripts/fruix.scm`: - `fruix source materialize SOURCE-FILE` with options: - `--source NAME` - `--store DIR` - `--cache DIR` - `--help` The command emits machine-readable metadata including: - declared source fields - materialized store path - effective source root - source tree hash - cache path - resolved Git commit if applicable - verified archive hash if applicable This gives Phase 16.2 an operator-usable entry point rather than limiting it to internal Scheme helpers. ### Validation tightened for archive-backed sources `src-txz` source validation now requires: - URL - SHA256 This is the right reproducibility boundary for archive downloads. ## Guix comparison This step continues to mirror the most useful Guix source boundary without copying it mechanically: - Guix models source objects with `origin` - Git-backed origins use `git-reference` Fruix's source materializer now plays a similar role for FreeBSD-specific source inputs: - local tree snapshots - FreeBSD Git refs/commits - official `src.txz` archives The key preserved idea is the same: source identity should become an explicit, recorded, materialized input rather than ambient host state. ## New files Added: - `tests/system/phase16-git-freebsd-source.scm.in` - `tests/system/phase16-txz-freebsd-source.scm.in` - `tests/system/run-phase16-source-materialization.sh` ## Validation Passing run: - `PASS phase16-source-materialization` - workdir: - `/tmp/fruix-phase16-source-materialization.QGuXi1` ### Git validation Validated a Git declaration: - name: - `stable15-git-ref` - URL: - `https://git.FreeBSD.org/src.git` - ref: - `stable/15` Resolved/materialized result: ```text materialized_source_store=/frx/store/dd1cc6b5ffa95b4d0c0f269522d5739da05e0f4ae81b1b314221d28b49d1981f-freebsd-source-stable15-git-ref materialized_source_root=/frx/store/dd1cc6b5ffa95b4d0c0f269522d5739da05e0f4ae81b1b314221d28b49d1981f-freebsd-source-stable15-git-ref/tree materialized_source_tree_sha256=d0d8e085d913a511d7fa1ba410040eb697a4cef800f354a092c65249ab3c4eb4 materialized_source_cache_path=/frx/var/cache/fruix/freebsd-source/git/9d432c47301c356bd2cede3400de40870e0b541b276888e34c68b882b9b894c7.git materialized_source_commit=332708a606f6bf0841c1d4a74c0d067f5640fe89 ``` The harness also confirmed: - repeated materialization returned the same store path - the cached Git repository exists - the materialized tree contains: - `Makefile` - `sys/conf/newvers.sh` ### `src.txz` validation Validated an archive declaration: - name: - `release15-src-txz` - URL: - `https://download.freebsd.org/releases/amd64/15.0-RELEASE/src.txz` - SHA256: - `83c3e8157b6d7afcae57167fda75693bf1e5f581ca149a6ecb2d398b71bdfab0` Resolved/materialized result: ```text materialized_source_store=/frx/store/2e7857fb2c067b32acb482d048b8d1c2eeffdecd213108b3b0a4b2a87d56bc68-freebsd-source-release15-src-txz materialized_source_root=/frx/store/2e7857fb2c067b32acb482d048b8d1c2eeffdecd213108b3b0a4b2a87d56bc68-freebsd-source-release15-src-txz/tree/usr/src materialized_source_tree_sha256=afbe26f2213a19685fc2c3b875d26fab67e2cfcd605716cc66f669dabeaf7572 materialized_source_cache_path=/frx/var/cache/fruix/freebsd-source/archives/64ac7cc7d27435406995d63ef0b87ed0c485ce953ee8e9126127ca8f2a451d98-src.txz materialized_source_sha256=83c3e8157b6d7afcae57167fda75693bf1e5f581ca149a6ecb2d398b71bdfab0 ``` The harness also confirmed: - repeated materialization returned the same store path - the cached archive exists - the effective materialized source root was detected as `tree/usr/src` - that root contains: - `Makefile` - `sys/conf/newvers.sh` ### Regression check Also re-ran: - `PASS phase16-declarative-source-build` This confirmed the new source materialization work did not break the earlier Phase 16.1 declarative source model path. ## Result Phase 16.2 is complete. Fruix can now fetch or materialize declared FreeBSD source inputs into `/frx/store` with cache-backed provenance under `/frx/var/cache/fruix/freebsd-source`. The next step is now clear and narrower: - teach native FreeBSD kernel/world/runtime builds to consume these materialized source artifacts instead of ambient `/usr/src` That will be the real handoff from source acquisition to source-driven native base builds.