Skip to content

Add animated state transitions to catwalk actors #183

Description

@williamthorsen

Problem

The catwalk scene currently tears down and rebuilds all Excalibur actors on every CanonicalRunStatus update. This causes visual snapping — the orchestrator teleports between stations, agents appear/disappear instantly, and gates toggle without transition. During a live run, this creates a jarring experience.

Proposed solution

Replace the tear-down-and-rebuild pattern in CatwalkScene.updateStatus() with diff-driven animation dispatch:

  1. Actor registryCatwalkScene maintains references to live actors keyed by identity (orchestrator singleton, agents by ID, gates by station pair, artifacts by composite key)
  2. Diff computation — On each status update, compute a CatwalkDiff via the existing diffCatwalkConfig() (already implemented and tested)
  3. Animation dispatch — For each diff category, call targeted animation methods on the affected actors:
    • Orchestrator walk: actions.moveTo() slides along the catwalk rail
    • Orchestrator working glow: sine-wave opacity pulse via onPreUpdate
    • Agent state transitions: actions.fade() tweens between opacity levels; working agents pulse
    • Agent deactivation: agents that complete their role fade to low opacity instead of being removed (preserves visual history)
    • Gate open: actions.scaleTo() shrinks gate height to zero over ~300ms
    • Artifact appearance: new artifacts fade in from invisible

Key design decisions

  • deactivated agent state: new AgentAnimationState value. Agents that leave the config transition to deactivated (low opacity, no pulse) rather than being killed. This preserves a visual record of which agents participated.
  • Sine-wave pulse via onPreUpdate: avoids conflicting with Excalibur's sequential action queue, allowing pulse and movement to run simultaneously.
  • Tunable constants: all animation values (DEACTIVATED_OPACITY, pulse ranges, frequency) live in constants/animation.ts for easy visual tuning.

Acceptance criteria

  • Orchestrator visually walks between stations (not teleporting) when the active phase changes
  • Orchestrator pulses when in working state, stops when idle
  • Agent state changes are visible as smooth opacity transitions
  • Working agents pulse; deactivated agents fade to low opacity
  • Gates animate open (scale Y to 0) rather than toggling visibility
  • New artifacts fade in at their station position
  • Scene updates smoothly when CanonicalRunStatus changes during a live run
  • No increase in entity count when status is unchanged (diff detects no changes)
  • All animation timing constants are tunable via constants/animation.ts

Scope exclusions

  • Station input/output visual layout (inputs left of divider, outputs right, divider line): the slot: 'input' | 'output' field already exists in the data model and differ; visual positioning is deferred
  • Chute animation: not in scope for this issue

Metadata

Metadata

Labels

featureAdded or improved external functionalityscope:factory

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions