Say that a server-declared prompt is recorded as sent and is not the task - #742
Say that a server-declared prompt is recorded as sent and is not the task#742v-positronic wants to merge 1 commit into
Conversation
…task The server block under inference.policy.server.* is the handshake metadata as the server sent it. A prompt field in it is the deployment's own declaration. It is fixed for the deployment. The instruction an episode sent is keys.TASK. The client reads only the declared stack and compress_images from the block, and nothing checks the rest. A test pins it: a declared prompt is recorded whole, and the task the episode sends reaches the wire unchanged, with no prompt beside it. Ticket: Positronic-Robotics/internal#1290 #refs
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9db3961ed6
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
|
||
| **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`. |
There was a problem hiding this comment.
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 👍 / 👎.
| # 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``. |
There was a problem hiding this comment.
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 👍 / 👎.
|
|
||
| @property | ||
| def meta(self) -> dict[str, Any]: | ||
| # The server block is the handshake as the server sent it, recorded whole and read nowhere here. |
There was a problem hiding this comment.
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 👍 / 👎.
Every episode of
2026-09-11-runway-tsuactuni2-143k-c3-prompt-variantsrecordsinference.policy.server.prompt = 'Pick up the green cube and place it on the red cube.', the same string across four tasks and three endpoints. The field reaches the customer's recordings.Where the string comes from: the policy server's handshake, not our code.
positronic/offboard/client.py:29: the client takesmetadatafrom the server's handshake reply.positronic/policy/remote.py:105(RemoteSession.meta): the client records that metadata whole underinference.policy.server.*.positronic/offboard/server.py:336-344: our own server builds its handshake metadata from host, port, the model source's meta, the checkpoint id, the session's meta, the declared stack,compress_imagesand the positronic version. No key isprompt.promptoutside tests finds the word only in observation dictionaries (vendors/openpi,vendors/dreamzero,policy/observation.py), which travel to the server, never back from it. The cube string itself is in our tree only as a dataset task value (cfg/ds/internal.py:125) and a sim instruction (cfg/eval/sim/positronic.py:48), on no server path.So the value is the served deployment's own declaration, and it differs per deployment: the rollouts runbook shows another deployment declaring
'Pick the object from the table and place it in the gray tote.'. Nothing of ours reads or checks the field:rollouts/report/fields.pyin platform names fiveserver.*fields andpromptis not one of them, and the rollouts runbook already carries a section that says the field is not the run's task.The change. The field stays and keeps its value. A note beside
SERVERinpositronic/policy/keys.py, a comment at the recording site inremote.py, and a paragraph indocs/inference.mdsay that the block is the handshake as the server sent it, that apromptin it is the deployment's declaration, and that the instruction an episode sent istask. A test pins that a declared prompt is recorded whole and that the task an episode sends reaches the wire unchanged, with no prompt beside it. No warning and no check is added.The test spells the handshake fields as strings on purpose, as the file's other fixtures do: a shared constant would leave nothing pinning the client to the wire.
The rules check did not run: first pass, not polished, and it is due before merge.
Ticket: Positronic-Robotics/internal#1290