Fixed fd number rbnx exports as ROBONIX_SOMA_STAGE_FD in somaβs
environment. Any fd β₯ 3 works β we pick 3 because itβs the first
non-stdio slot, which keeps ls /proc/<soma>/fd readable at a
glance. Soma reads the trigger line, then closes it.
Issue one Driver(cmd) RPC against a freshly-connected channel, then
release the channel. Returns the responseβs state string on success;
bail-errors when ok=false or the RPC itself fails. Used by the boot
path for both CMD_INIT and CMD_ACTIVATE, with identical timeout / channel
hygiene.
Probe a host:port. Returns Ok(()) when nothing is listening (we can
safely bind), Err describing the live owner otherwise. This is a
race-prone pre-check (someone else can grab the port between probe
and spawn) but in practice the failure mode it catches β a stale
previous-boot daemon β has been alive for minutes, not seconds, so
a single connect attempt is enough.
Apply top-level deployment variables, then expand every scalar in the
manifest. Build and boot share this preparation path so package locations,
target-manifest selectors, system settings, and package config all resolve
against the same environment.
Read the last max_lines lines of a file for embedding into an
error message. Best-effort: an unreadable/missing file returns an
empty string rather than an error β the caller already reports the
path, we just enrich when we can. We read the whole file (soma.log
is scribe-managed and stays small during boot), split, and take
the tail β no seek-from-end acrobatics needed for the boot-time
use case.
Summarize a package that exited before Atlas registration. Providers often
forward Python tracebacks through Scribe at info level, so the lifecycle-
specific parser above may intentionally return None. In that case the last
structured message is the most useful single-line cause for boot output.
Return the providerβs actual lifecycle failure rather than whichever
shutdown record happened to be written last. Scribe records are JSONL;
providers commonly report lifecycle transitions at info level, so prefer
-> ERROR (...) messages before falling back to an error-level record.
Compute a PackageEntryβs expected on-disk path. PURE β no I/O,
no logging, no cloning. path: entries land at manifest_dir/path;
url: entries land at cache_root/<name> (whether or not itβs
been cloned yet). Use entry_path_exists_on_disk to check
presence; use the public cmd::fetch::clone_remote_packages
(called from rbnx build) to actually populate the cache.
Cache directory name for a url-remote package: the git REPO name (last path
segment of the url, minus .git), NOT the per-instance provider id.
Render a one-line βwhat is this binary doingβ string for the boot
log. Pulls out the high-signal flags (port, vlm model+host) and
drops noisy ones (βcapabilities, βlog, raw API keys).
Per-binary required-arg sanity check, run before spawning.
Strip the leading <component>_ from the boot-log pkg_label.
system_memory β memory; primitive_tiago_chassis β tiago_chassis.
Keeps boot-output columns narrow (the section header above already
said which class the entry belongs to).
Spawn soma with an inherited pipe on SOMA_STAGE_FD. The parent
keeps the write end and later writes stage2\n to it (see
write_stage2_trigger below). Layered on spawn_system_binaryβs
stdio+scribe pattern but adds:
Translate a system.<name>: block into CLI args for the corresponding
Rust binary. Per-binary mapping kept narrow β adding a new flag means
touching exactly this function plus the binaryβs clap struct.
Poll atlas until a provider NOT in before appears. Returns the new
provider_id plus every distinct lifecycle Driver observed after the
declaration settle window. The caller verifies this list before sending
config or lifecycle commands.
Run fut while animating the boot spinner so the user sees the
[ β ] name msg_prefix N.Ns line update steadily even when the
underlying RPC takes a while (Driver(CMD_INIT) for sensor-warm-up
packages routinely sits at 30+ seconds). Without this the line goes
silent right after wait_for_registration finishes and rbnx looks
hung between OK lines.
Write the stage2\n trigger into the pipe rbnx and soma share
(see spawn_soma_binary). This is a one-shot: soma reads the
line, unblocks its skill-package launcher, and closes its read
end. rbnx-side we drop the writer here β no reason to hold it
open, and closing gives soma an immediate EOF on the (very
unlikely) chance it re-reads.