Newton live-MCP study · cheaper-model phase

Debug Cards for Newton agents

36 short notes (symptom → cause → check → repair), distilled from 245 earlier agent transcripts and given to agents in 78 trials across five models. Every time an agent opened a card, the transcript was read to judge whether the card was decisive, helpful, unused or misleading. Back to the study summary.

1. Verdict

Keep the Debug Cards as a short, title-listed reference and drop the procedure. They pay off for mid-tier and frontier models, not for the cheapest ones.

  • 8 of 36 cards did all the decisive work. Each names a task's actual cause: contact priority, contact damping, SDF edits, replay latency and sag, floating-base gains. They account for all 65 decisive uses out of 372.
  • Who benefits. GPT-6 Sol with cards and the MCP reached first passes faster than Opus and Astra without them (0.71×), at 37% of their cost. Opus and Astra gain a little on top of the MCP. Luna gains little, and Haiku nothing: it rarely opens a card.
  • Delivery that works: card titles listed in the prompt. Agents open 1–13 cards as files within 25 seconds. The MCP's cards() search and its automatic attachments were almost never used.
  • What hurt: the long mandatory procedure of the first two versions slowed every model. Titles plus four rules work best. Cards misled in 2 of 372 uses, both caused by Haiku's own measurement bug.
  • Next. Merge or drop the 13 mostly unused or never-opened cards. Add the two that were missing: a worked balance-controller recipe, and how to read the live simulation state. Move the decisive cards into Newton's documentation.
Effect of cards plus MCP, per model: geometric means over six tasks of per-task medians (below 1 is better).
ModelCards + MCP compared withTime to first passCost per trialPassesVerdict
Opus 5.5 · GPT-6 Astrathe MCP alone, same commit0.86× · 0.88×0.91× · 0.89×12/12 each✓ small gain
GPT-6 Solno harness0.82×0.76× (0.59× to the first pass)11/12 vs 12/12✓ cheaper, a bit faster
GPT-6 Lunano harness0.92×0.72×9/12 vs 10/12≈ within noise
Claude Haiku 4.5no harness––2/6 vs 2/6✗ rarely opens cards

2. The 36 cards at a glance

Grouped by what they did in the trials. Click a card to open it below.

decisivehelpfulmisleadingunusedbar length = number of uses (longest: 32); hover a segment for counts

3. Details

All 36 cards rendered as the agents saw them, with their uses and provenance

Edits and batches

BAT-01Edit never reached the solverMostly unused4 uses

A sweep returns the same result for very different settings: the edit never reached the solver

Symptoms

  • A sweep is flat, or a 'robustness' batch shows no spread.

Likely causes

  • Missing or wrong ModelFlags: gravcomp and mass/inertia need BODY_INERTIAL_PROPERTIES (not BODY_PROPERTIES); armature JOINT_DOF_INERTIAL_PROPERTIES; gains, damping, friction, limits JOINT_DOF_FORCE_PROPERTIES; shape materials, gap, solimp SHAPE_PROPERTIES; equality solref CONSTRAINT_PROPERTIES.
  • Construction-only: geom priority, condim, ctrl_source, joint_target_mode, solver options (cone, iterations, integrator, impratio). Never read by SolverMuJoCo: restitution, joint_velocity_limit, joint_enabled, body_inv_mass/inv_inertia; kf only with Newton contacts.
  • Inactive mode (mujoco.solref outside RAW mode) or the wrong array (CTL-01).
  • Only world 0 edited (BAT-02); a captured graph replays old pointers (BAT-04); reset/restore re-applied old values; the scenario setup never applied its perturbation.
  • Your harness dropped the value (JSON int keys became str, a stale variable). Or the knob is real but irrelevant (CON-03).

Checks

  • Positive control: push an extreme value through the same path; the output must change grossly.
  • report_solver_params(solver, kind) pending column (MCP solver_params); solver.check_world_values(name).
  • Read back the t=0 state of every world after scenario setup.

Repairs

  • Use the right flag, or rebuild the solver for construction-time fields and re-capture graphs; set values at build time in the script.

Pitfalls / shortcuts to avoid

  • Drawing physical conclusions from a flat sweep; writing compiled mjw_model arrays as the fix.

Edits and batches · cards-v1 · 1 attachment signature(s)

Uses in the trials (1 helpful · 3 unused)
  • helpful v6.1/cube_toss-luna-mcp-cards-v1-p0 (Luna, fail): 135 s: 'A batched positive control also confirmed that friction changes reach the solver: setting it to zero caused large drift'. Later kf=0 was used as a frictionless positive control (830 s).
  • unused v6.4/abc_arm-astra-mcp-cards-v3-p0 (Astra, pass): No flat sweep occurred.
  • unused v6.4/abc_arm-sol-mcp-cards-v3-p0 (Sol, pass): Read right after a flat effort-limit sweep (322s, every score 0.01616). No positive control was run; at 334s the agent went back to sweeping delay.
  • unused v6.5/cube_toss-astra-mcp-cards-v3-p0 (Astra, pass): No flat sweep.
Where it came from

7 grasp_drift trials misattributed nulls (one positive control settled it in ~10 s); 6 replay + 2 abc_arm no-op edits; unapplied perturbations in 3 abc_scratch MCP trials (~1200 s each in two, one failure).

Verification: Never-read list completed (joint_enabled, body_inv_mass/inv_inertia, kf only with Newton contacts).

BAT-02Only world 0 changesHelpful4 uses

Multi-world batch: only world 0 changes, or worlds disagree with the single-world run

Symptoms

  • World 0 behaves like the single-world run; other worlds do not.

Likely causes

  • Label lookups (list.index, endswith) return world 0's entry; hard-coded ranges; actuator indices assumed equal to DOF indices.
  • control.joint_target_q is coordinate-shaped when newton.use_coord_layout_targets is True (default): a FREE joint has 7 coordinates and 6 DOFs.
  • With MuJoCo contacts, mesh/heightfield assets come from the first world; meshes authored in world coordinates bake one placement; worlds must have the same shape types in the same order.
  • Tendon rows added with add_custom_values and no explicit mujoco:tendon_world stay in world 0 after replicate() (MJCF imports set it).

Checks

  • Twin test: N identical worlds with the same edit; report_health(..., twins=True).
  • Print edited arrays reshaped to (world_count, -1); compare control.joint_target_q.shape with model.joint_coord_count / joint_dof_count.
  • Run each scene alone and inside the batch; solver.check_world_values(name).

Repairs

  • Index with model.joint_target_q_start, model.find_joint_coords/find_joint_dofs(pattern, world=w), or newton.selection.WorldView / ArticulationView.
  • Set values in the builder before replication; meshes in shape-local coordinates, one mesh object per role; Newton contacts when geometry must differ per world; set tendon_world explicitly.

Pitfalls / shortcuts to avoid

  • Debugging physics from a batch where most worlds never received commands.

Edits and batches · cards-v1 · 2 attachment signature(s)

Uses in the trials (4 helpful)
  • helpful v6.2/g1_hard-luna-mcp-cards-v2-p0 (Luna, fail): Read when the batched static pose tipped; 890 s 'single-world and three-world static runs agree within 1.4e-5', so the fall was real (ruled out a batch artifact).
  • helpful v6.4/abc_arm-astra-mcp-cards-v3-p0 (Astra, pass): 114s 'Check task rollout equivalence': per-world batch vs task rollout max diff 2.4e-7, twins identical.
  • helpful v6.4/cube_toss-astra-mcp-cards-v3-p0 (Astra, pass): 59s batch result for one toss checked against module.evaluate (0.09517 both).
  • helpful v6.5/cube_toss-astra-mcp-cards-v3-p0 (Astra, pass): 85s batch vs single-world evaluate check (0.099988 both).
Where it came from

World-0-only edits in 7 trials; shared world-coordinate mesh in 5 Astra replay trials; tendon warning flood in 4/10 Astra dp_real; WorldView used 0/31.

Verification: tendon_world claim narrowed: rows added with add_custom_values stay in world 0; MJCF imports set it (both reproduced).

BAT-03Batch candidates as worldsHelpful32 uses

Each candidate costs a full rollout: evaluate candidates x scenarios as worlds of one model

Symptoms

  • Search is slow, serial, or done in a hand-written replica simulator.

Likely causes

  • Model, solver and graph rebuilt per candidate; one candidate per process.
  • SciPy Nelder-Mead's default simplex is 5% of nonzero parameters and tiny for zeros, so offset parameterizations do not move.
  • Very large batches exhaust memory; a tail-world failure above several thousand worlds was seen (cause unknown).

Checks

  • Time one evaluation and multiply by the planned count before launching.
  • Score a subset alone and at the end of a big batch; error vs world index.

Repairs

  • newton.utils.BatchRollout(build, N, solver=make_solver, dt=...): view.set_attribute(name, model, values, labels=...), reset, run(frames, record=...), or evaluate(candidates, scenarios, frames=, setup=, score=, passed=); see docs/concepts/batched_evaluation.rst. newton.selection.WorldView.set_attribute(..., solver) checks per-world support.
  • Cases whose setup writes a field the solver shares or reads only at construction (solver options, cone, condim) run in separate models automatically; pass build= for structural changes.
  • Drive population or least-squares optimizers with whole batches; chunk at a few thousand worlds and check chunk invariance; pass an explicit initial_simplex to Nelder-Mead.

Pitfalls / shortcuts to avoid

  • Surrogate replicas (CTL-07); fresh processes for search (keep them for the final check).

Edits and batches · cards-v1 · 1 attachment signature(s)

Uses in the trials (16 helpful · 16 unused)
  • helpful v6.1/abc_arm-luna-mcp-cards-v1-p0 (Luna, pass): 209 s: 'confirmed the BatchRollout setup ... accepts per-world gains, starts, and delayed command schedules. I'm moving the gain search into candidate-by-window batches'. Later ran the full-window candidate sweeps (652 s onward) the same way.
  • helpful v6.1/cube_toss-luna-mcp-cards-v1-p0 (Luna, fail): Candidate sweeps ran as batched candidates x 24-toss scenario tables (dbg_sweep, 'candidate passed failed scenarios' table at 205 s).
  • helpful v6.2/cube_toss-luna-mcp-cards-v2-p0 (Luna, pass): From 183 s every sweep (25-96 candidates x 200 tosses) ran as BatchRollout.evaluate in about 2-25 s each.
  • helpful v6.2/g1_hard-luna-mcp-cards-v2-p0 (Luna, fail): 340-415 s gain and feedforward sweeps ran as BatchRollout branches on high5.
  • helpful v6.3/abc_arm-luna-mcp-cards-v3-p0 (Luna, pass): 86 s: batch_fit builds one model with candidates x windows as worlds (W=C*S; 10 delays x 894 windows in 5 s), used for all ~30 sweeps.
  • helpful v6.3/cube_toss-luna-mcp-cards-v3-p0 (Luna, pass): 68-103 s: BatchRollout.evaluate over candidates x tosses (120 worlds) for every sweep.
  • helpful v6.4/abc_arm-astra-mcp-cards-v3-p0 (Astra, pass): 82-96s calibrate.py Harness packs 24 candidates x windows as worlds (2048 worlds, 0.4 s per eval) after reading BAT-03 and batched_evaluation.rst.
  • helpful v6.4/abc_arm-sol-mcp-cards-v3-p0 (Sol, pass): 58s writes cal_fit.batch_score, which runs candidates x windows as the worlds of one model with per-world gains, gravcomp and delay (4x32 cases in 0.48 s). Did not use BatchRollout.
  • helpful v6.4/cube_toss-astra-mcp-cards-v3-p0 (Astra, pass): 34-95s BatchRollout.evaluate over candidates x tosses (512 worlds).
  • helpful v6.4/g1_hard-astra-mcp-cards-v3-p0 (Astra, pass): 47-87s BatchRollout.evaluate gain sweep (12 cases), which established that gains alone do not work.
  • helpful v6.4/g1_track-astra-mcp-cards-v3-p0 (Astra, pass): 80-108s BatchRollout.evaluate: 36 gain candidates, then 6 playback rates as worlds.
  • helpful v6.5/abc_arm-astra-mcp-cards-v3-p0 (Astra, pass): 74-75s calibration.py Evaluator packs candidates x windows as worlds (16 delays in 0.5 s).
  • helpful v6.5/abc_arm-sol-mcp-cards-v3-p0 (Sol, pass): 99s and 139s: sweep_joint/batch_eval build candidates x windows as the worlds of one model with per-world gains and gravcomp (about 0.6 s per sweep).
  • helpful v6.5/cube_toss-astra-mcp-cards-v3-p0 (Astra, pass): 84-145s calibrate.Sweep on BatchRollout: 80 candidates x 50 tosses in 2.3 s.
  • helpful v6.5/g1_hard-astra-mcp-cards-v3-p0 (Astra, pass): 73s BatchRollout.evaluate gain sweep (12 cases), which showed that gains alone fail.
  • helpful v6.5/g1_track-astra-mcp-cards-v3-p0 (Astra, pass): 75-175s BatchRollout.evaluate: 18 then 54 (gains x rates) cases.
  • unused v6.1/g1_hard-luna-mcp-cards-v1-p0 (Luna, fail): Printed the BatchRollout.evaluate signature (38 s) but ran every experiment as a serial single-clip fresh process.
  • unused v6.2/g1_track-luna-mcp-cards-v2-p0 (Luna, pass): Only inspected BatchRollout signatures; sweeps ran sequentially in dbg_sweep.py.
  • unused v6.2/grasp_drift-luna-mcp-cards-v2-p0 (Luna, pass): The stiffness sweep ran live by editing model arrays, not with BatchRollout.
  • unused v6.3/abc_arm-haiku-mcp-cards-v3-p0 (Haiku, fail, attached): 1598 s: attached to a 'Failed to allocate 2640896 bytes' error at the end of a 240 s serial sweep cell; next action (1608 s) 'apply the best settings found to the file'; no batching or chunking change.
  • unused v6.3/abc_arm-luna-mcp-cards-v3-p1 (Luna, pass): Candidates still evaluated one model per candidate in serial fresh processes (107-790 s), not candidates x scenarios as worlds.
  • unused v6.3/cube_toss-luna-mcp-cards-v3-p1 (Luna, pass): Inspected the MCP evaluate signature (20 s) but swept candidates serially with module.evaluate.
  • unused v6.3/g1_hard-luna-mcp-cards-v3-p0 (Luna, fail): Only single-world rollouts.
  • unused v6.3/grasp_drift-luna-mcp-cards-v3-p0 (Luna, pass): Read the batch docs (23 s) but ran single-world live experiments.
  • unused v6.4/cube_toss-sol-mcp-cards-v3-p0 (Sol, pass): Read the batched_evaluation docs at 21s, but candidates were scored one at a time with module.evaluate.
  • unused v6.4/g1_hard-sol-mcp-cards-v3-p0 (Sol, pass): Only single-world MCP rollouts and fresh-process runs; no batching.
  • unused v6.4/g1_track-sol-mcp-cards-v3-p0 (Sol, pass): Serial MCP rollouts only.
  • unused v6.4/grasp_drift-astra-mcp-cards-v3-p0 (Astra, pass): Sweep ran with MCP branch(), not batched worlds.
  • unused v6.4/grasp_drift-sol-mcp-cards-v3-p0 (Sol, pass): No batching.
  • unused v6.5/g1_hard-sol-mcp-cards-v3-p0 (Sol, fail): Single-world in-process rollouts only.
  • unused v6.5/g1_track-sol-mcp-cards-v3-p0 (Sol, pass): Serial in-process rollouts only.
  • unused v6.5/grasp_drift-astra-mcp-cards-v3-p0 (Astra, pass): No batched sweep.
Where it came from

400 candidates in 23.6 s batched vs 136-210 s for ~200 serial (dp_real); C++ surrogates 10/10 Astra dp_real; 150 fresh runs (5.2 ks) in one replay trial; tail worlds in 3/4 Opus abc_arm.

Verification: evaluate() puts cases that write shared or construction-only fields into separate models automatically; build= is for structural changes.

BAT-04Live solver or graph changes break runsHelpful2 uses

Garbage, CUDA error 700, or silently lost steps after changing live solver objects or CUDA graphs

Symptoms

  • The run breaks or silently ignores changes after you modify live solver objects or graphs.

Likely causes

  • Graphs captured with old objects replay stale or freed pointers after swapping example.solver, re-capturing by hand, or writing compiled arrays.
  • Construction-only fields changed on live objects (cone, iterations, integrator, condim, priority, substeps, buffer sizes).
  • simulate() swaps state_0/state_1 inside the capture; with an odd substep count per graph, graph buffers and Python references disagree.
  • Scalar kernel arguments are frozen at capture; arrays are read at replay.

Checks

  • Same change in a fresh process, and eager (no graph).
  • After N launches compare solver.mjw_data.time and the state with an uncaptured run; change a scalar and see whether the trajectory changes.
  • report_health for runaway speed or zero contacts.

Repairs

  • Rebuild the Example/solver with the option passed in.
  • Capture an even number of substeps, or copy the final state back into state_0; pass changeable values in device arrays; re-capture after changing captured scalars.
  • MCP: newton_rebuild with arguments={"restart": true} recovers a broken process.

Pitfalls / shortcuts to avoid

  • Calling private capture helpers; writing mjw_model.opt.* as a fix.

Edits and batches · cards-v1 · 1 attachment signature(s)

Uses in the trials (1 helpful · 1 unused)
  • helpful v6.5/g1_hard-astra-mcp-cards-v3-p0 (Astra, pass): Final step comment 'Capture an even number of substeps so both state buffers retain their identity across CUDA graph launches' (card repair) for the 2-substep control split.
  • unused v6.5/grasp_drift-astra-mcp-cards-v3-p0 (Astra, pass): No live solver/graph changes.
Where it came from

6/16 grasp_drift MCP sessions broken (~1.1 ks); CUDA 700 in 4 MCP trials; odd-substep graph state in i6/g1_hard-astra-mcp-p1 (~220 s).

Verification: Correct call form: newton_rebuild with arguments={"restart": true}.

BAT-05Twin worlds disagreeHelpful7 uses

Identical worlds or repeated runs disagree

Symptoms

  • Results that should be identical are not.

Likely causes

  • Unconverged constraint solves (frictionloss, limits, contacts) at the default iterations, so the warm start changes the result.
  • GPU atomics accumulate in varying order; chaotic contact sequences (drops onto objects or rims) amplify tiny differences.
  • Per-world contact overflow (CON-06); a perturbation applied twice or not at all (BAT-01).

Checks

  • Three in-process runs vs one fresh run.
  • report_health(..., twins=True); stats["overflow_counts"] for ITERATIONS/LS_ITERATIONS.
  • Time of first divergence between twins; friction-off A/B.

Repairs

  • Raise iterations/ls_iterations until fresh and repeat agree.
  • Treat chaotic outcomes statistically (rates over many copies and seeds) and design for margin.
  • Use a deterministic mode (SolverMuJoCo(deterministic=wp.DeterministicMode.RUN_TO_RUN), CollisionPipeline(deterministic=True), wp.config.deterministic) only to debug single runs, after timing a short run (it compiles new kernels and can be much slower).

Pitfalls / shortcuts to avoid

  • Chasing bit-determinism; launching full batches in an untimed deterministic mode.

Edits and batches · cards-v1 · 2 attachment signature(s)

Uses in the trials (5 helpful · 2 unused)
  • helpful v6.2/g1_hard-luna-mcp-cards-v2-p0 (Luna, fail): Same twin/single-world comparison as BAT-02 at 725-890 s; confirmed worlds agree.
  • helpful v6.3/g1_track-luna-mcp-cards-v3-p1 (Luna, fail): Read after 1.5x runs disagreed (0.039 vs 0.079 m); 367-383 s in-process repeats and 436-478 s fresh-process runs (its check).
  • helpful v6.4/g1_hard-sol-mcp-cards-v3-p0 (Sol, pass): After high5 flipped between pass and fall at 342s, it ran 3 fresh and 6 in-process repeats (404s, 421s); 477s: 'occasional late falls across repeats'.
  • helpful v6.4/g1_track-astra-mcp-cards-v3-p0 (Astra, pass): 169s three repeated in-process runs agree (card check).
  • helpful v6.5/g1_hard-sol-mcp-cards-v3-p0 (Sol, fail): 1248s rebuilds the solver with iterations=200 and gets the same 5.68 cm root error, ruling out unconverged solves.
  • unused v6.5/cube_toss-astra-mcp-cards-v3-p0 (Astra, pass): Read with CON-11; no repeat-disagreement work.
  • unused v6.5/g1_track-astra-mcp-cards-v3-p0 (Astra, pass): No repeat comparison.
Where it came from

Fresh vs repeat fixed by more iterations in i10/abc_arm-opus-mcp-p0 (~170 s); twin spread in 6 abc_scratch trials; untimed deterministic mode ~350 s.

Verification: Named the deterministic switches (SolverMuJoCo deterministic=, CollisionPipeline deterministic=True, wp.config.deterministic). Signature regex fixed to match both message forms.

Scene building and cameras

BLD-01Wrong mass and inertiaMostly unused2 uses

Hand-built body: mass properties are wrong, outside physical bounds, or not what you set

Symptoms

  • Mass properties of a constructed body are implausible or ignored.

Likely causes

  • Wrong closed form: a solid ellipsoid has I_x = m(b^2+c^2)/5; a thin spherical shell has 5/3 of the solid sphere's inertia.
  • Density on overlapping primitives counts the overlap twice.
  • The builder adds shape mass and inertia after you set them unless lock_inertia=True or shapes have zero density.
  • Reading a stale model after a rebuild, or the diagonal of a rotated tensor instead of principal values.

Checks

  • After finalize: model.body_mass, eigenvalues of model.body_inertia, model.body_com; report_solver_params(solver, "body") for compiled values.
  • Ratios to solid and thin-shell inertias of the collider extents.

Repairs

  • builder.add_body(..., mass=, inertia=, com=, lock_inertia=True) with zero-density collision shapes; values well inside the band; re-check after every shape change. Docs: docs/concepts/mass_inertia.rst.

Pitfalls / shortcuts to avoid

  • Tuning inertia to change settling or rolling behaviour.

Scene building and cameras · cards-v1 · 1 attachment signature(s)

Uses in the trials (2 unused)
  • unused v6.4/cube_toss-astra-mcp-cards-v3-p0 (Astra, pass): Mass/inertia printed, but that is the task's own constraint audit.
  • unused v6.5/cube_toss-astra-mcp-cards-v3-p0 (Astra, pass): Mass/inertia check is the task's constraint audit.
Where it came from

30/31 abc_scratch trials wrote inertia by hand; one final failure from a 2.5x formula error.

Verification: No change; inertia formulas and the lock_inertia docstring verified.

BLD-02Seams in compound collidersNever openednever opened

Compound or mesh collider: seams, gaps, wrong radius, flipped faces

Symptoms

  • The collider is not the shape you meant.

Likely causes

  • Strips approximating a curved outline overshoot corners or leave gaps; overlaps at different tilts form steps.
  • Index or sign errors in a generator; reversed triangle winding.
  • MuJoCo convex-hulls non-convex meshes; Mesh(maxhullvert=...) (default 64) drops vertices; separate convex sections leave seams.
  • A new Mesh per world (slow builds); ShapeConfig(density=np.float64(...)) raises the Warp 'mul ... vec3f, float64' error.

Checks

  • World-space corners/vertices of every piece: min/max z and distance outside the outline.
  • Top-down labelled plot or render; drop-probe a grid of small spheres in one batch (rest heights reveal ridges and holes).
  • Signed mesh volume > 0; collider radius at profile stations; shape type MESH vs CONVEX_MESH; build time for 1 vs N worlds.

Repairs

  • Pieces from a polygon clipped to the outline with one continuous top surface.
  • One convex hull of a revolved profile with maxhullvert >= vertex count; overlap sections so no edge is exposed where contacts happen.
  • Build each Mesh once and reuse it; cast config scalars with float().

Pitfalls / shortcuts to avoid

  • Tuning materials to hide a seam or gap.

Scene building and cameras · cards-v1

Where it came from

Multi-piece support defects in 8 abc_scratch trials (15-640 s); profiled collider issues in 5 abc_bin trials (70-250 s).

Verification: float64 density corrected from 'slow build' to the reproduced Warp 'mul ... vec3f, float64' error, added as a symptom. maxhullvert default 64 stated.

BLD-03Camera calibration conventionsNever openednever opened

Calibrated camera: projected points miss the photo, or pixel-to-world placement is off

Symptoms

  • Image-derived geometry disagrees with known robot or fixture positions.

Likely causes

  • Frame conventions: Newton cameras look along local -Z with +Y up; an OpenCV optical frame is that frame rotated 180 deg about X; xyzw quaternions.
  • Distortion direction (RealSense inverse Brown-Conrady maps distorted pixels to rays; OpenCV the opposite) and coefficient order (k1, k2, p1, p2, k3).
  • A silhouette edge (object top, rim) unprojected onto the table plane; frame/sample index offsets.

Checks

  • Project known world points (robot base frames, FK of measured joints, fixtures) into the photo; a few pixels of error means a convention bug.
  • Round trip pixel -> ray -> plane -> pixel within ~0.5 px.
  • Render through the same intrinsics and overlay.

Repairs

  • newton.sensors.SensorCamera.Intrinsics.from_camera_matrix(K, D, width=, height=, distortion_model=...), then project, unproject, unproject_to_plane, compute_camera_rays.
  • Unproject each feature at its own height; keep a known-point validation in the analysis script.
  • Fit the camera pose from keypoints by least squares before any render-loss refinement.

Pitfalls / shortcuts to avoid

  • Adjusting focal length to absorb a pose error; pixel coordinates read by eye; trusting two fits made by the same method because they agree.

Scene building and cameras · cards-v1

Where it came from

Hand-written distortion code in 29/31 abc_scratch and 8/8 abc_twin; Intrinsics used 11/11 when named vs 0/11 when not; self-consistent wrong outline caused a final failure.

Verification: No change; Intrinsics API and camera frame conventions verified.

BLD-04Render visibility and colourNever openednever opened

Camera render: a shape is missing, visibility edits change nothing, or colours are off by a gamma

Symptoms

  • The render does not reflect the model you edited, or colours fit poorly.

Likely causes

  • Importers carry an rgba alpha of 0 into shape_opacity; collision-only shapes lack ShapeFlags.VISIBLE.
  • The camera's shape BVH and enabled set are built at finalize; later flag, opacity or mesh edits are ignored until model.bvh_build_shapes(state); poses need model.bvh_refit_shapes(state).
  • Back-face culling is on by default.
  • shape_color is sRGB while shading and HDR output are linear; textures must be RGBA uint8 and RenderConfig.enable_textures is off by default.

Checks

  • Shape-index image (create_shape_index_image_output) at the expected pixels.
  • model.shape_opacity, model.shape_flags & VISIBLE, and whether the index is among the first model.bvh_shape_count_enabled entries of model.bvh_shape_enabled.
  • Render with SensorCamera.RenderConfig(enable_backface_culling=False); the albedo output (create_albedo_image_output) should equal round(255*shape_color), as should a flat patch with ambient (1,1,1) and no lights.

Repairs

  • Set opacity and flags in the builder, or call bvh_build_shapes after edits; wind triangles counter-clockwise from outside.
  • Fit colours in linear light with per-shape masks in a closed loop (2-3 damped iterations), then convert with newton.utils.color_linear_to_srgb / color_srgb_to_linear rather than hand-written formulas.

