Skip to content

feat(rollout): node-based rollout pipeline - #575

Draft
ElmoPA wants to merge 1 commit into
rh/offline-keymap-fixfrom
rh/rollout-nodes
Draft

feat(rollout): node-based rollout pipeline#575
ElmoPA wants to merge 1 commit into
rh/offline-keymap-fixfrom
rh/rollout-nodes

Conversation

@ElmoPA

@ElmoPA ElmoPA commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

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 commented Aug 17, 2026

Copy link
Copy Markdown
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.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

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
ElmoPA changed the base branch from rh/offline-keymap-fix to graphite-base/575 August 17, 2026 04:39
@ElmoPA
ElmoPA changed the base branch from graphite-base/575 to rh/offline-keymap-fix August 17, 2026 04:40
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