Skip to content

Evaluate every Atomic Skill with the v1 protocol - #775

Merged
Yuan-Xinyi merged 2 commits into
codex/spatial-generalization-testsfrom
feat/atomic-skill-v1-evaluators
Oct 14, 2026
Merged

Yuan-Xinyi merged 2 commits into
codex/spatial-generalization-testsfrom
feat/atomic-skill-v1-evaluators

Conversation

@Yuan-Xinyi

@Yuan-Xinyi Yuan-Xinyi commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator

Stack

Description

This PR migrates the atomic-task benchmark framework from #642 onto the evaluator protocol introduced by #712. It intentionally migrates framework only: no historical benchmark results, reports, JSONL artifacts, videos, or measured success rates are included.

Common infrastructure added for every skill:

  • Replay observation windows/traces for raw TCP pose, arm and gripper joint state, active-object pose, articulation-joint state, and named scene-object poses.
  • Row-local StageEvidence generated only from replay measurements; missing or non-finite evidence fails only its environment row instead of aborting the batch.
  • Versioned atomic-skill-v1 stage criteria, standard failure codes, and focused positive, negative, boundary, terminal-settle, and partial-batch regression coverage.
  • Full physical-evaluator registration for all 15 Atomic Skills.
  • Every inferred grasp/release/contact condition is explicitly labeled source="measured_proxy"; raw pose and joint measurements remain simulation_state.

Coverage by Atomic Skill

Atomic Skill Replay evidence added Required atomic-skill-v1 stages and pass conditions
MoveEndEffector Settled terminal TCP pose. reached: terminal TCP position error ≤ 3 mm and orientation error ≤ 5°, including declared rotation symmetry.
MoveJoints Settled terminal arm joint positions. reached: joint-space L2 error ≤ 0.00524 rad.
PickUp Gripper state at grasp, object pose through lift, and gripper/object state after settling. grasped: gripper holding proxy succeeds.
lifted: object lifted ≥ 4 cm and stayed above the no-drop floor.
held: object remained retained after settling.
MoveHeldObject Object pose during transport plus object/gripper state over terminal settle. transported: actuation-end object error ≤ 1 cm / 5° with no drop.
settled: terminal object error remains ≤ 1 cm / 5° with no drop.
held: grasp remains retained after settling.
Place Gripper state at release and object pose over the settle interval. released: gripper release proxy succeeds.
placed: full 3D position error ≤ 1 cm; tilt error ≤ 5° by default, or full rotation error ≤ 5° when target yaw is enabled; no drop.
stable: settle drift ≤ 1 cm / 5° with no drop.
Press Target articulation-joint trace over the press interval. contacted: positive target-joint motion, labeled as a measured proxy.
pressed: peak signed stroke reaches ≥ 80% of the available stroke.
Slide Target articulation-joint trace during sliding and gripper state at release. grasped: motion occurs in the configured effect_joint_sign direction.
slid: signed requested displacement error ≤ 1 cm.
released: gripper release proxy succeeds. Opposite-direction travel cannot pass.
Twist Target-joint trace, executed TCP rotation trace, and gripper state at release. grasped: target-joint motion proxy confirms engagement.
twisted: signed executed TCP rotation about the requested axis has ≤ 5° error.
released: gripper release proxy succeeds. Opposite-direction rotation cannot pass.
OpenDoor Hinge-joint trace during opening and gripper state at release. grasped: hinge motion proxy confirms engagement.
opened: final hinge-angle error ≤ 5°.
released: gripper release proxy succeeds.
Pour Held-object pose during pouring plus object/gripper state over terminal settle. poured: peak signed object rotation about the configured axis has ≤ 5° error with no drop.
settled: terminal lift remains ≥ 4 cm with no drop.
held: grasp remains retained after settling.
AxisAlign Object pose during alignment plus object/gripper state over terminal settle. grasped: object-axis motion proxy confirms engagement.
aligned: actuation-end axis error ≤ 5°, lift ≥ 4 cm, and no drop.
settled: terminal axis error remains ≤ 5°, lift remains ≥ 4 cm, and no drop.
held: grasp remains retained.
PushObject Object pose at contact, throughout push, and after settling. contacted: object motion during contact, labeled as a measured proxy.
pushed: positive displacement toward the goal and actuation-end in-plane error ≤ 1 cm.
on_support_plane: settled in-plane error remains ≤ 1 cm, support-plane error ≤ 1 cm, and tilt ≤ 5°.
HandOver Source/destination gripper states and object pose across pickup, transfer, exchange, and settling. grasped: source hand holds the object.
transferred: both hands hold it with no drop.
handed_over: giver releases while receiver retains it.
receiver_released: receiver releases at the terminal target.
placed: final XY error ≤ 3 cm, signed Z error in [-10 cm, +3 cm], and no drop.
CoordinatedPickment Both gripper states and object pose across dual grasp, lift, synchronized motion, and settling. dual_grasped: both grasps established.
lifted: object lifted ≥ 4 cm with no drop.
moved: actuation-end object error ≤ 1 cm / 5° with no drop.
settled: terminal object error remains ≤ 1 cm / 5° with no drop.
held: both hands retain the object after settling.
CoordinatedPlacement Placing-object and support-object poses in their relative frame, plus role-specific gripper states. aligned: pre-release relative pose error ≤ 1 cm / 5° with no drop.
released: placing hand releases while the support hand remains holding.
stable: settled relative pose still matches the target within 1 cm / 5°, settle drift stays within 1 cm / 5°, and no drop occurs.

