5.5 KiB
Post-Phase 20: native build executor model
Date: 2026-04-06
Goal
Turn the now-proven native base-build placement options into one Fruix abstraction instead of treating them as unrelated paths.
The desired model is:
- same declared source identity
- same expected artifact kinds
- same staged-result shape
- same promotion/provenance shape
- different executor policy
So the question becomes:
- where should the build run?
and the answer is expressed as executor policy rather than as a separate architecture each time.
Executor model
Fruix now has an explicit native-build executor model with current executor kinds:
hostssh-guestself-hosted
and intended future extension points:
jailremote-builder
The new executor model is implemented in:
modules/fruix/system/freebsd/executor.scm
It defines a structured executor object that records at least:
kindnameversionproperties
What changed
1. Structured executor metadata
Native-build result metadata is no longer limited to a flat string such as:
guest-self-hosted
Instead, result/promotion objects now carry a structured executor description.
Representative executor objects now look like:
((kind . self-hosted)
(name . "guest-self-hosted")
(version . "4")
(properties . (...)))
or:
((kind . ssh-guest)
(name . "ssh-guest")
(version . "1")
(properties . (...)))
Promoted store metadata also now records compatibility fields derived from that executor object:
executor-kindexecutor-nameexecutor-version
2. Shared staged-result shape across executors
Both validated executor paths now converge on the same mutable staging layout under:
/var/lib/fruix/native-builds/<run-id>
with promoted artifacts staged under:
artifacts/worldartifacts/kernelartifacts/headersartifacts/bootloader
and promotion metadata recorded in:
promotion.scm
The heavy build work remains executor-specific, but the result shape is now shared.
3. Shared immutable promotion path
Both validated executor paths now promote through the same command:
fruix native-build promote RESULT_ROOT
That promotion creates immutable store identities for:
worldkernelheadersbootloader- result bundle
under /frx/store/....
Validated executor policies
self-hosted
The self-hosted guest helper now emits the structured executor metadata directly from:
/usr/local/bin/fruix-self-hosted-native-build
Validated self-hosted promotion flow:
PASS phase20-self-hosted-native-build-xcpngPASS phase20-native-build-store-promotion-xcpng
Representative promoted result:
result_store=/frx/store/0423193b9bd5e652bdb9d94d077e40dfcc3e9e78-fruix-native-build-result-15.0-STABLE-guest-self-hosted
world_store=/frx/store/5f67e95058186147206ff6f5da2243a09212e358-fruix-native-world-15.0-STABLE-guest-self-hosted
kernel_store=/frx/store/3a32797cc187a90e8273f205eababae6246568d9-fruix-native-kernel-15.0-STABLE-guest-self-hosted
headers_store=/frx/store/1d54d9814461f003e91add8cd37e94ac5f3d04ce-fruix-native-headers-15.0-STABLE-guest-self-hosted
bootloader_store=/frx/store/49f4885f0f05a324ac826f2618d4c7a923ca30d2-fruix-native-bootloader-15.0-STABLE-guest-self-hosted
ssh-guest
The host-initiated guest path now also stages a shared native-build result root under:
/var/lib/fruix/native-builds/<run-id>
instead of stopping at temporary build directories alone.
Its promotion metadata records executor policy as:
kind = ssh-guestname = ssh-guestversion = 1
with executor properties including:
transport = sshorchestrator = host- guest addressing / VM identity metadata
Validated host-initiated promotion flow:
PASS phase20-host-initiated-native-build-xcpngPASS phase20-host-initiated-native-build-store-promotion-xcpng
Representative promoted result:
result_store=/frx/store/ffe44f5d1ba576e1f811ad3fe3a526a242b5c4a5-fruix-native-build-result-15.0-STABLE-ssh-guest
world_store=/frx/store/89c7a71c3df148a1f99b13d57fd6be88243eb2cb-fruix-native-world-15.0-STABLE-ssh-guest
kernel_store=/frx/store/93bac81122022b40438d356146a6854b4ee48513-fruix-native-kernel-15.0-STABLE-ssh-guest
headers_store=/frx/store/dd7f39f526bca4849caf1eaf96ae25d29b43493c-fruix-native-headers-15.0-STABLE-ssh-guest
bootloader_store=/frx/store/78b1c6b0b5c0c2c1549f5f42f3d64b6d9293669b-fruix-native-bootloader-15.0-STABLE-ssh-guest
Important result
The same declared source and artifact contract now works across two different executor policies:
ssh-guestself-hosted
while preserving the same Fruix-native staging/promotion split:
- mutable result roots under
/var/lib/fruix/native-builds/... - immutable promoted identities under
/frx/store/...
That is the core architectural win of the executor model.
What is not yet fully unified
The host executor kind now exists in the model, but the fully shared staged-result-plus-promotion workflow is not yet wired through the existing host-local native build path.
So the executor model is introduced and real-VM validated across two policies, but not yet uniformly productized across every native-build entry point.
Result
Fruix now treats native-build placement as executor policy rather than as an architectural fork.
That means the next step is no longer to invent another build path from scratch.
It is to keep extending the same executor/result/promotion model so additional execution policies can plug into the same Fruix-native object story.