1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
//! The composed component runtime — the ONLY composition surface embedding
//! applications touch (scaffold-unification design, §5.2, finding B6).
//!
//! # Why this wrapper exists (the composition story)
//!
//! Before this module, every embedding host — frame-host's `runtime.rs` and
//! every `frame new` scaffold in the wild — hand-wrote the same five beamr
//! compositions, each of which hides a trap:
//!
//! 1. **Scheduler composition.** A bare `Scheduler::with_services` silently
//! installs an EMPTY built-in-function registry, so every `erlang:*`
//! import in hot-loaded bytecode resolves Deferred and guard-BIF dispatch
//! kills the process at its first arithmetic instruction with
//! `InvalidOperand("guard bif native import")` — the composition defect
//! attributed in `frame-host/attribution/gcbif-wedge/` (Artemis's
//! 2026-07-18 probe report, Round 2). [`ComponentRuntime::compose`]
//! absorbs the fix, [`crate::composition::compose_scheduler`]: gate-1 BIF
//! population BEFORE construction, so load-time import resolution binds
//! `erlang:*` to Native entries.
//! 2. **Support-module hot load.** A component's FFI bytecode is hot-loaded
//! directly on the scheduler, outside the registry's lifecycle — and the
//! registry's deferred-BIF wall did not cover it.
//! [`ComponentRuntime::load_support_module`] applies the same wall (the
//! crate-internal `composition::deferred_erlang_imports` scan both paths
//! share) and returns an opaque [`SupportModuleHandle`] instead of a
//! beamr atom.
//! 3. **Support-module unload.** The correct teardown is a dance: purge any
//! retained old generation, delete the current one, then VERIFY the module
//! is actually gone. [`ComponentRuntime::unload_support_module`] performs
//! and verifies it; the single-use handle makes a double unload
//! unrepresentable.
//! 4. **Mailbox acknowledgement values.** BEAM mailbox integers must fit the
//! small-integer term payload, and the low integers are usually claimed by
//! a child's message protocol (liveness, stop). Deriving an
//! acknowledgement from identifier bytes therefore means folding into
//! `reserved_below ..= Term::SMALL_INT_MAX` — previously hand-rolled
//! against `Term::SMALL_INT_MAX` in generated code, now
//! [`mailbox_integer`].
//! 5. **Teardown discipline.** `Scheduler::shutdown` is not cleanup: ordered
//! stop must have drained every process tree first.
//! [`ComponentRuntime::shutdown`] refuses while
//! [`ComponentRuntime::live_process_count`] is nonzero.
//!
//! Zero beamr types appear in this module's public signatures: bytecode is
//! `&[u8]`, modules are opaque handles, mailbox messages are the `i64` the
//! registry already speaks. The runtime's beamr dependency (and its feature
//! selection) is therefore declared in exactly one place — frame-core's own
//! manifest — instead of being fossilized into every generated application
//! (finding B6). [`crate::composition`] remains public as the wrapper's
//! ground truth for embedders that need raw scheduler access; applications
//! and frame-host itself compose only through this module.
pub use ;
pub use RuntimeError;
pub use mailbox_integer;