Backlight timeout + context-sensitive button - #2
Merged
Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR adds an LCD backlight auto-sleep feature with context-sensitive button behavior, implemented via a reducer-owned action semantic (display/buttonPress, display/sleep) plus RTK listener middleware to manage the timeout and hardware backlight syncing.
Changes:
- Replace
display/nextwithdisplay/buttonPress/display/sleepreducer semantics (wake when dark; cycle mode when lit; sleep resets to DEFAULT). - Add
registerBacklightTimeoutlistener middleware to dispatchsleep()after a configurable timeout, canceling/re-arming on every press. - Wire the feature into
app.js(render predicate broadened todisplay/*, backlight sync listener added, boot dispatch, and button handler updated) and document it (spec/plan/changelog).
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/store.test.js | Updates reducer tests for new buttonPress/sleep semantics. |
| src/store.js | Implements display/buttonPress and display/sleep; removes display/next. |
| src/config.test.js | Asserts new backlightTimeoutMs config field. |
| src/config.js | Adds backlightTimeoutMs: 30000 to runtime config. |
| src/backlight.test.js | Adds integration tests for listener-driven backlight timeout behavior. |
| src/backlight.js | Introduces RTK listener that arms/cancels a sleep timer on buttonPress. |
| docs/superpowers/specs/2026-07-25-backlight-timeout-design.md | Adds design spec for the behavior and architecture. |
| docs/superpowers/plans/2026-07-25-backlight-timeout.md | Adds implementation plan documenting the intended wiring and tests. |
| CHANGELOG.md | Adds an Unreleased entry describing the feature. |
| app.js | Wires new actions and listeners into the running app (render predicate, backlight sync, timeout registration, boot press, button handler). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Copilot review: boot buttonPress was dispatched after the initial pollAll, so a slow/hung 1-wire read delayed arming the 30s sleep timer. Now dispatched right after configureStore — spec doc wording updated to match. Tests 31 pass; virtual boot smoke shows lit frames. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (1)
src/backlight.test.js:33
- This timeout-reset test also relies on very small real-time windows (50ms with 30/30/40 waits). If the second
buttonPress()is delayed past the first 50ms window, the backlight could sleep before the reset press runs, making the test nondeterministic. Increasing the intervals keeps the same logic while making the test robust on slower machines.
test("a press mid-window resets the timeout", async () => {
const store = makeStore(50);
store.dispatch(buttonPress()); // lit, timer armed
await wait(30);
store.dispatch(buttonPress()); // lit -> cycles mode, re-arms timer
await wait(30); // 60ms after first press, 30ms after second
assert.equal(store.getState().display.isBacklit, true, "reset should have kept it lit");
Copilot review round 2: real-timer windows widened 4x (same ratios, per plan's flake recipe) so loaded machines can't skew assertions; mode-cycle test now waits out its armed timer instead of leaving a pending listener at suite end. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
LCD backlight now sleeps after 30 s. Button becomes context-sensitive: first press when dark wakes the backlight (mode untouched); presses while lit cycle DEFAULT ↔ DIAG and reset the timeout. Sleep resets mode to DEFAULT so a wake always shows main readings. Boot dispatches one
buttonPress— startup behaves exactly like a first press (lit, timer armed).How
display/buttonPress,display/sleep) — pure, tested.display/nextretired.src/backlight.js):cancelActiveListeners()→delay(30s)→sleep().isBacklittodisplay.setBacklight()— fires only on change, no per-render I2C writes. No piteknix changes (both drivers already supportsetBacklight).Testing
Spec:
docs/superpowers/specs/2026-07-25-backlight-timeout-design.md· Plan:docs/superpowers/plans/2026-07-25-backlight-timeout.mdBacklog noted for follow-ups: rename
sleepcreator (collides with delay-helper idiom), move backlight-sync listener intosrc/backlight.jsfor coverage, GPIOerrhandling inbutton.watch.🤖 Generated with Claude Code
https://claude.ai/code/session_01LWqqCXSnLqjh5WMDzPxSgy