Refs #642.

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • Enhancement (non-breaking change which improves an existing functionality)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (existing functionality will not work without user modification)
  • Documentation update

Screenshots

Not applicable; this is benchmark framework and evaluator logic.

Validation

  • black --check --diff --color ./ — 9007 files unchanged with black==26.3.1
  • tests/benchmark/motion_generation — 293 passed, 1 skipped
  • python docs/scripts/check_api_docs.py — 2487/2487 exports documented
  • python .agents/skills/project-dev-context/scripts/context.py affected --base origin/codex/spatial-generalization-tests --explain — no affected topics in this PR layer
  • git diff --check

The focused tests use an in-process compatibility shim because the local DexSim 0.5.0 environment does not expose dexsim.types.RTRenderMode; the shim is not part of this change. No live simulator/GPU benchmark run or result generation was performed.

Checklist

  • I have run the black . command to format the code base.
  • I reviewed affected documentation and agent context; no update is needed because this layer changes benchmark-only evaluators and tests.
  • Public API coverage passes (python docs/scripts/check_api_docs.py); no public API docs changed.
  • I have added tests that prove the framework and fixes are effective.
  • Dependencies are unchanged.

@Yuan-Xinyi Yuan-Xinyi added enhancement New feature or request motion gen Things related to motion generation for robot atomic action atomic action related functionality labels Oct 13, 2026
@greptile-apps

greptile-apps Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 2/5

[Medium impact] Refactors skill evaluation to use new observation protocol.

Not ready to merge: the three earlier findings still reject successful pushes, already-aligned grasps, and hands with unchanged joints.

Fix All in CodexFindings

  1. P1 Successful pushes fail contact ▶
  2. P1 Aligned objects fail grasp ▶
  3. P1 Unchanged joints reject grasps ▶
Fix with agent prompt
### Issue 1
scripts/benchmark/motion_generation/scenarios/atomic_skill_providers.py:1941-1944
The shipped push cases deliberately leave 2–3 mm of clearance at the end of `contact`. The object starts moving during `push`, but `push_contact` samples only `contact`. This reports `contact_established=False` even when the following push reaches its goal. Extend the measured-motion proxy into the part of `push` where contact actually happens.

### Issue 2
scripts/benchmark/motion_generation/scenarios/atomic_skill_providers.py:294-296
`grasp_established` requires the object's axis to rotate during `manipulate`. A valid `AxisAlign` case can start with its axis already pointing at `target_axis`. The robot still grasps and lifts it, but no rotation is needed. That successful case fails `grasped` because `moved` is zero. Collect grasp evidence from the gripper rather than requiring an axis change.

### Issue 3
scripts/benchmark/motion_generation/scenarios/atomic_task.py:932-935
`_gripper_holding` requires every joint to move between the open and grasp commands. For a valid multi-joint hand with one unchanged joint, `direction` is zero for that joint. Both distances are then zero, so `.all()` always returns false. The newly migrated single-arm grasp and retention checks reject successful grasps on these hands. Ignore unchanged joints when checking closure, while requiring evidence from the joints that do close.

---

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

Summary

