# racket-webview stdio protocol

The Qt backend is a child process of the Racket process. Communication uses
UTF-8 JSON records, one compact JSON object per line.

- stdin of `rktwebview_prg`: commands from Racket
- stdout of `rktwebview_prg`: handshake, results, and events
- stderr of `rktwebview_prg`: diagnostics only

No diagnostic text may be written to stdout.

## Compatibility

The existing numeric command identifiers in `rkt_protocol.h` and their JSON
payload objects are retained. The stdio transport adds only an envelope and a
request identifier. The request identifier allows replies to be matched even
when several Racket threads issue commands concurrently.

## Handshake

The backend writes this record after Qt has been initialized and the command
reader has started:

```json
{"type":"ready","protocol":1}
```

Racket must not send application commands until this record has been received.

## Command

```json
{"type":"command","id":17,"command":6,"data":{"wv":1,"url":"https://example.test"}}
```

Fields:

- `id`: positive request identifier chosen by Racket
- `command`: existing numeric command from `rkt_protocol.h`
- `data`: existing command payload object

## Result

```json
{"type":"result","id":17,"result":0,"data":null}
```

`result` has the same meaning as before. Depending on the command it can be a
`result_t`, a handle, a context identifier, a window-state value, or a metric.
For `CMD_CALL_JS`, `data` contains the JavaScript result string.

Every command now receives a result record, including commands that previously
returned `void`, such as close and setting the OU token. Their public Racket
return values remain unchanged.

## Event

```json
{"type":"event","wv":1,"data":"{\"event\":\"page-loaded\",...}"}
```

The `data` field is the original event JSON string. It is deliberately not
restructured by the transport, so existing event parsing remains unchanged.
Events are independent of command results.

## Shutdown

A normal shutdown sends `CMD_QUIT`, waits for its result, closes the child's
stdin, and waits for the child process. If the Racket process terminates
unexpectedly, the operating system closes the pipe; EOF on stdin makes the Qt
backend close all windows and quit.

## Structured stderr logging

The backend writes diagnostic logging to stderr, never to stdout. Log entries
created through `utils.h` are emitted as one line beginning with `json:` followed
by a compact JSON object:

```text
json:{"topic":"webview-backend","level":"debug","elapsed":1.234,"message":"..."}
```

Newlines and other control characters in the message are JSON escaped, so one
C++ log call always produces one physical stderr line. Consumers should also
accept unstructured stderr lines because Qt, Qt WebEngine, or another library
may write diagnostics directly.
