ci: calm-rotation CI failure screen (repo + PR number, gentle LED, snooze retired) - #20
Conversation
RepoState.failing/.stuck moved to FailingRun objects, which silently
made compute_alert_fingerprint include the PR/branch ref. GitHub's REST
API can leave pull_requests empty for a poll or two before populating
it, so the ref can flip ("" -> "#42") for the same ongoing failure,
which would flip the fingerprint and cause update_snooze to treat it
as a new alert (clearing an active/pending snooze, re-firing the LED).
Key the fingerprint on (repo, workflow, category) only, restoring the
original documented semantics and ref-invariance.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…snooze from run_once Task 4 of the ci_status overlay-rotation refactor. run_once now drives its draw path entirely from build_overlay_sequence, so failing/stuck runs rotate into view (and keep rotating) even with no CI run currently active, instead of only alerting via a separate PRIORITY_ALERT path gated on the running-badge machinery. The failure-driven LED is centralized through resolve_ci_led_value/LED_OFF_COLOR/LED_OFF_ELEMENTS, tracked via the new overlay_state["led_was_on"] key. The snooze subsystem is retired from the loop (snooze_state parameter removed from run_once and main()); the now-dead logic.py helpers and their tests are left in place for Task 5.
…ze_minutes default Review findings: README's "Overlay dwell/rotation." paragraph still enumerated only the running badge/quota frames, contradicting the already-updated ladder table; config.py's DEFAULTS still carried a dead snooze_minutes default and comment pointing at the deleted "Snoozing alerts" README section.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 565d426734
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if overlay_gap_elapsed(last_dwell_end, now) < OVERLAY_DWELL_SECONDS: | ||
| return "overlay dwell gap; staying silent (letting the ambient app reclaim the screen)" |
There was a problem hiding this comment.
Apply LED transitions before returning for the dwell gap
When a failure first appears or the last failure clears during an overlay silence gap—for example, when running_poll_seconds is configured below the 20-second dwell-plus-gap cycle—this early return sends no LED update. Consequently, a new failure does not light the LED and a resolved failure leaves it red until a later eligible draw, despite the documented per-poll LED lifecycle. Handle the on/off transition independently before returning for the panel dwell gap.
Useful? React with 👍 / 👎.
What & why
The CI failure screen was a priority-60 takeover that camped the panel (evicting the calendar) and only ever showed the workflow name. This reworks it on two axes:
CI FAIL owner/repo #42 · workflow(falls back to the branch for push/fork runs with no PR).evaluate_runsstopped discarding the run dict; the ref reuses the existing_pr_or_branchhelper.PRIORITY_ALERT(60) to the overlay tier (PRIORITY_OVERLAY, 21) and join the existing dwell/silence rotation, so they alternate calmly with the upcoming calendar event, the running badge, and the quota gauges — and now rotate even when no job is running (previously the rotation only ran during an active run). One frame per failing run.A gentle red LED stays lit while a workflow is failing (decoupled from which frame is on screen, with an explicit off on the failing→clear transition), mirroring
calendar_countdown's proven LED lifecycle — so losing the screen takeover doesn't mean losing noticeability. This also fixes a latent gap where the CI red LED never reliably turned off after a failure resolved.The start-button snooze subsystem is retired (no longer needed for a calm rotating frame):
compute_alert_fingerprint,update_snooze, thesnooze_stateplumbing, the per-pollget_busy()call, andsnooze_minutesconfig are all removed.PRIORITY_ALERT(60) remains defined inbusybar.displayas the ladder's alert slot; it's simply no longer drawn to byci_status. Nocalendar_countdownbehavior changes — its tiers still outrank the overlay rotation, so an imminent event still wins.Design & plan
docs/superpowers/specs/2026-08-08-ci-failure-rotation-frame-design.mddocs/superpowers/plans/2026-08-08-ci-failure-rotation-frame.mdTesting
#00000000off via both the piggybacked and standaloneLED_OFF_ELEMENTSpaths); unified shape-clear gate across the new frame seams; cross-repo sequence ordering; snooze tests removed.On-device verification (fw 1.1.1 — please confirm after deploy)
Not automatable in CI (spec §9):
poll_seconds = 120and a lone failure + no running job, the frame redraws sparsely (~every 120s) — the persistent LED, not the frame cadence, is what carries "don't miss it."Out-of-scope follow-up (noted, not in this PR)
integrations/calendar_countdown/README.md(~L150/167) still describes a persistent CI failure alert burying the calendar — dated phrasing now that CI failure rides the overlay rotation (the core claim, that the calendar climbs above it, still holds). The spec scoped calendar docs as a non-goal; happy to follow up separately.🤖 Generated with Claude Code