# Pushing study: evidence ledger

Public reproduction note: archive aliases and `SIMCOMPARE_ROOT` are portable placeholders; use your own archive and checkout locations. Private deployment identifiers are omitted.

Protocol: `PUSH-PROTOCOL-2026-09-21.md`. No engine-specific gain, friction or
geometry tuning. All runs use the same frozen `assets/push-reference.json`.
Reference generation used the remote MuJoCo installation, not the older local
test installation. Local tests are implementation checks, not reported trials.

Accepted-source directories (only completed strict JSON files):

- PhysX and MuJoCo CPU: `output/archive-rigid/push-01`.
- Newton/MuJoCo-Warp: `output/archive-rigid/push-02`.
- Genesis: `output/archive-rigid/push-03`.

## Retained diagnostics

Newton in push-01 incorrectly attributed wall forces to the table. Newton adds
numeric suffixes to native geometry names (e.g. `wall_left_6`); the first mapping
missed those suffixes. Positions are not repaired/relabelled after the fact:
rerun in push-02 with verified static geometry ownership. The interrupted next
trial and logs remain. This is a recorder correction, not a contact-parameter
change; do not mix push-01 Newton force plots with corrected evidence.

Genesis in push-01 used default all-bits collision masks for separately authored
static primitives. That allowed pad–wall/table collision pairs excluded by the
canonical MJCF and PhysX fixture. These trials are excluded from the matched
comparison. Push-03 sets primitive contype=4 and conaffinity=2 explicitly.
Subsequent trials also assert native mask readbacks for robot, objects and walls.
Earlier grasp/stack recordings have not been rerun or silently replaced by this
adapter correction; their physical interpretation needs this caveat if pads
could reach the table. The correction is material for this channel scene.

## Interpretation boundaries

All 28 corrected trials completed and passed the recording and model/FK gates.
Final report: `output/archive-rigid/push-report`; per-engine paired-control JSONs
are in `push-preview/*-controls.json`. The GPU was idle after completion; the
instance was not stopped. Raw evidence and logs are downloaded locally.

Every engine moves all three centres past the target at 100 and 90 mm; none
does so at 80 mm. All 90 mm perturbations/repeats/half-step trials also pass.
At 80 mm the initially rear cube finishes roughly 133 mm apart between CPU
MuJoCo and Genesis. This width has no separate repeat/timestep sweep yet.

Maximum object-path differences in mm from the 90 mm baseline (all objects,
matching timestamps, not just endpoints):

| Engine | Exact repeat | Larger of ±1 mm layouts | Half timestep |
|---|---:|---:|---:|
| PhysX | 0 | 2.399 | 0.274 |
| Newton / MuJoCo-Warp | 2.758 | 27.990 | 5.273 |
| MuJoCo CPU | 0 | 31.359 | 27.806 |
| Genesis | 0.002883 | 3.549 | 0.448 |

These are single paired comparisons, not uncertainty intervals. Both Newton
and Genesis are GPU-backed; no causal claim about GPU computation follows.

Only fingertip pads collide, not palm/arm visual meshes. Arm and fingers are
compliant; the arm can deflect and lose pad contact under obstruction.
The robot can visually pass through a block after losing pad contact. Report
this limitation explicitly; this is not a validated full-hand pushing asset.

The passage statistic is explicitly a final world-X threshold, not proof of
stable jamming or a complete real-world task-success definition. Continuous
object paths and controller/force recordings remain the primary evidence.
No claim that a larger force or a different arrangement is more physically
accurate. All static reaction arrows are omitted; forces on dynamic bodies are
native contact readbacks. Existing force timing conventions are retained.

## Reproduction

Generate the reference once with `push_scene.py assets/push-reference.json`.
Run each trial with `push_run.py --backend ENGINE --tape assets/push-reference.json
--width WIDTH --layout LAYOUT --seed 0 --dt DT --output UNIQUE.json`.
Batch definitions are in `setup/push.py`; outputs are never overwritten.

Build the final report using `push_report.py output/archive-rigid/push-01
--newton-directory output/archive-rigid/push-02
--genesis-directory output/archive-rigid/push-03 --output NEW_DIRECTORY`.
It fails on missing traces or mismatched scene/reference hashes. Use `--cases`
for explicitly labelled partial reports. `push_controls.py` compares unchanged
repeats, timestep sensitivity and ±1 mm layouts at identical timestamps.
