Skip to content

Reproduce confetti animation bug: non-deterministic particles#68

Merged
jappeace merged 2 commits intojappeace:masterfrom
jappeace-sloth:test/confetti-repro
Apr 19, 2026
Merged

Reproduce confetti animation bug: non-deterministic particles#68
jappeace merged 2 commits intojappeace:masterfrom
jappeace-sloth:test/confetti-repro

Conversation

@jappeace-sloth
Copy link
Copy Markdown

Summary

  • Adds 6 integration tests that render the confetti widget tree through hatter's rendering engine
  • Reproduces the root cause: confettiOverlay uses newStdGen instead of stConfettiSeed, making particles non-deterministic across re-renders
  • The diff engine sees changed widgets on every re-render, re-registers tweens, and restarts animation from scratch

Test results

  • 5 passing tests confirm the animation system itself works (tweens register, particles start at origin, targets are non-zero, fade end-state has alpha 0)
  • 1 failing test proves the bug: confettiOverlay is not deterministic across calls

Root cause

confettiOverlay (Views.hs:231) calls newStdGen on every invocation. AppState already has stConfettiSeed :: StdGen (AppState.hs:37) intended for deterministic particles, but confettiOverlay ignores it.

Test plan

  • cabal build passes
  • 66/67 tests pass; 1 expected failure (the reproducer)
  • Fix: make confettiOverlay accept StdGen parameter, pass stConfettiSeed

🤖 Generated with Claude Code

jappeace-sloth and others added 2 commits April 19, 2026 18:48
Add integration tests that render the confetti widget tree through
hatter's rendering engine and verify animation behaviour.

The reproducer test "confetti uses newStdGen" demonstrates the bug:
confettiOverlay uses newStdGen on every call, producing different
particle positions each render. The diff engine sees changed widgets,
re-registers tweens and restarts animation from scratch. AppState
already has stConfettiSeed for deterministic particles but
confettiOverlay ignores it.

Five passing tests confirm the animation system itself works:
- Tweens register on first render
- Tweens register on Stack 1->2 child transition
- Particles start at origin (0,0)
- Particles have non-zero target positions
- Fade end-state has alpha 0

Prompt: investigate why the animation for confetti doesn't work, make a reproducer first

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
confettiOverlay was calling newStdGen on every render, producing
different random particle positions each time. Hatter's diff engine
saw the changed widgets, re-registered tweens, and restarted the
animation from scratch on every re-render.

Now confettiOverlay takes a StdGen parameter. enterPRView passes
stConfettiSeed from AppState, which was already created for this
purpose but never used. The determinism test now passes.

Prompt: okay go do that then

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jappeace jappeace merged commit ed77e62 into jappeace:master Apr 19, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants