Skip to content

animaEngine 0.9.0 — the stability freeze

Choose a tag to compare

@github-actions github-actions released this 20 Jun 20:19
· 483 commits to main since this release

animaEngine 0.9.0 — the stability freeze

The release before 1.0 deliberately ships no new features. Its job
is to prove the 1.0 contract before promising it: measure what the
0.6–0.8 cycles built, harden the edges, and make the docs tell the
truth. Feature work stopped the day this phase opened; everything here
is migration safety, leak hunting, fuzzing, and audit.

Config that survives its own future

A top-level version key now records the config schema generation.
Files written before 0.9 have no key, are treated as schema v1, and
migrate on load — but the original is copied to config.toml.bak-v<n>
before any migration runs
, so a migration bug can never be why you
lose a config. A malformed version is treated as current rather than
risking the wrong migration, and unknown [section] tables (e.g. from
a newer build) survive a load → save round-trip instead of being
dropped. v1→v2 is an honest identity migration — every change so far
was additive — but the chain, backup, and forward-compat are in place
and tested for the first change that isn't.

Proving memory is bounded

  • Soak harness (scripts/soak.sh): a 16-entity synthetic scene
    under Xvfb, RSS least-squares-regressed against time to catch slow
    leaks. The regression fits the steady state only — a cold start
    legitimately steps memory once as the cache fills, and fitting across
    that step would cry "leak" on a flat run.
  • Leak audit: every pre-registered suspect came back bounded with a
    cited mechanism. The one real growth was the on-disk decode cache
    (content-addressed keying orphans a file on every asset edit, never
    reclaimed); cache::sweep now evicts oldest-first past a 1 GiB cap at
    startup, off-thread.
  • Perf HUD GPU block: the overlay (`Ctrl+Shift+``) shows a VRAM
    estimate, live texture count + uploads/frame, and draw calls — the
    same numbers the soak harness regresses, live.

Hardening

  • GPU surface-loss recovery. A lost surface reconfigures in place
    for the transient cases (resize, occlusion, the first frames after
    suspend); a loss that persists past a threshold — driver reset, GPU
    hot-unplug, device lost across S3 resume — rebuilds the whole renderer
    from the retained window, and exits cleanly for a restart if even that
    fails, rather than spinning on a dead device.
  • Expanded fuzzing. Three new cargo-fuzz targets over the
    hand-written parsers closest to untrusted bytes: the on-disk cache
    codec, the MP4 NALU length-prefix walk, and the Shimeji actions.xml
    reader, with committed seeds and a nightly CI run.
  • XWayland fractional-scaling click-through is now detected and
    warned about at startup instead of leaving misaligned clicks a
    mystery — an inherent XWayland limitation, documented with the
    workarounds.
  • Forward-compat with the upcoming rustc float-literal inference
    change (caught by the weekly beta-toolchain canary before it became a
    hard error).

Docs that match the code

  • Reality audit: every docs/*.md diffed against the code.
    config.md now documents every field (it was missing themes,
    locale, monitor mode, the per-state animation sets, the windows /
    groups / keybindings sections, and several env vars); the architecture
    diagrams were reconciled with the post-0.6 module layout; the threat
    model's stale claims were corrected (the AccessKit bridge is a live
    flag, hotkeys are rebindable, release artefacts carry Sigstore
    provenance, and the native-Wayland path is now near-parity through the
    same drag-drop validation boundary).
  • Cross-locale audit: 194 keys × 10 locales came back clean on key
    parity and placeholder parity — and the placeholder guarantee is now
    a test, so a translator dropping a { $var } fails CI. The sweep
    fixed six corrupted strings from an earlier batch.
  • Freeze rules published. CONTRIBUTING.md declares the bugfix-only
    window to 1.0: what qualifies (crash, data loss, regression, security,
    doc error, translation), what waits, and how exceptions get decided.

Audit notes (1.0-grade)

A full-tree re-audit, treated like the 0.5.0 pass. The panic surface is
clean: three unsafe blocks (two getuid, one wgpu surface handle, all
justified), and every production .unwrap() is either bounds-guarded
(the cache codec, also fuzzed) or a set-then-read invariant. The D-Bus
surface is five parameterless methods — no untrusted IPC input. Env
vars parse with fallbacks; size math is checked/saturating
throughout, gated by the decoded-bytes budget. Findings were fixed or
formally accepted in docs/threat-model.md.

Known limitations (accepted for 1.0)

  • openh264 runs in-process, unsandboxed. MP4/H.264 playback reaches
    Cisco's C decoder; we bound the input (caps, a pure-Rust demuxer that
    pre-validates, a fuzzed NALU walk) but don't isolate the decoder.
    A seccomp-confined decode thread is the right fix and is deferred past
    1.0. If you don't play video, nothing reaches it.
  • A native-Wayland device-loss rework and an App struct split are
    deliberately deferred — both are out of scope under the freeze.
  • The visual a11y matrix and a screen-reader walkthrough still want a
    human at a real session (tracked in docs/ux-audit-0.8.md).
# Debian / Ubuntu
sudo apt install ./anima-engine_0.9.0-1_amd64.deb

# AppImage
chmod +x animaEngine-0.9.0-x86_64.AppImage
./animaEngine-0.9.0-x86_64.AppImage