An exhaustive audit of the five crates on main @ 97b122d produced 217 findings: 62 High, 105 Medium, 45 Low, 3 Info, no Critical. Report: https://claude.ai/artifact/V7ttBMi4SbqxDQmKt9A8XH
Four of them were not found by reading the code. They came out of porting a real promotional animation to a scenario and watching it fail, which is why they sit first in the order below: they block the most ordinary thing a promo asks for, several elements entering and leaving in turn inside one continuous scene.
Work happens on chantier/audit-2026-09-25. One branch per fix, pulled from the chantier, squash-merged into it once CI is green. The chantier lands on main as a single pull request, and only with an explicit go.
Frozen before any dispatch
ConversionContext::for_viewport(w, h) is the single constructor the validator and the renderer share. Do not reintroduce ConversionContext::default() on a path that knows the real viewport.
The Painter trait signature does not change. Defaulted methods may be added; paint_content may not.
Seventeen fields deserialize, pass validation, appear in the exported schema and do nothing. Each is either implemented or removed so the unknown-attribute error catches it. Leaving one inert is the only option that contradicts the strictness contract the schema is sold on.
Order
Write partition
Each workstream owns a disjoint set of files. Cargo.toml, Cargo.lock, the module-registration lib.rs files, README.md, CLAUDE.md, .github/ and crates/rustmotion/skills/ are not written by a workstream: a line needed there is reported and applied in one pass at integration.
Resolved
Closed by 3ba6f76. Six of the seven red tests were real detection losses and are fixed; the seventh was a genuine reclassification, and its fixture moved back inside the frame to restore the invariant its own docstring claims rather than have the assertion relaxed. The audit's reproduction errors again with the message it gave before 8afc4c1. Full suite on a quiet tree: 1437 passed, 0 failed.
What the hold was
8afc4c1 is correct and stays, but it must not ship alone. Defaulting a container to column removes the cross-axis clamp a fixed-height card used to impose on an oversized child, so the child grows to its natural size and the layout box then matches its own grown content. check_content_overflows_box stops firing. Where the grown box crosses the frame edge check_viewport still catches it, reclassified; where it stays inside, or where the node carries bleed: true, the overflow is no longer reported at all.
A 300x80 card holding a 44px paragraph reports text (wrapped content exceeds its own box) before the change and Valid scenario after. The pattern covers 45 of the 98 card instances in examples/. Seven tests in geometry.rs fail, some of them legitimate reclassifications and some genuine losses; they are being sorted one by one rather than relaxed.
An exhaustive audit of the five crates on
main@97b122dproduced 217 findings: 62 High, 105 Medium, 45 Low, 3 Info, no Critical. Report: https://claude.ai/artifact/V7ttBMi4SbqxDQmKt9A8XHFour of them were not found by reading the code. They came out of porting a real promotional animation to a scenario and watching it fail, which is why they sit first in the order below: they block the most ordinary thing a promo asks for, several elements entering and leaving in turn inside one continuous scene.
Work happens on
chantier/audit-2026-09-25. One branch per fix, pulled from the chantier, squash-merged into it once CI is green. The chantier lands onmainas a single pull request, and only with an explicit go.Frozen before any dispatch
ConversionContext::for_viewport(w, h)is the single constructor the validator and the renderer share. Do not reintroduceConversionContext::default()on a path that knows the real viewport.The
Paintertrait signature does not change. Defaulted methods may be added;paint_contentmay not.Seventeen fields deserialize, pass validation, appear in the exported schema and do nothing. Each is either implemented or removed so the unknown-attribute error catches it. Leaving one inert is the only option that contradicts the strictness contract the schema is sold on.
Order
atwhen several steps exist — b9cf23astart_atopens the visibility window without rebasing the animation clock — 83f7ca68afc4c1opens in the geometry validator — 3ba6f76Write partition
Each workstream owns a disjoint set of files.
Cargo.toml,Cargo.lock, the module-registrationlib.rsfiles,README.md,CLAUDE.md,.github/andcrates/rustmotion/skills/are not written by a workstream: a line needed there is reported and applied in one pass at integration.Resolved
Closed by
3ba6f76. Six of the seven red tests were real detection losses and are fixed; the seventh was a genuine reclassification, and its fixture moved back inside the frame to restore the invariant its own docstring claims rather than have the assertion relaxed. The audit's reproduction errors again with the message it gave before8afc4c1. Full suite on a quiet tree: 1437 passed, 0 failed.What the hold was
8afc4c1is correct and stays, but it must not ship alone. Defaulting a container to column removes the cross-axis clamp a fixed-height card used to impose on an oversized child, so the child grows to its natural size and the layout box then matches its own grown content.check_content_overflows_boxstops firing. Where the grown box crosses the frame edgecheck_viewportstill catches it, reclassified; where it stays inside, or where the node carriesbleed: true, the overflow is no longer reported at all.A 300x80 card holding a 44px paragraph reports
text (wrapped content exceeds its own box)before the change andValid scenarioafter. The pattern covers 45 of the 98 card instances inexamples/. Seven tests ingeometry.rsfail, some of them legitimate reclassifications and some genuine losses; they are being sorted one by one rather than relaxed.