Repository navigation
Close the gaps left after the #344 and #359–#387 batch #438
Copy link
Copy link
Closed
13 / 1313 of 13 issues completedClosed
13 / 1313 of 13 issues completed
Copy link
Labels
enhancementNew feature or requestNew feature or request
Description
Tracking issue for the gaps left after #344 and #359–#387 were closed.
Every closed issue was re-verified against main (0.7.1, ef0b69e) by re-running its reproductions and rendering its requested features. Several fixes do not reach the render, some sub-requests were never delivered, and a user who built a real one-take product film with 0.7.0 reported further blockers. Each sub-issue below is self-contained: context, items with reproductions, known root causes and a definition of done.
Suggested order
- Regression: no icon renders since the icon cache rework (#365) #425 — regression: no icon renders (blocks every scenario using
icon). - Animations touching only border_radius, clip_path_progress or font_size are never applied #426 — animations touching only
border_radius,clip_path_progressorfont_sizeare dropped (one root cause behind Animating border_radius validates and has no effect #373, Animate clip-path: interpolate polygon, inset, circle and ellipse in keyframes #384 and a user report). - Camera: a world larger than the frame, per-segment easing, handheld shake, camera-aware validation #428 and Motion blur: pointer paths, in-flow ghost placement, velocity-oriented smear, smooth whip, camera motion blur #427 — free camera and motion blur: the user's main blockers.
- Text: letter_spacing on rich_text/gradient_text, animated tracking layout, static opacity vs animated opacity, caret after typed text #430, char_* presets: rotate_from, scale/baseline jitter, reflow (undelivered parts of #363) #429, Path drawing: draw_start on finished svg strokes, arrow/connector, draw_offset, svg d morph, dot at progress 0 #431, Transitions: feathered wipes leak at fixed edges, clip-path blob, iris pill, warnings for ignored fields #432, Pointer: waypoints without a click, readable hand/grab glyphs #433, Materials, 3D and backgrounds: inflated banding, globe arcs over time, layout-surface orientation, halo interpolation, box-shadow under transparent boxes #434, Validator and vocabulary consistency: arrow/connector bounds, overflow hints, gradient stops, duplicate warnings #437.
- Documentation errors found while verifying the latest features #436 — documentation, then Encoding default and release: 8-bit H.264 by default, publish main #435 — encoding default and release.
Sub-issues
- Regression: no icon renders since the icon cache rework (#365) #425 Regression: no icon renders since the icon cache rework (Icons: cache keyed by colour and size, no retry on HTTP 429, and render panics where still and sheet only warn #365) — merged in fix(icons): repair the attribute rewrite that stopped every icon rendering #439
- Animations touching only border_radius, clip_path_progress or font_size are never applied #426 Animations touching only border_radius, clip_path_progress or font_size are never applied — merged in fix(animation): make every animated property reach layout and the frame #443
- Motion blur: pointer paths, in-flow ghost placement, velocity-oriented smear, smooth whip, camera motion blur #427 Motion blur: pointer paths, in-flow ghost placement, velocity-oriented smear, smooth whip, camera motion blur
- Camera: a world larger than the frame, per-segment easing, handheld shake, camera-aware validation #428 Camera: a world larger than the frame, per-segment easing, handheld shake, camera-aware validation
- char_* presets: rotate_from, scale/baseline jitter, reflow (undelivered parts of #363) #429 char_* presets: rotate_from, scale/baseline jitter, reflow (undelivered parts of char_* presets are silently ignored on rich_text and gradient_text, and lack rotation, per-unit jitter and reflow #363) — merged in feat(char): add rotate_from, scale and baseline jitter, and reflow #450, closed after both stated gaps were resolved
- Text: letter_spacing on rich_text/gradient_text, animated tracking layout, static opacity vs animated opacity, caret after typed text #430 Text: letter_spacing on rich_text/gradient_text, animated tracking layout, static opacity vs animated opacity, caret after typed text — merged in fix(animation): make every animated property reach layout and the frame #443
- Path drawing: draw_start on finished svg strokes, arrow/connector, draw_offset, svg d morph, dot at progress 0 #431 Path drawing: draw_start on finished svg strokes, arrow/connector, draw_offset, svg d morph, dot at progress 0 — merged in fix(draw): make draw_start, draw_offset and svg path morph reach the frame #444
- Transitions: feathered wipes leak at fixed edges, clip-path blob, iris pill, warnings for ignored fields #432 Transitions: feathered wipes leak at fixed edges, clip-path blob, iris pill, warnings for ignored fields — merged in fix(transition): stop the feather leaking, give the pill its corners, add clip-path blob #448
- Pointer: waypoints without a click, readable hand/grab glyphs #433 Pointer: waypoints without a click, readable hand/grab glyphs — merged in fix(pointer): add per-waypoint click, redraw the hand and fist, make outline visible #442
- Materials, 3D and backgrounds: inflated banding, globe arcs over time, layout-surface orientation, halo interpolation, box-shadow under transparent boxes #434 Materials, 3D and backgrounds: inflated banding, globe arcs over time, layout-surface orientation, halo interpolation, box-shadow under transparent boxes — merged in fix(paint): dither the inflated ramp, face the surface, wire the halo lerp #445
- [~] Encoding default and release: 8-bit H.264 by default, publish main #435 Encoding default and release — item 1 merged in fix(encode): make 8-bit the default H.264 output #441; 0.8.0 is prepared and its publish dry-run is green, awaiting the tag
- Documentation errors found while verifying the latest features #436 Documentation errors found while verifying the latest features — merged in docs(skills): fix the broken examples and add the check that keeps them fixed #446
- Validator and vocabulary consistency: arrow/connector bounds, overflow hints, gradient stops, duplicate warnings #437 Validator and vocabulary consistency: arrow/connector bounds, overflow hints, gradient stops, duplicate warnings — merged in fix(validate): stop the false positives, name the right edge, warn once #449
Out of scope for now (to discuss)
- Sound effects generated from events (clicks, keystrokes): a synthesised score already exists.
- Free per-frame computed animation (springs, arcs, grouping): expressions and
node()cover part of it.
Rules for every sub-issue
- Test first: a test that fails on
main, a render test with pixel assertions for anything visual. - Verified end to end (scenario,
validate, render, image inspected) before the PR is merged. - Docs, rules and schema updated with any vocabulary change; a field the validator accepts must have an effect.
- One PR per sub-issue. No AI attribution in commits, PRs or comments.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request
Activity
LeadcodeDev commentedon Sep 29, 2026
#425 is merged (#439). The attribute rewrite left
width="84""behind, so no icon has parsed since #390; the existing tests assertedcontains("width=\"84\""), which is true of the broken string too. Render tests with pixel assertions now cover it — 0 coloured pixels on the revert.render --framealso exits 1 on an unresolvable icon like the other paths, and a cache filled under the old{slug}-{colour}-{w}x{h}naming is migrated rather than refetched.Its fourth item — an offline gate for icons — is #440 rather than part of that PR: #320 has since landed
--allow-remote-fonts, and the icon gate should follow that decision rather than precede it.LeadcodeDev commentedon Sep 29, 2026
Decomposition, file partition and frozen contracts
Recorded here so a session with no shared memory can resume it.
Waves
box_builderlibrich_textgradient_textcss/animationcss/cascade·svgshapearrowconnectoranimatorschema/videovalidate_schema·paint_passdot_maprender/backgroundrender/sceneanimatorintrinsicrich_texttext·transitionpaint_passvalidate_schema·geometrygradient_textcli/validateencode/tasksbox_buildertransitionrender/scenepointer·render/scenegeometryschema/shakeengine/shake#426 and #430 are merged into one workstream. They are the same architectural bug under two names:
with_cascaded_stylefolds resolved CSS into a typographic component's clone throughinherit_from, which only fills fields that areNone, so a component declaring its own staticletter-spacingorfont-sizenever sees the animated override at measurement time — only at paint time. Two workstreams editing that one mechanism is a decomposition error, so they are one.#427 and #428 share the camera logic in
render/scene.rs, so they get one writer and two pull requests rather than two writers and a merge conflict.Orchestrator-owned — no sub-agent writes these
crates/rustmotion/skills/SKILL.md,crates/rustmotion/skills/rules/*.md,crates/rustmotion-core/src/css/style.rs,crates/rustmotion-core/src/schema/scenario.rs, and everyCargo.toml.SKILL.mdalone was contended by seven of the twelve issues, because each one's definition of done says vocabulary changes update it. Agents report the exact text they want and where; the deltas are applied in one pass, as #436.Regime
Agents edit disjoint files in one shared checkout and run no git command at all — the orchestrator commits each workstream to its own branch by staging only that workstream's paths. Each agent gets its own
CARGO_TARGET_DIR, since cargo's lock on the target directory otherwise serialises the parallelism the partition just earned. Agents run targeted tests on their own crates only: a full-workspace run in a shared tree tests siblings' unfinished work, so it fails for reasons they cannot act on. The full suite is the orchestrator's, after each integration.Three findings that changed the plan
SceneShakecarriesimpacts: Vec<ShakeImpact>withdecay,frequencyandrotation: discrete beat-synced hits, not a continuous handheld wobble. The mechanism for a second signal additive overcameraexists; the mode does not. That puts the work inschema/shake.rsandengine/shake.rs, which nobody else writes, and takes item 4 out of the contention onrender/scene.rs.IRIS_PILL_CORNER_FRACTION = 0.2attransition.rs:655, used ashalf_w.min(half_h) * 0.2at line 692. A stadium needs it near 1.0.line.rsalready extracts a segment withPathMeasure;arrow.rsandconnector.rsstill use the dash[draw_len, total_len - draw_len + 0.01], and a zero-length dash with a round cap paints a solid dot. Port the existing fix rather than designing one.LeadcodeDev commentedon Sep 29, 2026
#427 is done — PR #452, green on all four CI jobs. The six items, each verified end to end (scenario,
validate, render, image inspected) as its definition of done asks.Camera motion blur is the one that needed a number before it could be decided, since #362 was parked on exactly that. Measured at 1920×1080 on real content, slope over 180 frames so startup drops out: 4.1 ms/frame without, 8.8 ms/frame at
samples: 8— 2.2× end to end rather than 8×, because encode and frame setup are paid once per frame whatever the render costs. A frame whose camera pose does not change across the shutter window takes the ordinary single-render path, so a held shot is free.#428 is now in progress on top of it, with a head start: the first item's root cause is diagnosed and written into that issue's thread — the content is not missing, the viewport clip is issued after the camera transform and travels with it, so a pan wider than the frame clips everything away. #451 filed that separately and is closed as a duplicate.
LeadcodeDev commentedon Sep 29, 2026
#428 is done — PR #453, stacked on #452 while that one waits for its merge.
All four items verified end to end with the issue's own scenarios. The first one was not a missing feature:
clip_rectwas issued after the camera transform, and Skia bakes a clip into device space using the matrix in force at that moment, so the clip travelled with the camera and a pan wider than the frame clipped everything away.validatehad the matching defect on its own side — the camera fold read the staticx/y/zoomfields, so a purely keyframe-driven camera folded as if it never moved.Handheld shake needed no code at all.
scene.shakealready composes additively incamera_pose_at, andeffective_cameraalready synthesises an identity camera when onlyshakeis set. Measured across an impact: −40 px at its peak on top of an ongoing pan, +4 the frame after, 0 before. Two regression tests pin that instead of a second mechanism.With this, every sub-issue of the batch is closed except #435's second half, which is the crates.io release and is a decision rather than work.
One pre-existing gap now written into
geometry-safety.mdrather than left to be discovered: the camera fold accounts forx,yandzoomonly, so an element brought into frame purely bycamera.rotationor an animatedoriginis still reported as an overflow.fix(motion-blur): ghost placement, path transforms, velocity-oriented…
feat(camera): pan across a world wider than the frame, per-keyframe e…
feat(camera): pan across a world wider than the frame, per-keyframe e…