Skip to content

plugrl_client.cpp: probe mode (SPEC 8.1) and the close reasons, checked in CI - #9

Merged
tactino merged 3 commits into
mainfrom
feat/cpp-client-probe
Oct 2, 2026
Merged

tactino merged 3 commits into
mainfrom
feat/cpp-client-probe

Conversation

@tactino

@tactino tactino commented Oct 1, 2026

Copy link
Copy Markdown
Member

The C++ reference client gets the probe mode that #8 gave the Python one, so both reference clients are checked against the stricter checker on every change. Stacked on #8: merge #8 first.

  • plugrl_client --probe host port batch runs the SPEC 8.1 probe environment until the server stops the run.
    • It executes each action chunk time-major, in the dtype the typestr names.
    • It flushes a chunk at the terminal step.
    • It reports the chunk-summed reward and the terminal observation.
  • Close reasons. A close frame now raises ServerClosed with its status code and reason, parsed as RFC 6455 lays it out, instead of a generic "server closed the connection". A text frame raises TextFrame. In probe mode:
    • plugrl-server-resync reconnects with nothing resent;
    • plugrl-server-stop exits 0;
    • a text frame exits 2.
  • Ended episodes are reset before the feedback is sent, for the reason conformance: probe environment (SPEC 8.1) and driven scenarios - the checker sees what a client does with each action #8's last commit gives.
  • Passive mode is unchanged. It keeps its positional arguments and its output, so the existing CI greps (dtype=<f8, first values: 0 0 0 1 0 0) still hold.
  • CI runs the C++ client through plugrl-conformance --probe --scenario all.
  • SPEC 8 now says both reference clients pass probe mode.

Checked on Linux (guangzhao, g++ with -Wall -Wextra):

  • It builds with no warnings.
  • It links only the C and C++ runtimes.
  • In probe mode, it passes all three scenarios in five runs of five: no violations, plus the text note both reference clients have.
  • In passive mode with float64 actions, the CI greps match.

…the checker sees what a client does with each action and how it handles closes

The passive checker watched one connection and could not tell chunk-summed
reward, terminal observations, time-major order, metadata-first, the close
reasons or text frames from their violations. With --probe the client runs a
probe env whose observation counts steps and echoes the applied action, and
the checker drives the connection: it speaks late, sends a 2 MiB metadata
frame, closes for a resync, stops the run, and answers with a text frame.
raw_client.py implements the probe env, and its --bug option breaks each
clause in turn; tests/test_conformance_probe.py checks that each is named.
…fter

Found by the probe checker itself, on Linux, in about one run in two of the
resync scenario: when the server's resync close arrived while the feedback
was being sent, the send raised, the reset after it never ran, and env 0
carried its finished episode onto the next connection (t = 7, 11, 15 for an
episode of 3). The packed feedback already holds the terminal observation,
so resetting first changes nothing the server sees.
…ed in CI in every scenario

`plugrl_client --probe host port batch` runs the probe environment, executes
each chunk time-major and flushes it at the terminal step, and handles the
section 7 close reasons: it reconnects after plugrl-server-resync with
nothing resent, exits 0 on plugrl-server-stop, and exits 2 on a text frame.
A close now raises ServerClosed with its code and reason, and a text frame
TextFrame, instead of one generic error. Passive mode is unchanged.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant