fn ensure_soma_defaults(
system: &mut HashMap<String, Value>,
manifest_dir: &Path,
manifest_path: &Path,
)Expand description
Make sure system.soma exists in the manifest map as a mapping,
and resolve any relative file paths inside it against manifest_dir.
v2 soma has four flat config keys — atlas_endpoint, listen,
provider_id, robot_yaml — and rbnx forwards them via CLI.
This helper handles the two “soma implied but not spelled out” manifest patterns:
system.soma:with no body — a bare tag or null.- no
system.soma:at all, butprimitive:/skill:present.
In both cases we promote / insert an empty mapping so the rest of deploy.rs (system_cli_args, the builtin loop, the stage 2 pipe) sees a populated entry. Existing operator-supplied values are NEVER overwritten.
It also normalises the two path-valued fields inside system.soma
— robot_yaml and config — from possibly relative to always
absolute. rbnx passes both straight through to robonix-soma as
CLI flags without chdir-ing, and soma itself only resolves paths
relative to its --config file’s parent dir (not the manifest’s
dir), so any relative value written by the operator has to be
pinned here or soma will try to open it from its own cwd — which
on systemd-launched Jetsons is /, producing errors like
read Soma config '/soma_config.local.yaml' … No such file.
Semantics: if the value is absolute it is left untouched (operator
escape hatch for bind-mounts, /opt paths, etc.); if it’s relative
(including bare filenames like soma.yaml) it is joined onto the
manifest’s own directory. Non-string values are ignored — malformed
manifests will surface the type mismatch at soma CLI parse time
rather than being silently rewritten here.
robot_yaml auto-injection: soma refuses to boot without a
--robot-yaml — it needs the robot description before it can
spawn any primitive in stage 1. Previously we left this to the
operator, but the failure mode (“missing robot_yaml” → soma exits
→ rbnx sits in wait_for_soma_stage1 for the full 180s timeout
before reporting failure) is disproportionately painful for a
missing default. So: if the operator hasn’t set robot_yaml and
a file literally named soma.yaml sits next to the manifest, we
inject that path. If neither is present, we leave the slot empty
— soma will bail on config parse with a clear error, and the
stage-1 waiter (see wait_for_soma_stage1) will surface soma’s
early exit instead of waiting for the timeout. Operators who
want a different name still just set robot_yaml: explicitly.