Pitfalls / shortcuts to avoid

  • Judging colours by eye; changing light intensity to fix a colour-space error.

Scene building and cameras · cards-v1 · 1 attachment signature(s)

Where it came from

Visibility episodes in 5/8 abc_twin; texture errors in 2 (120-150 s each); sRGB conversions hand-written in 17/17 visual trials.

Verification: Culling setting placed on SensorCamera.RenderConfig. Added the albedo-output check and the public sRGB conversion helpers.

BLD-05Edits must reach collision geometryDecisive10 decisive · 10 uses

Geometry edits (SDF, mesh) do not reach collision or rendering; probing contacts at a pose

Symptoms

  • Geometry changes do not show up where they should.

Likely causes

  • Collision samples the SDF data the model holds. A texture SDF from Mesh.build_sdf has a coarse grid plus fine bricks only in a narrow band; cells without fine data cannot be edited at fine resolution. Edits to a copy, or a rebuilt SDF that is not registered, do not reach collision.
  • The rendered surface is a separately extracted isomesh; cameras only draw VISIBLE model shapes.
  • Subtracting only the tool's current pose leaves material between frames; editing one level only.

Checks

  • Identity (is) between the SDF data the model references and the object you edit.
  • Sample before and after at known inside/outside points with the sampler collision uses.
  • Collide-only probe: set the pose in a state, pipeline.collide(state, contacts), then newton.eval_rigid_contact_kinematics or a load sum; restore; compare with a fresh model.
  • Removed volume by grid sampling vs the analytic swept volume.

Repairs

  • Edit in place on both levels; there is no public edit API, so isolate private-field access in one helper and prefer a public API if your version has one.
  • Subtract the swept volume between consecutive poses; widen the band beforehand if edits go deeper; SDF.extract_isomesh() after edits; keep construction unedited.

Pitfalls / shortcuts to avoid

  • Editing the render mesh; notify or pipeline rebuilds for in-place texture edits.

Scene building and cameras · cards-v1

Uses in the trials (10 decisive)
  • decisive v6.1/sdf_grind-luna-mcp-cards-v1-p0 (Luna, pass): 42-51 s: ran the card's identity check: 'The debug-card identity check passes: the mesh's attached SDF is the exact object being edited, and the model's coarse and fine texture handles are those same textures'. 294 s: 'added an in-place Boolean SDF subtraction over each frame's swept wheel segment, updating both' levels. Passed first full check (removed-volume error 1.9%).
  • decisive v6.2/sdf_grind-luna-mcp-cards-v2-p0 (Luna, pass): 13-35 s ran the card's identity check (model textures 'is' the workpiece textures) and collide-only probe (43 contacts, 15.4 kN); 259 s in-place subtraction of the swept segment on coarse + fine subgrids (card repair); 346 s probe shows groove cleared. Read via glob 'BLD-05*.md', not logged in card_usage.json.
  • decisive v6.3/sdf_grind-luna-mcp-cards-v3-p0 (Luna, pass): 15 s: 'checking whether the live collision model holds that same SDF object and how its coarse and fine texture levels are represented before choosing the in-place edit' (its identity check); final: 'subtracts the wheel's swept volume from both SDF texture levels used by collision, then refreshes the rendered surface'.
  • decisive v6.3/sdf_grind-luna-mcp-cards-v3-p1 (Luna, pass): Read via a BLD-05* glob that card_usage.json missed. 20 s: 'The BLD-05 card points to two requirements here: edit the same texture SDF object the model collides against, and subtract the entire swept volume between frames'; 245-302 s in-place swept-cylinder subtraction, isomesh refreshed.
  • decisive v6.4/sdf_grind-astra-mcp-cards-v3-p0 (Astra, pass): 19s 'Card BLD-05 confirms that removal must update both levels of the sparse SDF in place, then re-extract the visible surface. I'll also subtract the volume swept between wheel poses'; 33s identity checks; 62s collide-only probe.
  • decisive v6.4/sdf_grind-opus-mcp-cards-v3-p0 (Opus, pass): Final design is the card's repair: 'copies the SDF's two textures (fine and coarse)... subtracts the volume the wheel swept since the previous frame... confirmed the model uses those same texture objects (checked with `is`)... all access to private fields stays inside that class'; isomesh re-extracted.
  • decisive v6.4/sdf_grind-sol-mcp-cards-v3-p0 (Sol, pass): 24s: 'collision reads those textures directly. I'll update both levels in place from the wheel's swept segment each frame, then extract the render mesh'. 39s identity check (s._coarse_texture is model._texture_sdf_coarse_textures[0]). 105-143s samples inside/outside points, compares grid volume with the analytic sweep, and runs a collide-only load probe. All are the card's checks and repairs.
  • decisive v6.5/sdf_grind-astra-mcp-cards-v3-p0 (Astra, pass): 15s 'Card BLD-05 identifies the key issue: removal must update both levels of the sparse SDF that collision samples, then regenerate the visible surface'; 19/53s identity checks; final swept-volume subtraction on both levels.
  • decisive v6.5/sdf_grind-opus-mcp-cards-v3-p0 (Opus, pass): Final: helper '_TextureSdfCutter' edits 'the SDF's two storage levels (coarse grid and fine detail blocks)... model and collision pipeline hold those exact texture objects (I confirmed this)... extract_isomesh()... swept shape... no material left behind between frames'.
  • decisive v6.5/sdf_grind-sol-mcp-cards-v3-p0 (Sol, pass): 23s and 47s identity and handle checks between the workpiece SDF textures and model._texture_sdf_*. 64s: 'share the same texture handles, so an in-place texture edit will reach hydroelastic collision. I'm adding a swept-wheel subtraction to both the coarse grid and the fine subgrids, then extracting the render mesh'. 122s collide-only load probe; 150s grid volume vs analytic sweep.
Where it came from

All 10 sdf_grind trials spent about half the trial (first edit at 118-226 s) learning the SDF layout.

Verification: No change; SDF API is experimental and has no edit method.

Contacts and friction

CON-01Contact parameters come from the other shapeDecisive10 decisive · 19 uses

Contact parameters come from the other shape: priority, solmix and max rules

Symptoms

  • A held or resting object sinks into one partner, or slides, although its own material is stiff and rough.
  • Edits to the object's (or support's) material have no effect on that pair.

Likely causes

  • The partner geom has higher mujoco:geom_priority: its solref, solimp, friction and condim alone define the contact.
  • At equal priority, solref/solimp mix by mujoco:geom_solmix (min if a solref is negative); friction (per component) and condim take the larger of the two, so lowering one side does nothing. Both contact paths apply these rules.
  • A soft robot-wide default_shape_cfg was inherited by fingers or feet.

Checks

  • newton.utils.report_solver_params(solver, "geom", select=[...]) (MCP solver_params("geom", ...)): priority, solref, solimp, friction, condim of both sides. URDF shapes may be labelled shape_N: select via model.shape_body.
  • Per-pair values the solver integrates: solver_contacts(select, detail=True) (MCP), or active rows of solver.mjw_data.contact (CON-07).
  • Penetration per pair: report_health(model, state, solver, penetration=d)["penetration"] (pairs deeper than d, default 0.01 m) or MCP contacts_between(a, b).

Repairs

  • Put the intended material on the deciding geom (or equalize priority).
  • Build time: builder.shape_material_ke/kd/mu[i], and mujoco:* custom attributes after SolverMuJoCo.register_custom_attributes(builder). Live: assign model.shape_material_*, then solver.notify_model_changed(newton.ModelFlags.SHAPE_PROPERTIES). Priority and condim are construction-only: rebuild the solver.

Pitfalls / shortcuts to avoid

  • Stiffening the object that loses the priority contest.
  • Raising mu when mu x total normal force already exceeds the load many times.

Contacts and friction · cards-v1 · 1 attachment signature(s)

Uses in the trials (10 decisive · 1 helpful · 8 unused)
  • decisive v6.1/grasp_drift-luna-mcp-cards-v1-p0 (Luna, pass): 375 s: report_solver_params('geom') rows for finger and cube shapes (CON-01 check). 453 s: 'the fingers have higher MuJoCo geom priority than the cube, so their very soft material sets the contact law'. Fix: finger shape_material_ke/kd set to the cube's (the card's 'put the intended material on the deciding geom'). Passed first try.
  • decisive v6.2/grasp_drift-luna-mcp-cards-v2-p0 (Luna, pass): 75 s solver_params('geom') on the finger shapes -> 116.7 s 'finger geoms have priority 1 and therefore impose friction 1.0 and a 0.2 s contact time constant; the cube's ... are not the deciding values' -> 240 s stiffen only the finger contacts (card repair: material on the deciding geom).
  • decisive v6.3/grasp_drift-luna-mcp-cards-v3-p0 (Luna, pass): 168 s: 'the finger geoms are assigned higher MuJoCo contact priority, so they override the cube's stiff contact material'; the fix puts a stiff material on the deciding finger geoms (176 s).
  • decisive v6.3/grasp_drift-luna-mcp-cards-v3-p1 (Luna, pass): 21 s: 'checking ... which shape's material wins for those contacts'; 115 s root cause: 'Finger priority makes that soft response govern the cube contacts'; the fix matches finger ke/kd to the cube (116 s).
  • decisive v6.4/grasp_drift-astra-mcp-cards-v3-p0 (Astra, pass): 14s 'I'm using the Newton debug cards. The finger shapes have higher contact priority than the cube, so they override its stiff material with the robot's much softer defaults' (before any measurement); final fix stiffens only the finger pads. Also auto-attached at 121.7 s.
  • decisive v6.4/grasp_drift-opus-mcp-cards-v3-p0 (Opus, pass): 25-27s solver_params('geom') on pads and cube (card check) shows pad priority 1 with soft solref 0.2; 80s gives pads their own stiff material. Final root cause: 'pads have contact priority 1, so their contact settings alone decide... inherited the robot-wide default'.
  • decisive v6.4/grasp_drift-sol-mcp-cards-v3-p0 (Sol, pass): 20s: 'the material that controls a contact depends on which shape has priority'. 56s: 'The finger geoms have priority over the cube, so their soft contact response controls the pinch'. Fix: the cube's ke/kd on the finger geoms. Root cause reported as stated in the card.
  • decisive v6.5/grasp_drift-astra-mcp-cards-v3-p0 (Astra, pass): 48s 'The finger pads have higher contact priority than the cube, so they override its stiff material with the robot's much softer defaults. I measured about 10.8 mm of penetration'; final pad-only stiffening.
  • decisive v6.5/grasp_drift-opus-mcp-cards-v3-p0 (Opus, pass): 15s solver_params('geom') on pads and cube; 93s pad material ('The pads win the MuJoCo priority contest... alone define the grasp'); final root cause matches the card.
  • decisive v6.5/grasp_drift-sol-mcp-cards-v3-p0 (Sol, pass): Read via 'cat cards/CON-{01,03,04,08,09}.md', which card_usage.json missed, and auto-attached at 43.3s. 41s: 'checking which geometry controls that softness'. 58s assigns finger shape_material_ke/kd plus notify(SHAPE_PROPERTIES), the card's live repair. 72s: 'the fingers have higher contact priority, so their soft material (ke=250, kd=10) overrides the cube's much stiffer material'.
  • helpful v6.1/grasp_drift-haiku-mcp-cards-v1-p0 (Haiku, pass): 140 s: 'According to CON-01 ... The gripper fingers have priority=1, which means their friction takes precedence'. Added mu=2.0 to the finger default (shipped, a secondary change; stiffening was the main fix).
  • unused v6.1/cube_toss-luna-mcp-cards-v1-p0 (Luna, fail): No priority or solmix check. Single cube vs plane, no visible effect.
  • unused v6.3/cube_toss-luna-mcp-cards-v3-p0 (Luna, pass): No priority/solmix check or edit.
  • unused v6.3/cube_toss-luna-mcp-cards-v3-p1 (Luna, pass): No visible use.
  • unused v6.3/g1_hard-luna-mcp-cards-v3-p0 (Luna, fail, attached): Attached on 'higher geom_priority' in a report; no reaction.
  • unused v6.4/cube_toss-astra-mcp-cards-v3-p0 (Astra, pass): solver_params('geom') printed at 34s; no priority issue pursued.
  • unused v6.4/cube_toss-sol-mcp-cards-v3-p0 (Sol, pass): No priority or solmix checks.
  • unused v6.5/cube_toss-astra-mcp-cards-v3-p0 (Astra, pass): No priority issue.
  • unused v6.5/cube_toss-sol-mcp-cards-v3-p0 (Sol, pass): No priority action.
Where it came from

Root cause in 32/32 grasp_drift trials; Opus median 47 s to root cause with per-contact readout vs 128 s from kernels.py; max-rule surprises in 7 abc_scratch trials (10-95 s).

Verification: Added: element-wise min when either solref is negative; priority/solmix/max rules apply on both contact paths (kernels.py:123). The penetration check now notes report_health lists pairs only above the penetration= threshold (default 0.01 m). contacts_between marked MCP-only.

CON-02Contact stiffness and dampingDecisive11 decisive · 24 uses

Contacts too soft, or stiffening does nothing: how shape ke/kd become MuJoCo solref

Symptoms

  • Penetration or rebound is off, and the stiffness you set does not behave like N/m.

Likely causes

  • The mapping depends on model.mujoco.solref_mode and the contact path. Builder shapes default to legacy MJCF_DEFAULT: unit-mass numerics timeconst = 2/kd, dampratio = kd/(2*sqrt(ke)), not N/m. Force-space mode scales by (1-dmax) and body_invweight0, only with Newton contacts (use_mujoco_contacts=False). mujoco.solref is used only in RAW mode.
  • Impedance is acceleration-level: under a fixed push (a grip) one solref sinks a lighter body more; under its own weight the sink is mass-independent.
  • refsafe: a positive timeconst below 2*dt is evaluated as 2*dt; stiffer gains then saturate.

Checks

  • report_solver_params(solver, "geom", select): solref, solimp, solref_mode, pending.
  • Effective N/m at a steady hold: normal force / penetration (MCP contacts_between(a, b)); compiled timeconst vs 2*dt.
  • Mass test, load fixed: sink halves under a fixed push (unchanged under own weight) for legacy contacts; force-space contacts sink by load/ke.

Repairs

  • Pick tau >= 2*dt (a few substeps) and zeta near 1 for resting contact; legacy mapping: kd = 2/tau, ke = (kd/(2*zeta))**2. Verify in the report.
  • Impacts that barely rebound need an overdamped contact (zeta well above 1); bouncy impacts need zeta below 1. Sweep kd over a wide range (an order of magnitude or more each way), batched together with friction, before changing solvers.
  • Stiffer than 2*dt allows: reduce dt; direct-format negative solref bypasses refsafe (test stability).
  • For impacts, set the damping ratio from the measured rebound ratio (rebound energy falls as zeta rises).

Pitfalls / shortcuts to avoid

  • shape_material_restitution is not read by SolverMuJoCo.
  • Re-deriving the mapping from kernels.py: see docs/solvers/mujoco.rst (Contact solref conversion) and docs/concepts/simulation_tuning_mujoco.rst.

Contacts and friction · cards-v1 · changed: cards-v2: overdamped contacts for impacts that barely rebound · 1 attachment signature(s)

Uses in the trials (11 decisive · 8 helpful · 5 unused)
  • decisive v6.1/grasp_drift-haiku-mcp-cards-v1-p0 (Haiku, pass): 92 s diagnostic prints the card's mapping, 'Gripper shape kd: 10 -> timeconst = 2/kd = 0.2 s (>> 2*dt ...)'. 95 s: 'root cause: the gripper is 320x softer than the cube'. Then stiffened default_shape_cfg (final ke=2500, kd=100), which fixed the drift (0.10 mm in the TCP frame).
  • decisive v6.2/cube_toss-luna-mcp-cards-v2-p0 (Luna, pass): 268 s grid uses the card's legacy mapping kd=2/tau, ke=(kd/(2*zeta))^2; 650 s tau=5 ms, zeta=0.5 cut orientation 0.97 -> 0.43 rad; final ke=2.5e5, kd=800 (tau 2.5 ms, zeta 0.8). Also auto-attached at 1121.6 s ('deep penetration'), after the fix, with no effect.
  • decisive v6.2/grasp_drift-luna-mcp-cards-v2-p0 (Luna, pass): 240 s 'whose 0.2 s legacy contact time constant lets the pads sink deeply' (tau = 2/kd with kd=10); finger ke/kd 10x: 26.3 -> 2.03 mm.
  • decisive v6.3/cube_toss-luna-mcp-cards-v3-p0 (Luna, pass): 103 s sweep parameterised with its legacy mapping kd=2/tau, ke=(kd/(2*zeta))^2, batched with friction; final tau=2 ms, zeta=1.5 (code comment cites the mapping).
  • decisive v6.3/grasp_drift-haiku-mcp-cards-v3-p0 (Haiku, pass): 141 s: prints compiled geom_solref (0.2 s time constant, its check); 153 s: 'The contact stiffness parameters are too soft'; stiffens the finger default ke/kd, verifies solref and re-tunes the damping ratio 7.07 -> 1.12 (177-202 s).
  • decisive v6.4/cube_toss-astra-mcp-cards-v3-p0 (Astra, pass): 48/59s read mujoco.rst solref-conversion section the card points to; 74-95s batched mu x ke x kd sweep with kd up to 1000-3000; 104s 'Lower friction and stronger contact damping produced the main improvement'.
  • decisive v6.4/cube_toss-opus-mcp-cards-v3-p0 (Opus, pass): 22s ev() parameterizes kd=2/tau, ke=(kd/(2*zeta))**2 (card's legacy mapping); 38s tau x zeta sweep; final tau=2 ms, zeta=2 ('impacts barely rebound'), the card's overdamped-impact repair.
  • decisive v6.4/cube_toss-sol-mcp-cards-v3-p0 (Sol, pass): 53s sweeps kd 5-800 alongside mu; the 88s mu x kd grid up to 3200 finds an overdamped contact (kd 1600) that, with mu 0.2, cuts error from 0.093 to 0.018 m. The card says 'impacts that barely rebound need an overdamped contact... sweep kd over a wide range, batched together with friction'. Final: mu 0.18, kd 1600.
  • decisive v6.5/cube_toss-astra-mcp-cards-v3-p0 (Astra, pass): 42s 'sweeping friction and impact damping over a broad range' (card repair: sweep kd an order of magnitude each way, batched with friction); 58s read the solref section; 137s 'much better fit with sliding friction near 0.18 and substantially stronger impact damping'; final kd 1000.
  • decisive v6.5/cube_toss-opus-mcp-cards-v3-p0 (Opus, pass): 17s P() maps tau/zeta to kd=2/tau, ke=(kd/(2*zeta))**2; final ke/kd 'mean a 2 ms contact time constant and a damping ratio of 1.5... starter's 20 ms constant gave soft, deep impacts'.
  • decisive v6.5/cube_toss-sol-mcp-cards-v3-p0 (Sol, pass): 94s sweeps mu x tau x zeta using the card's legacy mapping kd=2/tau, ke=(1/(tau*zeta))**2; the best region is an overdamped short contact. The final PARAMS comment reads 'tau=2 ms, zeta=2' (ke 6.25e4, kd 1000, mu 0.18).
  • helpful v6.1/cube_toss-luna-mcp-cards-v1-p0 (Luna, fail): 479 s: swept ke at fixed kd ('normal contact damping ... keeping its time constant fixed'), using the card's ke/kd->solref mapping. It kept the nominal 20 ms time constant and never tried the shorter tau that the impacts needed.
  • helpful v6.1/grasp_drift-luna-mcp-cards-v1-p0 (Luna, pass): Read right before the diagnosis. Used to interpret the compiled finger solref '(0.2 s, 0.316)' and to verify '(0.0025 s, 1.414)' after the fix (534 s).
  • helpful v6.3/cube_toss-luna-mcp-cards-v3-p1 (Luna, pass): 124 s: kd swept 200-3200 jointly with mu (wide range, batched with friction), reaching the strongly damped kd=800.
  • helpful v6.3/grasp_drift-luna-mcp-cards-v3-p0 (Luna, pass): 168 s: compares compiled time constants (0.2 s fingers vs 0.0025 s cube) to quantify the softness.
  • helpful v6.4/grasp_drift-astra-mcp-cards-v3-p0 (Astra, pass): 69s stiffness sweep along the legacy mapping ((250,10)...(250000,1000)); final comment 'legacy MuJoCo solref (0.2, 0.316)... gains give solref (0.002, 1), near the 2*sim_dt stability floor'. Also auto-attached at 23.7 s with the deep-penetration reply.
  • helpful v6.4/grasp_drift-opus-mcp-cards-v3-p0 (Opus, pass): Pad ke=1.6e5, kd=800 chosen as '2.5 ms time constant (just above the solver's 2×dt floor) with critical damping' (card's legacy mapping and refsafe).
  • helpful v6.5/grasp_drift-astra-mcp-cards-v3-p0 (Astra, pass): Final comment 'These gains give MuJoCo solref (0.0025 s, sqrt(2)), above its 2*dt clamp' (card mapping/refsafe).
  • helpful v6.5/grasp_drift-opus-mcp-cards-v3-p0 (Opus, pass): 93s code comment 'Legacy solref mapping: timeconst = 2/kd, dampratio = kd/(2*sqrt(ke))'; pads set to 4 ms, zeta 1.
  • unused v6.3/cube_toss-haiku-mcp-cards-v3-p0 (Haiku, pass): No citation or mapping check; 138-141 s continues its pre-card 'very stiff, very damped' + more-substeps sweep (sweep2 at 103 s predates the read) to ke=1e5, kd=3000, 100 substeps.
  • unused v6.3/g1_hard-luna-mcp-cards-v3-p0 (Luna, fail): No contact-stiffness change.
  • unused v6.3/g1_hard-luna-mcp-cards-v3-p1 (Luna, fail, attached): Attached on 'deep penetration (> 10 mm)'; no contact change; 115 s raises servo bandwidth instead.
  • unused v6.4/grasp_drift-sol-mcp-cards-v3-p0 (Sol, pass): The finger ke=8e4/kd=8e2 were copied from the cube's existing material, not derived from the solref mapping.
  • unused v6.5/grasp_drift-sol-mcp-cards-v3-p0 (Sol, pass): Read via 'cat cards/CON-{02,07}.md' (not logged). The fix copies the cube's ke/kd onto the fingers; no solref reasoning.
Where it came from

Mapping re-derived from kernels.py in 16/22 cube_toss trials and ~892 s over grasp_drift restart trials; mass normalization diagnosed in 5 replay trials (150-300 s); >=21/24 replay finals stiffened contacts.

Verification: Mass claim corrected using a CPU test: the default (legacy) sink is mass-independent under the body's own weight and halves only under a fixed push; force-space contacts sink by load/ke. Builder shapes default to the legacy MJCF_DEFAULT mode. Mass test and symptom rewritten; contacts_between marked MCP-only.

CON-03Slow creep is a friction floorMostly unused12 uses

A firmly held object creeps slowly and no contact parameter moves it

Symptoms

  • A stiff grasp still slides along the pads at a constant slow rate; no rotation, fingers fixed to the hand.

Likely causes

  • Discretization floor of soft friction: friction rows act on velocity with a reference time constant clamped to 2*dt (refsafe), so slip scales with dt; it is not Coulomb slip.
  • kf (read only with Newton contacts and the elliptic cone) saturates at the same clamp.
  • Rule out CON-01 and CON-07 first.

Checks

  • Friction budget: mu x total normal force >> m(g+a).
  • One batched one-at-a-time table: mu x2, kf x10 (where read), impratio x4, iterations x5, ke x4, dt/2. Only dt moves the creep: this card.
  • Active rows of solver.mjw_data.contact: solreffriction (or solref where it is 0) below 2*dt means the clamp is active.

Repairs

  • More substeps if dt may change; keep the elliptic cone (CON-04).
  • Empirical: lowering solimp dmin/dmax on the deciding geom in small steps reduced creep, at the cost of penetration and a cliff where the grip is lost.
  • Otherwise report the residual and stop (harness lesson L02).

Pitfalls / shortcuts to avoid

  • noslip: no SolverMuJoCo option; MuJoCo Warp raises NotImplementedError: noslip solver not implemented.
  • Switching integrator: rk4 was worse and euler no better than implicitfast wherever tried.
  • Collision every substep helps only with deep or soft contacts; ablate it.

Contacts and friction · cards-v1 · 1 attachment signature(s)

