Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/inference.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ The model source (`checkpoints_dir`, `checkpoint`, device...) is fixed at server

**What crosses the wire is the server's call, not the client's.** A server that wants smaller frames declares `RestrictImageSize` in its rig-side stack (640x640 by default); one behind a proxy with a message-size cap declares `remote(compress_images=True)` and the rig JPEG-encodes frames before sending. A server whose checkpoint speaks a different end-effector frame declares `ChangeEEFrame` with the transform placing that frame relative to the rig's `default`, and the rig converts poses (see [End-effector frames](codecs.md#end-effector-frames)). The client builds whatever the handshake declares, and only that — connecting to a server that declares no stack fails with an error naming the version it runs. What the declared stack must achieve is checked where it matters: the harness refuses to emit an action scheduled further than `MAX_ACTION_SKEW_SEC` from now, which is what a stack that never anchored its chunk to the rig's clock produces.

**The handshake is recorded as the server sent it.** Every episode stores the server's handshake metadata under `inference.policy.server.*`. The client reads the declared stack and `compress_images` from it and records the rest without a check. A `prompt` field there is the deployment's own declaration. It is fixed for the deployment and does not follow the episode. The instruction an episode sent is `task`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Do not label arbitrary handshake metadata as deployment-fixed

For servers that return different prompt values between sessions, this tells downstream users to treat valid per-episode metadata as a fixed deployment property. The framework does not define that semantic: Session.meta explicitly covers both model and episode facts (positronic/policy/base.py:76-79), and PolicyServer._serve_session merges each newly created session's metadata into that connection's handshake (positronic/offboard/server.py:334-348). The mock test only demonstrates passthrough and cannot establish ownership or lifetime, so qualify this as a convention of the observed deployment or define and enforce a protocol-level contract before documenting it generally.

Useful? React with 👍 / 👎.


> **Recording inference I/O:** Pass `--policy.recording_dir=s3://bucket/path` to write a rerun `.rrd` file per episode capturing the raw and server-side observation/action boundaries. Useful for debugging codec behavior and visualizing what the policy actually received.

## Local Inference
Expand Down
14 changes: 14 additions & 0 deletions positronic/offboard/tests/test_remote_policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,20 @@ def test_remote_session_normalizes_single_dict(open_session):
assert round_trip(session, rt, {}) == [{keys.ROBOT_COMMAND: 'X', 'timestamp': 0.0}]


def test_a_prompt_the_server_declares_is_recorded_as_sent_and_the_task_still_goes_out(open_session):
"""A ``prompt`` in the handshake is the deployment's declaration. It is recorded whole under the server
block, it is not the episode's task, and the task the episode sends reaches the wire unchanged."""
declared = 'Pick up the green cube and place it on the red cube.'
endpoint, mock_ws = _mock_endpoint(metadata={'model_name': 'm', 'prompt': declared})
session, rt = open_session(endpoint)

assert session.meta['server.prompt'] == declared
round_trip(session, rt, {keys.TASK: 'put the banana on the plate'})
sent = mock_ws.infer.call_args.args[0]
assert sent[keys.TASK] == 'put the banana on the plate'
assert 'prompt' not in sent


def test_remote_session_passes_through_none(open_session):
endpoint, mock_ws = _mock_endpoint()
mock_ws.infer.return_value = None
Expand Down
3 changes: 3 additions & 0 deletions positronic/policy/keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
# What a policy reports about itself through its ``meta``; a remote policy nests the server's meta under
# ``SERVER``, and the harness records the result under ``POLICY_META``. ``TYPE`` names the policy at the top
# level and the vendor under ``SERVER``, so a reader composes a prefix with a field: f'{SERVER_META}.{TYPE}'.
# The block under ``SERVER`` is the handshake metadata as the server sent it. The client reads its declared
# stack and ``compress_images`` from it and records the rest without a check. A ``prompt`` in it is the
# deployment's own declaration, fixed for that deployment. The instruction an episode sent is ``keys.TASK``.
Comment on lines +6 to +8

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Remove call-flow narration from the keys module

Rule diff-comments violated:
The added comment narrates what the client, recorder, and episode code happen to do rather than an invariant needed to understand or use the constants declared here. Limit this comment to the local meaning of SERVER, and keep cross-component behavior in the user-facing documentation.

AGENTS.md reference: AGENTS.md:L7-L8

Useful? React with 👍 / 👎.

TYPE = 'type'
CHECKPOINT_PATH = 'checkpoint_path'
EXPERIMENT_NAME = 'experiment_name'
Expand Down
1 change: 1 addition & 0 deletions positronic/policy/remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ def cancel(self):

@property
def meta(self) -> dict[str, Any]:
# The server block is the handshake as the server sent it, recorded whole and read nowhere here.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Remove consumer narration from RemoteSession.meta

Rule diff-comments violated:
The comment describes later recording behavior and the absence of readers elsewhere, neither of which is a constraint on this property and both of which can change without making this method wrong. Delete the comment; the one-line return already states that the server metadata is nested and flattened.

AGENTS.md reference: AGENTS.md:L7-L8

Useful? React with 👍 / 👎.

return flatten_dict({policy_keys.TYPE: 'remote', policy_keys.SERVER: self._session.metadata})

def close(self):
Expand Down
Loading