PURPOSE

Strategy pattern for the reward pipeline’s reveal and collect phases. Replaces if (source === 'pull') branches in the orchestrator with a presenter adapter that selects a strategy from PresentationHints on the batch. Two built-in strategies: a default card-flip + fly-to-target flow, and a pull pass-through that defers to the existing pull-engine.

OWNS

  • The RewardPresenter interface (optional presentReveal + presentCollect async methods).
  • defaultPresenter — stubbed standard card spawn + flip + burst, then fly-to-target with counter settle.
  • pullPresenter — no-op pass-through that lets the pull screen drive its own reveal/collect.
  • getPresenter(batch) — resolver that picks a presenter based on batch.presentation.revealMode, batch.presentation.collectMode, and batch.source.

READS FROM

  • RewardBatch (type from ../data/reward-types) — specifically batch.presentation.revealMode, batch.presentation.collectMode, and batch.source.

PUSHES TO

  • Nothing direct. Returns presenter strategies for the orchestrator to await. Method bodies in defaultPresenter are currently TODOs; method bodies in pullPresenter are intentional no-ops because the pull engine handles its own animations.

DOES NOT

  • Does not advance the reward pipeline phase — that is the orchestrator’s job.
  • Does not own the pull engine’s reveal flow — pull presenter is a pass-through.
  • Does not handle revealMode === 'none' or collectMode === 'none' — the orchestrator skips those phases entirely without consulting a presenter.
  • Does not spawn DOM, fire bursts, run fly-to animations, or settle counters today — the default presenter’s bodies are stubbed pending visual wiring.
  • Does not register additional source-specific presenters beyond pull.

Signals

  • presentReveal(batch) — promise resolves when reveal animations are done (cards shown, bursts fired).
  • presentCollect(batch) — promise resolves when all fly-to animations and counter settles are done.
  • Either method may be absent on a presenter; the orchestrator skips that phase.

Entry points

  • getPresenter(batch: RewardBatch): RewardPresenter — the orchestrator’s resolution call.
  • defaultPresenter — exported strategy for standard rewards.
  • pullPresenter — exported strategy for pull-source batches.

Pattern notes

  • Resolution rule: if either revealMode or collectMode is 'custom' and batch.source === 'pull', return pullPresenter; otherwise return defaultPresenter.
  • 'default' modes route to defaultPresenter; 'none' modes are handled upstream by the orchestrator skipping the phase, not by a presenter variant.
  • The pull pass-through is acknowledged as transitional debt — long-term goal is to extract the pull-engine reveal into a real presenter adapter.
  • Adding a new source with custom presentation means: define its presenter object here, then extend the getPresenter branch to map batch.source to it.
  • Default presenter’s documented behavior (card spawn into #fx-floating, igniteBloom + spawnBurst, 50ms stagger, flyToTarget per grant card to wallet anchor, pulseTarget on landing, counter settle via displayOverride release) describes the intended implementation; current bodies are stubs that resolve immediately.