Hosting a Shell is a baked prelude plus one boot call
Embedding ral-core is static PRELUDE = baked_prelude!(); boot_shell(terminal, &PRELUDE) and the existing per-turn eval entries —
the rest is host-specific. The REPL host (ral), the agent host
(exarch, exarch-architecture), and the
test harnesses all spelled the same embedding ritual structurally: two
postcard blobs behind two OnceLocks, then Shell::new → seed env → register prelude → register type hints. core/src/host.rs names the
missing type and the one function that deduplicate it.
BakedPreludeis the missing type. It holds the build-time IR and scheme blobs and their once-decoded forms (from_blobsconst, lazycomp()/schemes());bake_runtime()bakes from the embedded prelude source for test binaries, which have no build-time blob. Thebaked_prelude!()macro expandsinclude_bytes!(OUT_DIR/…)in the host crate (each crate has its ownOUT_DIR).boot_shell(terminal, &BakedPrelude) -> Shellis the kernel. Construct, seed default env, register the prelude, register its type hints — everything a turn-evaluating host needs before its own builtins, rc files, or capability frames. Per-turn evaluation reuses the existingcompile_and_typecheck/session_schemes/eval_top_levelentries unchanged.- The bake moves into core, both halves.
bake_prelude_to_out_dir()is the build-script half (parse → elaborate → bake → two blobs intoOUT_DIR, with rerun-if-changed on the shape-defining files); each host’sbuild.rsshrinks to one call.postcardleaves both hosts and enters core once. - The schema-evolution hazard collapses to one file. The baked
prelude is a schema-less blob: a shape change to the IR or scheme types
silently corrupts a decode unless the rerun-if-changed list pins every
shape file. That contract had been spelled in three places that must
agree; with the only encode site and the only decode site in
host.rs, it is one list (compilation-ladder). - No builder, no config bag. The API is exactly the missing type and the one kernel function; the divergent steps — terminal handling, rc sourcing, the agent watchdog and library, output capture — stay in the hosts, interposed before and after the call.
One behavioural shift, verified inert: because boot_shell registers the
prelude (which pushes the user scope) before the host binds TERMINAL,
that binding now lands in the user scope rather than the prelude scope.
Lookup, completion, and scheme seeding all walk every scope, so the result
is identical; only which’s provenance label for TERMINAL shifts from
prelude to local, which is the more accurate description of a
host-injected runtime value (core, repl).