colmugx/acp/runtime does not have a README file

    RuntimeCancelOutboundHandler

    type RuntimeCancelOutboundHandler = async (
    RequestId
    ) -> Unit

    RuntimeOutboundFailureHandler

    type RuntimeOutboundFailureHandler = async (
    RequestId
    , RuntimeOutboundFailure) -> Unit

    RuntimeError

    pub(all) suberror RuntimeError {
    InvalidOptions
    ReaderFailed
    ReaderEmptyChunk
    EventQueueClosed
    EventQueueBackpressure(limit~ : Int)
    WriterQueueClosed
    WriterQueueBackpressure(limit~ : Int)
    WriterFailed
    FramingFailed
    JsonRpcDecodeFailed
    JsonRpcEncodeFailed
    ReducerFailed
    TaskControlMissing
    TaskRequestMismatch
    HandlerFailed
    NotificationFailed
    ResponseHandlerFailed
    OutboundCancelUnavailable
    OutboundCancelFailed
    OutboundCompletionFailed
    CloseCleanupFailed(primary_kind~ : String, cleanup_phase~ : String)
    }

    Failures at the native runtime boundary.

    These errors deliberately carry only failure categories. Peer payloads, prompts, files, tokens, and environment values never enter a trace or an error string produced by the runtime.

    RuntimeHandlerPort

    Protocol dispatch seams. They are values rather than globals so tests and composition roots can inject memory or faulting implementations.

    RuntimeHandlerResult

    pub(all) enum RuntimeHandlerResult {
    HandlerSuccess(Json)
    HandlerError(
    JsonRpcError
    )
    }

    Result returned by an inbound request handler. A handler failure is raised through the async port and becomes RuntimeError::HandlerFailed.

    RuntimeOptions

    pub(all) struct RuntimeOptions {
    max_frame_bytes : Int
    queue_capacity : Int
    read_chunk_bytes : Int
    }

    Native runtime bounds. The event and writer queues are intentionally bounded so backpressure is observable instead of becoming unbounded heap growth.

    RuntimeOutboundFailure

    pub(all) struct RuntimeOutboundFailure {
    reason : RuntimeOutboundFailureKind
    }

    Typed completion data for a locally initiated request. The reason is intentionally a category, never a peer payload or arbitrary exception.

    RuntimeOutboundFailureKind

    pub(all) enum RuntimeOutboundFailureKind {
    Protocol
    Framing
    Reader
    Writer
    Handler
    Notification
    EndOfInput
    EventQueue
    Runtime
    } derive(Eq,
    Debug
    )

    Closed, finite categories for a locally initiated request completion. Arbitrary close strings never cross this boundary.

    RuntimePorts

    pub(all) struct RuntimePorts {
    reader : RuntimeReaderPort
    writer : RuntimeWriterPort
    handlers : RuntimeHandlerPort
    cancel_outbound : async (
    RequestId
    ) -> Unit?
    trace : (RuntimeTraceEvent) -> Unit
    }

    All per-connection runtime dependencies.

    RuntimeProcessPorts

    The spawned-agent handle handed back with client-side process ports. The ports value drives the single connection engine; child, child_stdin, and child_stdout expose the real moonbitlang/async process seams so a composition root can close the child's stdin (the ACP stdio shutdown signal), wait for the exit status, or cancel the child without any wrapper API duplicating the underlying library.

    RuntimeReaderPort

    pub(all) struct RuntimeReaderPort {
    read : async (Int) -> Bytes?
    }

    Caller-owned asynchronous input seam. None is the only EOF signal.

    RuntimeTraceEvent

    pub(all) struct RuntimeTraceEvent {
    direction : String
    phase : String
    request_id : String
    method_name : String
    error_kind : String
    }

    A redacted runtime trace record. Only routing metadata and a static failure category are exposed to the sink.

    RuntimeWriterPort

    pub(all) struct RuntimeWriterPort {
    write : async (Bytes) -> Unit
    }

    Caller-owned asynchronous output seam. Each call receives one complete newline-delimited frame and must either write all bytes or raise.

    runtime_default_options

    fn runtime_default_options() -> RuntimeOptions

    runtime_libc_write

    fn runtime_libc_write(fd : Int, buffer : Bytes, count : Int) -> Int

    Public wrapper over the raw diagnostics writer so the blackbox suite can prove the byte path against a real pipe. Not exported through the stable facade.

    runtime_process_ports

    async fn[G] runtime_process_ports(group :
    TaskGroup
    [G], handlers~ : RuntimeHandlerPort, command~ : String, args? : Array[String], extra_env? : Map[String, String], inherit_env? : Bool, cancel_outbound? : async (
    RequestId
    ) -> Unit?, trace? : (RuntimeTraceEvent) -> Unit) -> RuntimeProcessPorts raise RuntimeError

    Construct the client side of one ACP stdio connection over a spawned child process. The child's stdin is the writer target and its stdout is the reader source; the child's stderr is redirected to this process's real stderr so agent diagnostics stay diagnostics and stdout stays pure frames. Both pipe ends are raw, unbuffered @process handles, so every frame write is delivered to the operating system in that call — the pinned flush-per-write discipline, structurally identical to runtime_stdio_ports.

    The child is spawned with no_wait = true inside the caller's task group: when the group terminates, the async process layer cancels its wait task, which gracefully terminates the child (then forcefully after its timeout) and reaps it. Child lifetime is therefore bound to the structured concurrency scope that owns the connection — no background reaper loop, no detached process. A well-behaved agent additionally observes the stdin EOF a composition sends through child_stdin.close() before teardown.

    Fail-fast mapping (the closed stable RuntimeError set has no process category, so each failure keeps its precise kind in the trace, mirroring the documented closest-category mapping of the outbound channel): an empty command is rejected as InvalidOptions before any OS call; a failed stdout pipe is ReaderFailed and a failed stdin pipe is WriterFailed (the seam that could not be constructed); an OS spawn rejection — including a missing command — is InvalidOptions with trace kind process_spawn_failed, because the caller's process configuration was rejected before any I/O seam ever ran. Every failure is typed and accompanied by one trace event; nothing degrades silently.

    runtime_request_id_text

    fn runtime_request_id_text(id :
    RequestId
    ) -> String

    runtime_stderr_trace

    fn runtime_stderr_trace(RuntimeTraceEvent) -> Unit

    Default trace sink: one write(2) per event to the real standard error. Stdout is never touched here, so the protocol channel keeps carrying newline-delimited ACP frames only. The sink type (RuntimeTraceEvent) -> Unit has no failure channel: when the OS rejects a diagnostics write (for example a closed stderr under a daemon supervisor), the event is dropped without inventing a failure the trace contract cannot carry. Protocol I/O failures stay fully typed at the reader/writer seams.

    runtime_stdio_ports

    fn runtime_stdio_ports(trace? : (RuntimeTraceEvent) -> Unit) -> RuntimePorts

    Serve the native ACP stdio boundary of this process. The reader reads the real stdin chunk-wise (None is EOF, non-empty chunks only, exactly the RuntimeReaderPort contract). The writer writes each complete newline-delimited frame to the real stdout in one Output::write call: @stdio.Output wraps the raw file descriptor with no userspace buffering (moonbitlang/async/src/stdio/stdio.mbt), so every write is handed to the operating system immediately — the pinned flush-per-write discipline holds structurally because no buffered writer layer exists on this path.

    The handler seams exist only for engine runners with an outbound channel. response and outbound_failure are deliberate no-op observers: reply delivery to parked submitters is owned by the engine's outbound channel, never by these callbacks. The legacy dispatch seams (request, notification) abort fail-fast: these ports exist for owner-loop runners, and a legacy handler dispatch through them would silently answer nothing, so it must crash loudly instead.

    Diagnostics go to the trace sink, defaulting to stderr. Nothing in this constructor writes to stdout, and it performs no I/O at all beyond binding the process file descriptors.

    runtime_trace_event

    fn runtime_trace_event(direction : String, phase : String, request_id : String, method_name : String, error_kind : String) -> RuntimeTraceEvent

    runtime_trace_stderr_line

    fn runtime_trace_stderr_line(event : RuntimeTraceEvent) -> String

    Render one redacted trace event as exactly one diagnostics line ending in a single newline. The five trace fields keep their fixed order; every value is sanitized first. This renderer is the exact text the default stderr sink writes, which keeps the diagnostics format unit-testable.

    runtime_validate_options

    fn runtime_validate_options(options : RuntimeOptions) -> Unit raise RuntimeError