GustShell plugs into Gust through three adapters: a parser reads the YAML file, a task worker (GustShell.TaskWorker.Adapter) runs each task, and a runtime adapter stops a task's command when the task is cancelled.

When a YAML DAG is loaded, the parser validates it, builds the task graph and prepares each task's command and execution options up front, so a broken DAG fails when it is parsed, not halfway through a run. Templates are checked at this point too, but only rendered when each task attempt starts.

For each task, Gust starts a task worker that runs the command through erlexec. The OS process is monitored, and stdout and stderr are collected as they are emitted. When the process exits, the worker turns the exit status into a result or a GustShell.ShellExitError and reports it back to the run. Gust stores the result when the task has save: true.

By default each command starts in its own process group, and the whole group is killed when the task stops. This keeps commands that spawn children, like make or a shell pipeline, from leaving orphaned processes behind.

Unlike Python DAGs, there is no per-run setup: the command runs directly from the parsed definition. The on_finished_callback DAG option is accepted but has no effect for shell DAGs.