From the 2026-07-06 codebase audit (docs/audits/codebase-audit-2026-07-06.md, in-repo). Finding IDs are stable — cite them in fixes.
Severity: High · Status: CONFIRMED (all items traced against src and shipped dist)
The four API sections of readme.md are wrong in load-bearing ways. One rewrite unit — regenerate from the shipped .d.ts, not from memory:
- C9 — "Engine Only" example cannot run (
readme.md:224): calls engine.setContainer({...}) — no such method on Elastica (the container is set via initialCondition(elements, rect, cb)). Second line throws TypeError. Even without that line the example never calls initialCondition, so update() no-ops and the spatial hash degenerates (C36).
- C10 — BoundaryBox example is fiction (
readme.md:112-126): isStatic, mass, restitution, displayScale, shape — none exist; BoundaryBoxProps = HTMLAttributes<HTMLDivElement> (boundary-box.tsx:9). The real static mechanism — data-state="static" — is documented only in JSDoc. There is no per-element mass/restitution/shape API in DOM mode at all (audit open question 11: planned or fiction?).
- C11 — CanvasBox example uses the wrong vocabulary (
readme.md:128-144): shape="rectangle" + isStatic vs the real 'rect' | 'circle' + static (types.ts:36, canvas-box.tsx:27). 'rectangle' falls through both renderer branches → the particle collides but is never drawn. Bonus: the engine's own ShapeType is 'rectangle' | 'circle' while react-canvas uses 'rect' — one concept, two vocabularies (unifying is breaking, but pre-1.0).
- C12 — config table wrong on defaults (
readme.md:100-110): useOBB documented false, actual true (elastica.ts:70); gridSize documented 8 — true for DomElastica only (engine/canvas: 4); solver.slop/solver.percent missing entirely. gridSize semantics are C8 (spatial-hash issue).
- C13 — quick start renders broken (
readme.md:26-52): renderElement writes container-space top-left coords — correct only if each box is position: absolute; top: 0; left: 0 inside a sized container. The README shows plain in-flow divs, no container sizing, and key={i} index keys (the exact trigger for the registration corruption in C5). Either BoundaryBox enforces the contract (one line of CSS) or the contract is the first line of the docs.
- C20 — README claims both modes support shapes (
readme.md:9): DOM mode cannot do circles at all (boundary-box.tsx:49-52).
- C57 — "initialCondition … called once on mount" is false (
readme.md:94): runs 2-3× on mount, on every debounced resize, on rect moves, and (canvas) on every register/unregister. Users put one-time setup in it and get repeated side effects.
- C82 —
containerOffsets documented as pixels, actually fractions (readme.md:106; borders.ts:26-27, 40-65, 79-80): multiplied by container dimensions, with an asymmetric sign convention (top/left positive, bottom/right negative). {top: 10} insets by 10× the container height and flings everything out.
Direction
Rewrite all four sections against dist/*.d.ts + actual defaults; make every example a file that is compiled/run (even a tiny CI smoke — see the CI issue) so the README can't drift again. Depends on API decisions in open questions 3 and 11.
Severity: High · Status: CONFIRMED (all items traced against src and shipped dist)
The four API sections of
readme.mdare wrong in load-bearing ways. One rewrite unit — regenerate from the shipped.d.ts, not from memory:readme.md:224): callsengine.setContainer({...})— no such method onElastica(the container is set viainitialCondition(elements, rect, cb)). Second line throwsTypeError. Even without that line the example never callsinitialCondition, soupdate()no-ops and the spatial hash degenerates (C36).readme.md:112-126):isStatic,mass,restitution,displayScale,shape— none exist;BoundaryBoxProps = HTMLAttributes<HTMLDivElement>(boundary-box.tsx:9). The real static mechanism —data-state="static"— is documented only in JSDoc. There is no per-element mass/restitution/shape API in DOM mode at all (audit open question 11: planned or fiction?).readme.md:128-144):shape="rectangle"+isStaticvs the real'rect' | 'circle'+static(types.ts:36,canvas-box.tsx:27).'rectangle'falls through both renderer branches → the particle collides but is never drawn. Bonus: the engine's ownShapeTypeis'rectangle' | 'circle'while react-canvas uses'rect'— one concept, two vocabularies (unifying is breaking, but pre-1.0).readme.md:100-110):useOBBdocumentedfalse, actualtrue(elastica.ts:70);gridSizedocumented 8 — true for DomElastica only (engine/canvas: 4);solver.slop/solver.percentmissing entirely. gridSize semantics are C8 (spatial-hash issue).readme.md:26-52):renderElementwrites container-space top-left coords — correct only if each box isposition: absolute; top: 0; left: 0inside a sized container. The README shows plain in-flow divs, no container sizing, andkey={i}index keys (the exact trigger for the registration corruption in C5). Either BoundaryBox enforces the contract (one line of CSS) or the contract is the first line of the docs.readme.md:9): DOM mode cannot do circles at all (boundary-box.tsx:49-52).readme.md:94): runs 2-3× on mount, on every debounced resize, on rect moves, and (canvas) on every register/unregister. Users put one-time setup in it and get repeated side effects.containerOffsetsdocumented as pixels, actually fractions (readme.md:106;borders.ts:26-27, 40-65, 79-80): multiplied by container dimensions, with an asymmetric sign convention (top/left positive, bottom/right negative).{top: 10}insets by 10× the container height and flings everything out.Direction
Rewrite all four sections against
dist/*.d.ts+ actual defaults; make every example a file that is compiled/run (even a tiny CI smoke — see the CI issue) so the README can't drift again. Depends on API decisions in open questions 3 and 11.