Known issues
Every open defect in the code and the paper that we know of: what it does, where it is documented, and which step fixes it.
Last checked: 2026-11-06, against phase1/planar at b354251. This page is updated whenever an issue is found or closed. The full records are in the discussion compendium (reports/discussion-compendium/ in c-gnn: sections “Step 1”, “Plans” and “Code issues”). Walkthrough pages show many of these issues as they happen.
Open: contact layer
| Issue | Effect | Documented | Fix in |
|---|---|---|---|
| Ties under deep penetration. εpen = 10 mm is ten times εon, so both corners of a tilted box edge can count as touching. | 357 of 4,000 demo poses jittered by about 3 mm are ambiguous (tracked by a test). Since step 2 a tied pose cannot be a solver success or a search node. | Step 1, Step 2, README | Step 3: tighten εpen once the cost stops rewarding penetration (rollouts reach 9.9 mm today) |
| Labels can flicker near θe along a trajectory. | A 3-frame flicker on the demo (frames 623–625) where the tilt hovers at 1.83°. | Step 1 | Execution monitor: hysteresis with thresholds from a noise model |
The 3D catalog (step.yaml) keeps the old defects: closed faces over-count bits, ±y faces, unset template IDs, a Python loop over templates, closest-pair ties broken by “first candidate”. |
Wrong formations and slow compiles for 3D scenes only. | Walkthrough 2, 3, 9 | Frozen with 3D (Decision 3); the planar catalog replaces it |
Open: candidates and search
| Issue | Effect | Documented | Fix in |
|---|---|---|---|
| The search ignores the solver’s success flag. It accepts when the requested bits are in band. | Edits the solver reports as failed can become nodes. | Walkthrough 7, 8 | Step 3 (with Λ and H wired in) |
| A node stores the requested formation, not the one reached. | In a 12-round run, 28 of 30 nodes record a formation they do not have. | Walkthrough 8 | Step 3 |
| A break is accepted without checking that the contact left. | 6 of 7 accepted breaks in that run left the contact in band. | Walkthrough 8 | Step 3 |
| No goal test, goal input or budget; expansion is breadth-first in catalog order. | The search cannot aim at a goal or stop at one. | Walkthrough 8 | Step 4 (ranker, LTS/PHS) |
ContactGraph drops edges: self.edges is never set when edges are passed, and edges_excluded is discarded. |
Nothing downstream uses the graph yet, so no visible effect today. | Walkthrough 4 | Superseded by Decision 8 (attention; exclusions from geometry) |
Open: solver and execution
| Issue | Effect | Documented | Fix in |
|---|---|---|---|
| MPPI’s arrival term is signed and linear (104 φ). | It rewards penetration: the shove seen on walkthrough page 7. | Walkthrough 7 | Step 3 (cost experiment) |
MPPI’s dwell term penalizes velocity, not drift from the task-end pose (hold_target is computed but unused). |
Its docstring describes a different term than the code runs. | Compendium, code issues | Step 3 |
| GPU runs are not repeatable between processes by default. | The same MPPI call ended once flush and once tipped 1.4°. | Step 1, README | Workaround: XLA_FLAGS=--xla_gpu_deterministic_ops=true (about 13% slower) |
| MPPI fails the chain’s edits. In 24 full rollouts of the chain’s edits, none passes the solver’s success check, the passive breaks included (not because of ties). | Edits that Cand offers are not realized, so the search cannot follow the chain. |
Step 2, compendium | Step 3 (cost and success criteria) |
| Margins are unbounded with the disk in the formation. The disk’s force has no limit, so its support cone often fills all of 3D. | The margin cannot rank formations that use the disk. | Step 2 | Decision 6: manipulator force limits. The LP gate takes them already (force_limit, LP-3); the disk’s limit is still unknown |
| The exact hold test is float32. | Its answers within tolerance of the boundary depend on compilation (jitted and eager runs differ on 3 of 136 near-boundary cases). Wrong only near the support boundary in the benchmark (within 0.33 mm of disk height on CPU, 0.67 mm on GPU): 21–26 false rejections and 1–2 false acceptances among 416 near-boundary cases. | Step 2 | Acceptable for now; a margin threshold if it matters. The LP gate behaves alike (float32: 383–386 of 416, every miss an “uncertain” rejection or one of the same 12 upstream disagreements; LP tutorial) |
| The LP gate in 3D is float32-limited. Rounding builds up in linrax’s dense tableau over the long pivot sequences of 3D cones (50–130 generators). | About 1% of supported 3D cases end “uncertain” (rejected), and some exits read 0 (the margin is underestimated). Nothing is certified wrongly. | LP tutorial, compendium (hold-test LPs) | Reinversion (rebuild the tableau from the final basis and continue), with the 3D build |
Open: tests and configuration
| Issue | Effect | Documented | Fix in |
|---|---|---|---|
tests/test_local_solver.py reads gradient_warm_start, which MPPISolver no longer has. |
The script fails if run; pytest collects no test from it. | Compendium, code issues | Fix-up PR for Angelo |
| Step height h = a/4 in the code, 3a/8 in the paper’s numbers. | The paper’s worked numbers are stale (h = a/4 was signed off in Decision 7). | Compendium, status board | Paper backlog |
Open: paper backlog
The paper still follows the old chain or older decisions in these places:
- The chain of Decisions 2 and 7: the example formations and edits, the labels and caption of Figure 1, and the figures of the legal chain and the marking graph.
- The marking-graph figure’s caption still says graph distance equals Hamming distance (the lemma now gives bounds within a factor of four).
- Proposition
gap-miss(i), and the root and live subgraphs. - Decision 8: attention instead of typed edges, and exclusions derived from geometry.
sec:novel, to be rewritten around the survey’s claim-status table.- The worked numbers for h = a/4.
Closed recently
| Issue | Closed by |
|---|---|
linrax could loop forever (no iteration cap; cycling on degenerate 3D LPs), which hangs a whole vmap batch |
Its pivot loop is replaced: a cap of 300 pivots per phase, Bland’s leaving rule, artificial rows marked correctly (Nov 6) |
| linrax, the LP solver, has no license file | Accepted (Aykut, Nov 6): linrax stays, pinned to 0.3.0 |
| linrax returned infeasible points as “optimal” in float32: a basic slack at −1 when need has zero rows (the planar case), pivots on noise at its default tolerance, negative weights with a large exit cap | Householder-spread rows, primal and dual from the final basis, pivot tolerance 10−4, cap 10, every answer checked, e29d96f |
| The hold test’s margin was positive on a cone that is a single ray, and the test failed for fewer than three generators (neither occurred in the planner, which passes 16) | Candidate planes through one generator; margin proved and tested to be the signed distance, 1986c73 |
Cand had no Valid check: a second contact per pair, excluded formations, transport always legal |
Edit set with Valid, transfer and pass-through; transport only when supported (step 2) |
| The hold test’s “not supported” was uncertified: the MPAX LPs rejected 192–194 of 416 supported near-boundary cases | Exact planar test with a witness or a Farkas certificate (step 2) |
| No transfer generator: g → gv needed a break and a make through a marking where the box does not touch the floor | transfer(c → d) and the pivot pass-through (step 2) |
The paper’s Lemma markgraph-struct and Remark cube assumed make and break only |
Restated with transfer and pass-through, and checked exhaustively (step 2) |
| One physical contact lit 3 to 6 template bits (closed faces share edges) | Principal-contact on-set, ca4123b |
| The hold test used one tie-broken point per contact, blended by smoothing; ±y faces on a planar body | Contact-set endpoints as support points, planar catalog, ca4123b |
| The step corner belonged to riser and platform; the floor–riser junction lit a bit | Corner ownership (Decision 4), ca4123b |
| Exclusions by integer index, then dropped; no vertex features for gv, sv | step2d.yaml with named templates and vertices, ca4123b |
| Half-plane penetrations charged to the wrong surface (−31 mm into the platform) | Penetration attribution (approved Nov 5), ca4123b |
Python loop over templates in Catalog.gap |
Planar catalog groups templates by kernel, one vmap each, ca4123b (the 3D catalog still loops) |
| NaN gradients in the planar kernels | Safe norms and roots, b2665cb |
| The length rule produced {gv, s} at the pivot, and called a box tipped 7° flat | θe = arcsin(εon/h) ≈ 1.83°, 5f5a2e8 |
pyproject.toml was invalid TOML |
Fixed upstream in Angelo’s phase1/dev; verified Nov 5 |