Warm Daemon Protocol

pygotm serve starts a warm kernel subprocess that speaks newline-delimited JSON-RPC over stdin and stdout. It is not a network server. The kernel daemon stays behind process and file boundaries.

Framing

Each request is one JSON object on stdin. Each response is one JSON object on stdout. Progress events and diagnostics are written to stderr so stdout remains protocol-only.

Required request examples:

{"id":"1","method":"version"}
{"id":"2","method":"schema_config"}
{"id":"3","method":"schema_output","params":{"config_path":"gotm.yaml"}}
{"id":"4","method":"run","params":{"config_path":"gotm.yaml","output_path":"out.nc","max_steps":3}}
{"id":"5","method":"shutdown"}

Response shape:

{"id":"1","ok":true,"result":{"pygotm_version":"X.Y.Z"}}
{"id":"4","ok":false,"error":{"code":10,"message":"..."}}

Methods

version

Returns the same manifest-shaped fields as pygotm version --json plus a warmup status. Startup warmup is self-contained and does not require validation reference data.

schema_config

Returns the curated GOTM config schema used by external tools.

schema_output

Returns output variable metadata. Passing params.config_path allows the daemon to include state-dependent FABM or ice records.

run

Runs one config and writes one NetCDF output. Progress events are emitted to stderr in the same shape as pygotm run --progress json.

shutdown

Returns one final success response and exits with code 0.

State

Each run request creates a fresh GotmDriver run, finalizes model state, and clears field registries the same way as one-shot pygotm run. Daemon warmth comes from the Python process and Numba compiled specializations, not from hidden simulation state.