feat(rollout): node-based rollout pipeline - #575
Draft
ElmoPA wants to merge 1 commit into
Draft
Conversation
Contributor
Author
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
This was referenced Aug 17, 2026
Rollout policy -- when to query the model, how many predicted actions to commit, whether to blend overlapping plans -- lived as imperative code in two divergent places: PipelineAlgo.inference_step (action queue + a PUSHSHAPES_PLAN_BLEND env var read mid-function) and PolicyRollout.rollout_step (i %% query_frequency plus hardcoded action slicing). Neither was configurable and they disagreed. Training already solved this shape: an ordered list of stages over one dict, where the list IS the control flow. Same contract here, node(state) -> state: ObsCadence WHEN to query (on_queue_empty | every_n | always) ObsAssemble obs -> model input (runs the training transform list) PolicyStep algo.step, NOT forward_eval (which is teacher-forced) ChunkCommit WHICH actions execute (n_keep, temporal-ensembling blend) ActionDequeue one action per control step ActionToRobot model action space -> robot interface Defaults reproduce rollout.py exactly: QUERY_FREQUENCY=30 at 30 Hz, i.e. one inference per second and 30 actions per plan. Verified the emitted action at step i equals chunk row (i %% 30) of the plan made at (i//30)*30. Nodes declare reads/writes and RolloutPipeline validates the key flow at build time, so an ordering mistake fails at startup instead of surfacing as a None mid-episode on hardware.
ElmoPA
changed the base branch from
rh/offline-keymap-fix
to
graphite-base/575
August 17, 2026 04:39
ElmoPA
force-pushed
the
rh/rollout-nodes
branch
from
August 17, 2026 04:40
b110f4e to
d6d3344
Compare
ElmoPA
changed the base branch from
graphite-base/575
to
rh/offline-keymap-fix
August 17, 2026 04:40
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Rollout policy -- when to query the model, how many predicted actions to commit,
whether to blend overlapping plans -- lived as imperative code in two divergent
places: PipelineAlgo.inference_step (action queue + a PUSHSHAPES_PLAN_BLEND env
var read mid-function) and PolicyRollout.rollout_step (i %% query_frequency plus
hardcoded action slicing). Neither was configurable and they disagreed.
Training already solved this shape: an ordered list of stages over one dict,
where the list IS the control flow. Same contract here, node(state) -> state:
ObsCadence WHEN to query (on_queue_empty | every_n | always)
ObsAssemble obs -> model input (runs the training transform list)
PolicyStep algo.step, NOT forward_eval (which is teacher-forced)
ChunkCommit WHICH actions execute (n_keep, temporal-ensembling blend)
ActionDequeue one action per control step
ActionToRobot model action space -> robot interface
Defaults reproduce rollout.py exactly: QUERY_FREQUENCY=30 at 30 Hz, i.e. one
inference per second and 30 actions per plan. Verified the emitted action at
step i equals chunk row (i %% 30) of the plan made at (i//30)*30.
Nodes declare reads/writes and RolloutPipeline validates the key flow at build
time, so an ordering mistake fails at startup instead of surfacing as a None
mid-episode on hardware.