Uses in the trials (3 helpful · 9 unused)
  • helpful v6.2/grasp_drift-luna-mcp-cards-v2-p0 (Luna, pass): Next read at 13 s was CON-01 (CON-03: 'Rule out CON-01 and CON-07 first'); 24 s plan checks contact materials before the creep hypothesis, which was never needed.
  • helpful v6.4/grasp_drift-opus-mcp-cards-v3-p0 (Opus, pass): 174s 'ke/kd/mu no longer matter (creep floor)'; 391s solimp sweep (card's empirical repair); final cites 'debug card CON-03'; pad solimp (0.3,0.6) cut 10 cm drift from 2.0 to 0.42 mm (margin only: 2.0 mm already passed).
  • helpful v6.5/grasp_drift-opus-mcp-cards-v3-p0 (Opus, pass): Final: 'remaining slow, linear creep is the soft-friction floor described in debug card CON-03. Only solimp dmax moved it'; dmax 0.6 gives 0.42 mm (margin; 2.0 mm already passed).
  • unused v6.1/grasp_drift-haiku-mcp-cards-v1-p0 (Haiku, pass): Read 'for slow creeping' then moved straight to CON-02. No creep/dt checks.
  • unused v6.1/grasp_drift-luna-mcp-cards-v1-p0 (Luna, pass): No creep/dt table or noslip discussion.
  • unused v6.2/grasp_drift-haiku-mcp-cards-v2-p0 (Haiku, fail): No friction budget or batched one-at-a-time table; creep never examined.
  • unused v6.3/grasp_drift-haiku-mcp-cards-v3-p0 (Haiku, pass): No visible use.
  • unused v6.3/grasp_drift-luna-mcp-cards-v3-p1 (Luna, pass): No visible use.
  • unused v6.4/grasp_drift-astra-mcp-cards-v3-p0 (Astra, pass): Stopped at 0.32/2.0 mm; no creep work.
  • unused v6.4/grasp_drift-sol-mcp-cards-v3-p0 (Sol, pass): No dt or creep table; the starter's solimp was left unchanged.
  • unused v6.5/grasp_drift-astra-mcp-cards-v3-p0 (Astra, pass): Stopped at 0.33/2.01 mm.
  • unused v6.5/grasp_drift-sol-mcp-cards-v3-p0 (Sol, pass): No action (brace-expanded read, not logged in card_usage.json).
Where it came from

18/18 Opus grasp_drift trials hunted it after passing (median ~440 s, ~8.4 ks total, one gain); noslip searched in 23/32; rk4 worse 6/6; creep halved with dt (i4/grasp_drift-opus-restart-p0 L392-L421).

Verification: kf is read only with Newton contacts plus the elliptic cone. The solreffriction check falls back to solref when solreffriction is 0. Exact noslip message quoted. Solimp repair marked empirical; integrator remark softened to an observation.

CON-04Slip: friction cone and impratioHelpful14 uses

Held object rotates or slips during motion: friction cone and impratio

Symptoms

  • In-hand rotation or slip under acceleration; a tail of copies drop the object.

Likely causes

  • SolverMuJoCo uses Newton's default cone (pyramidal) and MuJoCo's default impratio (1.0) unless the constructor or model.mujoco sets them. Pyramidal cones with soft friction rows slip more.
  • Changing the cone changes the soft-contact model, not only the solver.
  • No torsional friction about the grip axis (condim 3 on the deciding geom, CON-05), or too little normal force (CON-09).

Checks

  • report_solver_params(solver, "option"): cone and impratio (compiled as opt.impratio_invsqrt).
  • A/B as separate models in one batch: cone="elliptic" with a moderate impratio vs pyramidal, all else fixed; measure slip and rotation in the pad frame.

Repairs

  • SolverMuJoCo(model, cone="elliptic", impratio=...) for grasps; options are construction-time, so rebuild.
  • Re-run any low-friction negative control after switching (CON-10).
  • Use pyramidal only for cost or convergence reasons, and then re-validate holds.

Pitfalls / shortcuts to avoid

  • Raising mu while the friction budget is already large (see CON-03).
  • Assuming either cone is always more stable: compare at fixed dt.

Contacts and friction · cards-v1

Uses in the trials (7 helpful · 7 unused)
  • helpful v6.1/cube_toss-luna-mcp-cards-v1-p0 (Luna, fail): 570-711 s: 'Following CON-04, added model-backed cone/impratio settings ... pyramidal cone worsened ... keep elliptic'; impratio 1-20 had no effect. Ruled out the cause (about 140 s).
  • helpful v6.1/grasp_drift-haiku-mcp-cards-v1-p0 (Haiku, pass): 80 s: 'CON-04 is about slip during motion. The script already uses cone="elliptic" with impratio=50.0'. This ruled out cone/impratio.
  • helpful v6.1/grasp_drift-luna-mcp-cards-v1-p0 (Luna, pass): 174 s: 'The symptom matches ... CON-04; this model already selects an elliptic friction cone and high impratio, so I'm measuring actual in-hand drift'. This ruled out cone/impratio.
  • helpful v6.2/grasp_drift-luna-mcp-cards-v2-p0 (Luna, pass): 24.2 s 'already uses an elliptic cone with impratio=50, so the basic CON-04 repair is present' (ruled out).
  • helpful v6.3/grasp_drift-luna-mcp-cards-v3-p0 (Luna, pass): 15 s solver_params('option'); 28 s: 'starts with an elliptic friction cone and impratio=50, so the common low-friction-cone default is already addressed' (ruled out).
  • helpful v6.3/grasp_drift-luna-mcp-cards-v3-p1 (Luna, pass): 21 s: 'already uses an elliptic friction cone and a high impratio, so the obvious solver defaults are not the failure' (ruled out).
  • helpful v6.5/grasp_drift-opus-mcp-cards-v3-p0 (Opus, pass): 159-193s added condim-4/torsional and impratio-200 knobs (card's 'no torsional friction about the grip axis', impratio): no effect, cause ruled out (~35 s).
  • unused v6.2/grasp_drift-haiku-mcp-cards-v2-p0 (Haiku, fail): No cone/impratio check (the scene is already elliptic with impratio 50); next actions inspected gripper joint values.
  • unused v6.3/grasp_drift-haiku-mcp-cards-v3-p0 (Haiku, pass): 118 s: tried to print solver.cone_type/impratio (its check), got an AttributeError and dropped it.
  • unused v6.4/grasp_drift-astra-mcp-cards-v3-p0 (Astra, pass): Cone/impratio untouched.
  • unused v6.4/grasp_drift-opus-mcp-cards-v3-p0 (Opus, pass): Impratio 200/5 tried at 228s, but as part of CON-03's one-at-a-time table; no cone change.
  • unused v6.4/grasp_drift-sol-mcp-cards-v3-p0 (Sol, pass): The starter already used an elliptic cone (impratio 50); not touched.
  • unused v6.5/grasp_drift-astra-mcp-cards-v3-p0 (Astra, pass): Cone/impratio untouched.
  • unused v6.5/grasp_drift-sol-mcp-cards-v3-p0 (Sol, pass): No action (brace-expanded read, not logged in card_usage.json).
Where it came from

Pyramidal increased slip 1.3-3x in 11/11 grasp_drift trials that measured it (3 over limit); 23/24 replay finals elliptic, the exception failed.

Verification: No change. Verified defaults (pyramidal cone, impratio 1.0), the constructor arguments, and that options are construction-only.

CON-05Torsional and rolling frictionMostly unused11 uses

Torsional or rolling friction does nothing; released objects keep rolling

Symptoms

  • Spin or roll resistance edits are ignored, or released objects roll freely.

Likely causes

  • condim 3 (default) has only sliding friction; 4 adds torsional, 6 adds rolling. A contact takes condim from the higher-priority geom, else the larger of the two.
  • condim and priority are read only at construction; live edits are ignored, and writing mjw_model.geom_condim breaks the solve.
  • Torsional/rolling friction resists spin and roll, not translation.
  • MuJoCo Warp warns at construction when a condim-6 geom has a friction component below 1e-5. Contacts clamp each component to at least 1e-5, but tiny coefficients with condim 6 (and the pyramidal cone) can still go NaN (CON-11).

Checks

  • report_solver_params(solver, "geom"): condim, priority, friction_inactive.
  • Per contact: solver.mjw_data.contact.dim and the 5-component friction.
  • Object velocity right after release (a moving release looks like rolling, see FIT-04).

Repairs

  • Set custom_attributes={"mujoco:condim": 6} (or 4) at build time on the deciding geoms, keep torsional/rolling friction >= 1e-5, rebuild the solver.

Pitfalls / shortcuts to avoid

  • Adding condim to fix linear slip.
  • Live writes to compiled condim.

Contacts and friction · cards-v1 · 2 attachment signature(s)

Uses in the trials (3 helpful · 8 unused)
  • helpful v6.1/cube_toss-luna-mcp-cards-v1-p0 (Luna, fail): 360-450 s: 'Contact report confirms default condim=3 leaves the measured material's torsional and rolling friction inactive'. Added mujoco:condim 6 and tested extremes, which ruled out torsional/rolling friction (worse full-set score); about 2 min.
  • helpful v6.3/cube_toss-luna-mcp-cards-v3-p0 (Luna, pass): 139 s: 'torsional and rolling friction are inactive because the model uses MuJoCo condim=3'; condim 6 kept in the final model; auto-attached again at 345 s on the 'condim leaves out' warning, after which the table plane was set to condim 6 too (361-382 s).
  • helpful v6.5/cube_toss-sol-mcp-cards-v3-p0 (Sol, pass): Also auto-attached at 381s. After the pass was saved, it tested condim 4/6 with torsional/rolling friction against orientation error (295-395s, about 100 s). 431s: 'changed the scores only slightly, so I kept the simpler contact setup'. This ruled out a cause.
  • unused v6.2/cube_toss-haiku-mcp-cards-v2-p0 (Haiku, pass, attached): Attached to the condim warning from a mu_rolling=0.001 probe; never opened, condim unchanged; at 78 s it moved on to verifying mu=0.2, kd=1000.
  • unused v6.2/cube_toss-luna-mcp-cards-v2-p0 (Luna, pass): Auto-attached at 335.4 s; the condim-6 test was already planned at 284/321 s, the 385 s condim sweep gave no position gain and the final keeps condim 3 (the ~170 s condim detour, 284-456 s, predates the card).
  • unused v6.4/cube_toss-astra-mcp-cards-v3-p0 (Astra, pass): Torsional/rolling friction left at defaults.
  • unused v6.4/cube_toss-opus-mcp-cards-v3-p0 (Opus, pass, attached): Attached to the condim warning during a mu_torsional sweep; card('CON-05') never opened. Final 'torsional and rolling friction: no effect, because the solver ignores them' restates the warning text itself.
  • unused v6.4/cube_toss-sol-mcp-cards-v3-p0 (Sol, pass): No condim, torsional or rolling friction action.
  • unused v6.4/grasp_drift-opus-mcp-cards-v3-p0 (Opus, pass): No condim/torsional change.
  • unused v6.5/cube_toss-opus-mcp-cards-v3-p0 (Opus, pass, attached): Attached to the condim warning after a mu_torsional/mu_rolling sweep; not opened. Final 'torsional and rolling friction have no effect, because... condim 3 ignores them' comes from the warning text.
  • unused v6.5/grasp_drift-astra-mcp-cards-v3-p0 (Astra, pass): No condim change.
Where it came from

No effect on linear creep in 6 grasp_drift trials; condim-3 rolling in 7 abc_scratch trials; condim 6 in 16/24 replay finals; condim warning in 8 trials (corpus).

Verification: Exact reproduced warning strings. The MJ_MINMU warning comes from MuJoCo Warp put_model; contacts already clamp friction to at least 1e-5, so the NaN risk is described via CON-11 rather than as a hard threshold.

CON-06Missing contactsHelpful2 uses

Expected contacts are missing: objects pass through, fall through, launch, or one world misbehaves

Symptoms

  • Contacts you expect are absent or dropped; identical worlds behave differently.

Likely causes

  • Large detection gap: ShapeConfig.gap=None falls back to builder.rigid_gap (0.1 m default) and a pair's gap is the sum of both shapes' gaps, so nearby pieces overflow the buffers.
  • nconmax/njmax too low (set by hand or sized from the initial state). nconmax is per world, but all worlds share one buffer of nconmax x world_count contacts; njmax limits each world.
  • Filtered pairs: collision group 0 collides with nothing, equal negative groups never collide with each other, shapes without ShapeFlags.COLLIDE_SHAPES, explicit filter pairs, shapes on one body.

Checks

  • report_health(model, state, solver) (MCP: health()): stats["overflow_counts"], newton_contact_overflow, contacts_lost_per_world, affected worlds.
  • Gap per shape (model.shape_gap, report gap column); count contacts at rest before and after cutting the gap.
  • model.shape_collision_group and model.shape_flags of the new shapes; apply the group rule to each pair.

Repairs

  • A gap of a few mm on small shapes (above the per-step travel of fast ones); nconmax/njmax with margin for the largest world count; re-check after adding shapes.
  • Give each free body its own negative group, or a positive group shared with its partners.

Pitfalls / shortcuts to avoid

  • Filtering 'warn' or 'Warp' lines out of logs: overflow is printed once per solver.
  • Retuning stiffness or friction for a world that lost its contacts.

Contacts and friction · cards-v1 · 1 attachment signature(s)

Uses in the trials (1 helpful · 1 unused)
  • helpful v6.3/g1_hard-luna-mcp-cards-v3-p0 (Luna, fail): 754 s: 'checking the solver's actual floor contacts'; health() at 761 s showed 12 contacts and no overflow, ruling out missing contacts.
  • unused v6.5/abc_arm-astra-mcp-cards-v3-p0 (Astra, pass, attached): Attached to health() 'MuJoCo contact buffer full: nacon 0 >= naconmax 0' on a contact-free arm; read as a file at 25.4 s, then ignored. No detour.
Where it came from

Overflow in 18/31 abc_scratch trials (18-260 s per episode); shared negative collision group hid object contact ~570 s; overflow messages in 15 trials (corpus).

Verification: Added the current 'constraint overflow in world' message and the full Newton-contacts overflow message; older-build strings labelled. nconmax described precisely (per world, one shared buffer of nconmax x world_count). Gap repair corrected for fast shapes.

CON-07Contact force readoutsMostly unused6 uses

Contact force readouts are zero or implausible, or raw contact rows mislead

Symptoms

  • Force or parameter readouts contradict what the simulation visibly does.

Likely causes

  • mjw_data.cfrc_ext is filled only when MuJoCo's post-constraint RNE runs: force/acceleration sensors, opt.run_rne_postconstraint, or model.request_state_attributes("body_qdd") (or body_parent_f) before creating states.
  • Raw rows include inactive speculative contacts (dist > includemargin, efc_address == -1) and other pairs.
  • Deep penetration creates side or tip contacts with odd normals.

Checks

  • At rest, total vertical contact force should be about m*g.
  • Keep only active rows of the pair of interest; map geoms with solver.mjc_geom_to_newton_shape and model.shape_body; print dist, solref, solimp, friction, dim and the efc force.
  • Prefer the helpers: contacts_between(a, b, detail=True) and solver_contacts(select, detail=True) (MCP), newton.sensors.SensorContact, or solver.update_contacts(contacts, state) with MuJoCo contacts on MuJoCo Warp.

Repairs

  • Read forces through the solver's contact path and sanity-check totals before drawing conclusions.

Pitfalls / shortcuts to avoid

  • Concluding 'the feet are unloaded' from a zero cfrc_ext.

Contacts and friction · cards-v1

Uses in the trials (1 helpful · 5 unused)
  • helpful v6.3/g1_hard-luna-mcp-cards-v3-p0 (Luna, fail): contacts_between on the feet (780 s) showed 47 N and 247 N normal forces; 866 s concludes 'tipping over the planted support points, not the feet sliding'.
  • unused v6.4/grasp_drift-astra-mcp-cards-v3-p0 (Astra, pass): contacts_between readouts are also named in CON-01.
  • unused v6.4/grasp_drift-opus-mcp-cards-v3-p0 (Opus, pass): Readouts via contacts_between, also named in CON-01; no CON-07-specific action.
  • unused v6.4/grasp_drift-sol-mcp-cards-v3-p0 (Sol, pass): The contacts_between/solver_params helpers it used are also named in CON-01. Nothing CON-07-specific (cfrc_ext, inactive rows) was used.
  • unused v6.5/grasp_drift-astra-mcp-cards-v3-p0 (Astra, pass): contacts_between readouts are also named in CON-01.
  • unused v6.5/grasp_drift-sol-mcp-cards-v3-p0 (Sol, pass): Read together with the solver_contacts(detail=True) call it recommends, which CON-01 also names, so it had no separate effect (brace-expanded read, not logged).
Where it came from

Zero cfrc_ext taken at face value in i7/g1_hard-opus-mcp-p0 L430-L474; blended/inactive rows misread in 3 grasp_drift restart trials (~120 s).

Verification: Added model.request_state_attributes("body_qdd") as the way to make cfrc_ext non-zero (reproduced: 0 without, m*g with). update_contacts noted as MuJoCo Warp only.

CON-08Grasp never formsMostly unused9 uses

Fingers close past the object with almost no force: the grasp never forms

Symptoms

  • The grasp never forms; only one pad touches at a time, or none.

Likely causes

  • The hand is not where the real or intended hand is: latency, gravity sag, soft gains (FIT-03). Most common in log replays.
  • Object too small along the closing axis, off the closing line, or pads close above/below its equator.
  • Contacts too compliant (CON-02) or a soft deciding geom (CON-01).
  • Pair missing or filtered (CON-06); pinch force never builds (CON-09).

Checks

  • Pad pose in the object frame at the close command vs the recorded/intended pad pose (FK of measured joints). Centimetre offsets mean tracking.
  • Both pads have active rows at closure: MCP solver_contacts(select), or active rows of solver.mjw_data.contact.
  • Pipeline distance vs geometric overlap from shape transforms; A/B use_mujoco_contacts.
  • Simulated pad-to-pad distance during the hold vs the logged opening; stiffen contacts once as a test: if the shortfall stays, it is geometry.

Repairs

  • Fix arm tracking first; size the gripped dimension from the recorded opening and cross-check with images.
  • Then stiffen contacts in force units and make the force limit bind.

Pitfalls / shortcuts to avoid

  • Raising friction while the normal force is near zero; tuning contacts while the pads close in the wrong place.

Contacts and friction · cards-v1

Uses in the trials (2 helpful · 7 unused)
  • helpful v6.2/grasp_drift-luna-mcp-cards-v2-p0 (Luna, pass): 127-240 s traced both pads with contacts_between(detail=True) (card check: both pads active), finding 12-14 mm penetration and cube rotation.
  • helpful v6.3/grasp_drift-luna-mcp-cards-v3-p1 (Luna, pass): 80-87 s: raw mjw_data.contact rows mapped to shapes; 85 s: 'Raw MuJoCo data confirms cube-finger contacts are being generated ... rather than a missing-collider problem'.
  • unused v6.1/grasp_drift-luna-mcp-cards-v1-p0 (Luna, pass): Only an implicit 'grip slip ... rather than a missed grasp' (373 s). No CON-08 checks.
  • unused v6.2/grasp_drift-haiku-mcp-cards-v2-p0 (Haiku, fail): 96-117 s compared gripper targets with model.joint_q (static initial values) and concluded 'joint limits prevent the gripper from closing'; the wrong conclusion came from reading the model instead of the state, and the card's pad-contact checks were never run.
  • unused v6.3/grasp_drift-luna-mcp-cards-v3-p0 (Luna, pass): No visible use.
  • unused v6.4/grasp_drift-opus-mcp-cards-v3-p0 (Opus, pass): No grasp-geometry check.
  • unused v6.4/grasp_drift-sol-mcp-cards-v3-p0 (Sol, pass): No action.
  • unused v6.5/grasp_drift-opus-mcp-cards-v3-p0 (Opus, pass): No grasp-geometry check.
  • unused v6.5/grasp_drift-sol-mcp-cards-v3-p0 (Sol, pass): No action (brace-expanded read, not logged in card_usage.json).
Where it came from

All 16 abc_replay trials started here (60-680 s to first hold); object size from logged opening in 6 abc_scratch trials (80-250 s).

Verification: solver_contacts marked MCP-only, with a raw mjw_data.contact fallback.

CON-09Grip force limit never bindsHelpful9 uses

Grip force or finger gap is wrong: the force limit never binds, or the finger-mirror equality yields

Symptoms

  • The gripper squeezes with the wrong force, or its fingers are not symmetric under load.

Likely causes

  • A position servo pushes kp*(target-q) - kd*qd; if kp times the remaining error is below the limit, the limit never binds.
  • The limit sits in an array the solver does not read: JOINT_TARGET actuators (MJCF <position> imports) take the joint cap from joint_effort_limit; mujoco.actuator_forcerange applies only with actuator_has_forcerange, at construction.
  • forcelimited without has_forcerange gives range (0, 0): 'invalid force range'.
  • Equality constraints (finger mirror, loop closures) use a soft default solref, so the violation grows with force.

Checks

  • Per-pad normal force (MCP contacts_between(object, pads, detail=True), or SensorContact) vs the limit; kp x (target - q_hold) vs the limit.
  • report_solver_params(solver, "actuator"): compiled gainprm, forcerange, from, joint_actfrcrange.
  • Mirror residual from both finger q; report_solver_params(solver, "equality") for eq_solref.

Repairs

  • Stiff enough servo so the limit saturates, limit = intended force, set where read (joint_effort_limit, or forcerange + has_forcerange + forcelimited at build), rebuild.
  • Stiffen model.mujoco.eq_solref (tau >= 2*dt, zeta ~1), refresh with CONSTRAINT_PROPERTIES.

Pitfalls / shortcuts to avoid

  • Editing actuator_gainprm/forcerange live for JOINT_TARGET actuators; copying gains into actuator attributes 'for consistency' (broke compilation).

Contacts and friction · cards-v1 · 1 attachment signature(s)

Uses in the trials (3 helpful · 6 unused)
  • helpful v6.1/grasp_drift-luna-mcp-cards-v1-p0 (Luna, pass): 426 s: contacts_between('shake_cube','fr3_leftfinger', detail=True), the card's per-pad normal-force check, gave about 7.7 N per pad with 10-11 mm penetration, which fed the 453 s diagnosis.
  • helpful v6.3/grasp_drift-luna-mcp-cards-v3-p0 (Luna, pass): 79 s: 'checking the effective finger contact material and grip loads'; 84-89 s per-pad contacts_between normal force and penetration (its check).
  • helpful v6.3/grasp_drift-luna-mcp-cards-v3-p1 (Luna, pass): 21 s: 'checking whether the fingers actually load the cube symmetrically'; 28 s per-pad contacts_between(detail=True) (its check).
  • unused v6.2/grasp_drift-haiku-mcp-cards-v2-p0 (Haiku, fail): No per-pad force vs limit check.
  • unused v6.2/grasp_drift-luna-mcp-cards-v2-p0 (Luna, pass): Pad normal force (~11 N) was logged but never compared with a force limit; no actuator check.
  • unused v6.4/grasp_drift-opus-mcp-cards-v3-p0 (Opus, pass): Grip force (12 N/pad) read only to confirm the friction budget.
  • unused v6.4/grasp_drift-sol-mcp-cards-v3-p0 (Sol, pass): No action.
  • unused v6.5/grasp_drift-opus-mcp-cards-v3-p0 (Opus, pass): Grip force read only to state 'not too little grip force'.
  • unused v6.5/grasp_drift-sol-mcp-cards-v3-p0 (Sol, pass): No action (brace-expanded read, not logged in card_usage.json).
Where it came from

'invalid force range' in 9 trials (corpus); soft mirror found in one check in the fastest abc_bin trial; eq_solref edited in 10/24 replay trials.

Verification: contacts_between marked MCP-only, with SensorContact as the alternative. Compile error, actuator attributes and report columns verified.

CON-10Negative control still liftsNever openednever opened

A negative control holds: the object lifts with near-zero friction or an open gripper

Symptoms

  • A control that should fail passes, often only in some copies.

Likely causes

  • Squeeze x residual friction exceeds the weight: 2*mu*F >= m*g.
  • Wedging or caging: non-parallel faces, pad bumps, multi-sphere necks, seams between convex pieces; soft contacts let geometry interlock; pads close off the equator.
  • condim 6 torsional/rolling friction still acts; high impratio stiffens friction.
  • A diverged copy is counted as held (CON-11), or the metric measures a different point than the criterion (tipping raises the centre).

Checks

  • Compute 2*mu*F/(m*g) for the control.
  • At lift-off (MCP contacts_between(object, None, detail=True), or SensorContact): normal vs tangential force, carrying shapes, upward normal components (wedge).
  • Run controls on the full jittered ensemble with several seeds, in the same batch as the positive check.
  • Track lowest point and orientation as well as the centre; check state.body_q is finite per copy.

Repairs

  • Stiffen normal contacts; one convex hull where fingers touch; smallest pinch force that still holds nominally; correct object size and grasp height; re-run controls after every geometry, material or solver change.

Pitfalls / shortcuts to avoid

  • Moving the start pose so caging does not happen for your seeds; lowering rolling friction alone.

Contacts and friction · cards-v1

Where it came from

7 replay trials (35-300 s, one verifier failure after 2-copy control tests); >=14 abc_scratch trials (70-1086 s); tipping misread in 5.

Verification: contacts_between marked MCP-only, with SensorContact as the alternative.

CON-11NaN and exploding worldsHelpful6 uses

Some worlds go NaN or explode

Symptoms

  • A subset of worlds diverges while identical-looking worlds are fine.

Likely causes

  • MuJoCo Warp 3.14's Newton solver with the pyramidal cone, condim 6 and near-zero sliding friction (~0.002) returns NaN in the first steps, while MuJoCo C stays finite; CG and the elliptic cone stay finite.
  • Tiny torsional/rolling friction with condim 6 (see the MJ_MINMU warning).
  • Constraint buffer overflow; dropped rows destabilize the step (CON-06).
  • Contacts too stiff for dt, or bodies starting in penetration.

Checks

  • report_health(model, state, solver, per_world=True): non-finite worlds, runaway speed, overflow counts, deepest pairs.
  • Batch A/B as separate models: elliptic vs pyramidal; solver="cg" vs "newton".
  • solver.mjw_data.nefc vs njmax; friction triples vs 1e-5; lowest point at t=0 vs the support.

Repairs

  • Elliptic cone; torsional/rolling >= 1e-5 with condim 6; explicit njmax/nconmax; lower dt or soften the unstable contact; stress-test with a large jittered batch.

Pitfalls / shortcuts to avoid

  • Metrics that count a NaN copy as 'held' or 'placed'.
  • Shipping extra iterations for a once-per-solver linesearch message without an A/B.

Contacts and friction · cards-v1 · 4 attachment signature(s)

Uses in the trials (5 helpful · 1 unused)
  • helpful v6.1/cube_toss-luna-mcp-cards-v1-p0 (Luna, fail): 598-615 s: report_health check per the card. NOTES: 'Following MSG-01/CON-11 ... no health warnings ... the one-off linesearch event did not recur', so it did not ship extra iterations.
  • helpful v6.2/cube_toss-luna-mcp-cards-v2-p0 (Luna, pass): Linesearch-limit warning checked with health() at 146 s; NOTES 'all metrics were finite': ruled out, no iteration change.
  • helpful v6.3/cube_toss-luna-mcp-cards-v3-p0 (Luna, pass): Read for a linesearch-limit warning; ran health() (402 s), which was ok, and made no solver change. Ruled out a problem.
  • helpful v6.4/cube_toss-astra-mcp-cards-v3-p0 (Astra, pass): After the linesearch-limit warning, 151s A/B with ls_iterations=100: same score, ruled out.
  • helpful v6.5/cube_toss-astra-mcp-cards-v3-p0 (Astra, pass): After the linesearch-limit warning, 247s A/B with ls_iterations=100: metric change 1e-7, ruled out.
  • unused v6.5/cube_toss-sol-mcp-cards-v3-p0 (Sol, pass): Linesearch warning left as is; final message does not mention it.
Where it came from

Diverged worlds in 4 replay episodes (190-320 s); NaN metrics or linesearch/non-finite messages in 32 trials (corpus).

Verification: NaN cause tied to the recorded MuJoCo Warp 3.14 repro (Newton solver, pyramidal cone, sliding friction ~0.002); CG and the elliptic cone stay finite. The torsional/rolling claim is softened.

Actuators and control

CTL-01Servo edits have no effectHelpful27 uses

Servo gain or target edits have no, partial or unexpected effect

Symptoms

  • Gain or target changes do not show up in the motion, or a moving reference lags by a constant phase.

Likely causes

  • Gains are compiled at construction and refreshed only by solver.notify_model_changed(newton.ModelFlags.JOINT_DOF_FORCE_PROPERTIES) (or the broader JOINT_DOF_PROPERTIES).
  • JOINT_TARGET actuators (including MJCF <position>/<velocity> imports) read model.joint_target_ke/kd; model.mujoco.actuator_gainprm/biasprm/forcerange are ignored for them.
  • POSITION mode is gainprm=[kp], biasprm=[0,-kp,-kd]: damping pulls toward zero velocity and joint_target_qd is unused (only VELOCITY and POSITION_VELOCITY create a velocity actuator).
  • A reset/restore re-applied old values, or only world 0 was edited (BAT-02).

Checks

  • report_solver_params(solver, "actuator"): compiled gainprm/biasprm, from, pending. Raw: solver.mjw_model.actuator_gainprm/actuator_biasprm via solver.mjc_actuator_to_newton_idx.
  • model.joint_target_mode per DOF; model.mujoco.ctrl_source.
  • One-joint step response at two gains.

Repairs

  • Write joint_target_ke/kd for every world, notify, and re-apply after any reset.
  • Track a moving reference with a POSITION servo via the target offset q* = q_ref + (kd*qd_ref + tau_ff)/kp, or use POSITION_VELOCITY.
  • Read docs/solvers/mujoco.rst: Actuators; Actuator gains and control source; Runtime updates.

Pitfalls / shortcuts to avoid

  • Mirroring gains into actuator_gainprm 'for consistency'; treating writes to solver.mjw_model as a model edit (a later notify or a new solver overwrites them; use them only for per-step gain scheduling you own).

Actuators and control · cards-v1 · 1 attachment signature(s)

Uses in the trials (18 helpful · 8 unused · 1 misleading)
  • helpful v6.1/g1_hard-luna-mcp-cards-v1-p0 (Luna, fail): 803 s: 'adding the documented position-servo velocity offset' (target += kd*qd_ref/kp). Pre-fall joint RMSE went from 0.086 to 0.049; kept in the final.
  • helpful v6.1/g1_track-luna-mcp-cards-v1-p0 (Luna, pass): Exp8 adds 'q_target += (kd/kp)*qdot_ref' (code comment: 'POSITION servos damp toward zero joint velocity, so offset their position targets'), which cut early joint RMSE to about 0.03. Part of the final controller.
  • helpful v6.2/g1_hard-luna-mcp-cards-v2-p0 (Luna, fail): 121 s report_solver_params('actuator') -> 165 s 'servo parameters are reaching SolverMuJoCo and are clamped at the effort limits' (ruled out).
  • helpful v6.2/g1_track-luna-mcp-cards-v2-p0 (Luna, pass): 1121 s reference-velocity feedforward q_ref += (kd/kp)*qd_ref (the card's target-offset law) made the 2x stress playback pass; compiled gains and limits confirmed.
  • helpful v6.3/g1_hard-luna-mcp-cards-v3-p0 (Luna, fail): 394 s: target = q + (tau + kd*qd)/kp (the card's target-offset law) used to deliver the feedforward torques.
  • helpful v6.3/g1_track-luna-mcp-cards-v3-p0 (Luna, pass): 67 s: writes joint_target_ke/kd then solver.notify_model_changed (its repair); 171 s velocity-feedforward target offset, kept in the final controller.
  • helpful v6.3/g1_track-luna-mcp-cards-v3-p1 (Luna, fail): Final step adds target += (kd/kp)*qd_ref (velocity feedforward, the card's target-offset law).
  • helpful v6.4/abc_arm-astra-mcp-cards-v3-p0 (Astra, pass): Gain writes go to joint_target_ke/kd with notify(ModelFlags.JOINT_DOF_FORCE_PROPERTIES|...), the card's route.
  • helpful v6.4/g1_hard-astra-mcp-cards-v3-p0 (Astra, pass): 47-73s gain sweep uses the card's target offset targets += refv*kd/kp.
  • helpful v6.4/g1_hard-sol-mcp-cards-v3-p0 (Sol, pass): 38s gain sweeps use notify_model_changed(JOINT_DOF_FORCE_PROPERTIES). The final step uses target += (tau + kd*qd_ref)/kp, which is CTL-01's offset formula.
  • helpful v6.4/g1_track-astra-mcp-cards-v3-p0 (Astra, pass): 26s 'position servos damp motion toward zero velocity' (card cause); reference-velocity compensation targets += v*kd/kp is in the final controller.
  • helpful v6.4/g1_track-sol-mcp-cards-v3-p0 (Sol, pass): Final target lead is 0.5*(kd/kp)*qd_ref, from CTL-01's q* = q_ref + kd*qd_ref/kp (436s: 'Half compensation for the servo's velocity damping cuts joint error sharply'). The agent cites CTL-01/CTL-02 at 597s. Not needed to pass.
  • helpful v6.5/abc_arm-astra-mcp-cards-v3-p0 (Astra, pass): Gain writes to joint_target_ke/kd with notify(ModelFlags.JOINT_DOF_FORCE_PROPERTIES), the card's route.
  • helpful v6.5/g1_hard-astra-mcp-cards-v3-p0 (Astra, pass): 32s 'servos also damp toward zero velocity, so the current targets omit velocity feedforward'; 73s sweep with targets += kd/kp*v.
  • helpful v6.5/g1_hard-sol-mcp-cards-v3-p0 (Sol, fail): All gain sweeps call notify_model_changed(JOINT_DOF_FORCE_PROPERTIES); 741s compares compiled actuator_gainprm with model gains (card check).
  • helpful v6.5/g1_track-astra-mcp-cards-v3-p0 (Astra, pass): 75-104s sweep and final controller use velocity feed-forward targets (card target offset).
  • helpful v6.5/g1_track-opus-mcp-cards-v3-p0 (Opus, pass): Read before the gain sweep: 26s used ModelFlags.JOINT_DOF_FORCE_PROPERTIES (no SolverNotifyFlags error, unlike the other Opus G1 trials); 75s tried the card's target offset (vff = kd/kp*qd_ref), no gain.
  • helpful v6.5/g1_track-sol-mcp-cards-v3-p0 (Sol, pass): 47-59s checks model gains, the notify method and the JOINT_DOF_FORCE_PROPERTIES flag; every gain sweep then calls notify_model_changed(JOINT_DOF_FORCE_PROPERTIES).
  • unused v6.1/abc_arm-luna-mcp-cards-v1-p0 (Luna, pass): Gains are written at build time in build_model. No notify flags, servo-law offsets or actuator-array checks from the card appear.
  • unused v6.3/abc_arm-luna-mcp-cards-v3-p0 (Luna, pass): Gains set at build time through the starter's build_model; no notify or target-offset use.
  • unused v6.3/grasp_drift-haiku-mcp-cards-v3-p0 (Haiku, pass, attached): Attached because dir(solver) printed 'SolverNotifyFlags' (false match); no effect.
  • unused v6.4/abc_arm-sol-mcp-cards-v3-p0 (Sol, pass): Gains were written per world before the solver was built. No notify call, gain readback or target-offset use followed.
  • unused v6.4/g1_hard-opus-mcp-cards-v3-p0 (Opus, pass, attached): Attached to the SolverNotifyFlags AttributeError; card not opened. 36s switched to newton.ModelFlags.JOINT_DOF_PROPERTIES, which the error text itself names.
  • unused v6.4/g1_track-opus-mcp-cards-v3-p0 (Opus, pass, attached): Attached to the SolverNotifyFlags error; not opened. 23s fixed with newton.ModelFlags as the error text says.
  • unused v6.5/abc_arm-sol-mcp-cards-v3-p0 (Sol, pass): Gains were written before solver construction; no card-specific action.
  • unused v6.5/g1_hard-opus-mcp-cards-v3-p0 (Opus, pass, attached): Attached to the SolverNotifyFlags error; not opened. 22s listed newton.ModelFlags members and moved on (the error text names the fix).
  • misleading v6.3/g1_track-haiku-mcp-cards-v3-p0 (Haiku, fail): 134 s: 'Perfect! I found the issue. The POSITION servo mode needs a velocity offset'; 158 s adds notify_model_changed. The joints only looked frozen because its probe stepped a fresh model.state(). Its report_solver_params check (174 s) then showed correctly compiled gains.
Where it came from

31/80 g1 trials read solver source for the servo law (1/30 once a starter documented it); no-op gain sweeps in replay; SolverNotifyFlags errors in 16 trials.

Verification: Current SolverNotifyFlags error message added, with the old form kept. Servo law, flags and the 'pending' report entry verified.

CTL-02Floating base falls under joint PDDecisive11 decisive · 23 uses

Floating-base robot sags, sways and falls under joint-PD tracking; feedforward is fought by the servo

Symptoms

  • Whole-body sag and an under-damped sway about the ankles; or computed torques that the servo resists.

Likely causes

  • kp sized from rotor armature (a reflected-inertia frequency) rather than gravity load; kd sized the same way leaves the whole-body sway mode under-damped.
  • Very high gains cause contact chatter and foot slip.
  • Feedforward torque realized as a target offset once per control period while the servo's kp*(q*-q) - kd*qd acts every physics step; velocity feedforward missing; the effort limit clips the sum.

Checks

  • Static gravity torque per stance joint (newton.eval_inverse_dynamics_passive, or MuJoCo qfrc_bias at zero velocity) vs kp x tolerable error.
  • Steady-state joint error and solver.mjw_data.actuator_force / limit.
  • Sway period from root pitch; compare kd with body inertia about the ankle axis.
  • Static hold with zero motion; actuator force vs planned torque over one control period.

Repairs

  • kp from load, kd near-critical for the body mode, per joint group; keep effort limits.
  • Gravity/inverse-dynamics feedforward instead of extreme gains or integrators (CTL-04).
  • Recompute target offsets every physics step, including kd*qd_ref; lower servo impedance where feedforward carries the load.

Pitfalls / shortcuts to avoid

  • One global gain sweep; joint integrators in double support.

Actuators and control · cards-v1

Uses in the trials (11 decisive · 11 helpful · 1 misleading)
  • decisive v6.2/g1_hard-luna-mcp-cards-v2-p0 (Luna, fail): 165 s gravity check from the card: 'largest gravity load asks for roughly 0.21 rad of servo error' -> gravity + reference-velocity feedforward with scaled kp/kd (joint RMSE 0.156 -> 0.024 rad in the final).
  • decisive v6.2/g1_track-haiku-mcp-cards-v2-p0 (Haiku, pass): 73 s 'The issue is clear from card CTL-02: the gains are based on actuator inertia rather than gravity load'; 97 s gravity torque / kp check -> 'scale kp by 16.3x'; gains raised at 117 s (snapshot pass at 240 s); final 50 Hz natural frequency (25x kp).
  • decisive v6.2/g1_track-luna-mcp-cards-v2-p0 (Luna, pass): 164 s 'checking compiled servo gains, gravity load'; NOTES 'static bias torque / kp peaks at 0.265 rad' -> kp 10x (KP_SCALE=10 in the final).
  • decisive v6.3/g1_track-luna-mcp-cards-v3-p0 (Luna, pass): 21 s: 'controller gains are very low: they were derived from reflected armature inertia, which matches the failure pattern in CTL-02'; 146 s gravity torques via eval_inverse_dynamics_passive (its check); final = 20 Hz servos + reference velocity compensation + ankle balance.
  • decisive v6.3/g1_track-luna-mcp-cards-v3-p1 (Luna, fail): 36 s: 'existing gains are scaled from reflected armature alone, which the debug card flags as too weak for whole-body gravity loads'; KP_SCALE=10 in the final controller.
  • decisive v6.4/g1_track-astra-mcp-cards-v3-p0 (Astra, pass): 26s 'Its gains are based on motor armature, which underestimates the load carried by the legs' (card cause); final 'stronger stance gains'.
  • decisive v6.4/g1_track-opus-mcp-cards-v3-p0 (Opus, pass): 23-66s gain sweep from 10 Hz up; final 'Cause: the servos were too soft. Their stiffness was set from rotor armature at 10 Hz... sagged under body weight' (card cause); '>~90 Hz the stiff servos chatter against the ground' (card: high gains cause chatter).
  • decisive v6.4/g1_track-sol-mcp-cards-v3-p0 (Sol, pass): 41s: 'the card points out that the current gains are sized from armature, which can leave the whole-body sway mode underdamped'. A wide gain sweep followed (stable from 12x); final kp is 20x and kd 12x the armature-based values.
  • decisive v6.5/g1_hard-astra-mcp-cards-v3-p0 (Astra, pass): 303s 'Reducing servo stiffness was important—the stronger servos were fighting the computed torque between updates' (card: feedforward fought by the servo; lower servo impedance); final kp=10, kd=0.1.
  • decisive v6.5/g1_track-astra-mcp-cards-v3-p0 (Astra, pass): 18s 'Its floating-base tracking card points to two likely causes: gains sized from motor inertia...'; 46s gravity qfrc_bias check (card check); final 'stronger, damped servos'.
  • decisive v6.5/g1_track-opus-mcp-cards-v3-p0 (Opus, pass): Final 'Cause: the servo gains were set from the motor armature alone (a 10 Hz frequency)... far too soft to hold up the robot's weight'; fix 50 Hz, zeta 3. Notes foot slip at stiffer settings (card pitfall).
  • helpful v6.1/g1_hard-luna-mcp-cards-v1-p0 (Luna, fail): Gravity-torque check via eval_inverse_dynamics_passive (346 s). 449 s: 'Static gravity torques at the starting pose are modest'. A 25 Hz gain raise (kept for legs and waist) ruled out sag and torque headroom as the high5 cause.
  • helpful v6.1/g1_track-luna-mcp-cards-v1-p0 (Luna, pass): 39 s: 'position servos sized only from reflected rotor inertia can leave the body unsupported'. Exp1 raised 10 to 20 Hz (final 22 Hz); Exp2 gravity feedforward via eval_inverse_dynamics_passive did not help and was removed (about 25 s). Gains alone at 20 Hz still fell.
  • helpful v6.2/g1_hard-haiku-mcp-cards-v2-p0 (Haiku, fail): 41.5 s 'gains are sized from actuator inertia rather than gravity load, and there's no gravity feedforward' (card cause); feedforward tried and reverted at 158-171 s; final uniform kp=1000, kd=50 (353 s) contradicts the card's repair (load-sized gains, feedforward instead of extreme gains). wave passes, high5 falls.
  • helpful v6.3/g1_hard-luna-mcp-cards-v3-p0 (Luna, fail): Read via a CTL-02* glob that card_usage.json missed. 91 s: adds reference inverse-dynamics torques 'as servo target offsets, including velocity compensation'; kept in final ('reference velocity and gravity compensation'). Enough for wave, not for high5.
  • helpful v6.3/g1_hard-luna-mcp-cards-v3-p1 (Luna, fail): 227 s: 'express the computed joint torques as servo target offsets'; 616 s adds reference-velocity feedforward 'to cancel the damping lag' (the card's 'velocity feedforward missing').
  • helpful v6.4/g1_hard-astra-mcp-cards-v3-p0 (Astra, pass): QP torques sent as target offsets through low-impedance servos (kp=20, kd=2) refreshed every 2 substeps (card: feedforward via offsets, lower servo impedance).
  • helpful v6.4/g1_hard-opus-mcp-cards-v3-p0 (Opus, pass): 33-39s raised servo gains (x3/10/30 of the armature-based starter); x30 gains kept in the final controller, but stiffness alone still fell.
  • helpful v6.4/g1_hard-sol-mcp-cards-v3-p0 (Sol, pass): 8s: 'sends reference joint angles to position servos with no root or contact feedback... gain tuning alone may leave the base drifting'. The final controller applies ID torque through servo target offsets that include kd*qd_ref (card repair). It also ran a global gain sweep (card pitfall) and kept 16x armature-sized gains.
  • helpful v6.5/g1_hard-opus-mcp-cards-v3-p0 (Opus, pass): 19-28s stiff gains tried first ('Stiff gains alone still fall'); 341-353s torque-saturation check ('No saturation'); final gain scale 42.
  • helpful v6.5/g1_hard-sol-mcp-cards-v3-p0 (Sol, fail): 35s: 'the current gains are based on motor inertia and may be too weak for the body load' (card cause), followed by gain sweeps. Final gains: legs 16x, arms 6.5x armature-sized. No feedforward was shipped.
  • helpful v6.5/g1_track-sol-mcp-cards-v3-p0 (Sol, pass): 44s: 'checking servo gain and velocity tracking first'; 113-129s CoM over ankles, qfrc_bias and actuator_force checks. The sweep stopped at 8x, and 171s concluded 'Gain changes alone did not stop the fall' (v6.4 shows 12x or more suffices). Final kp 5x, kd 4x.
  • misleading v6.3/g1_track-haiku-mcp-cards-v3-p0 (Haiku, fail): Seen only as a cards() search hit. 273 s: 'Looking at the CTL-02 debug card, I realize the issue might be gravity'; adds gravity feedforward against the same measurement artifact, removed again at 423-431 s.
Where it came from

All 50 g1_track/g1_hard trials started here (30-120 s); servo-fights-feedforward in 5/8 Astra g1_hard trials (60-120 s).

Verification: No change; API names verified (eval_inverse_dynamics_passive, mjw_data.actuator_force).

CTL-03Infeasible reference motionDecisive6 decisive · 20 uses

Joints track the reference but the robot tips or its feet spin: the reference is not dynamically feasible

Symptoms

  • The motion itself cannot be balanced by this robot; tracking it better makes it fall more reliably.

Likely causes

  • Retargeted clips lift heels, pivot or skate planted feet, float or sink soles.
  • Reference ZMP/CoP leaves the support polygon; torque demands exceed effort limits.
  • Small feet: little support area and friction moment; when the robot tips, feet unload and yaw friction collapses while stiff hip-yaw servos pass the turning torque.
  • Linear interpolation of low-rate keyframes gives impulsive accelerations; finite differences amplify them.

Checks

  • FK the reference (newton.eval_fk on a scratch state): sole height and tilt per foot.
  • Reference CoM/ZMP from smoothed CoM acceleration vs the support polygon of the foot colliders.
  • Reference inverse dynamics (newton.eval_inverse_dynamics_force or mujoco.mj_inverse) vs model.joint_effort_limit.
  • Per-foot normal force and yaw over a turn; required yaw moment vs mu*N*r.

Repairs

  • Make the plan feasible before tracking: flat-foot leg IK at planted poses, CoM/ZMP clamp with margin, smoothing (zero-lag Gaussian or spline, then differentiate), inverse-dynamics feedforward.
  • Or a contact-constrained inverse-dynamics QP (friction cone, CoP limits) whose slack goes to unscored quantities.
  • Soften hip yaw; low-pass unscored root yaw.

Pitfalls / shortcuts to avoid

  • Stacking joint-space heuristics against an infeasible reference; editing the scored reference itself.

Actuators and control · cards-v1

Uses in the trials (6 decisive · 9 helpful · 5 unused)
  • decisive v6.3/g1_hard-luna-mcp-cards-v3-p1 (Luna, fail): 227 s: switches to a whole-body torque QP enforcing the reference foot poses (its repair); 892 s 'lets yaw yield ... since the score checks root position and uprightness' and 1244 s low-passes hip/waist yaw (its 'soften hip yaw; low-pass unscored root yaw'). The delivered controller is that QP blended with PD, and it still failed high5.
  • decisive v6.4/g1_hard-astra-mcp-cards-v3-p0 (Astra, pass): 87s 'stiffness alone cannot keep high5 upright: joint error falls below the limit, but the robot still tips' (card symptom); 162s contact-constrained inverse-dynamics QP (card repair) passes high5 at 190s.
  • decisive v6.4/g1_hard-opus-mcp-cards-v3-p0 (Opus, pass): 96s 'adding leg IK that keeps feet planted', 251s CoM clamp, 318s Gaussian-smoothed root yaw, 254s soft hip yaw (hy=0.1): card repairs (flat-foot IK, CoM/ZMP clamp, smoothing, soften hip yaw). 352s 'SIG=0.15 passes on high5'.
  • decisive v6.4/g1_hard-sol-mcp-cards-v3-p0 (Sol, pass): 134s FK of the reference ankle poses (card check). 243s: 'reference feet remain nearly planted through the turn, while the current simulation loses foot contact... trying a contact aware whole body controller'. Final fix is an OSQP contact-constrained ID-QP with foot-wrench limits (card repair).
  • decisive v6.5/g1_hard-astra-mcp-cards-v3-p0 (Astra, pass): 125s 'stronger servos reduce joint error below 0.05 rad, but every variant still falls... adding a contact-constrained controller' (card symptom and QP repair); final 250 Hz double-support QP with soft root yaw.
  • decisive v6.5/g1_hard-opus-mcp-cards-v3-p0 (Opus, pass): 28s 'reference likely not balanceable as-is. Checking reference feasibility'; 141s flat-foot IK; 284s 'trying softer hip-yaw servos (CTL-03)'; 353-378s CoM-clamped table: 'Breakthrough'. These are the card's repairs and make up the final controller.
  • helpful v6.1/g1_hard-luna-mcp-cards-v1-p0 (Luna, fail): Re-read at 546 s after three failed experiments. FK of the reference feet (701 s). 1315 s: 'switching to the CTL-03 feedforward check: compute inverse-dynamics joint torques for the reference', which put mj_inverse feedforward in the final (pre-fall joint RMSE 0.028). The card's CoM/ZMP clamp, foot-yaw and hip-yaw repairs were never tried.
  • helpful v6.1/g1_track-luna-mcp-cards-v1-p0 (Luna, pass): Re-read at 259 s. The 276 s FK of the reference feet ('reference feet stay essentially planted and flat') ruled out an infeasible reference.
  • helpful v6.2/g1_hard-luna-mcp-cards-v2-p0 (Luna, fail): 584 s CoM vs support-box check; 1246 s 'reference CoM approaches the front edge of the foot support ... testing the card's suggested yaw-torque reduction' (hip/waist yaw at 0.2x). Its main repair (planted-foot leg IK, CoM clamp, smoothing) was never tried.
  • helpful v6.2/g1_track-luna-mcp-cards-v2-p0 (Luna, pass): 434-442 s foot FK over the clip: soles 0.8-4.9 mm, tilt <= 0.063 rad, 'No obvious foot scuff/lift infeasibility' (ruled out).
  • helpful v6.3/g1_hard-luna-mcp-cards-v3-p0 (Luna, fail): Read via glob, missed by card_usage.json. 59-91 s: reference inverse dynamics vs effort limits (its check), concluding 'mostly dynamically trackable'; 255 s switches to 'a contact aware whole body controller ... enforcing foot contact constraints' (its QP repair), abandoned by ~620 s.
  • helpful v6.3/g1_track-luna-mcp-cards-v3-p1 (Luna, fail): 159 s: 'in-place body turn while both reference ankle centers stay almost fixed ... points to stance balance and yaw/foot interaction'; adds a YAW_SERVO_SCALE knob.
  • helpful v6.4/g1_track-opus-mcp-cards-v3-p0 (Opus, pass): Only the optional clip: 125s 'high5... joints are tracking fine and the clip itself can't be balanced with joint tracking alone' (card symptom). No effect on the required wave criteria.
  • helpful v6.5/g1_hard-sol-mcp-cards-v3-p0 (Sol, fail): 90s FK of reference feet and 198s reference CoM/ZMP vs feet (card checks). 470-735s attempts the card's OSQP ID-QP; it fell repeatedly (OSQP 'solved inaccurate' at max_iter) and was abandoned after about 265 s. The repair is valid (v6.4 and plain Sol pass with it); the implementation failed.
  • helpful v6.5/g1_track-sol-mcp-cards-v3-p0 (Sol, pass): 113s compares the reference CoM with the ankle positions over the clip (card check).
  • unused v6.3/g1_track-luna-mcp-cards-v3-p0 (Luna, pass): No visible use.
  • unused v6.4/g1_track-astra-mcp-cards-v3-p0 (Astra, pass): Optional high5 left falling.
  • unused v6.4/g1_track-sol-mcp-cards-v3-p0 (Sol, pass): No reference feasibility checks.
  • unused v6.5/g1_track-astra-mcp-cards-v3-p0 (Astra, pass): Optional high5 left falling.
  • unused v6.5/g1_track-opus-mcp-cards-v3-p0 (Opus, pass): high5 (optional) left falling: 'would likely need a balance controller'. No reference-feasibility work.
Where it came from

Named in 43/80 g1 trials; 300-1300 s per affected Opus g1_hard trial; foot yaw slip 27/80; contact-constrained ID QP passed 8/8 Astra g1_hard.

Verification: No change; API names verified (eval_fk, eval_inverse_dynamics_force).

CTL-04Feedback destabilizesDecisive2 decisive · 12 uses

A feedback channel destabilizes as soon as it is enabled, or integral action makes standing worse

Symptoms

  • Closing a loop makes things worse instead of better.

Likely causes

  • Sign or frame error: quaternion order (Newton xyzw vs MuJoCo wxyz), world vs body angular velocity, COM vs origin velocity (CTL-06); an unnormalized rotation axis.
  • Positive feedback through targets computed from measured quantities the correction itself moves (measured foot anchors, toe-edge tipping).
  • A frame of delay when feedback runs at the frame rate instead of the physics rate.
  • Double support is a closed kinematic chain: leg integrators wind up against each other through the floor.

Checks

  • Per-channel impulse test at small gain: perturb and verify the correction opposes the perturbation.
  • Unit-test the orientation-error function on known rotations.
  • Feedback at frame rate vs per physics step.
  • Ablate ki on a static hold; log left/right integrator states and foot slip.

Repairs

  • Derive feedback directions from a Jacobian or the model; normalize axes; anchor to fixed planted references; add foot-flattening feedback; run feedback every physics step.
  • No leg joint integrators in double support: use model feedforward, or a task-space (CoM) integrator with anti-windup.

Pitfalls / shortcuts to avoid

  • Deleting the channel or sweeping its sign instead of finding the bug.

Actuators and control · cards-v1

Uses in the trials (2 decisive · 5 helpful · 5 unused)
  • decisive v6.1/g1_track-luna-mcp-cards-v1-p0 (Luna, pass): After reading, ran per-channel impulse tests (290 s hip pitch, 409 s ankle, 492 s yaw, 643 s roll) and moved feedback into a Warp kernel run every 2 ms substep (Exp5). NOTES: 'CTL-04 suggests the large combined 50 Hz feedback loop was too aggressive'. The passing fix (717 s) is substep-rate pitch/yaw feedback plus rate damping.
  • decisive v6.2/g1_track-luna-mcp-cards-v2-p0 (Luna, pass): 689 s unit-tested quat_pitch_xyzw on known rotations and ran a small-gain polarity test (card checks) -> 720 s 'found the balance loop's effective sign ... kept the robot upright and brought nominal RMSEs under threshold'.
  • helpful v6.1/g1_hard-luna-mcp-cards-v1-p0 (Luna, fail): 912 s: unit-tested quat_rotation_error_xyzw on known rotations (CTL-04 check) before adding pitch/x feedback. The feedback still ran once per frame rather than per physics step, as the card recommends.
  • helpful v6.2/g1_hard-luna-mcp-cards-v2-p0 (Luna, fail): 796-890 s ankle impulse test (card check) found a positive ankle-pitch target opposes forward pitch; the first implementation still had the sign reversed (982-1077 s, ~100 s) and the ablation the card recommends found it.
  • helpful v6.4/g1_hard-sol-mcp-cards-v3-p0 (Sol, pass): 79s probes how small leg-target offsets move the base 'before adding feedback' (impulse test); 127-171s per-channel feedback ablations. That feedback route was dropped for the WBC at 243s.
  • helpful v6.5/g1_hard-sol-mcp-cards-v3-p0 (Sol, fail): 117s per-joint-pair impulse tests (+0.03 rad target offsets, root dpos/rpy response) before adding leg-target feedback and offsets.
  • helpful v6.5/g1_track-sol-mcp-cards-v3-p0 (Sol, pass): 140s and 151s per-joint-pair +/-0.1 rad impulse tests map the root response. They set the signs of the final stance offsets and the root-x/pitch feedback through ankle/hip pitch targets (171s, 257-488s).
  • unused v6.3/g1_hard-luna-mcp-cards-v3-p0 (Luna, fail): Pelvis/ankle feedback added later (866-1119 s) without its impulse/sign tests.
  • unused v6.3/g1_track-luna-mcp-cards-v3-p1 (Luna, fail): Swept the feedback sign (203-212 s, 'negative pos feedback trial') rather than running its impulse test.
  • unused v6.4/g1_track-astra-mcp-cards-v3-p0 (Astra, pass): No feedback channel added.
  • unused v6.5/g1_hard-astra-mcp-cards-v3-p0 (Astra, pass): No feedback-channel debugging.
  • unused v6.5/g1_track-astra-mcp-cards-v3-p0 (Astra, pass): No feedback channel.
Where it came from

Destabilizing channels in 11 Opus g1 trials (one unresolved FAIL); integrator harm in 12 trials (50-700 s).

Verification: No change.

CTL-05Hand-written IK divergesMostly unused5 uses

Hand-written IK or Jacobian diverges, blows up, or returns zeros

Symptoms

  • Inverse kinematics diverges near straight limbs or yields zero sensitivities.

Likely causes

  • Near-straight knees/elbows are singular; joint limits bind.
  • wp.array.numpy() on a CPU array returns a view: a 'copy' taken before a perturbation aliases the perturbed data.
  • Your FK disagrees with the simulator on joint order or quaternion convention.

Checks

  • Compare your FK with newton.eval_fk for the same joint_q.
  • np.shares_memory(a, b) on arrays used in finite differences.
  • Condition number at the reference pose; clamp against model.joint_limit_lower/upper.

Repairs

  • newton.ik.IKSolver with IKObjectivePosition, IKObjectiveRotation, IKObjectiveJointLimit (batched, limits), or newton.eval_jacobian.
  • Damped least squares with task priorities (feet first); .numpy().copy().

Pitfalls / shortcuts to avoid

  • Finite differences on aliased arrays; undamped pseudo-inverses.

Actuators and control · cards-v1 · 1 attachment signature(s)

Uses in the trials (5 unused)
  • unused v6.2/g1_hard-luna-mcp-cards-v2-p0 (Luna, fail): No hand-written IK or Jacobian.
  • unused v6.3/g1_hard-luna-mcp-cards-v3-p0 (Luna, fail): No hand IK problems; no visible use.
  • unused v6.3/g1_track-luna-mcp-cards-v3-p1 (Luna, fail): No visible use.
  • unused v6.4/g1_hard-astra-mcp-cards-v3-p0 (Astra, pass): No IK written.
  • unused v6.5/g1_hard-astra-mcp-cards-v3-p0 (Astra, pass): No IK.
Where it came from

8 g1 trials (40-460 s), incl. CPU .numpy() view aliasing; newton.ik used in 0/80.

Verification: No change; newton.ik classes verified and CPU .numpy() view aliasing reproduced.

CTL-06Newton vs MuJoCo conventionsHelpful13 uses

Newton vs MuJoCo state conventions and names break a planner, estimator or feedback law

Symptoms

  • Conversions and lookups between Newton and the solver's MuJoCo model are subtly wrong.

Likely causes

  • Newton FREE joint: q = position + xyzw quaternion; qd = COM linear velocity and angular velocity, both in the parent (world) frame.
  • MuJoCo free joint: qpos uses wxyz; qvel = body-origin linear velocity (world) and angular velocity in the body frame. Scalar joints: qpos = joint_q + mujoco:dof_ref.
  • Compiled body and joint names are Newton labels with '/' replaced by '_' (a suffix on duplicates); geom names are '<shape label>_<shape index>'.
  • A solver-built MjModel was not loaded from XML, so mj_saveLastXML has nothing to save.

Checks

  • Round-trip solver.convert_joint_coords_to_mujoco(q, qd) and convert_joint_coords_from_mujoco(...).
  • Compare mj_forward body poses with newton.eval_fk; run a rotated and translated copy of the motion.

Repairs

  • Use the converters (batched over time); never hand-reorder.
  • model.find_bodies(pattern) + solver.newton_body_to_mjc_body (similar maps exist for shapes, joints, DOFs, actuators).
  • XML: SolverMuJoCo(model, save_to_mjcf=path); binary: mujoco.mj_saveModel(solver.mj_model, path).
  • Docs: docs/concepts/model_based_control.rst (coordinates, converting states, the solver's MuJoCo model).

Pitfalls / shortcuts to avoid

  • endswith name matching; testing only at rest.

Actuators and control · cards-v1 · 2 attachment signature(s)

Uses in the trials (9 helpful · 4 unused)
  • helpful v6.1/cube_toss-luna-mcp-cards-v1-p0 (Luna, fail): 232 s: checked convert_joint_coords_to/from_mujoco and gravity alongside a finite-difference vs logged-velocity test. 324 s: release velocities and free flight agree, which ruled out a state-convention error.
  • helpful v6.1/g1_hard-luna-mcp-cards-v1-p0 (Luna, fail): 613 s: looked up solver.convert_joint_coords_to_mujoco. The final feedforward converts reference q/qd through it before mujoco.mj_inverse (CTL-06 repair: use the converters).
  • helpful v6.3/g1_hard-luna-mcp-cards-v3-p0 (Luna, fail): 47 s: solver.convert_joint_coords_to_mujoco used to build reference qpos/qvel for mj_inverse.
  • helpful v6.3/g1_track-luna-mcp-cards-v3-p1 (Luna, fail): 159 s: 'checking the state conventions'; balance code comments 'Newton stores the free-joint quaternion as xyzw' and uses world-frame angular velocity (final lines 181-192).
  • helpful v6.4/g1_hard-astra-mcp-cards-v3-p0 (Astra, pass): 92s convert_joint_coords_to_mujoco, newton_body_to_mjc_body and find_bodies for foot-support FK on solver.mj_model (card's converters and maps).
  • helpful v6.4/g1_hard-sol-mcp-cards-v3-p0 (Sol, pass): 179-231s uses convert_joint_coords_to_mujoco, mjc_dof_to_newton_dof and newton_body_to_mjc_body, and reads model_based_control.rst (the card's doc pointer). The final WBC calls solver.convert_joint_coords_to_mujoco.
  • helpful v6.5/g1_hard-astra-mcp-cards-v3-p0 (Astra, pass): 93s convert_joint_coords_to_mujoco + newton_body_to_mjc_body for reference FK on solver.mj_model.
  • helpful v6.5/g1_hard-sol-mcp-cards-v3-p0 (Sol, fail): 491s uses mjc_body_to_newton and mjc_dof_to_newton_dof maps for the whole-body controller (later abandoned).
  • helpful v6.5/g1_track-astra-mcp-cards-v3-p0 (Astra, pass): 40-46s convert_joint_coords_to_mujoco + mj_forward for the gravity-torque check.
  • unused v6.2/g1_hard-luna-mcp-cards-v2-p0 (Luna, fail): No Newton/MuJoCo state conversion or name lookup followed.
  • unused v6.2/g1_track-luna-mcp-cards-v2-p0 (Luna, pass): No conversion or name-lookup work followed.
  • unused v6.4/g1_track-astra-mcp-cards-v3-p0 (Astra, pass): No Newton/MuJoCo conversions.
  • unused v6.5/g1_track-sol-mcp-cards-v3-p0 (Sol, pass): No converter or name-map use.
Where it came from

Free-joint convention source reads in 20/80 g1 trials; converter adopted in 15/30 g1_mpc once documented; name/XML errors in 8 trials (corpus).

Verification: Geom names are '<label>_<index>' and keep '/'; only body and joint names replace '/' with '_'. Added qpos = joint_q + dof_ref. XML save uses SolverMuJoCo(save_to_mjcf=), mj_saveModel writes binary; mj_saveLastXML failure explained.

CTL-07Planner diverges from plantMostly unused3 uses

Planner or private-model predictions diverge from the plant within one control period

Symptoms

  • One-step or one-period predictions differ from the plant by far more than numerical noise.

Likely causes

  • The planner takes one coarse step where the plant takes several fine steps with torque-limited servos and stiff contacts.
  • The planning model's gains, force ranges or timestep differ from the plant's (the solver's mj_model keeps construction-time values; notify updates the Warp model only).
  • State conversion errors (CTL-06).
  • Finite differences straddle contact activation or actuator saturation.
  • Hand-edited MuJoCo copies keep a stale dof_invweight0 after mass/armature edits (call mujoco.mj_setConst); replica friction (tanh) differs from MuJoCo's frictionloss constraint.

Checks

  • From the same state and command, step planner and plant once; compare per coordinate. Repeat with planner step = plant step. Over a horizon, newton.utils.compare_trajectories(plant, planner, tolerance=...) gives divergence time and top contributors per signal.
  • Planner vs plant actuator_gainprm/biasprm/forcerange.
  • Predicted vs measured cost change for a small step; vary the FD epsilon.

Repairs

  • Plan at the plant step, or validate a coarser step first; copy commanded gains into the planning model.
  • Smaller FD perturbations, smoothed contacts in the planning model only, regularization and line search, derivatives refreshed at contact changes.
  • Prefer batched Newton rollouts (BAT-03) to replicas.

Pitfalls / shortcuts to avoid

  • Validating a replica only where friction, damping and armature are zero.

Actuators and control · cards-v1 · 1 attachment signature(s)

Uses in the trials (3 unused)
  • unused v6.2/abc_arm-luna-mcp-cards-v2-p0 (Luna, pass): Read in the opening batch; no planner or replica was built, no follow-up.
  • unused v6.4/g1_hard-astra-mcp-cards-v3-p0 (Astra, pass): No planner/private-model divergence.
  • unused v6.5/g1_hard-astra-mcp-cards-v3-p0 (Astra, pass): No planner model.
Where it came from

13/16 Astra g1_mpc trials (100-1400 s; live one-step probe found it in ~130 s); FD across contacts 7/16; replica mismatch in dp_real/abc_arm.

Verification: Added a horizon check with newton.utils.compare_trajectories.

CTL-08Fails at contact changesMostly unused6 uses

Controller holds a stance but fails at support changes, landings, or late in a cyclic motion

Symptoms

  • Contact switching, flight or momentum is where the controller breaks.

Likely causes

  • Instantaneous whole-body QP/inverse dynamics has no preview of contact changes or momentum; rigid point contacts vs soft contacts; soft (penalized) dynamics rows; support points on a tilted foot.
  • Stance decided by foot height alone while swing feet move fast near the floor.
  • Horizon shorter than the contact or momentum cycle; no CoM or terminal term.
  • Sampling MPC: per-world inputs not reaching the worlds, noise scale vs cost temperature, too few knots, weights trading the wrong quantity, servos too soft for target sampling.

Checks

  • QP-planned accelerations vs plant accelerations; every force-carrying point actually in contact.
  • Reference foot height and speed vs the schedule.
  • Error per cycle at a horizon covering one full cycle; open-loop vs closed-loop replay.
  • Spread of final states across sampling worlds; per-term cost of nominal vs best.

Repairs

  • Keep QPs for quasi-static balance; for stepping or jumping use preview control (iLQR on solver.mj_model, or sampling on batched plant copies with newton.utils.BatchRollout).
  • Contact classification by speed and height with hysteresis; horizon >= one contact cycle; CoM/terminal costs; replan every period.
  • Verify world spread before tuning noise, knots, horizon, iterations.

Pitfalls / shortcuts to avoid

  • Writing a full QP/TSID before benchmarking batched sampling (harness lesson L06).

Actuators and control · cards-v1

Uses in the trials (6 unused)
  • unused v6.2/g1_hard-luna-mcp-cards-v2-p0 (Luna, fail): No preview/MPC or contact-schedule work followed.
  • unused v6.3/g1_hard-luna-mcp-cards-v3-p0 (Luna, fail): No visible use.
  • unused v6.3/g1_hard-luna-mcp-cards-v3-p1 (Luna, fail): No visible use.
  • unused v6.4/g1_hard-astra-mcp-cards-v3-p0 (Astra, pass): QP chosen for quasi-static double support; no preview/MPC work.
  • unused v6.4/g1_track-astra-mcp-cards-v3-p0 (Astra, pass): No whole-body controller.
  • unused v6.5/g1_hard-astra-mcp-cards-v3-p0 (Astra, pass): No preview control.
Where it came from

QP-first in 19/30 g1_mpc (200-1065 s per detour); height-only schedules 7; horizon drift ~12/30; MPPI tuning 6+.

Verification: No change; design advice from trial patterns.

CTL-09Passes own runs, fails held-outHelpful10 uses

Controller passes its own runs but fails a repeated, held-out or loaded run

Symptoms

  • The verdict is not stable across repeats, perturbations or machine load.

Likely causes

  • A marginal closed loop (contact discontinuities, thin CoP/ZMP margin) validated with one run per case.
  • Wall-clock-adaptive logic tuned under the agent's own concurrent load; BLAS threads oversubscribed or limited after NumPy/SciPy import.
  • Plans precomputed from construction-time parameters (frame rate, duration) go stale when those change.
  • The delivered file differs from the tested one.

Checks

  • K repeats per case with perturbed starts, nearby rates and thread settings: pass fraction and margin.
  • Compute per control step solo vs loaded (mean, max); threadpoolctl.threadpool_info().
  • Change the playback rate after construction vs resample before construction.
  • Run the delivered file in a fresh process with the stated command.

Repairs

  • Remove the marginality (horizon, smoothing, margins); prefer settings with pass fraction 1.0.
  • Deterministic compute with fixed margin, or load-probe scaling; thread limits before imports.
  • Derive plans from the motion's time base on demand.

Pitfalls / shortcuts to avoid

  • One run per clip; timing measurements taken while other runs share the GPU.

Actuators and control · cards-v1

Uses in the trials (7 helpful · 3 unused)
  • helpful v6.2/g1_hard-luna-mcp-cards-v2-p0 (Luna, fail): ~1650 s NOTES: 'The live-process slow high5 result did not reproduce in a fresh process (CTL-09)' -> restored the fresh-checked settings.
  • helpful v6.2/g1_track-luna-mcp-cards-v2-p0 (Luna, pass): Validated 1.25x, 1.5x (twice) and 2.0x playback in fresh processes before freezing (822-881 s, 1169-1237 s).
  • helpful v6.4/g1_hard-astra-mcp-cards-v3-p0 (Astra, pass): threadpool_limits before use; fresh-process validate_g1.py at 0.9x and +2 s hold.
  • helpful v6.4/g1_hard-sol-mcp-cards-v3-p0 (Sol, pass): 5 fresh runs per case (581s, 623s) exposed 1 fall in 5 on 0.9x ('treating that as a real failure', 627s). It tightened foot-wrench margins until 12/12 in-process and 6/6 fresh runs passed (752s, 1003s). Robustness came from this check; the controller itself came from CTL-03.
  • helpful v6.4/g1_track-astra-mcp-cards-v3-p0 (Astra, pass): 184-203s fresh-process checks at held-out rates 1.35x/1.75x/2.5x.
  • helpful v6.5/g1_hard-astra-mcp-cards-v3-p0 (Astra, pass): threadpool_limits(1); 580s 'Fixed iteration interval avoids wall-clock-dependent adaptation' (adaptive_rho_interval=50); fresh-process 0.9x and 20 s checks.
  • helpful v6.5/g1_track-astra-mcp-cards-v3-p0 (Astra, pass): 199s checks 'playback rates reserved from tuning and a longer hold'; 294s fresh-process 1.25x-2.5x and 20 s runs.
  • unused v6.1/g1_hard-luna-mcp-cards-v1-p0 (Luna, fail): No repeat, perturbed or loaded-run validation beyond the procedure's fresh-process check.
  • unused v6.1/g1_track-luna-mcp-cards-v1-p0 (Luna, pass): No repeat, loaded or rate-after-construction checks beyond the procedure's fresh-process 1.0x/1.5x checks.
  • unused v6.5/g1_hard-sol-mcp-cards-v3-p0 (Sol, fail): Shipped a knife-edge hip-offset schedule (852s: amp 0.199 and 0.201 fall, 0.200 passes; 1110s: 0.217 and 0.221 fall, 0.219 passes) checked with one fresh run per case. The card's marginality warning was not acted on.
Where it came from

All 5 g1_mpc failures (1000-2400 s chasing flips); time-guard misfires under self-inflicted load in 3; stale precomputed plans after rate change in 3 g1_hard runs.

Verification: No card change; removed its non-Newton 'budget throttl' signature regex.

Fitting to data

FIT-01Inconsistent identification fitsHelpful10 uses

Identification fit is inconsistent or negative, or many parameter sets fit equally well

Symptoms

  • The fitted parameters are unstable or unphysical although the error looks acceptable.

Likely causes

  • Noise and filter lag in differentiated signals bias equation-error least squares; Coulomb friction switches sign near zero velocity; excitation too weak.
  • Only base parameter combinations are identifiable; latency, damping, armature and offsets trade off; joints are coupled.
  • Candidates mapping to invalid inertias are corrected at finalize with only a one-line count warning, so they are not what was scored.

Checks

  • Pooled vs per-recording fits; change the filter and see if coefficients move.
  • Refit from two starts or on two splits; profile one parameter at a time.
  • builder.validate_inertia_detailed = True during search.

Repairs

  • Use equation-error least squares only as an initial guess; then fit the scored output error (open-loop windows) in Newton, batched (BAT-03), e.g. newton.utils.compare_trajectories(log, records, ...).objective() per world.
  • Parameterize so values are valid by construction; regularize toward nominal physical values; accept candidates on the total score only.

Pitfalls / shortcuts to avoid

  • Hunting joint conventions once the pooled fit predicts torque; combining per-joint winners.

Fitting to data · cards-v1 · 1 attachment signature(s)

Uses in the trials (4 helpful · 6 unused)
  • helpful v6.1/abc_arm-luna-mcp-cards-v1-p0 (Luna, pass): Used the torque regression only as an initial guess (83 s), then profiled one joint at a time (338-379 s: 'profiling joints 2 and 3 individually') and fit the scored output error in batches, following FIT-01's checks and repair.
  • helpful v6.3/abc_arm-luna-mcp-cards-v3-p1 (Luna, pass): 50 s: 'a principled starting point ... before spending time on expensive dynamics rollouts'; equation-error gains used only as the 'torque_guess' start (316 s), then candidates judged on the task's output-error scorer.
  • helpful v6.4/abc_arm-astra-mcp-cards-v3-p0 (Astra, pass): 148-157s output-error least_squares on the batched rollout with log-bounded (valid by construction) parameters.
  • helpful v6.5/abc_arm-astra-mcp-cards-v3-p0 (Astra, pass): 127-254s output-error least_squares with log-parameterized gains and armature.
  • unused v6.1/cube_toss-luna-mcp-cards-v1-p0 (Luna, fail): No least-squares identification or inertia validation. No reference to the card.
  • unused v6.2/abc_arm-luna-mcp-cards-v2-p0 (Luna, pass): Read at a plateau; next actions came from FIT-02's checks, no split refits or regularization.
  • unused v6.3/abc_arm-luna-mcp-cards-v3-p0 (Luna, pass): No equation-error fit, regularisation or validity parameterisation; no visible use.
  • unused v6.3/cube_toss-luna-mcp-cards-v3-p0 (Luna, pass): No visible use.
  • unused v6.4/abc_arm-sol-mcp-cards-v3-p0 (Sol, pass): No FIT-01-specific action (no validate_inertia, no per-recording or two-split refits). The equation-error-then-output-error workflow it used is already in FIT-03.
  • unused v6.5/abc_arm-sol-mcp-cards-v3-p0 (Sol, pass): No equation-error fit, inertia validation or split refits.
Where it came from

Inconsistent equation-error fits in >=8/22 dp_real trials; all 22 refit output error; silent inertia correction in i4/dp_real-opus-mcp-p0 L87.

Verification: 'Silently corrected' changed to a one-line count warning. Added compare_trajectories(...).objective() as the fit objective.

FIT-02Error floor no variant movesHelpful4 uses

Error plateaus at the same value under every variant: residual floor, missing mechanism, or reference bias

Symptoms

  • A residual that parameters do not move.

Likely causes

  • Unmodelled loads or conditions specific to one recording.
  • Load-dependent gear friction (fc + mu*|tau|): constant Coulomb friction cannot fit slow and fast phases together.
  • The reference is biased (tracker offset, in-hand offset): physics cannot remove it.
  • Chaotic outcomes (impacts).

Checks

  • Correlate window error with torque, speed and episode; bin the residual by |tau|; compare holding torque with predicted gravity torque.
  • Decompose: (sim hand - real FK hand) + (sim object - sim hand) - (reference - real FK hand); time-shift scan.
  • Start-state consistency (measured qd vs dq/dt); per-trajectory percentiles; bootstrap at the evaluation size.

Repairs

  • Test one targeted mechanism and keep it only if held-out data improves, e.g. update dof_frictionloss per step from the applied torque in a SolverMuJoCo subclass.
  • Otherwise down-weight or report the residual and stop.

Pitfalls / shortcuts to avoid

  • Pushing unrelated parameters (gains, masses, geometry) to their bounds to absorb a measurement offset: it overfits one episode and fails unseen ones; refitting on the outlier alone.

Fitting to data · cards-v1

Uses in the trials (3 helpful · 1 unused)
  • helpful v6.1/cube_toss-luna-mcp-cards-v1-p0 (Luna, fail): 232 s start-state consistency check (finite-difference positions vs logged velocities) and the pre/post-impact error decomposition (324, 527, 1073 s) follow FIT-02's checks and localized the error to impacts.
  • helpful v6.2/abc_arm-luna-mcp-cards-v2-p0 (Luna, pass): 519-529 s dbg_diag computed per-joint RMSE and correlation of window error with |tau| and speed (card check) -> joint-4 gain/effort sweep at 548 s (no gain), then gravcomp refinement.
  • helpful v6.2/cube_toss-luna-mcp-cards-v2-p0 (Luna, pass): 586 s phase split (pre-contact 1.4 mm / 0.013 rad) and start-state check (measured vs finite-difference velocity) localized the error to the first table contact -> 635 s contact tau/zeta sweep.
  • unused v6.4/abc_arm-astra-mcp-cards-v3-p0 (Astra, pass): No residual-floor analysis.
Where it came from

Floors in all 52 sysid trials; load-dependent friction found in 1/22 dp_real (best margin); reference-bias chases in 7 Opus replay trials (300-2000 s, unseen-episode failures).

Verification: No change.

FIT-03Replay latency, sag and gainsDecisive11 decisive · 11 uses

Replayed robot misses the recording: latency, gravity sag and servo gains

Symptoms

  • The simulated arm is stiffer, faster and better gravity-compensated than the real one.

Likely causes

  • Logged commands are leader targets; the real servo adds latency and finite stiffness.
  • MJCF gravcomp=1 removes a sag the real arm shows.
  • Default gains and damping differ from the real controller.
  • One global command delay applied to channels with different latencies (arm vs gripper).

Checks

  • Without simulation: sweep a zero-order-hold delay of the command vs measured q per joint; mean(measured - delayed command) vs gravity torque gives partial gravcomp; regress torque on (cmd(t-d) - q, qd, 1) for kp/kd; latency per channel.
  • Then batch candidate (delay, kp, kd, gravcomp) sets as worlds (BAT-03) and score per-joint error with newton.utils.compare_trajectories(log, records, times=, candidate_times=rollout.record_time) (RMSE, divergence time, worst joints).

Repairs

  • Fit delay, per-joint gains, per-link partial gravcomp (model.mujoco.gravcomp + BODY_INERTIAL_PROPERTIES), armature and friction jointly on all episodes; hold one episode out.
  • Set the delay to the faster channel and add the slower channel's lag through servo dynamics.

Pitfalls / shortcuts to avoid

  • Raising gains to 'track better' (the real arm is soft and late); gravcomp edits with the wrong flag; world-0-only edits (BAT-02).

Fitting to data · cards-v1

Uses in the trials (11 decisive)
  • decisive v6.1/abc_arm-luna-mcp-cards-v1-p0 (Luna, pass): 34 s: 'The matching card is FIT-03; its checks point first to command latency and the torque-to-error relationship'. Then ran a delay sweep, a torque regression for kp/kd, and at 1031 s a gravcomp sweep that 'found the shared cause' (scale 0.84 plus a per-link override). Final = delay 0.09 s + per-joint gains + partial per-link gravcomp, which is FIT-03's repair.
  • decisive v6.2/abc_arm-haiku-mcp-cards-v2-p0 (Haiku, fail): 55 s NOTES: 'Based on FIT-03 debug card: the real servo adds latency' -> 65 s delay sweep (0.0367 -> 0.0284 rad), delay kept in the final file (0.05 s). Partial use only: the card's 'real arm is soft' framing led to a downward-only gain sweep (0.5-1.0x at 120 s) and the wrong conclusion 'gains are already optimal'; the card's torque regression and partial-gravcomp check were never run.
  • decisive v6.2/abc_arm-luna-mcp-cards-v2-p0 (Luna, pass): 80 s ran the card's check offline (regress torque on cmd(t-d)-q, qd per joint over a delay grid) -> kp [64,85,73,9,9,6] and kd; 271 s 'torque-fitted gains plus a 40 ms delay' 0.0314 -> 0.0161 rad; 449 s partial gravcomp (card repair) -> final 0.85. Read via glob 'FIT-03*.md', not logged in card_usage.json.
  • decisive v6.3/abc_arm-luna-mcp-cards-v3-p0 (Luna, pass): 19 s: 'The provided card points to latency, gravity compensation, and servo response as likely causes'; first sweeps are command delay (86 s) and gravcomp (116 s); final fix = 80 ms delay + gravcomp ~0.8 on lower links (451-519 s) + per-joint gains.
  • decisive v6.3/abc_arm-luna-mcp-cards-v3-p1 (Luna, pass): 12 s: 'inspect the replay setup and FIT-03/FIT-05 guidance'; 59-67 s regresses torque on (cmd(t-d)-q, -qd, 1) per joint over delays (the card's check); final = 70 ms delay, regressed gains, MJCF gravcomp scaled 0.85 (504-535 s).
  • decisive v6.4/abc_arm-astra-mcp-cards-v3-p0 (Astra, pass): 37s 'The logs show both a timing mismatch and different effective servo gains... sweep delay, gains, damping, and gravity compensation together in batched Newton rollouts'; final 'calibrated gains, armature, friction, partial gravity compensation, and an 11 ms command delay'.
  • decisive v6.4/abc_arm-opus-mcp-cards-v3-p0 (Opus, pass): 10s `cat FIT-03*`; 24s zero-order-hold delay sweep of cmd vs q without sim, 86s regression of torque on cmd(t-d)-q and qd for kp/kd, 43/111s partial gravcomp sweep: the card's checks. Final: delay 0.06 s, fitted kp/kd, gravcomp 0.85, friction.
  • decisive v6.4/abc_arm-sol-mcp-cards-v3-p0 (Sol, pass): 25s: 'The XML also enables full gravity compensation on several links; I'll test delay and servo dynamics'; 28s regresses torque on (cmd(t-d)-q, -qd, 1) per delay (the card's check verbatim); final fix is 50 ms delay, per-joint kp/kd, per-link partial gravcomp [1.25,0.75,1.5,0.5,0.5], friction.
  • decisive v6.5/abc_arm-astra-mcp-cards-v3-p0 (Astra, pass): 39s 'The model currently applies full gravity compensation to most links, and its servo gains are the nominal simulation values' (card causes); 75-133s delay sweep, gravcomp x kp grid, least-squares fit of delay/kp/kd/gravcomp; final gains, armature, friction, 23 ms delay, partial gravcomp.
  • decisive v6.5/abc_arm-opus-mcp-cards-v3-p0 (Opus, pass): 14-19s delay estimate from logs without sim; 131s static-pose regression; final 'tau ≈ kp·(cmd − q) + a·G(q)... latency about 30–50 ms' then batched fit of delay/gains/gravcomp 0.85/friction (card checks and repairs).
  • decisive v6.5/abc_arm-sol-mcp-cards-v3-p0 (Sol, pass): 35s: 'The arm XML has full gravity compensation, while the recorded shoulder and elbow torques are substantial. I'm checking gravity compensation and command timing'. 51s sweeps a zero-order-hold command delay against measured q without simulation (card check). Final: 60 ms delay, partial proximal/distal gravcomp, per-joint gains.
Where it came from

Core work in 8/8 abc_arm and 24/24 replay trials (60-280 s avoidable overhead); shared-delay coupling 4 trials; release-pose sag errors in 13 abc_scratch.

Verification: Added compare_trajectories with rollout.record_time for per-joint scoring.

FIT-04Impacts, slides and rest posesDecisive4 decisive · 11 uses

Impacts, slides and rest poses do not match recordings

Symptoms

  • Where objects end up differs from the recording.

Likely causes

  • Friction not estimated from data; support height wrong (the lowest point of a rotated or multi-shape body is not centre minus radius); contact time constant/damping off (CON-02); restitution is not read by SolverMuJoCo.
  • The release state differs (hand pose, velocity, gripper timing, pad drag): the most common placement cause.
  • Bodies start in penetration or above the support.

Checks

  • Physics-first estimates: mu ~ a/g from flat sliding deceleration; support height = centre height - lowest-vertex offset at the measured orientation; damping from the rebound ratio.
  • At release: simulated vs recorded hand pose, opening and object velocity; contacts at the stopping frame.
  • Settle test with the robot away; lowest point per body at t=0.
  • One batched one-at-a-time table; freeze the flat knobs.

Repairs

  • Calibrate support height and friction first, then sweep contact tau/zeta batched.
  • Fix the release pose and timing before touching geometry; place objects at support height plus their lowest-point offset.

Pitfalls / shortcuts to avoid

  • Inventing unobserved slopes, ridges or COM offsets to fit one episode; raising rims past the observed outline; torsional/rolling friction for translation errors.

Fitting to data · cards-v1

Uses in the trials (4 decisive · 6 helpful · 1 unused)
  • decisive v6.1/cube_toss-luna-mcp-cards-v1-p0 (Luna, fail): Followed FIT-04's checks: 135 s 'clean contact-slide segments suggest a sliding friction coefficient near 0.21' (mu ~ a/g); 324/527 s release and free-flight vs post-impact split; 935 s table height from the recorded lowest points. The card's 'restitution is not read by SolverMuJoCo' led at 734-830 s to 'testing the restitution-capable XPBD solver'. The final deliverable (XPBD + data-derived mu 0.23 + table +1 mm) follows from this. The card's tau/zeta step was skipped.
  • decisive v6.3/cube_toss-luna-mcp-cards-v3-p1 (Luna, pass): 49 s: 'sweeping friction and impact dissipation first'; the first sweep covers mu, kd and table_height (support height) (71 s); final mu 0.18, kd 800, table -2.5 mm.
  • decisive v6.4/cube_toss-astra-mcp-cards-v3-p0 (Astra, pass): 28s lowest-vertex support height at measured orientation; 59s 'mu from slides [0.178 0.200 0.218...]' (card's physics-first estimates); 42s 'table surface about 2 mm below'; final mu 0.175, table -2 mm.
  • decisive v6.4/cube_toss-opus-mcp-cards-v3-p0 (Opus, pass): 22s first sweep is table height then mu (card: 'calibrate support height and friction first, then sweep contact tau/zeta'); 37s 'friction alone moved position error 0.099 → 0.037 m'; final mu 0.18, table -1.2 mm.
  • helpful v6.2/cube_toss-luna-mcp-cards-v2-p0 (Luna, pass): 67 s the card's physics-first estimates (rebound ratio ~0.15, sliding deceleration 2.8 m/s^2); 102/419 s lowest-vertex support height about -3 mm, adopted as table_height -0.003 (odd split 0.0185 -> 0.0177 m).
  • helpful v6.3/cube_toss-luna-mcp-cards-v3-p0 (Luna, pass): Follows its repair order: friction plus contact tau/zeta sweep batched (103 s), condim/torsional (172 s), tau/zeta x substeps (233 s), then fine mu around 0.2 (278 s).
  • helpful v6.4/cube_toss-sol-mcp-cards-v3-p0 (Sol, pass): 104s computes support height as final z minus the lowest-vertex offset at the measured orientation (the card's check), giving -2 mm; table_height -0.002 was adopted with little effect. Friction was swept widely before contact tuning.
  • helpful v6.5/cube_toss-astra-mcp-cards-v3-p0 (Astra, pass): 32-42s rest-pose table height ('table surface about 1.9 mm below'), kept at -1.9 mm; friction came from the sweep.
  • helpful v6.5/cube_toss-opus-mcp-cards-v3-p0 (Opus, pass): Final table height -1 mm from 'recorded cubes come to rest... ~1 mm below the half-width' (card support-height check, small gain). The main fix, mu 0.5→0.18, came from a generic sweep after tau/zeta.
  • helpful v6.5/cube_toss-sol-mcp-cards-v3-p0 (Sol, pass): 61s computes the lowest-vertex height at the terminal frames (card check). 112s: 'lowest vertex around 1.8 mm below the nominal table plane, so I'm checking that small height offset'. 118s height sweep; the offset was not adopted (table_height stayed 0).
  • unused v6.3/cube_toss-haiku-mcp-cards-v3-p0 (Haiku, pass): No friction estimate from slide deceleration and no support-height check; lowered mu at 167-171 s only from sweep results ('try even lower friction').
Where it came from

Physics-first estimates shortened search in >=10/22 cube_toss; release-state causes in 13 abc_scratch while 28/31 finals invented floor shaping; rim perching >=12 (180-770 s).

Verification: No change.

FIT-05Calibration fails unseen dataHelpful32 uses

A calibration passes on the data you have but fails on unseen recordings

Symptoms

  • A fit that passes on all provided data fails on held-out cases by a small amount.
  • Score differences between candidates are smaller than the spread between recordings.

Likely causes

  • Tuning on every provided case leaves no estimate of the error on new cases: the margin you see is optimistic.
  • Fine grids (many digits) fit the noise of the sample, not the physics.
  • Extra mechanisms (another solver, extra friction terms, offsets) add freedom that lowers the training error without improving prediction.

Checks

  • Split the provided cases (for example even and odd indices, or by recording): tune on one half and score the other. The gap between the two is your noise floor.
  • Per-case error distribution: a few bad cases can dominate the mean; check which cases carry the error and whether held-out-like cases resemble them.
  • Refit on the other split: parameters that move by more than their sweep step are not identified (FIT-01).

Repairs

  • Accept a candidate only on the held-out half, with a margin larger than the train/held-out gap; report both scores.
  • Prefer a few physically meaningful parameters (damping ratio, friction, support height, delay) estimated from data over many tuned ones; stop refining below the noise floor.
  • After choosing, refit on all data only if the held-out score stays within the margin.

Pitfalls / shortcuts to avoid

  • Grids finer than the noise floor; switching solvers or adding mechanisms to recover the last few percent on training data; reporting the training score as the expected verification score.

Fitting to data · cards-v2

Uses in the trials (15 helpful · 17 unused)
  • helpful v6.2/abc_arm-luna-mcp-cards-v2-p0 (Luna, pass): check.py holds out 16 logs of 8 episodes and tunes on the rest; 449 s and 1043 s reject changes 'smaller than the train/holdout spread'.
  • helpful v6.2/cube_toss-luna-mcp-cards-v2-p0 (Luna, pass): check.py tunes on even tosses and scores odd tosses; every candidate validated on the odd half (675 s, 1115 s).
  • helpful v6.3/abc_arm-luna-mcp-cards-v3-p0 (Luna, pass): 19 s: 'reserve a separate episode split for validation'; 63 s 24/8 episode split with train/val columns in every sweep; 654 s scores a second disjoint 8-episode split (0.0164 rad) before editing.
  • helpful v6.3/abc_arm-luna-mcp-cards-v3-p1 (Luna, pass): Episode split train {5,7,9,11} / val {6,8,10,13} from 230 s; 756-771 s scores a separate unseen 8-episode set (0.0208 rad) before finishing.
  • helpful v6.3/cube_toss-luna-mcp-cards-v3-p0 (Luna, pass): 17 s: 'tune on a representative split and reserve the remaining tosses as a held-out check'; even-index train / odd-index validation (285 s, 313 s).
  • helpful v6.3/cube_toss-luna-mcp-cards-v3-p1 (Luna, pass): 49 s: even/odd split, 'tuning on half the recordings and checking the other half'; fine sweeps reported on both halves (227 s).
  • helpful v6.4/abc_arm-astra-mcp-cards-v3-p0 (Astra, pass): 28s episodes split evenly into fit/validation; 207s full validation 0.0174 vs train 0.0157.
  • helpful v6.4/abc_arm-opus-mcp-cards-v3-p0 (Opus, pass): 19s split episodes odd/even (train/val); 307s 8-episode bootstrap of held-out risk ('p95 ≈ 0.024, so the tail needs work').
  • helpful v6.4/abc_arm-sol-mcp-cards-v3-p0 (Sol, pass): 5s plan to 'fit parameters on a subset of the logs and check them on separate episodes'; every sweep is scored on separate train/validation window samples; 423s even/odd episode parity check (0.0180 vs 0.0164).
  • helpful v6.4/cube_toss-astra-mcp-cards-v3-p0 (Astra, pass): 28s even/odd split; 95/113s reserved-200 validation 0.0137 m / 0.302 rad.
  • helpful v6.4/cube_toss-sol-mcp-cards-v3-p0 (Sol, pass): 95s and 168s even/odd toss split ('lower friction value holds up on both halves'); 238s bootstrap over groups of 170 tosses for margin.
  • helpful v6.5/abc_arm-astra-mcp-cards-v3-p0 (Astra, pass): 26/39s split by episode parity 'so validation will use episodes excluded from tuning'; 325s full validation 0.0168.
  • helpful v6.5/abc_arm-sol-mcp-cards-v3-p0 (Sol, pass): 79s holds out 8 episodes (val_ids); later sweeps (from 178s) score each candidate on train and validation; final 0.01834 rad on the held-out episodes vs 0.01824 on all 64 logs.
  • helpful v6.5/cube_toss-astra-mcp-cards-v3-p0 (Astra, pass): 32s even/odd split; 113/178s reserved-200 validation 0.0137 m / 0.301 rad.
  • helpful v6.5/cube_toss-sol-mcp-cards-v3-p0 (Sol, pass): 34s builds disjoint train/validation toss groups; 259s cross-checks both; 283s even/odd and first/last-200 splits before saving.
  • unused v6.2/abc_arm-haiku-mcp-cards-v2-p0 (Haiku, fail): From 120 s it tuned directly on its own held-out episodes 09-16 with ever finer delay/friction grids (ultra_fine_tune, squeeze_harder), the card's named pitfall; local 0.02337 vs verification 0.0258 rad.
  • unused v6.2/g1_hard-luna-mcp-cards-v2-p0 (Luna, fail): No calibration split; not applicable to a controller task.
  • unused v6.3/g1_track-luna-mcp-cards-v3-p0 (Luna, pass): Its 1.25-2x speed probes (337-385 s) come from the task's unseen faster playback, not a data split.
  • unused v6.3/g1_track-luna-mcp-cards-v3-p1 (Luna, fail): No visible use.
  • unused v6.3/grasp_drift-luna-mcp-cards-v3-p0 (Luna, pass): No visible use.
  • unused v6.4/g1_hard-astra-mcp-cards-v3-p0 (Astra, pass): No calibration.
  • unused v6.4/g1_hard-sol-mcp-cards-v3-p0 (Sol, pass): Tested 0.9x playback because the task statement requires it; no data split.
  • unused v6.4/g1_track-astra-mcp-cards-v3-p0 (Astra, pass): No calibration.
  • unused v6.4/g1_track-sol-mcp-cards-v3-p0 (Sol, pass): The faster-playback sweeps follow the task statement; no split logic.
  • unused v6.4/grasp_drift-astra-mcp-cards-v3-p0 (Astra, pass): No calibration.
  • unused v6.4/sdf_grind-astra-mcp-cards-v3-p0 (Astra, pass): No calibration.
  • unused v6.5/g1_hard-astra-mcp-cards-v3-p0 (Astra, pass): No calibration.
  • unused v6.5/g1_hard-sol-mcp-cards-v3-p0 (Sol, fail): No split; tested 0.9x playback as the task requires.
  • unused v6.5/g1_track-astra-mcp-cards-v3-p0 (Astra, pass): No calibration.
  • unused v6.5/g1_track-sol-mcp-cards-v3-p0 (Sol, pass): The faster-playback sweeps follow the task statement.
  • unused v6.5/grasp_drift-astra-mcp-cards-v3-p0 (Astra, pass): No calibration.
  • unused v6.5/sdf_grind-astra-mcp-cards-v3-p0 (Astra, pass): No calibration.
Where it came from

Added in cards-v2 from the v6.1 traces (cube toss and ABC arm calibrations that passed on the provided data and failed unseen cases).

Messages

MSG-01Message lookup tableHelpful12 uses

Quick reference: Newton, MuJoCo Warp and Warp messages and the card that explains each

Symptoms

  • A warning or exception text from Newton, SolverMuJoCo, MuJoCo Warp or Warp. Read the whole message first: many name the fix.

Lookup

message (substring)meaningcard
invalid force range for actuatorforcelimited without has_forcerangeCON-09
broadphase overflow, contact overflow, constraint overflow in world, exceed the MuJoCo Warp contact buffer; older: exceeded MJWarp limit, nefc overflow, narrowphase overflow, nconmax overflowcontacts or constraint rows droppedCON-06
linesearch iteration(s) limit reachedoften harmless once; A/B before raisingCON-11
solver iteration(s) limit (iterations N) reachedunconverged solveBAT-05
< MJ_MINMU (1e-05) with condim=6near-zero torsional/rolling frictionCON-05
that their mujoco:condim leaves outfriction component inactiveCON-05
requires homogeneous worldsworlds differ in shape/joint types or countsBAT-02
Skipping joint entry N for tendon Mtendon rows without mujoco:tendon_world before replicate()BAT-02
Inertia validation corrected N bodiesinvalid inertia corrected at finalizeFIT-01
CUDA error 700, Failed to allocatestale graph or live-object reuse; batch too bigBAT-04
Couldn't find a function '<op>' compatible with the arguments (Python scope); in kernels Input types must be the same, Couldn't find function overload for, must have the same scalar typeno implicit int-to-float or float64 promotion: write 2.0, wp.float32(x), float(x); from add_shape_*, a np.float64 config scalarBLD-02 (config case)
WarpCodegenTypeError, assigning to existing symbolkernel variable changes type; start with a float literal-
SolverNotifyFlagsremoved in 1.5: use newton.ModelFlagsCTL-01
Custom attribute 'mujoco:X' is not defineduse mujoco:condim, mujoco:geom_solimp, mujoco:geom_priority after SolverMuJoCo.register_custom_attributesCON-01
Invalid name, mj_name2id -1, No XML model loadedflattened compiled names; save with save_to_mjcf= or mj_saveModelCTL-06
add_shape_box() takes 2 positional argumentsonly body is positional-
Specified texture channels do not matchtextures must be RGBA uint8BLD-04
NotImplementedError: noslip solver not implementedno noslip in MuJoCo WarpCON-03
LinAlgErrorsingular IK, or derivatives across contactsCTL-05, CTL-07
joint_target_pos was removeduse joint_target_q-

Checks

  • newton.utils.report_health(model, state, solver) (MCP health()) counts overflow and iteration-limit events per world; the solver prints each type only once.
  • inspect.signature(...) and the docstring before retrying a call that raised TypeError/AttributeError.

Pitfalls / shortcuts to avoid

  • Grepping solver source before reading the message and the docstring; filtering 'warn' lines out of logs.

Messages · cards-v1 · 5 attachment signature(s)

Uses in the trials (5 helpful · 7 unused)
  • helpful v6.1/cube_toss-luna-mcp-cards-v1-p0 (Luna, fail): 583 s: looked up the linesearch-limit warning and went to CON-11 (586 s). A second read at 768 s, after a cone-assignment error not listed in the table, had no effect.
  • helpful v6.2/cube_toss-luna-mcp-cards-v2-p0 (Luna, pass): Auto-attached at 314.8 s to 'Custom attribute mujoco:condim is not defined'; 322 s card('MSG-01') -> 327 s added SolverMuJoCo.register_custom_attributes and the rebuild succeeded.
  • helpful v6.3/cube_toss-luna-mcp-cards-v3-p0 (Luna, pass, attached): Attached to 'Custom attribute mujoco:condim is not defined'; file read at 146 s; next call adds SolverMuJoCo.register_custom_attributes (152 s). The error text also named the fix.
  • helpful v6.4/cube_toss-astra-mcp-cards-v3-p0 (Astra, pass): Read for the linesearch warning; its 'often harmless once; A/B before raising' led to the 151s A/B.
  • helpful v6.5/cube_toss-sol-mcp-cards-v3-p0 (Sol, pass, attached): Attached on the rebuild error "Custom attribute 'mujoco:condim' is not defined". 5 s later it added SolverMuJoCo.register_custom_attributes(cube), which the error text also names. A file read at 418s routed the linesearch-limit warning to CON-11.
  • unused v6.1/sdf_grind-haiku-mcp-cards-v1-p0 (Haiku, fail, attached): Auto-attached to 'WarpCodegenAttributeError ... Could not find function wp.texture_shape' (MSG-01's table only covers WarpCodegenTypeError). No reference to it. The next actions (212-246 s) dropped texture editing for isomesh vertex removal plus an SDF rebuild.
  • unused v6.2/g1_track-haiku-mcp-cards-v2-p0 (Haiku, pass, attached): Attached to 'Control.joint_target_pos was removed'; the message named joint_target_q and the agent reverted at 432 s without opening the card.
  • unused v6.4/abc_arm-astra-mcp-cards-v3-p0 (Astra, pass): Read with solver source after 'SolverMuJoCo.reset() missing... state'; the fix (reset(self.s0)) came from the source signature.
  • unused v6.4/g1_track-astra-mcp-cards-v3-p0 (Astra, pass): Read after a WorldSetup.schedule AttributeError not in its table; fixed via inspect.getsource in the same step.
  • unused v6.5/abc_arm-astra-mcp-cards-v3-p0 (Astra, pass): Read with CON-06; no message acted on.
  • unused v6.5/cube_toss-astra-mcp-cards-v3-p0 (Astra, pass): Read without a triggering message.
  • unused v6.5/g1_hard-astra-mcp-cards-v3-p0 (Astra, pass): Read without a triggering message.
Where it came from

Routed messages in 98/245 trials (corpus); SolverNotifyFlags 16, linesearch 20, invalid force range 9, No XML model 6, Warp argument-type errors 6.

Verification: Rows and symptoms updated to the current reproduced strings: overflow, Warp kernel-scope errors, SolverNotifyFlags, noslip, joint_target_pos, XML save. Grew to 475 words.

What each task needed
The knowledge each task turned on and the card that states it, with passes of harness trials that did or did not read it.
TaskWhat it neededCard(s)Passes when the first card was readPasses when not readTimes decisivePasses in arms without cards (all models)
G1 trackingStiffer, load-based servo gains with velocity feedforward, and balance feedback through the joints for faster playback.CTL-02, CTL-0110/121/1912/13
G1 hardTracking clips whose reference is not dynamically feasible: make the plan feasible or balance through a contact-aware controller.CTL-03, CTL-045/100/368/13
Grasp driftThe finger pads have a higher geom priority and inherit a soft robot-wide contact default, so the pads' material decides the contact; stiffen the deciding geoms.CON-0111/111/21012/13
Cube tossContact damping high enough that impacts barely rebound, friction near 0.2, validated on held-out tosses.CON-02 (v2), FIT-04, FIT-0510/111/2811/13
ABC arm replayCommand delay, per-joint gains and partial gravity compensation fitted jointly across logs, checked on held-out logs.FIT-03, FIT-0510/110/21111/13
SDF grindingEdit the SDF data that collision samples, in place on both levels, along the swept tool path.BLD-0510/100/31011/13
Harness versions and prompts
The three versions and their passes per model.
HarnessWhat the agent getsPrompt characters addedPasses (per model)
cards-v1
v6.1
35 cards as a skill; index path in the prompt; MCP card helpers and attachments; a seven-step procedure (criteria checklist, local check script, cards before source, one change at a time, loop monitor, save passing versions, stop with margin).2,381Haiku 2/6; Luna 4/6
cards-v2
v6.2
36 cards (adds FIT-05, revises CON-02); all card titles listed in the prompt with an instruction to open the matching cards before the first experiment; an eight-step procedure adding a tested metric module, a held-out split, in-process experiments, wide sweeps first, a noise floor, and no finishing while a criterion fails.6,636Haiku 2/6; Luna 5/6
cards-v3
v6.3–v6.5
the lite harness: the same 36 cards and title list, and four rules instead of the procedure (check the criteria as verification will, with a held-out split; prefer the task's own evaluation and wide sweeps; open a card when a symptom is unclear; do not finish while a criterion fails).4,220Astra 12/12; Haiku 2/6; Luna 9/12; Opus 12/12; Sol 11/12
cards-v1: 35 cards, +2,381 prompt characters
Debug Cards: /WORKSPACE/.agents/skills/newton-debug-cards/INDEX.md lists notes on Newton simulation problems (symptom, likely causes, checks, repairs), one file per card in /WORKSPACE/.agents/skills/newton-debug-cards/cards/. In the live session, cards('query') and card('id') read the same cards (see the hosted script's notes above).

Procedure (for any Newton simulation task):
1. Criteria. Copy every stated requirement into CHECKLIST.md: each metric with its threshold and window, every stated variation (unseen cases, perturbations, rates), every limit and constraint, and the command verification runs.
2. Check script. Write check.py. It runs the deliverable the way verification will (a fresh process with the stated command), covers the closest local analog of each stated variation, and prints one line per criterion (value, threshold, worst-case margin) plus the minutes left. Run it on the starting files: this is your baseline.
3. Diagnose before tuning. Name the symptom and find its card in the Debug Card index (for an error or warning message, card MSG-01). Run the card's checks before reading Newton source. Before using an unfamiliar API, check its signature (inspect.signature, help) instead of guessing.
4. Experiment. Change one cause at a time. The first time you use a way of editing the model, apply an extreme value and confirm that the output changes. Time one evaluation, then run variants side by side where you can (newton.utils.BatchRollout). Log one line per experiment in NOTES.md: the change and the worst margin.
5. Loop monitor. After three experiments in a row that do not improve the worst margin, stop sweeping: split the error into its parts, look for a shared cause, and re-read the matching card.
6. Save. When check.py passes every criterion, copy the deliverable files to pass_<n>/ before changing anything else.
7. Finish. When every criterion passes with a clear margin (about 20%) in a fresh-process run of the stated command, report and stop. If a margin is thin and more than a quarter of the time is left, work only on that criterion, re-run check.py after each change, and restore the saved copy if anything regresses.
Shell: run anything longer than a minute in the background with output to a file and its own timeout, and poll with short commands; stop processes by their PID, never by pattern; name scratch files dbg_*.py.
cards-v2: 36 cards, +6,636 prompt characters
Debug Cards (/WORKSPACE/.agents/skills/newton-debug-cards/INDEX.md; one file per card in /WORKSPACE/.agents/skills/newton-debug-cards/cards/) are short notes on Newton simulation problems: symptom, likely causes, checks, repairs. In the live session, cards('query') and card('id') read the same cards (see the hosted script's notes above).
Cards by title:
- BAT-01: A sweep returns the same result for very different settings: the edit never reached the solver
- BAT-02: Multi-world batch: only world 0 changes, or worlds disagree with the single-world run
- BAT-03: Each candidate costs a full rollout: evaluate candidates x scenarios as worlds of one model
- BAT-04: Garbage, CUDA error 700, or silently lost steps after changing live solver objects or CUDA graphs
- BAT-05: Identical worlds or repeated runs disagree
- BLD-01: Hand-built body: mass properties are wrong, outside physical bounds, or not what you set
- BLD-02: Compound or mesh collider: seams, gaps, wrong radius, flipped faces
- BLD-03: Calibrated camera: projected points miss the photo, or pixel-to-world placement is off
- BLD-04: Camera render: a shape is missing, visibility edits change nothing, or colours are off by a gamma
- BLD-05: Geometry edits (SDF, mesh) do not reach collision or rendering; probing contacts at a pose
- CON-01: Contact parameters come from the other shape: priority, solmix and max rules
- CON-02: Contacts too soft, or stiffening does nothing: how shape ke/kd become MuJoCo solref
- CON-03: A firmly held object creeps slowly and no contact parameter moves it
- CON-04: Held object rotates or slips during motion: friction cone and impratio
- CON-05: Torsional or rolling friction does nothing; released objects keep rolling
- CON-06: Expected contacts are missing: objects pass through, fall through, launch, or one world misbehaves
- CON-07: Contact force readouts are zero or implausible, or raw contact rows mislead
- CON-08: Fingers close past the object with almost no force: the grasp never forms
- CON-09: Grip force or finger gap is wrong: the force limit never binds, or the finger-mirror equality yields
- CON-10: A negative control holds: the object lifts with near-zero friction or an open gripper
- CON-11: Some worlds go NaN or explode
- CTL-01: Servo gain or target edits have no, partial or unexpected effect
- CTL-02: Floating-base robot sags, sways and falls under joint-PD tracking; feedforward is fought by the servo
- CTL-03: Joints track the reference but the robot tips or its feet spin: the reference is not dynamically feasible
- CTL-04: A feedback channel destabilizes as soon as it is enabled, or integral action makes standing worse
- CTL-05: Hand-written IK or Jacobian diverges, blows up, or returns zeros
- CTL-06: Newton vs MuJoCo state conventions and names break a planner, estimator or feedback law
- CTL-07: Planner or private-model predictions diverge from the plant within one control period
- CTL-08: Controller holds a stance but fails at support changes, landings, or late in a cyclic motion
- CTL-09: Controller passes its own runs but fails a repeated, held-out or loaded run
- FIT-01: Identification fit is inconsistent or negative, or many parameter sets fit equally well
- FIT-02: Error plateaus at the same value under every variant: residual floor, missing mechanism, or reference bias
- FIT-03: Replayed robot misses the recording: latency, gravity sag and servo gains
- FIT-04: Impacts, slides and rest poses do not match recordings
- FIT-05: A calibration passes on the data you have but fails on unseen recordings
- MSG-01: Quick reference: Newton, MuJoCo Warp and Warp messages and the card that explains each
Before your first experiment, open the one to three cards whose titles match the task's problem and run their checks.

Procedure (for any Newton simulation task):
1. Criteria. Copy every stated requirement into CHECKLIST.md: each metric with its threshold and window, every stated variation (unseen cases, perturbations, rates), every limit and constraint, and the command verification runs.
2. Measurement. Put the metric code in one module (metrics.py) that both your experiments and check.py import. Test it once on a case with a known answer (for example the reference compared with itself gives zero error) before trusting it.
3. Check script. check.py runs the deliverable the way verification will (a fresh process with the stated command), covers the closest local analog of each stated variation (if verification uses cases you cannot see, tune on part of your data and let check.py score the rest; cards FIT-05 and CTL-09), and prints one line per criterion (value, threshold, margin) plus the minutes left. Run it on the starting files: this is your baseline.
4. Diagnose before tuning. Name the symptom, find its card (for an error or warning message, card MSG-01), and run the card's checks before reading Newton source. Before using an unfamiliar API, check its signature (inspect.signature, help) instead of guessing.
5. Experiment quickly. Run experiments in-process (the live session if you have one, or one script that evaluates many variants, e.g. newton.utils.BatchRollout), not one fresh process per variant. Sweep the parameters you are allowed to change over a wide range (about 0.1x to 10x) before building new mechanisms. Change one cause at a time; the first time you use a way of editing the model, confirm with an extreme value that the output changes. Log one line per experiment in NOTES.md: the change and the worst margin. Differences smaller than the spread between your tuning and held-out scores are noise; do not tune them.
6. Loop monitor. After three experiments in a row that do not improve the worst margin, stop sweeping: split the error into its parts, look for a shared cause, and re-read the matching card.
7. Save. When your quick measurement passes every criterion, run check.py; if it passes, copy the deliverable files to pass_<n>/ before changing anything else.
8. Finish. When check.py passes every criterion with a clear margin (about 20%), report and stop; do not make cosmetic edits afterwards. If a margin is thin and more than a quarter of the time is left, work only on that criterion and restore the saved copy if anything regresses. While any criterion fails and more than a quarter of the time is left, do not finish: go back to step 4 with a different hypothesis and the cards you have not read yet.
Shell: run anything longer than a minute in the background with output to a file and its own timeout, and poll with short commands; stop processes by their PID, never by pattern; name scratch files dbg_*.py.
cards-v3: 36 cards, +4,220 prompt characters
Debug Cards (/WORKSPACE/.agents/skills/newton-debug-cards/INDEX.md; one file per card in /WORKSPACE/.agents/skills/newton-debug-cards/cards/) are short notes on Newton simulation problems: symptom, likely causes, checks, repairs. In the live session, cards('query') and card('id') read the same cards (see the hosted script's notes above).
Cards by title:
- BAT-01: A sweep returns the same result for very different settings: the edit never reached the solver
- BAT-02: Multi-world batch: only world 0 changes, or worlds disagree with the single-world run
- BAT-03: Each candidate costs a full rollout: evaluate candidates x scenarios as worlds of one model
- BAT-04: Garbage, CUDA error 700, or silently lost steps after changing live solver objects or CUDA graphs
- BAT-05: Identical worlds or repeated runs disagree
- BLD-01: Hand-built body: mass properties are wrong, outside physical bounds, or not what you set
- BLD-02: Compound or mesh collider: seams, gaps, wrong radius, flipped faces
- BLD-03: Calibrated camera: projected points miss the photo, or pixel-to-world placement is off
- BLD-04: Camera render: a shape is missing, visibility edits change nothing, or colours are off by a gamma
- BLD-05: Geometry edits (SDF, mesh) do not reach collision or rendering; probing contacts at a pose
- CON-01: Contact parameters come from the other shape: priority, solmix and max rules
- CON-02: Contacts too soft, or stiffening does nothing: how shape ke/kd become MuJoCo solref
- CON-03: A firmly held object creeps slowly and no contact parameter moves it
- CON-04: Held object rotates or slips during motion: friction cone and impratio
- CON-05: Torsional or rolling friction does nothing; released objects keep rolling
- CON-06: Expected contacts are missing: objects pass through, fall through, launch, or one world misbehaves
- CON-07: Contact force readouts are zero or implausible, or raw contact rows mislead
- CON-08: Fingers close past the object with almost no force: the grasp never forms
- CON-09: Grip force or finger gap is wrong: the force limit never binds, or the finger-mirror equality yields
- CON-10: A negative control holds: the object lifts with near-zero friction or an open gripper
- CON-11: Some worlds go NaN or explode
- CTL-01: Servo gain or target edits have no, partial or unexpected effect
- CTL-02: Floating-base robot sags, sways and falls under joint-PD tracking; feedforward is fought by the servo
- CTL-03: Joints track the reference but the robot tips or its feet spin: the reference is not dynamically feasible
- CTL-04: A feedback channel destabilizes as soon as it is enabled, or integral action makes standing worse
- CTL-05: Hand-written IK or Jacobian diverges, blows up, or returns zeros
- CTL-06: Newton vs MuJoCo state conventions and names break a planner, estimator or feedback law
- CTL-07: Planner or private-model predictions diverge from the plant within one control period
- CTL-08: Controller holds a stance but fails at support changes, landings, or late in a cyclic motion
- CTL-09: Controller passes its own runs but fails a repeated, held-out or loaded run
- FIT-01: Identification fit is inconsistent or negative, or many parameter sets fit equally well
- FIT-02: Error plateaus at the same value under every variant: residual floor, missing mechanism, or reference bias
- FIT-03: Replayed robot misses the recording: latency, gravity sag and servo gains
- FIT-04: Impacts, slides and rest poses do not match recordings
- FIT-05: A calibration passes on the data you have but fails on unseen recordings
- MSG-01: Quick reference: Newton, MuJoCo Warp and Warp messages and the card that explains each

Working rules:
- Check the stated criteria the way verification will. If verification uses cases you cannot see, tune on part of your data and confirm on the rest (card FIT-05).
- Prefer the task's own evaluation code and quick in-process experiments; sweep the parameters you may change over a wide range before adding new mechanisms.
- When a symptom or message is unclear, open its card before reading Newton source.
- Finish when every criterion passes with margin. While one fails and more than a quarter of the time is left, keep working on it.
How the cards were made, delivered and judged
  • Mined: six readers went through all 245 transcripts of the earlier iterations for episodes where agents struggled; 110 draft cards were merged into 35. FIT-05 was added later from the first harness iteration.
  • Checked: a verifier resolved all 62 API names, reproduced 14 warning scenarios and corrected 23 cards.
  • Neutral: general Newton knowledge only, with no task values and no verifier details. SDF grinding was never mined and serves as the held-out task.
  • Delivered: as an agent skill in the workspace, with all titles listed in the prompt (from cards-v2 on). In MCP trials they were also available through cards(), card() and automatic attachment when a reply matched a card's message (20 cards).
  • Classified: one reader per group of trials judged every card use from the transcript, quoting the evidence (shown under each card). “Decisive” means the fix followed the card, not that it could not have been found without it.
Every harness trial 78 trials
Every harness trial: cards used (* = attached by the MCP host) with their class, what the task needed, and for failures the reason.
TrialVerdictCards (class)What it neededFailure
v6.1/abc_arm-haiku-mcp-cards-v1-p0fail–Replay calibration of the YAM arm: fit command latency (~90 ms), per-joint servo gains, and partial per-link gravity compensation (real arm sags) jointly with batched output-error evaluation.Never opened a card (no index or card read). Ran 60+ serial grid sweeps through newton_execute over delay, friction, damping and armature and pushed them to extremes (friction 3.6 N m, armature x0.0125, delay 22 ms) to absorb the unmodelled gravity sag. Never tried gravcomp or per-joint gains. Timed out at 1800 s: held-out 0.0243 rad vs 0.023.
v6.1/abc_arm-luna-mcp-cards-v1-p0passFIT-03 (decisive), FIT-01 (helpful), CTL-01 (unused), BAT-03 (helpful)Replay calibration: command latency (~90 ms), per-joint servo gains, and partial per-link gravity compensation fitted jointly on output error.
v6.1/cube_toss-haiku-mcp-cards-v1-p0fail–Data-first contact calibration: friction from slide deceleration (~0.18), table height from resting heights (~-1 mm), and a short, well-damped contact time constant for near-plastic impacts (kd ~500-1000 under the legacy ke/kd->solref mapping).Never opened a card and never used the MCP. Ran 26 serial full checks of hand-picked configs and found heavy damping by brute force (ke=480, kd=37250, 100 substeps, mu 0.245), but never estimated friction or table height from the data. Accepted a local 0.0202 m (0.8% over the limit) and stopped at 1012 s with about 13 min left; held-out 0.0223 m.
v6.1/cube_toss-luna-mcp-cards-v1-p0failFIT-04 (decisive), FIT-01 (unused), BAT-03 (helpful), BAT-01 (helpful), CON-02 (helpful), CON-01 (unused), CON-05 (helpful), CTL-06 (helpful), FIT-02 (helpful), CON-04 (helpful), MSG-01 (helpful), CON-11 (helpful)Data-first contact calibration: friction from slide deceleration (~0.18), table height from resting heights, and a short, well-damped contact time constant for near-plastic impacts (kd ~500-1000), all with real margin on unseen tosses.Overfit to a thin margin. Never shortened the MuJoCo contact time constant (kept kd=100, i.e. tau 20 ms, and swept only zeta). Switched to XPBD and hand-tuned mu to 4 decimals, relaxation, torsion and table height to a local 0.01896 m (5% margin, against the procedure's ~20%). Held-out 0.02003 m failed by 0.16%. Missing: A sharper FIT-04/CON-02 line: 'the starter kd=100 means a 20 ms contact time constant; toss impacts need tau of a few ms (kd ~500-1000) before friction tuning, so sweep tau, not only zeta'.
v6.1/g1_hard-haiku-mcp-cards-v1-p0fail–Beyond load-based servo gains (enough for wave), high5's turn and weight shift needs balance-aware control: check reference feasibility (CoM/ZMP vs support, foot yaw in the turn), with inverse-dynamics feedforward plus CoM/ZMP-clamped or contact-constrained balance feedback at physics rate and softened hip yaw.Never opened a card. Did blind uniform gain sweeps (5-200 Hz), a velocity-target attempt and a CTRL_DIRECT torque-control detour. Its live tests reset state inconsistently ('falls even with a fixed target'), and joint-index bugs corrupted its own metrics. Gave up at 556 s with about 20 min left, shipping 35 Hz gains (wave passes, high5 and high5 0.9x fall).
v6.1/g1_hard-luna-mcp-cards-v1-p0failCTL-02 (helpful), CTL-03 (helpful), CTL-04 (helpful), CTL-06 (helpful), CTL-09 (unused), CTL-01 (helpful), BAT-03 (unused)Balance-aware control for high5's turn and weight shift: reference feasibility (CoM/ZMP vs support polygon, foot yaw), ID feedforward plus CoM/ZMP-aware feedback at physics rate, softened hip yaw (on top of load-based gains).Partially applied the right card: took CTL-03's inverse-dynamics feedforward and CTL-01's velocity offset, but balanced with heuristic frame-rate pitch/x feedback through hip/ankle targets. It never checked reference CoM/ZMP or foot yaw in the turn. Spent the full budget on about 14 serial single-clip runs; wave passes, both high5 runs fall at about 2.1 s. Missing: A concrete, tested balance-controller recipe for a weight-shifting/turning humanoid clip (CoM or capture-point feedback mapped to ankle/hip targets every physics step, or a small contact-constrained ID QP), with starting gains and how to verify CoM/ZMP margin.
v6.1/g1_track-haiku-mcp-cards-v1-p0pass–Servo gains sized from rotor armature (10 Hz) are far too soft for the gravity/whole-body load. Load-based, much stiffer gains (optionally plus a velocity-feedforward target offset) keep the G1 upright on wave.
v6.1/g1_track-luna-mcp-cards-v1-p0passCTL-02 (helpful), CTL-03 (helpful), CTL-09 (unused), CTL-01 (helpful), CTL-04 (decisive)Servo gains far too soft (10 Hz from armature). Stiffer load-based gains suffice (haiku: 50 Hz alone); luna instead combined 22 Hz gains, velocity feedforward and physics-rate attitude feedback.
v6.1/grasp_drift-haiku-mcp-cards-v1-p0passCON-04 (helpful), CON-03 (unused), CON-02 (decisive), CON-01 (helpful)The fingers have higher geom priority and inherit the robot's soft default_shape_cfg (ke=250, kd=10, i.e. a 0.2 s time constant), so their soft material decides the pad/cube contact. Stiffen the deciding finger geoms (or the default).
v6.1/grasp_drift-luna-mcp-cards-v1-p0passCON-04 (helpful), CON-03 (unused), CON-01 (decisive), CON-08 (unused), CON-09 (helpful), CON-02 (helpful)Higher-priority finger geoms inherit the soft robot default material and decide the pad/cube contact. Stiffen the finger (deciding) geoms.
v6.1/sdf_grind-haiku-mcp-cards-v1-p0failMSG-01* (unused)Edit the SDF the model's collision pipeline actually holds, in place (coarse and fine texture levels), subtracting the wheel volume swept between consecutive poses, then re-extract the isomesh. A rebuilt SDF that is not registered never reaches collision.Never opened a card, BLD-05 included. Rebuilt a new SDF from a vertex-filtered isomesh every 20 frames and assigned it to self.workpiece_sdf only (unregistered with the model, inside try/except: pass), so collision geometry never changed (removed volume 0). Declared success from a '240 vertices removed' proxy without measuring volume or load, and ended at 516 s.
v6.1/sdf_grind-luna-mcp-cards-v1-p0passBLD-05 (decisive)In-place edit of the collision-held texture SDF (both levels) by the swept wheel volume between poses, plus isomesh re-extraction.
v6.2/abc_arm-haiku-mcp-cards-v2-p0failFIT-03 (decisive), FIT-05 (unused)Identify the real servo from the logs: per-joint kp/kd from a torque regression on (delayed command - q, qd) (shoulder gains well above nominal, wrist gains lower), a ~40 ms command delay, and partial gravity compensation (~0.85).Read FIT-03 but applied only its latency part plus a uniform friction scale; never regressed per-joint gains or tried partial gravcomp; overfit fine grids on its local held-out split; stopped at 876 s of 1800 s after misreading the clock ('about 4 minutes left' at 836 s with ~16 min remaining). Verification 0.0258 rad vs 0.023.
v6.2/abc_arm-luna-mcp-cards-v2-p0passFIT-03 (decisive), FIT-05 (helpful), CTL-07 (unused), FIT-01 (unused), FIT-02 (helpful)Identify the real servo from the logs: per-joint kp/kd from a torque regression on (delayed command - q, qd) (shoulder gains well above nominal, wrist gains lower), a ~40 ms command delay, and partial gravity compensation (~0.85).
v6.2/cube_toss-haiku-mcp-cards-v2-p0passCON-05* (unused)Calibrate contact from the data: low sliding friction (mu ~0.19-0.2) and a short, well-damped contact time constant (tau ~2-5 ms via the legacy ke/kd mapping, i.e. much larger kd/ke than the defaults); a ~3 mm lower support helps the margin. Found by a 5-toss live sweep (58-74 s) without reading any card.
v6.2/cube_toss-luna-mcp-cards-v2-p0passFIT-04 (helpful), FIT-05 (helpful), CON-02 (decisive), BAT-03 (helpful), MSG-01 (helpful), CON-11 (helpful), CON-05 (unused), FIT-02 (helpful)Calibrate contact from the data: low sliding friction (mu ~0.19-0.2) and a short, well-damped contact time constant (tau ~2-5 ms via the legacy ke/kd mapping, i.e. much larger kd/ke than the defaults); a ~3 mm lower support helps the margin.
v6.2/g1_hard-haiku-mcp-cards-v2-p0failCTL-02 (helpful)Make high5 feasible for the robot: anchor the planted feet flat with leg IK, clamp the commanded CoM inside the support polygon with margin, smooth the reference without lag, on top of load-sized stiff servos with gravity/inverse-dynamics feedforward.Never opened CTL-03. 90-330 s went to reading model.joint_q as the live state ('servo not moving'), then it reset the file and set extreme uniform gains; stopped at 390 s of 1800 s with a report of 'expected' passes and no high5 check. high5 and high5_slow fell (root RMSE 0.82 m).
v6.2/g1_hard-luna-mcp-cards-v2-p0failCTL-02 (decisive), CTL-03 (helpful), CTL-08 (unused), CTL-01 (helpful), CTL-06 (unused), FIT-05 (unused), CTL-09 (helpful), CTL-04 (helpful), CTL-05 (unused), BAT-03 (helpful), BAT-02 (helpful), BAT-05 (helpful)Make high5 feasible for the robot: anchor the planted feet flat with leg IK, clamp the commanded CoM inside the support polygon with margin, smooth the reference without lag, on top of load-sized stiff servos with gravity/inverse-dynamics feedforward.Read CTL-03 and ran its CoM check but applied only the hip-yaw softening; built ankle, xy-lean and height feedback loops instead of making the reference feasible. Lost ~100 s to a reversed feedback sign and ~200 s confirming batch vs single-world agreement; ran out of time with high5 root RMSE 0.043 m locally and 0.088 m in verification (upright on all clips, joints pass).
v6.2/g1_track-haiku-mcp-cards-v2-p0passCTL-02 (decisive), MSG-01* (unused)Size servo stiffness from the gravity load instead of rotor armature (about 10-25x the 10 Hz armature gains) so stance joints stay inside the error budget; with only 10x, a correctly signed root-pitch-to-ankle balance loop is also needed.
v6.2/g1_track-luna-mcp-cards-v2-p0passCTL-02 (decisive), CTL-03 (helpful), CTL-09 (helpful), BAT-03 (unused), CTL-01 (helpful), CTL-04 (decisive), CTL-06 (unused)Size servo stiffness from the gravity load instead of rotor armature (about 10-25x the 10 Hz armature gains) so stance joints stay inside the error budget; with only 10x, a correctly signed root-pitch-to-ankle balance loop is also needed.
v6.2/grasp_drift-haiku-mcp-cards-v2-p0failCON-04 (unused), CON-03 (unused), CON-09 (unused), CON-08 (unused)The finger geoms win the contact priority contest and their soft legacy contact (ke=250, kd=10 -> solref tau 0.2 s) lets the pads sink 12-14 mm and the cube rotate; stiffen the finger contact material (~10x ke/kd).Never opened CON-01/CON-02 or ran solver_params('geom'); misread static model.joint_q as live state and 'fixed' the finger joint limits (-0.02 m); its test appended aliased example.state_0 references, so displacement read 0.00 mm; declared success at 491 s. Verification: 10 cm drift 26.4 mm (limit 5). Missing: Reading live state: model.joint_q/body_q hold the initial configuration and state_0/state_1 swap every substep, so measure from state_0 and copy .numpy() each frame.
v6.2/grasp_drift-luna-mcp-cards-v2-p0passCON-03 (helpful), CON-04 (helpful), CON-01 (decisive), CON-02 (decisive), CON-08 (helpful), CON-09 (unused), BAT-03 (unused)The finger geoms win the contact priority contest and their soft legacy contact (ke=250, kd=10 -> solref tau 0.2 s) lets the pads sink 12-14 mm and the cube rotate; stiffen the finger contact material (~10x ke/kd).
v6.2/sdf_grind-haiku-mcp-cards-v2-p0fail–Edit the SDF texture data the collision model already references, in place on both the coarse grid and the fine subgrids, subtracting the wheel's swept volume between consecutive poses; verify with a collide-only load probe.Never opened a card and made no MCP calls; rebuilt a new SDF from a filtered isomesh into self.workpiece_sdf, which collision never reads (BLD-05: 'a rebuilt SDF that is not registered does not reach collision'); its check.py did not test removal on the collision side; declared success at 763 s. Removed volume 0, groove load unchanged.
v6.2/sdf_grind-luna-mcp-cards-v2-p0passBLD-05 (decisive)Edit the SDF texture data the collision model already references, in place on both the coarse grid and the fine subgrids, subtracting the wheel's swept volume between consecutive poses; verify with a collide-only load probe.
v6.3/abc_arm-haiku-mcp-cards-v3-p0failBAT-03* (unused)Command latency (~70-90 ms) plus reduced gravity compensation on the lower arm links (the real arm sags), with per-joint servo gain/friction calibration, accepted on held-out episodes.Never opened a card or the index; ran ~30 serial global-scale sweeps (delay, uniform kp/kd scale, armature, friction up to 9x) on all 64 logs, never touched gravity compensation or per-joint terms; plateaued at 0.0256 rad (held-out 0.0251 > 0.023) and was cut off at the time limit (last tool call rejected at 1800 s).
v6.3/abc_arm-luna-mcp-cards-v3-p0passFIT-03 (decisive), FIT-05 (helpful), BAT-03 (helpful), FIT-01 (unused), CTL-01 (unused)Command latency (~70-90 ms) plus reduced gravity compensation on the lower arm links (the real arm sags), with per-joint servo gain/friction calibration, accepted on held-out episodes.
v6.3/abc_arm-luna-mcp-cards-v3-p1passFIT-03 (decisive), FIT-05 (helpful), FIT-01 (helpful), BAT-03 (unused)Command latency (~70-90 ms) plus reduced gravity compensation on the lower arm links (the real arm sags), with per-joint servo gain/friction calibration, accepted on held-out episodes.
v6.3/cube_toss-haiku-mcp-cards-v3-p0passFIT-04 (unused), CON-02 (unused)Low sliding friction (~0.2) and a stiff, strongly damped contact (impacts barely rebound: tau of a few ms, zeta >= 1 under the legacy ke/kd -> solref mapping), calibrated batched on a train/validation split.
v6.3/cube_toss-luna-mcp-cards-v3-p0passFIT-04 (helpful), FIT-05 (helpful), FIT-01 (unused), BAT-03 (helpful), CON-01 (unused), CON-02 (decisive), CON-05 (helpful), MSG-01* (helpful), CON-11 (helpful)Low sliding friction (~0.2) and a stiff, strongly damped contact (impacts barely rebound: tau of a few ms, zeta >= 1 under the legacy ke/kd -> solref mapping), calibrated batched on a train/validation split.
v6.3/cube_toss-luna-mcp-cards-v3-p1passFIT-04 (decisive), FIT-05 (helpful), CON-01 (unused), CON-02 (helpful), BAT-03 (unused)Low sliding friction (~0.2) and a stiff, strongly damped contact (impacts barely rebound: tau of a few ms, zeta >= 1 under the legacy ke/kd -> solref mapping), calibrated batched on a train/validation split.
v6.3/g1_hard-haiku-mcp-cards-v3-p0fail–high5's root turn and weight shift cannot be balanced by joint-space PD: it needs model-based balance, i.e. contact-constrained inverse-dynamics (QP) torques delivered as servo target offsets, with unscored root yaw as slack / softened hip yaw.Never opened a card; cycled armature-scaled gain frequencies (20-100 Hz), acceleration and velocity feedforward, and damping ratios with no balance model; high5 and 0.9x high5 fall (root RMSE 0.79-0.81 m) while wave passes.
v6.3/g1_hard-luna-mcp-cards-v3-p0failCTL-02 (helpful), CTL-03 (helpful), BAT-03 (unused), CTL-01 (helpful), CTL-06 (helpful), CTL-04 (unused), CTL-08 (unused), CTL-05 (unused), CON-06 (helpful), CON-07 (helpful), CON-01* (unused), CON-02 (unused)high5's root turn and weight shift cannot be balanced by joint-space PD: it needs model-based balance, i.e. contact-constrained inverse-dynamics (QP) torques delivered as servo target offsets, with unscored root yaw as slack / softened hip yaw.Tried CTL-03's QP at 255 s, but its hand-built contact estimate (reference feet a few mm above the floor, then a fixed-contact solve) gave no or wrong support reaction and worse tracking. It reverted at ~600 s to gravity feedforward plus heuristic pelvis/foot feedback; high5 falls at frame ~103; it stopped at 1345 s. Missing: A worked balance recipe for humanoids on SolverMuJoCo position servos: a per-step contact-constrained inverse-dynamics QP on solver.mj_model (feet as unilateral contacts with friction-cone/CoP limits, not rigid 6-DoF constraints; unscored root yaw as slack) delivered as q* = q + (tau + kd*qd)/kp with reduced servo kp, plus a short turn/weight-shift segment as its pass check.
v6.3/g1_hard-luna-mcp-cards-v3-p1failCTL-02 (helpful), CTL-03 (decisive), CTL-08 (unused), CON-02* (unused)high5's root turn and weight shift cannot be balanced by joint-space PD: it needs model-based balance, i.e. contact-constrained inverse-dynamics (QP) torques delivered as servo target offsets, with unscored root yaw as slack / softened hip yaw.Implemented the right approach (contact QP, target offsets, yaw slack), but with the feet as fixed 6-axis constraints blended with stiff PD. It tipped during the high5 turn and the 0.9x run (root RMSE 0.40/0.32 m); it stopped at 1409 s. Missing: A worked balance recipe for humanoids on SolverMuJoCo position servos: a per-step contact-constrained inverse-dynamics QP on solver.mj_model (feet as unilateral contacts with friction-cone/CoP limits, not rigid 6-DoF constraints; unscored root yaw as slack) delivered as q* = q + (tau + kd*qd)/kp with reduced servo kp, plus a short turn/weight-shift segment as its pass check.
v6.3/g1_track-haiku-mcp-cards-v3-p0failCTL-01 (misleading), CTL-02 (misleading)Servo gains sized from the gravity load instead of rotor armature (kp up ~4-10x, near-critical kd), reference-velocity feedforward in the target, and a small pelvis pitch/position correction through the legs, validated with margin on faster playback.Measurement bug: it read a fresh model.state(), so nothing appeared to move, and it chased servo, ctrl and graph causes for ~5 min. It then shipped untested 35 Hz armature-scaled gains at 513 s (70% of the budget unused). Wave passes, but the unseen faster playback misses root RMSE by 0.4 mm (0.0404 > 0.04 m).
v6.3/g1_track-luna-mcp-cards-v3-p0passCTL-02 (decisive), CTL-03 (unused), CTL-01 (helpful), FIT-05 (unused)Servo gains sized from the gravity load instead of rotor armature (kp up ~4-10x, near-critical kd), reference-velocity feedforward in the target, and a small pelvis pitch/position correction through the legs, validated with margin on faster playback.
v6.3/g1_track-luna-mcp-cards-v3-p1failCTL-01 (helpful), CTL-02 (decisive), CTL-03 (helpful), FIT-05 (unused), CTL-06 (helpful), CTL-05 (unused), CTL-04 (unused), BAT-05 (helpful)Servo gains sized from the gravity load instead of rotor armature (kp up ~4-10x, near-critical kd), reference-velocity feedforward in the target, and a small pelvis pitch/position correction through the legs, validated with margin on faster playback.Marginal closed loop: 1.5x-playback root RMSE ranged 0.021-0.079 m across in-process runs, and it shipped after two fresh runs at 492 s (73% of budget left). The verifier's faster playback scored 0.0434 > 0.04 m. It did not read CTL-09 (repeat/held-out margin).
v6.3/grasp_drift-haiku-mcp-cards-v3-p0passCON-02 (decisive), CON-03 (unused), CON-04 (unused), CTL-01* (unused)The finger geoms win the contact (higher geom priority) and inherit the robot-wide soft default (ke=250, kd=10 -> 0.2 s time constant); put a stiff material on the deciding finger geoms.
v6.3/grasp_drift-luna-mcp-cards-v3-p0passCON-04 (helpful), CON-01 (decisive), CON-02 (helpful), CON-08 (unused), CON-09 (helpful), FIT-05 (unused), BAT-03 (unused)The finger geoms win the contact (higher geom priority) and inherit the robot-wide soft default (ke=250, kd=10 -> 0.2 s time constant); put a stiff material on the deciding finger geoms.
v6.3/grasp_drift-luna-mcp-cards-v3-p1passCON-04 (helpful), CON-03 (unused), CON-01 (decisive), CON-08 (helpful), CON-09 (helpful)The finger geoms win the contact (higher geom priority) and inherit the robot-wide soft default (ke=250, kd=10 -> 0.2 s time constant); put a stiff material on the deciding finger geoms.
v6.3/sdf_grind-haiku-mcp-cards-v3-p0fail–Edit the texture SDF that the collision pipeline references in place on both coarse and fine levels, subtracting the wheel's swept volume between consecutive poses, then re-extract the isomesh.Never opened a card. Its kernel overwrote voxels inside the wheel's current pose with 1e9 via copy_to/copy_from instead of a signed-distance subtraction of the swept volume. It tried per-frame pipeline rebuilds and a too-slow mesh rebuild, then shipped without a full-pass check, claiming success at ~800 s. Verifier: 8% of the groove cleared, 48% of the volume removed, load ratio 0.99.
v6.3/sdf_grind-luna-mcp-cards-v3-p0passBLD-05 (decisive)Edit the texture SDF that the collision pipeline references in place on both coarse and fine levels, subtracting the wheel's swept volume between consecutive poses, then re-extract the isomesh.
v6.3/sdf_grind-luna-mcp-cards-v3-p1passBLD-05 (decisive)Edit the texture SDF that the collision pipeline references in place on both coarse and fine levels, subtracting the wheel's swept volume between consecutive poses, then re-extract the isomesh.
v6.4/abc_arm-astra-mcp-cards-v3-p0passFIT-03 (decisive), BAT-03 (helpful), FIT-01 (helpful), FIT-05 (helpful), CTL-01 (helpful), BAT-02 (helpful), FIT-02 (unused), BAT-01 (unused), MSG-01 (unused)Model the real servo loop: a command latency (~25-85 ms zero-order hold), data-fitted per-joint gains (stiffer than nominal on joints 1-3), partial gravity compensation (~0.7-0.85) and higher joint friction, fitted on some episodes and checked on held-out episodes.
v6.4/abc_arm-opus-mcp-cards-v3-p0passFIT-03 (decisive), FIT-05 (helpful)Model the real servo loop: a command latency (~25-85 ms zero-order hold), data-fitted per-joint gains (stiffer than nominal on joints 1-3), partial gravity compensation (~0.7-0.85) and higher joint friction, fitted on some episodes and checked on held-out episodes.
v6.4/abc_arm-sol-mcp-cards-v3-p0passFIT-03 (decisive), FIT-05 (helpful), FIT-01 (unused), BAT-03 (helpful), CTL-01 (unused), BAT-01 (unused)Model the real servo: command latency (~50-60 ms), reduced or partial per-link gravity compensation instead of the XML's full gravcomp, and per-joint gains and friction fitted on open-loop output error with a held-out episode check.
v6.4/cube_toss-astra-mcp-cards-v3-p0passFIT-04 (decisive), CON-02 (decisive), BAT-03 (helpful), BAT-02 (helpful), FIT-05 (helpful), CON-11 (helpful), MSG-01 (helpful), CON-01 (unused), BLD-01 (unused), CON-05 (unused)Lower sliding friction (~0.18) plus a stiff (timeconst ~2 ms), critically to over-damped contact instead of the soft 20 ms starter contact, with the table ~1-2 mm lower; FIT-04 gives friction/support height and the order, CON-02 the tau/zeta mapping and overdamped impacts.
v6.4/cube_toss-opus-mcp-cards-v3-p0passCON-02 (decisive), FIT-04 (decisive), CON-05* (unused)Lower sliding friction (~0.18) plus a stiff (timeconst ~2 ms), critically to over-damped contact instead of the soft 20 ms starter contact, with the table ~1-2 mm lower; FIT-04 gives friction/support height and the order, CON-02 the tau/zeta mapping and overdamped impacts.
v6.4/cube_toss-sol-mcp-cards-v3-p0passFIT-04 (helpful), FIT-05 (helpful), BAT-03 (unused), CON-01 (unused), CON-02 (decisive), CON-05 (unused)Fit sliding friction (~0.18) and a short, strongly overdamped contact (large kd, zeta >> 1) jointly over a wide range, checked on held-out tosses.
v6.4/g1_hard-astra-mcp-cards-v3-p0passCTL-03 (decisive), CTL-02 (helpful), CTL-01 (helpful), CTL-06 (helpful), CTL-09 (helpful), BAT-03 (helpful), CTL-05 (unused), CTL-07 (unused), CTL-08 (unused), FIT-05 (unused)high5 cannot be balanced by joint PD alone: make the reference dynamically feasible (planted-foot leg IK, CoM clamp, low-passed root yaw, soft hip yaw) or use a contact-constrained inverse-dynamics QP fed through low-impedance servos; stiffer gains are needed but not sufficient.
v6.4/g1_hard-opus-mcp-cards-v3-p0passCTL-03 (decisive), CTL-02 (helpful), CTL-01* (unused)high5 cannot be balanced by joint PD alone: make the reference dynamically feasible (planted-foot leg IK, CoM clamp, low-passed root yaw, soft hip yaw) or use a contact-constrained inverse-dynamics QP fed through low-impedance servos; stiffer gains are needed but not sufficient.
v6.4/g1_hard-sol-mcp-cards-v3-p0passCTL-02 (helpful), CTL-03 (decisive), CTL-01 (helpful), BAT-03 (unused), FIT-05 (unused), CTL-04 (helpful), CTL-06 (helpful), BAT-05 (helpful), CTL-09 (helpful)Contact-aware inverse-dynamics control (QP with foot wrench/friction/CoP limits) applied through the position servos as target offsets, robust across repeated fresh runs and 0.9x playback.
v6.4/g1_track-astra-mcp-cards-v3-p0passCTL-02 (decisive), CTL-01 (helpful), BAT-03 (helpful), CTL-09 (helpful), BAT-05 (helpful), CTL-03 (unused), CTL-04 (unused), CTL-06 (unused), CTL-08 (unused), FIT-05 (unused), MSG-01 (unused)The servo gains are sized from rotor armature (10 Hz), far too soft for the gravity load: raise them to ~40-70 Hz equivalent (kp from load) with near-critical damping; velocity feed-forward is optional.
v6.4/g1_track-opus-mcp-cards-v3-p0passCTL-02 (decisive), CTL-03 (helpful), CTL-01* (unused)The servo gains are sized from rotor armature (10 Hz), far too soft for the gravity load: raise them to ~40-70 Hz equivalent (kp from load) with near-critical damping; velocity feed-forward is optional.
v6.4/g1_track-sol-mcp-cards-v3-p0passCTL-02 (decisive), CTL-03 (unused), FIT-05 (unused), CTL-01 (helpful), BAT-03 (unused)Servo gains sized for the whole-body gravity load instead of rotor armature (roughly 12-50x kp with more damping), so the robot stands and tracks wave, including faster playback.
v6.4/grasp_drift-astra-mcp-cards-v3-p0passCON-01 (decisive), CON-02 (helpful), CON-03 (unused), CON-04 (unused), CON-07 (unused), BAT-03 (unused), FIT-05 (unused)The finger pads have higher mujoco:geom_priority and inherit the soft robot-wide default material (solref 0.2 s), so their material alone decides the grasp contact: give the pads a stiff material (timeconst ~2-4 ms, zeta ~1). Optionally, lower the pad solimp to reduce the residual soft-friction creep.
v6.4/grasp_drift-opus-mcp-cards-v3-p0passCON-01 (decisive), CON-02 (helpful), CON-03 (helpful), CON-04 (unused), CON-05 (unused), CON-07 (unused), CON-08 (unused), CON-09 (unused)The finger pads have higher mujoco:geom_priority and inherit the soft robot-wide default material (solref 0.2 s), so their material alone decides the grasp contact: give the pads a stiff material (timeconst ~2-4 ms, zeta ~1). Optionally, lower the pad solimp to reduce the residual soft-friction creep.
v6.4/grasp_drift-sol-mcp-cards-v3-p0passCON-01 (decisive), CON-02 (unused), CON-03 (unused), CON-04 (unused), CON-08 (unused), CON-09 (unused), BAT-03 (unused), CON-07 (unused)The finger geoms win the geom_priority contest and inherit the soft robot-wide default ke/kd, so they decide the pinch; give the fingers stiff contact material.
v6.4/sdf_grind-astra-mcp-cards-v3-p0passBLD-05 (decisive), FIT-05 (unused)Edit the workpiece texture SDF in place on both levels (coarse and subgrid textures) that the model and collision reference (identity check), subtract the wheel's swept volume between consecutive poses, and re-extract the isomesh.
v6.4/sdf_grind-opus-mcp-cards-v3-p0passBLD-05 (decisive)Edit the workpiece texture SDF in place on both levels (coarse and subgrid textures) that the model and collision reference (identity check), subtract the wheel's swept volume between consecutive poses, and re-extract the isomesh.
v6.4/sdf_grind-sol-mcp-cards-v3-p0passBLD-05 (decisive)Subtract the wheel's swept volume in place from both texture-SDF levels (the objects the collision pipeline references) every frame, then re-extract the render isomesh.
v6.5/abc_arm-astra-mcp-cards-v3-p0passFIT-03 (decisive), BAT-03 (helpful), FIT-01 (helpful), FIT-05 (helpful), CTL-01 (helpful), CON-06* (unused), MSG-01 (unused)Model the real servo loop: a command latency (~25-85 ms zero-order hold), data-fitted per-joint gains (stiffer than nominal on joints 1-3), partial gravity compensation (~0.7-0.85) and higher joint friction, fitted on some episodes and checked on held-out episodes.
v6.5/abc_arm-opus-mcp-cards-v3-p0passFIT-03 (decisive)Model the real servo loop: a command latency (~25-85 ms zero-order hold), data-fitted per-joint gains (stiffer than nominal on joints 1-3), partial gravity compensation (~0.7-0.85) and higher joint friction, fitted on some episodes and checked on held-out episodes.
v6.5/abc_arm-sol-mcp-cards-v3-p0passFIT-03 (decisive), FIT-05 (helpful), BAT-03 (helpful), CTL-01 (unused), FIT-01 (unused)Model the real servo: command latency (~50-60 ms), reduced or partial per-link gravity compensation instead of the XML's full gravcomp, and per-joint gains and friction fitted on open-loop output error with a held-out episode check.
v6.5/cube_toss-astra-mcp-cards-v3-p0passCON-02 (decisive), FIT-04 (helpful), BAT-03 (helpful), BAT-02 (helpful), FIT-05 (helpful), CON-11 (helpful), BAT-05 (unused), BAT-01 (unused), MSG-01 (unused), CON-01 (unused), BLD-01 (unused)Lower sliding friction (~0.18) plus a stiff (timeconst ~2 ms), critically to over-damped contact instead of the soft 20 ms starter contact, with the table ~1-2 mm lower; FIT-04 gives friction/support height and the order, CON-02 the tau/zeta mapping and overdamped impacts.
v6.5/cube_toss-opus-mcp-cards-v3-p0passCON-02 (decisive), FIT-04 (helpful), CON-05* (unused)Lower sliding friction (~0.18) plus a stiff (timeconst ~2 ms), critically to over-damped contact instead of the soft 20 ms starter contact, with the table ~1-2 mm lower; FIT-04 gives friction/support height and the order, CON-02 the tau/zeta mapping and overdamped impacts.
v6.5/cube_toss-sol-mcp-cards-v3-p0passFIT-04 (helpful), FIT-05 (helpful), CON-01 (unused), CON-02 (decisive), CON-05 (helpful), MSG-01* (helpful), CON-11 (unused)Fit sliding friction (~0.18) and a short, strongly overdamped contact (large kd, zeta >> 1) jointly over a wide range, checked on held-out tosses.
v6.5/g1_hard-astra-mcp-cards-v3-p0passCTL-03 (decisive), CTL-02 (decisive), CTL-01 (helpful), CTL-06 (helpful), CTL-09 (helpful), BAT-03 (helpful), BAT-04 (helpful), CTL-04 (unused), CTL-05 (unused), CTL-07 (unused), CTL-08 (unused), FIT-05 (unused), MSG-01 (unused)high5 cannot be balanced by joint PD alone: make the reference dynamically feasible (planted-foot leg IK, CoM clamp, low-passed root yaw, soft hip yaw) or use a contact-constrained inverse-dynamics QP fed through low-impedance servos; stiffer gains are needed but not sufficient.
v6.5/g1_hard-opus-mcp-cards-v3-p0passCTL-03 (decisive), CTL-02 (helpful), CTL-01* (unused)high5 cannot be balanced by joint PD alone: make the reference dynamically feasible (planted-foot leg IK, CoM clamp, low-passed root yaw, soft hip yaw) or use a contact-constrained inverse-dynamics QP fed through low-impedance servos; stiffer gains are needed but not sufficient.
v6.5/g1_hard-sol-mcp-cards-v3-p0failCTL-02 (helpful), CTL-03 (helpful), BAT-03 (unused), FIT-05 (unused), CTL-01 (helpful), CTL-06 (helpful), CTL-04 (helpful), BAT-05 (helpful), CTL-09 (unused)Contact-aware inverse-dynamics control (QP with foot wrench/friction/CoP limits) applied through the position servos as target offsets, robust across repeated fresh runs and 0.9x playback.Mostly non-knowledge, plus a failed implementation. After the ID-QP attempt failed (470-735s), it fell back to a hand-tuned, knife-edge hip-pitch offset schedule. It then judged root RMSE per coordinate (3.3 cm) although its own Euclidean value was 5.7 cm (433s and 1366s; final message: 'a per-frame Euclidean-distance RMSE is a different metric'). The verifier's Euclidean root RMSE on 0.9x high5 was 5.74 cm against a 4 cm limit. It ran to 1710 s. Missing: A worked recipe for contact-aware ID-QP tracking through position servos (per-physics-step updates, heel and toe contact points, CoP/friction margins, solver tolerances) that makes CTL-03's repair implementable; the metric choice was a non-knowledge error.
v6.5/g1_track-astra-mcp-cards-v3-p0passCTL-02 (decisive), CTL-01 (helpful), BAT-03 (helpful), CTL-09 (helpful), CTL-06 (helpful), CTL-03 (unused), CTL-04 (unused), BAT-05 (unused), FIT-05 (unused)The servo gains are sized from rotor armature (10 Hz), far too soft for the gravity load: raise them to ~40-70 Hz equivalent (kp from load) with near-critical damping; velocity feed-forward is optional.
v6.5/g1_track-opus-mcp-cards-v3-p0passCTL-02 (decisive), CTL-01 (helpful), CTL-03 (unused)The servo gains are sized from rotor armature (10 Hz), far too soft for the gravity load: raise them to ~40-70 Hz equivalent (kp from load) with near-critical damping; velocity feed-forward is optional.
v6.5/g1_track-sol-mcp-cards-v3-p0passCTL-01 (helpful), CTL-02 (helpful), CTL-03 (helpful), CTL-04 (helpful), BAT-03 (unused), FIT-05 (unused), CTL-06 (unused)Servo gains sized for the whole-body gravity load instead of rotor armature (roughly 12-50x kp with more damping), so the robot stands and tracks wave, including faster playback. Balance feedback through the leg targets is an alternative.
v6.5/grasp_drift-astra-mcp-cards-v3-p0passCON-01 (decisive), CON-02 (helpful), CON-03 (unused), CON-04 (unused), CON-05 (unused), CON-07 (unused), BAT-03 (unused), BAT-04 (unused), FIT-05 (unused)The finger pads have higher mujoco:geom_priority and inherit the soft robot-wide default material (solref 0.2 s), so their material alone decides the grasp contact: give the pads a stiff material (timeconst ~2-4 ms, zeta ~1). Optionally, lower the pad solimp to reduce the residual soft-friction creep.
v6.5/grasp_drift-opus-mcp-cards-v3-p0passCON-01 (decisive), CON-02 (helpful), CON-03 (helpful), CON-04 (helpful), CON-08 (unused), CON-09 (unused)The finger pads have higher mujoco:geom_priority and inherit the soft robot-wide default material (solref 0.2 s), so their material alone decides the grasp contact: give the pads a stiff material (timeconst ~2-4 ms, zeta ~1). Optionally, lower the pad solimp to reduce the residual soft-friction creep.
v6.5/grasp_drift-sol-mcp-cards-v3-p0passCON-01 (decisive), CON-03 (unused), CON-04 (unused), CON-08 (unused), CON-09 (unused), CON-02 (unused), CON-07 (unused)The finger geoms win the geom_priority contest and inherit the soft robot-wide default ke/kd, so they decide the pinch; give the fingers stiff contact material.
v6.5/sdf_grind-astra-mcp-cards-v3-p0passBLD-05 (decisive), FIT-05 (unused)Edit the workpiece texture SDF in place on both levels (coarse and subgrid textures) that the model and collision reference (identity check), subtract the wheel's swept volume between consecutive poses, and re-extract the isomesh.
v6.5/sdf_grind-opus-mcp-cards-v3-p0passBLD-05 (decisive)Edit the workpiece texture SDF in place on both levels (coarse and subgrid textures) that the model and collision reference (identity check), subtract the wheel's swept volume between consecutive poses, and re-extract the isomesh.
v6.5/sdf_grind-sol-mcp-cards-v3-p0passBLD-05 (decisive)Subtract the wheel's swept volume in place from both texture-SDF levels (the objects the collision pipeline references) every frame, then re-extract the render isomesh.
Card table the overview as a table
The 36 Debug Cards. Read: harness trials whose agent opened the card (file or card()), per model. Attached: times the MCP host attached it automatically. Trace classes: every read or attachment classified from the transcript as decisive (the main diagnosis or fix follows it), helpful (informed a check or ruled out a cause), unused, or misleading (a detour). Value: high = decisive at least twice or decisive and mostly useful; some = useful in at least a third of uses; low = mostly unused; misleading = more detours than help; not used.
CardWhat it saysRead in trials (by model)AttachedTrace classesValue
BAT-01A sweep returns the same result for very different settings: the edit never reached the solver. A sweep that changes nothing usually means the edit never reached the solver: wrong ModelFlags, a construction-only field, only world 0, or a dropped value. Test the edit path with an extreme value first.Astra 2, Sol 1, Luna 1–1 helpful · 3 unusedlow
BAT-02Multi-world batch: only world 0 changes, or worlds disagree with the single-world run. In multi-world batches, label lookups and hard-coded indices often hit only world 0, and some assets come from the first world. Index per world and run twin tests.Astra 3, Luna 1–4 helpfulsome
BAT-03Each candidate costs a full rollout: evaluate candidates x scenarios as worlds of one model. Evaluate candidates × scenarios as worlds of one model (newton.utils.BatchRollout) instead of one process or rebuild per candidate; time one evaluation before launching a search.Luna 13, Astra 10, Sol 8116 helpful · 16 unusedsome
BAT-04Garbage, CUDA error 700, or silently lost steps after changing live solver objects or CUDA graphs. Swapping solvers, re-capturing CUDA graphs or changing construction-only fields on a live example gives garbage or CUDA error 700; rebuild the example instead.Astra 2–1 helpful · 1 unusedsome
BAT-05Identical worlds or repeated runs disagree. Identical worlds or repeated runs disagree because of unconverged solves, GPU atomics or chaotic contacts; raise iterations and judge chaotic outcomes statistically.Astra 3, Sol 2, Luna 2–5 helpful · 2 unusedsome
BLD-01Hand-built body: mass properties are wrong, outside physical bounds, or not what you set. Hand-built bodies: check mass and inertia against closed forms; the builder adds shape mass and inertia unless lock_inertia is set.Astra 2–2 unusedlow
BLD-02Compound or mesh collider: seams, gaps, wrong radius, flipped faces. Colliders built from many primitives or meshes leave seams, gaps, steps and convex-hull artifacts; probe them with a batch of small spheres.–––not used
BLD-03Calibrated camera: projected points miss the photo, or pixel-to-world placement is off. Calibrated cameras: Newton looks along −Z (OpenCV is rotated 180° about X), distortion models run in opposite directions; validate by projecting known points and use SensorCamera.Intrinsics.–––not used
BLD-04Camera render: a shape is missing, visibility edits change nothing, or colours are off by a gamma. Camera renders with missing or wrongly coloured shapes: opacity and visibility flags, BVH rebuilds after edits, back-face culling, sRGB versus linear colour.–––not used
BLD-05Geometry edits (SDF, mesh) do not reach collision or rendering; probing contacts at a pose. Geometry edits (SDF, mesh) must change the data collision actually samples (both SDF levels), not a copy; verify with sampled removed volume and a collide-only probe.Luna 4, Opus 2, Astra 2, Sol 2–10 decisivehigh
CON-01Contact parameters come from the other shape: priority, solmix and max rules. In SolverMuJoCo a contact's stiffness, friction and dimension come from the higher-priority shape, or are mixed and maxed at equal priority; editing the losing shape changes nothing.Luna 7, Astra 4, Sol 4, Opus 2, Haiku 1110 decisive · 1 helpful · 8 unusedhigh
CON-02Contacts too soft, or stiffening does nothing: how shape ke/kd become MuJoCo solref. How shape ke/kd map to MuJoCo's contact time constant and damping ratio, including the 2·dt clamp. From cards-v2: impacts that barely rebound need an overdamped contact.Luna 8, Opus 4, Astra 4, Sol 4, Haiku 3111 decisive · 8 helpful · 5 unusedhigh
CON-03A firmly held object creeps slowly and no contact parameter moves it. Slow creep of a firmly held object is the discretization floor of soft friction, which scales with dt; no contact parameter removes it. Report it and stop.Haiku 3, Luna 3, Opus 2, Astra 2, Sol 2–3 helpful · 9 unusedlow
CON-04Held object rotates or slips during motion: friction cone and impratio. Grasped objects that slip or rotate under motion: use the elliptic friction cone (Newton's default is pyramidal) and a higher impratio; both are set at construction.Luna 5, Haiku 3, Opus 2, Astra 2, Sol 2–7 helpful · 7 unusedsome
CON-05Torsional or rolling friction does nothing; released objects keep rolling. Torsional and rolling friction act only with condim 4 or 6, set at construction; they resist spin and roll, not sliding.Luna 3, Astra 2, Sol 2, Opus 133 helpful · 8 unusedlow
CON-06Expected contacts are missing: objects pass through, fall through, launch, or one world misbehaves. Missing contacts: a large detection gap overflows the contact buffers, nconmax/njmax are too low, or collision groups and filters exclude the pair.Luna 111 helpful · 1 unusedsome
CON-07Contact force readouts are zero or implausible, or raw contact rows mislead. Contact force readouts are zero unless MuJoCo's post-constraint pass runs; raw contact rows include inactive and unrelated contacts.Astra 2, Sol 2, Opus 1, Luna 1–1 helpful · 5 unusedlow
CON-08Fingers close past the object with almost no force: the grasp never forms. A grasp that never forms: the hand is not where it should be (latency, sag, soft gains), the object is the wrong size, or the contact is too soft.Luna 4, Opus 2, Sol 2, Haiku 1–2 helpful · 7 unusedlow
CON-09Grip force or finger gap is wrong: the force limit never binds, or the finger-mirror equality yields. Grip force limits that never bind or live in an array the solver ignores; finger-mirror equality constraints that yield under load.Luna 4, Opus 2, Sol 2, Haiku 1–3 helpful · 6 unusedsome
CON-10A negative control holds: the object lifts with near-zero friction or an open gripper. A negative control (no friction, open gripper) still lifts the object: wedging or caging, squeeze × residual friction, torsional friction, or a diverged copy counted as held.–––not used
CON-11Some worlds go NaN or explode. NaN or exploding worlds: the pyramidal cone with condim 6 at near-zero friction, constraint overflow, or contacts too stiff for dt.Luna 3, Astra 2, Sol 1–5 helpful · 1 unusedsome
CTL-01Servo gain or target edits have no, partial or unexpected effect. Servo gains are compiled at construction and need notify_model_changed; joint-target actuators read joint_target_ke/kd; the POSITION mode ignores target velocity.Luna 9, Astra 6, Sol 6, Opus 1, Haiku 1418 helpful · 8 unused · 1 misleadingsome
CTL-02Floating-base robot sags, sways and falls under joint-PD tracking; feedforward is fought by the servo. A floating-base robot sags and falls under joint PD when gains come from rotor inertia instead of load; use load-based gains, near-critical damping and feedforward applied every physics step.Luna 8, Opus 4, Astra 4, Sol 4, Haiku 3–11 decisive · 11 helpful · 1 misleadinghigh
CTL-03Joints track the reference but the robot tips or its feet spin: the reference is not dynamically feasible. Joints track but the robot tips or its feet spin: the reference motion is not dynamically feasible; make it feasible (foot IK, CoM/ZMP clamp, smoothing) or use a contact-aware QP.Luna 8, Opus 4, Astra 4, Sol 4–6 decisive · 9 helpful · 5 unusedhigh
CTL-04A feedback channel destabilizes as soon as it is enabled, or integral action makes standing worse. A feedback channel that destabilizes at once has a sign or frame error or positive feedback through measured anchors; run feedback every physics step, avoid leg integrators in double support.Luna 6, Astra 3, Sol 3–2 decisive · 5 helpful · 5 unusedhigh
CTL-05Hand-written IK or Jacobian diverges, blows up, or returns zeros. Hand-written IK or Jacobians diverge near singularities; use newton.ik; .numpy() of a CPU array is a view, not a copy.Luna 3, Astra 2–5 unusedlow
CTL-06Newton vs MuJoCo state conventions and names break a planner, estimator or feedback law. Newton and MuJoCo state conventions differ (xyzw vs wxyz, COM vs origin velocity, world vs body frame) and compiled names are flattened; use the converters.Luna 6, Astra 4, Sol 3–9 helpful · 4 unusedsome
CTL-07Planner or private-model predictions diverge from the plant within one control period. A planner's predictions diverge from the plant within one control period: coarser steps, different gains or stale MuJoCo copies; plan at the plant step or with batched rollouts.Astra 2, Luna 1–3 unusedlow
CTL-08Controller holds a stance but fails at support changes, landings, or late in a cyclic motion. Controllers that hold a stance but fail at contact changes need preview (iLQR or sampling MPC on batched copies), contact hysteresis and long enough horizons.Astra 3, Luna 3–6 unusedlow
CTL-09Controller passes its own runs but fails a repeated, held-out or loaded run. A controller that passes its own runs but fails repeated, held-out or loaded runs is marginal; remove the marginality and validate over many runs.Astra 4, Luna 4, Sol 2–7 helpful · 3 unusedsome
FIT-01Identification fit is inconsistent or negative, or many parameter sets fit equally well. Inconsistent identification fits: use equation-error least squares only as a start, then fit the scored output error in batched rollouts, with valid parameterizations and regularization.Luna 6, Astra 2, Sol 2–4 helpful · 6 unusedsome
FIT-02Error plateaus at the same value under every variant: residual floor, missing mechanism, or reference bias. An error floor that no variant moves: an unmodelled mechanism or a biased reference; test one mechanism on held-out data, otherwise report the residual and stop.Luna 3, Astra 1–3 helpful · 1 unusedsome
FIT-03Replayed robot misses the recording: latency, gravity sag and servo gains. Replays that miss the recording: fit command delay, per-joint gains, partial gravity compensation and friction jointly across episodes, holding one out.Luna 4, Opus 2, Astra 2, Sol 2, Haiku 1–11 decisivehigh
FIT-04Impacts, slides and rest poses do not match recordings. Impacts, slides and rest poses that miss recordings: estimate friction, support height and damping from the data first, and fix the release state before geometry.Luna 4, Opus 2, Astra 2, Sol 2, Haiku 1–4 decisive · 6 helpful · 1 unusedhigh
FIT-05A calibration passes on the data you have but fails on unseen recordings. A calibration that passes on the provided data but fails unseen cases: tune on part of the data, check on the rest, and stop tuning below the noise floor (added in cards-v2).Astra 12, Luna 10, Sol 8, Opus 1, Haiku 1–15 helpful · 17 unusedsome
MSG-01Quick reference: Newton, MuJoCo Warp and Warp messages and the card that explains each. A lookup table from Newton, MuJoCo Warp and Warp warning and error messages to the card that explains each.Astra 6, Luna 245 helpful · 7 unusedsome