Skip to content

calendar: graceful fallback when start-takeover animation is undrawable - #19

Merged
sumitake merged 1 commit into
mainfrom
dev/claude/start-anim-fallback
Aug 7, 2026
Merged

calendar: graceful fallback when start-takeover animation is undrawable#19
sumitake merged 1 commit into
mainfrom
dev/claude/start-anim-fallback

Conversation

@sumitake

@sumitake sumitake commented Aug 7, 2026

Copy link
Copy Markdown
Owner

What

Makes the calendar_countdown v1.6 start-takeover robust against a mistyped start_animation config value (feature landed in #18).

The takeover draws a full-panel stock AnimationElement (shared/<start_animation>.anim) for the first start_window_seconds after an event begins. If start_animation names an animation that isn't on the device (operator typo — the default meeting_72x16 is valid), the live device rejects the draw with DrawResult.ERROR every poll. Because the takeover is the only thing on screen, state["last_shape"] never commits, run_once re-clears + re-fails each poll, and the panel stays DARK for the whole window (~60 s) instead of showing anything.

Change

run_once now falls back to the normal in-progress (ENDS) layout for that poll when a just_started takeover draw returns ERROR — so a typo degrades to a live countdown rather than a blank panel, and logs the misconfiguration.

  • Only ERROR triggers the fallback, deliberately:
    • REJECTED → a strictly-higher-priority app owns the screen; the in-progress layout draws at a lower priority (PRIORITY_AMBIENT vs the takeover's PRIORITY_AMBIENT_URGENT) and would be rejected too — a pointless second draw.
    • UNREACHABLE → device down; the loop's own backoff (main()) handles it.
  • Per-poll, not latched — self-heals the next poll once the config is fixed or the animation appears, no restart. Matches the module's existing retry-not-assume discipline (LED / chirp commit only on confirmed success).
  • No extra clear() before the fallback draw: the failed takeover landed nothing and the shape-tracker clear already fired for any real id-set change (last_shape is never the takeover shape, since a takeover ERROR never commits it).

Tests & docs

  • Four new FakeClient tests in tests/test_calendar_loop.py: ERROR falls back to the in-progress layout and commits its shape; REJECTED and UNREACHABLE do not fall back; the fallback is per-poll (not latched). Full suite green: 363 passed.
  • README corrected — it had described the mistyped-name case as leaving the panel dark; it now documents the graceful fallback.
  • stdlib + BusyBarClient only; no new deps.

🤖 Generated with Claude Code

…on is undrawable

The v1.6 start-takeover draws a full-panel stock AnimationElement
(shared/<start_animation>.anim) for the first start_window_seconds after
an event begins. If start_animation names an animation absent from the
device (an operator typo -- the default meeting_72x16 is valid), the live
device rejects the draw with DrawResult.ERROR every poll. Since the
takeover is the ONLY thing on screen, state never commits and run_once
re-clears + re-fails each poll, leaving the panel DARK for the whole
window instead of showing anything.

run_once now falls back to the normal in-progress ("ENDS") layout for that
poll when a just_started takeover draw returns ERROR, so a mistyped
start_animation degrades to a live countdown rather than a blank screen,
and logs the misconfiguration. Only ERROR triggers the fallback: REJECTED
(a higher-priority app owns the screen -- the lower-priority in-progress
draw would be rejected too) and UNREACHABLE (device down -- handled by the
loop's backoff) do not. Per-poll, not latched, so it self-heals the moment
the config is fixed or the animation appears, no restart needed.

Adds four FakeClient tests (ERROR falls back; REJECTED/UNREACHABLE do not;
fallback is per-poll not latched) and corrects the README, which had
described the mistyped-name case as leaving the panel dark.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sumitake
sumitake merged commit 43078c8 into main Aug 7, 2026
4 checks passed
@sumitake
sumitake deleted the dev/claude/start-anim-fallback branch August 7, 2026 08:08
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.

1 participant