Repository F# setup
open System
open System.IO
open System.Threading
open System.Threading.Tasks
open Axial
open Axial.Console
open Axial.FileSystem
open Axial.PlatformService
open Axial.Process

ProcessCommand, ProcessSpec, ProcessStream, ProcessResult, ProcessError, the DSL, and IProcess are target-neutral. A browser cannot start an operating-system process, so Process.live and native stream adapters are available only on .NET.

Fable applications can construct specifications and run them against an IProcess implementation that delegates execution to a worker or another host:

Fragment
open Axial.Process.DSL

type AppEnvironment =
    { Process: IProcess }
    interface IHasProcess with member this.Process = this.Process

let workflow =
    cmd $"device-tool inspect"
    |> toFlow

An interpreter implements IProcess.Execute, returning a lazy Flow<unit, ProcessError, ProcessResult> and awaiting the supplied observer serially with backpressure. It must not start work while constructing the Flow. Streaming constructors additionally require an IHasClock environment for Axial's supervised producer.

workflow above is construction-only: it builds a specification and a Flow that asks for IProcess when run, and nothing executes until then. Supply an interpreter that delegates execution to a worker or another host, for example:

Fragment
open Axial

/// A minimal interpreter that delegates to a worker and returns its result locally.
type WorkerProcess(execute: ProcessSpec -> Async<ProcessResult>) =
    interface IProcess with
        member _.Execute(specification, observe) =
            Flow.fromAsync (execute specification)

Flow.fromAsync treats a worker exception as a defect; use Flow.attemptAsync and map the exception into ProcessError when the worker reports typed failures.