Migrates all 15 Atomic Skills to replay-based atomic-skill-v1 evaluators.

  • Skill providers can request measured replay windows for their actions.
  • Each skill now gets a versioned result for its measured stages.
  • Arm moves score their measured endpoint against the target.
  • Pick, transport, and place results check objects through settling.
  • Door, press, slide, and twist results score their action stages.
  • Pouring and axis alignment score the object's motion and final state.
  • Push tasks score object movement and its settled support pose.
  • Two-hand tasks score handoffs, shared grips, and relative placement.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Provider resolves replay windows] --> B[Replay samples simulator state]
  B --> C[Raw observation traces]
  C --> D[Row-local stage evidence]
  D --> E[Versioned skill criteria]
  E --> F[Stage results and task success]
Loading

Reviews (2) · Last reviewed commit: "fix(benchmark): tighten atomic skill acc..." · Reviewed by Greptile

Comment on lines +1860 to +1863
"push_contact",
contact.start,
contact.stop,
frozenset({"object_pose"}),

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 Successful pushes fail contact

The shipped push cases deliberately leave 2–3 mm of clearance at the end of contact. The object starts moving during push, but push_contact samples only contact. This reports contact_established=False even when the following push reaches its goal. Extend the measured-motion proxy into the part of push where contact actually happens.

Prompt To Fix With AI
This is a comment left during a code review.
Path: scripts/benchmark/motion_generation/scenarios/atomic_skill_providers.py
Line: 1860-1863

Comment:
**Successful pushes fail contact**

The shipped push cases deliberately leave 2–3 mm of clearance at the end of `contact`. The object starts moving during `push`, but `push_contact` samples only `contact`. This reports `contact_established=False` even when the following push reaches its goal. Extend the measured-motion proxy into the part of `push` where contact actually happens.

---

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

Comment on lines +251 to +253
measurements={"grasp_established": moved > 1.0e-5},
method="object_axis_motion_proxy",
source="measured_proxy",

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 Aligned objects fail grasp

grasp_established requires the object's axis to rotate during manipulate. A valid AxisAlign case can start with its axis already pointing at target_axis. The robot still grasps and lifts it, but no rotation is needed. That successful case fails grasped because moved is zero. Collect grasp evidence from the gripper rather than requiring an axis change.

Prompt To Fix With AI
This is a comment left during a code review.
Path: scripts/benchmark/motion_generation/scenarios/atomic_skill_providers.py
Line: 251-253

Comment:
**Aligned objects fail grasp**

`grasp_established` requires the object's axis to rotate during `manipulate`. A valid `AxisAlign` case can start with its axis already pointing at `target_axis`. The robot still grasps and lifts it, but no rotation is needed. That successful case fails `grasped` because `moved` is zero. Collect grasp evidence from the gripper rather than requiring an axis change.

---

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

Comment on lines +924 to +927
direction = torch.sign(grasp_qpos - open_qpos)
closed = (final - open_qpos) * direction
remaining = (grasp_qpos - final) * direction
return ((closed >= gap) & (remaining >= gap)).all(dim=-1)

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 Unchanged joints reject grasps

_gripper_holding requires every joint to move between the open and grasp commands. For a valid multi-joint hand with one unchanged joint, direction is zero for that joint. Both distances are then zero, so .all() always returns false. The newly migrated single-arm grasp and retention checks reject successful grasps on these hands. Ignore unchanged joints when checking closure, while requiring evidence from the joints that do close.

Prompt To Fix With AI
This is a comment left during a code review.
Path: scripts/benchmark/motion_generation/scenarios/atomic_task.py
Line: 924-927

Comment:
**Unchanged joints reject grasps**

`_gripper_holding` requires every joint to move between the open and grasp commands. For a valid multi-joint hand with one unchanged joint, `direction` is zero for that joint. Both distances are then zero, so `.all()` always returns false. The newly migrated single-arm grasp and retention checks reject successful grasps on these hands. Ignore unchanged joints when checking closure, while requiring evidence from the joints that do close.

---

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

@Yuan-Xinyi
Yuan-Xinyi requested a review from yangchen73 October 13, 2026 12:49
@Yuan-Xinyi
Yuan-Xinyi requested a review from yangchen73 October 14, 2026 03:10
@Yuan-Xinyi
Yuan-Xinyi merged commit 49646b8 into codex/spatial-generalization-tests Oct 14, 2026
1 check passed
@Yuan-Xinyi
Yuan-Xinyi deleted the feat/atomic-skill-v1-evaluators branch October 14, 2026 03:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

atomic action atomic action related functionality enhancement New feature or request motion gen Things related to motion generation for robot

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants