diff --git a/docs/PLAN_2.md b/docs/PLAN_2.md new file mode 100644 index 0000000..22bd3c3 --- /dev/null +++ b/docs/PLAN_2.md @@ -0,0 +1,360 @@ +# Fruix on FreeBSD, Path B: Real Guix/Fruix Integration First, Then a Minimal bhyve System + +This document extends `docs/PLAN.md` after the completion of Phases 1 through 4 on the current FreeBSD amd64 prototype track. The next major objective is no longer to validate isolated subsystems, but to connect them through a real Guix/Fruix execution path and ultimately boot a minimal Fruix system in bhyve. + +Unlike a prototype-image-first strategy, this plan takes **Path B directly**: + +- prioritize real Guix/Fruix checkout and runtime integration on FreeBSD, +- connect package lowering, derivation generation, daemon/store behavior, and system composition, +- and only then generate and boot a minimal bhyve image from that integrated path. + +This is slower than assembling an image from ad hoc prototypes, but it better preserves the architectural goal: a genuine Fruix system built through Guix-style mechanisms rather than merely a FreeBSD image with Fruix-like parts. + +Throughout this plan, the experimental store root remains: + +- `/frx/store` +- `/frx/var` +- `/frx/etc` + +rather than `/gnu/store`. + +## Naming and Fork Identity Policy + +This plan assumes that the project is now **Fruix** as a user-facing system, in the same way that the store root has already moved from `/gnu` to `/frx`. + +The naming policy for the next phases is: + +- the user-facing CLI should become `fruix` +- user-facing daemon, service, help text, generated documentation, and system identity should prefer `fruix` over `guix` +- new fork-specific modules and code should prefer `fruix` namespaces and naming +- the `/frx` path family remains the canonical store/state/config root for FreeBSD work +- internal upstream-derived module namespaces should **not** be renamed mechanically just for branding +- names containing `gnu` should be preserved where they refer to actual GNU concepts or components, such as: + - GNU packages + - GNU Shepherd + - `gnu-build-system` + +This means the early integration work will often need to distinguish between: + +- the **current upstream-derived internal checkout reality**, where the failing command path is still `./pre-inst-env guix ...`, and +- the **desired Fruix product boundary**, where the operator-facing command should become `fruix`. + +Accordingly, the next phases should first make the current checkout runnable, then establish a controlled rename boundary for the user-facing command and related interfaces, rather than attempting a blanket internal rename of every `guix` or `gnu` identifier. + +--- + +## Current State at the End of Phase 4 + +The following have already been validated on the active FreeBSD amd64 host: + +- fixed local Guile path suitable for subprocess-heavy Scheme work +- FreeBSD jail-first build isolation prototype +- privilege drop and build-user isolation prototype +- `/frx/store` prototype with GC-style rooted retention +- reusable FreeBSD GNU build-system adaptation across representative packages +- prototype FreeBSD package-definition/profile layer +- Shepherd build and runtime supervision on FreeBSD +- Shepherd `rc.d` integration prototype +- Shepherd bridge layer for FreeBSD rc.d, loopback/network, tmpfs, and user/group administration + +The largest remaining blocker before real system generation is still the live upstream-derived checkout/runtime path, especially: + +- `./pre-inst-env guix --version` +- `Wrong type to apply: #` + +That blocker is the first item in the next phase because without it, system composition cannot honestly move from prototype scaffolding to real Fruix/Guix execution. Resolving it is also the prerequisite for introducing a trustworthy `fruix` user-facing command boundary on top of the current checkout. + +--- + +## Phase 5: Real Guix Checkout and Host Runtime Unblocking on FreeBSD + +### Intermediate Goal 5.1: Unblock the Uninstalled Checkout Command Path and Establish the `fruix` CLI Boundary + +The immediate goal is to move from “the checkout configures and builds some generated scripts” to “the checkout actually runs on FreeBSD”. + +Because the current checkout still exposes an upstream-derived `guix` command path, this step must also define how the user-facing `fruix` command is introduced without forcing a premature blanket rename of internal identifiers. + +**Verification Goal 5.1:** Investigate and fix the runtime failure in the uninstalled checkout command path: + +- `./pre-inst-env guix --version` +- `./pre-inst-env guix repl` +- `./pre-inst-env guix build --help` + +Then, once that path works, introduce a first user-facing `fruix` command boundary for the checkout, whether by renamed frontend, generated wrapper, compatibility symlink policy, or another documented transition mechanism. + +The investigation must identify whether the `leave-on-EPIPE` failure is due to: + +- macro expansion / module ordering assumptions, +- Guile version or module interaction, +- FreeBSD-specific POSIX behavior, +- generated source ordering, +- or a latent upstream bug exposed by FreeBSD. + +Produce: + +- a dedicated reproducer harness, +- a root-cause report, +- and either: + - an in-repo patch queue for the Guix checkout, or + - a precise upstreamable fix series. + +**Success Criteria:** `./pre-inst-env guix --version` succeeds on FreeBSD using the fixed local Guile stack, at least one additional non-trivial checkout subcommand works, and there is a documented first-step user-facing `fruix` frontend policy for the live checkout. + +### Intermediate Goal 5.2: Validate Package Lowering and Derivation Generation + +Once the checkout is runnable, the next boundary is host-side lowering rather than builder-side phase execution. + +**Verification Goal 5.2:** Demonstrate that a real Guix checkout on FreeBSD can lower at least one tiny package to a derivation using the `/frx` store settings. This step should verify: + +- package -> bag lowering, +- bag -> derivation lowering, +- imported module closure materialization, +- fixed-output source origin handling, +- and generation of a real derivation file targeting `/frx/store`. + +The initial validation target should be intentionally small, such as a previously successful package from the build-system work (`hello`, `which`, or similar). + +**Success Criteria:** a real derivation is emitted by Guix on FreeBSD, references `/frx/store`, and can be inspected as a normal derivation rather than only as a prototype metadata file. + +### Intermediate Goal 5.3: Establish Store Connection and Minimal Daemon RPC Integration + +At this point, the remaining gap is the connection between host-side lowering and actual store-backed builds. + +**Verification Goal 5.3:** Connect the runnable checkout to a minimal FreeBSD-aware store/daemon path. This should include: + +- confirming `open-connection` / store socket behavior on FreeBSD, +- minimal daemon configuration for `/frx/store`, +- validating store registration and metadata behavior, +- and ensuring that at least one real derivation can be submitted to the daemon. + +This phase may still rely on prototype jail/build-user implementations while integrating them incrementally into daemon behavior. + +**Success Criteria:** a real checkout command path can contact a FreeBSD-aware daemon/store path and submit at least one derivation-backed build request, with the intended user-facing interface moving toward `fruix`. + +--- + +## Phase 6: Real FreeBSD-Backed Store Builds Through Guix/Fruix Mechanisms + +### Intermediate Goal 6.1: Build a Real Package Into `/frx/store` + +The builder-side phase runners proved that GNU packages can build on FreeBSD. This phase requires proving that they can do so through real lowering + store + daemon plumbing. + +**Verification Goal 6.1:** Build at least one small GNU package from a real Guix package definition all the way into `/frx/store`, through the daemon path. Validate: + +- store path creation, +- output registration, +- runtime execution from the store, +- and preservation of declared references. + +**Success Criteria:** `fruix build`-style execution succeeds for at least one real package on FreeBSD and produces a usable output in `/frx/store`, even if the underlying checkout still retains transitional upstream-derived command plumbing. + +### Intermediate Goal 6.2: Integrate FreeBSD Jail/Privilege Prototypes Into the Real Build Path + +The current jail/build-user work is still prototype-scoped. It now needs to become part of the actual FreeBSD build path. + +**Verification Goal 6.2:** Adapt the daemon build path so that real derivation builds use the already validated FreeBSD primitives: + +- thin jails, +- explicit `nullfs` mount plans, +- dropped build users, +- `/frx/store` read semantics, +- and per-build writable scratch/output directories. + +At least one real package build should be observed executing inside that integrated jail/build-user path. + +**Success Criteria:** a real Guix/Fruix build runs inside a FreeBSD jail with dropped build credentials and succeeds into `/frx/store`. + +### Intermediate Goal 6.3: Validate Profiles and User-Facing Package Installation + +Once real builds land in the store, the next user-facing layer is profile generation. + +**Verification Goal 6.3:** Demonstrate that a user profile can be produced from real store items on FreeBSD, not only from the earlier package/profile prototype layer. Validate: + +- profile symlink generation, +- transaction semantics at least in a minimal form, +- PATH usability, +- and user access to built packages. + +**Success Criteria:** a package built through the real FreeBSD store path can be installed into a user profile and executed through that profile. + +--- + +## Phase 7: Declarative Fruix System Composition on FreeBSD + +### Intermediate Goal 7.1: Define a Minimal Fruix Operating-System Model + +The package layer alone is not enough; there must be a system-level object that describes an installable/bootable Fruix system. + +**Verification Goal 7.1:** Define a minimal Fruix system model for FreeBSD, analogous in spirit to Guix System’s operating-system record, that can describe: + +- kernel and boot assets, +- essential FreeBSD base packages, +- `/etc` configuration files, +- activation requirements, +- Shepherd configuration, +- file systems, +- users/groups, +- and host identity settings. + +This may begin in Fruix-specific modules rather than attempting immediate full upstream Guix OS integration. + +**Success Criteria:** a declarative system description can be evaluated into a coherent system closure specification rather than only a loose collection of packages. + +### Intermediate Goal 7.2: Generate a Minimal System Closure and Activation Payload + +The next step is to turn the system model into concrete filesystem content. + +**Verification Goal 7.2:** Generate a minimal system closure for FreeBSD that includes at least: + +- FreeBSD kernel and boot files, +- minimal userland, +- required `/etc` files, +- Shepherd service definitions and startup hook, +- activation scripts, +- and references into `/frx/store`. + +This phase should decide and document whether the first boot target uses: + +- FreeBSD init + `rc.d` to launch Shepherd, or +- Shepherd as PID 1. + +For the first integrated boot target, FreeBSD init + `rc.d` is acceptable if it is generated declaratively from the system definition. + +**Success Criteria:** a system closure directory tree can be generated reproducibly from a declarative Fruix system description. + +### Intermediate Goal 7.3: Validate an Installable Root Filesystem Tree + +Before generating a disk image, validate that the system closure can be materialized as a rootfs tree suitable for installation or image creation. + +**Verification Goal 7.3:** Build a root filesystem tree that contains: + +- bootable kernel/loader content, +- generated configuration, +- declared users/groups, +- Shepherd launch integration, +- and enough runtime content to reach a login prompt or equivalent ready state. + +**Success Criteria:** the generated rootfs is internally coherent and passes static validation for image construction. + +--- + +## Phase 8: FreeBSD/Fruix Image Construction for bhyve + +### Intermediate Goal 8.1: Create a Reproducible Disk Image Build Path + +Now that the system closure exists, produce a real boot medium from it. + +**Verification Goal 8.1:** Create tooling to generate a bootable bhyve-compatible disk image from the Fruix system closure. This should include: + +- partition map creation, +- filesystem creation, +- rootfs population, +- boot asset installation, +- and serial-console-friendly configuration. + +The first target should prefer the simplest debuggable bhyve path, likely: + +- raw disk image, +- UEFI boot, +- FreeBSD kernel/loader, +- serial console. + +**Success Criteria:** a reproducible image file is generated from the declarative Fruix system description and passes boot-structure sanity checks. + +### Intermediate Goal 8.2: Integrate Image Generation With the Fruix System Definition Layer + +The image builder should not remain a detached shell-only utility. + +**Verification Goal 8.2:** Connect image generation to the system description layer so that the image is the output of system composition, not a manual afterthought. Ideally, this begins to resemble a minimal FreeBSD analogue of `fruix system image`, even if some internal machinery still derives from upstream Guix code paths. + +**Success Criteria:** a single declarative Fruix system description can drive image generation end-to-end. + +--- + +## Phase 9: Boot a Minimal Fruix System in bhyve + +### Intermediate Goal 9.1: Reach a Serial-Console Boot Milestone + +The first VM target should be intentionally narrow: boot the generated image and prove it reaches a known-good ready state. + +**Verification Goal 9.1:** Create a bhyve launcher/validation harness that: + +- boots the generated image, +- captures serial output, +- waits for a ready marker, +- and tears down the VM cleanly. + +The ready marker may initially be one of: + +- a login prompt, +- a Shepherd status marker, +- or a deterministic boot-complete message. + +**Success Criteria:** the Fruix image boots in bhyve and reaches a deterministic serial-console ready state. + +### Intermediate Goal 9.2: Validate In-Guest Shepherd and Core Services + +After basic boot, verify that the system behaves like a Fruix system and not merely a FreeBSD guest with some files copied in. + +**Verification Goal 9.2:** Validate in the running bhyve guest that: + +- Shepherd is active, +- the expected essential services are started, +- the generated configuration is in effect, +- and the system closure in the guest matches the declared build outputs. + +**Success Criteria:** the bhyve guest boots the generated Fruix system and runs Shepherd-managed core services successfully. + +### Intermediate Goal 9.3: Validate Minimal Operator Usability + +The final milestone for the first bhyve system is not completeness, but minimal usefulness. + +**Verification Goal 9.3:** Confirm that the guest supports a minimal operator workflow, such as: + +- console login or root shell access, +- inspection of Shepherd service status, +- reading generated configuration files, +- and optionally basic networking. + +**Success Criteria:** a human operator can boot the bhyve guest and verify a minimally usable Fruix environment from inside the VM. + +--- + +## Optional Phase 10: Replace Transitional Pieces With More Native Fruix/Guix Machinery + +This phase is intentionally deferred until after the first real bhyve success. + +Possible follow-up work includes: + +- replacing residual prototype-only composition layers with true Guix-native system-generation mechanisms, +- deeper integration of FreeBSD package definitions with real package records and lowering paths, +- improving daemon/store metadata fidelity, +- turning image generation into a true `fruix` command, +- and evaluating whether Shepherd-as-PID-1 is worth pursuing beyond the validated `rc.d` bridge path. + +--- + +## Recommended Immediate Order of Work + +If work begins on this plan now, the recommended near-term order is: + +1. **Phase 5.1** — fix the `leave-on-EPIPE` checkout/runtime blocker +2. **Phase 5.2** — prove real derivation generation on FreeBSD with `/frx/store` +3. **Phase 5.3 / 6.1** — connect real builds to the daemon/store path and land one package in `/frx/store` +4. **Phase 6.2** — attach the real build path to FreeBSD jail/build-user isolation +5. **Phase 7** — define the minimal declarative Fruix system model and rootfs closure +6. **Phase 8–9** — generate and boot the first bhyve image + +This ordering keeps the project honest: the bhyve image milestone will be the output of genuine Guix/Fruix integration work rather than a prototype assembled around unresolved core runtime issues. It also keeps the naming transition disciplined: user-facing `fruix` surfaces can be introduced deliberately on top of a working checkout instead of via a destabilizing whole-tree rename. + +--- + +## Final Target of This Plan + +The end goal of this Path B plan is: + +> A minimal Fruix system for FreeBSD, generated through real Guix/Fruix-style mechanisms, exposed to operators through `fruix` user-facing interfaces, stored under `/frx`, bootable in bhyve, and capable of running Shepherd-managed core services. + +This target explicitly assumes selective renaming rather than blanket renaming: Fruix at the product boundary, stable upstream-derived internal names where they continue to provide architectural or maintenance value, and preserved GNU naming where it refers to genuine GNU components. + +That is the next major milestone after the completed foundational and prototype phases. diff --git a/docs/PROGRESS.md b/docs/PROGRESS.md index 2bc0f46..f4e3df5 100644 --- a/docs/PROGRESS.md +++ b/docs/PROGRESS.md @@ -1536,3 +1536,31 @@ 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 diff --git a/docs/PROMPT.md b/docs/PROMPT.md index a398c87..7bb6285 100644 --- a/docs/PROMPT.md +++ b/docs/PROMPT.md @@ -1,4 +1,4 @@ -Your task is described in ./docs/PLAN.md. Current progress is stored in ./docs/PROGRESS.md. +Your task is described in ./docs/PLAN_2.md. Current progress is stored in ./docs/PROGRESS.md. Perform the next step towards the final goal. Update the progress file and `git commit` after each subphase (or even in between, if adequate).