component AppRunner { goal { Pull and run containerized RIA applications, auto-configuring hardware access from image labels. Own the ria-app CLI over a container engine. } interface { AppCommands { CLI ria-app with subcommands: pull, run, list, stop, logs, and configure; a global --sudo flag. } RunBehavior { run auto-pulls the image if absent and derives container flags from the image's ria.* labels. } } } expand AppRunner { logic { The engine is the first of docker or podman on PATH, optionally sudo-prefixed. Image references resolve against a configured registry and namespace; fully-qualified references pass through. Hardware flags are derived from ria.profile and ria.hardware labels: GPU access when an NVIDIA profile and runtime are present, USB device passthrough for USB SDRs, and host networking for USRP, ThinkRF, and Pluto; flags can be overridden or dry-run. } constraints { There is no Python SDK; it is a subprocess wrapper and exits with an error if no container engine is found. Config is AppConfig (registry, namespace, sudo) at ~/.ria/toolkit.json with environment-variable fallbacks. } decisions { SubprocessWrapper { Decision: ria-app shells out to a container engine (the first of docker or podman on PATH) rather than exposing a Python SDK or using an engine client library. Scope: Governs how the runner controls containers. Consequences: A container engine must be present on PATH and the tool exits with an error when none is found; there is no in-process programmatic API for callers. Trade-offs: Reuses the installed engine and its existing auth and configuration directly at the cost of no library-level integration point. } } }