Skip to content

fix(gym): separate policy and controller action traces - #695

Merged
yuecideng merged 2 commits into
mainfrom
codex/post-680-action-contract-fixes
Sep 27, 2026
Merged

yuecideng merged 2 commits into
mainfrom
codex/post-680-action-contract-fixes

Conversation

@yuecideng

@yuecideng yuecideng commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Description

This PR makes EmbodiChain action semantics explicit across RL rollouts, expert demonstrations, and LeRobot recording.

Previously, one rollout action field could represent either a raw policy request or an executed controller command. That ambiguity caused stale qpos snapshots, incompatible action widths when policy and joint recorders were combined, and loss of velocity data for position-velocity demonstrations.

The implementation now provides:

  • ActionTrace with separate requested, processed, and executed action stages.
  • Explicit rollout_action_semantics values for policy-request and expert-controller buffers.
  • Expert controller qpos history with compatibility aliases for existing callers.
  • Correct preservation of complete [qpos, qvel] position-velocity expert actions.
  • Safe inactive-row masking for direct controller demos without an ActionManager.
  • Tests for direct controller snapshots, mixed-width recorders, position-velocity encoding, and ActionManager traces.

The existing action contracts and rollout buffer layout remain compatible; the new trace and semantics metadata clarify how each recorded action should be interpreted.

Related: #680

Type of change

  • Bug fix (non-breaking change)
  • Enhancement (non-breaking change)
  • New feature (non-breaking change)
  • Breaking change (existing functionality will not work without modification)
  • Documentation update

Validation

  • Focused EmbodiChain tests: 145 passed under Python 3.11.
  • black --check --diff --color ./ passed.
  • API documentation coverage: 2293/2293 exports.
  • git diff --check passed.

Checklist

  • I have run the black . command to format the code base.
  • I reviewed affected documentation and agent context; existing guidance remains accurate.
  • I have added tests that prove my fix is effective.
  • Dependencies have been updated, if applicable.

@yuecideng yuecideng added bug Something isn't working gym robot learning env and its related features dataset labels Sep 26, 2026
@greptile-apps

greptile-apps Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 4/5

[Medium risk] Adds action tracing to capture policy requests and controller commands.

The PR does not appear safe to merge because mixed position-velocity recording can save policy requests under an expert-action schema.

Fix All in CodexFindings

  1. P1 Legacy recorder saves policy requests ▶
  2. P2 Mixed recording remains untested ▶
Fix with agent prompt
### Issue 1
embodichain/lab/gym/envs/managers/datasets.py:515-522
When a policy-contract recorder runs alongside a legacy recorder in a position-velocity expert environment, the shared rollout buffer holds policy requests rather than `[qpos, qvel]` commands. This branch returns those requests for the legacy recorder, so it saves actions with the wrong meaning and potentially the wrong width for its declared expert schema.

### Issue 2
tests/gym/envs/test_demo.py:224-232
These tests stop after preprocessing and masking; they never check what the recorder saves from executed-qpos history. Add a recording test with simultaneous policy and legacy recorders whose action widths differ. Without it, the mixed-contract behavior this change targets can regress unnoticed.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

The PR refreshes direct-controller qpos snapshots, retains controller-qpos history for recorders, adds action traces, and preserves position-velocity rollout actions for legacy recording.

  • Mixed policy and legacy recording still needs a distinction between policy requests and expert commands when the expert spec uses position-velocity actions.
  • The earlier mixed-recording test concern remains: the added tests check action-list selection, not persistence with both recorder types active.
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart LR
  P[Policy action] --> B[Shared rollout buffer: policy request]
  P --> M[ActionManager]
  M --> H[Controller qpos history]
  B --> R[Policy-contract recorder]
  B --> L[Legacy recorder with position-velocity spec]
  H -. not selected by new branch .-> L
Loading

Reviews (2) · Last reviewed commit: "refactor(gym): unify action traces and c..."

Comment thread embodichain/lab/gym/envs/managers/datasets.py
Comment on lines +224 to +232
def test_controller_action_refreshes_executed_qpos_snapshot() -> None:
"""A direct controller command must not reuse a prior manager snapshot."""
env = _controller_action_env()
env._last_action_manager_qpos = torch.full((2, 3), 99.0)

prepared = env._preprocess_action(ControllerAction(torch.ones(2, 3)))

assert isinstance(prepared, ControllerAction)
torch.testing.assert_close(env._last_action_manager_qpos, torch.ones(2, 3))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Mixed recording remains untested These tests stop after preprocessing and masking; they never check what the recorder saves from executed-qpos history. Add a recording test with simultaneous policy and legacy recorders whose action widths differ. Without it, the mixed-contract behavior this change targets can regress unnoticed.

Prompt To Fix With AI
This is a comment left during a code review.
Path: tests/gym/envs/test_demo.py
Line: 224-232

Comment:
**Mixed recording remains untested** These tests stop after preprocessing and masking; they never check what the recorder saves from executed-qpos history. Add a recording test with simultaneous policy and legacy recorders whose action widths differ. Without it, the mixed-contract behavior this change targets can regress unnoticed.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Codex Fix in Claude Code

@yuecideng
yuecideng force-pushed the codex/post-680-action-contract-fixes branch from ac264d2 to 87e2625 Compare September 26, 2026 16:43
@yuecideng
yuecideng force-pushed the codex/post-680-action-contract-fixes branch from 87e2625 to f7af523 Compare September 26, 2026 16:44
Comment on lines +515 to +522
if (
expert_spec is not None
and expert_spec.joint_command_mode == "position_velocity"
):
# Position-velocity expert rows are already encoded as
# [qpos, qvel] in the rollout buffer. Executed qpos history
# intentionally contains only qpos and must not replace it.
return torch.as_tensor(stored_actions).detach().cpu().clone()

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 Legacy recorder saves policy requests When a policy-contract recorder runs alongside a legacy recorder in a position-velocity expert environment, the shared rollout buffer holds policy requests rather than [qpos, qvel] commands. This branch returns those requests for the legacy recorder, so it saves actions with the wrong meaning and potentially the wrong width for its declared expert schema.

Prompt To Fix With AI
This is a comment left during a code review.
Path: embodichain/lab/gym/envs/managers/datasets.py
Line: 515-522

Comment:
**Legacy recorder saves policy requests** When a policy-contract recorder runs alongside a legacy recorder in a position-velocity expert environment, the shared rollout buffer holds policy requests rather than `[qpos, qvel]` commands. This branch returns those requests for the legacy recorder, so it saves actions with the wrong meaning and potentially the wrong width for its declared expert schema.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Codex Fix in Claude Code

@yuecideng yuecideng changed the title fix(gym): preserve executed qpos across action contracts fix(gym): separate policy and controller action traces Sep 26, 2026
@yuecideng
yuecideng merged commit 556a431 into main Sep 27, 2026
9 checks passed
@yuecideng
yuecideng deleted the codex/post-680-action-contract-fixes branch September 27, 2026 03:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working dataset gym robot learning env and its related features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant