Skip to content

fix(daemon): close the resume-race that undoes manual-override handback - #10

Merged
cnewkirk merged 1 commit into
mainfrom
fix/manual-resume-stale-reference-v2
Aug 8, 2026
Merged

fix(daemon): close the resume-race that undoes manual-override handback#10
cnewkirk merged 1 commit into
mainfrom
fix/manual-resume-stale-reference-v2

Conversation

@cnewkirk

@cnewkirk cnewkirk commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Re-landing 86f8d93 through a proper PR (originally direct-pushed to main,
reverted in #9).

All three resume triggers (power-cycle, control-file, resume-trigger scene)
flipped the controller out of SUSPENDED via a bare on_resume(), but never
refreshed the settle-and-compare classifier's stale _cmd_brightness/
_cmd_on reference (last set before the suspension) or granted the grace
window _restore_after_security already uses for the identical race on the
security-exit path. Since _tick_once always classifies before it drives,
the very next settle judgment after a resume compared the freshly-resumed
live brightness against that stale target and re-suspended within one tick,
defeating the resume outright.

Confirmed live 2026-08-08: motion-triggered brightness churn repeatedly
power-cycled the zone overnight, and every single resume was undone by the
next tick's stale comparison — 10 spurious suspends in one session, the zone
stuck SUSPENDED at 100% by morning.

Adds _resume_locked(), used by all three trigger sites: resets
_obs_brightness/_obs_classified and opens _classify_grace_until for one
fade + settle window, same as the security-restore path. A genuine override
after the grace still suspends normally (covered by a dedicated test).

Regression tests for all three paths, verified to fail on the pre-fix code
(reverted call sites, ran red, restored).

All three resume triggers (power-cycle, control-file, resume-trigger
scene) flipped the controller out of SUSPENDED via a bare on_resume(),
but never refreshed the settle-and-compare classifier's stale
_cmd_brightness/_cmd_on reference (last set before the suspension) or
granted the grace window _restore_after_security already uses for the
identical race on the security-exit path. Since _tick_once always
classifies before it drives, the very next settle judgment after a
resume compared the freshly-resumed live brightness against that
stale target and re-suspended within one tick, defeating the resume
outright.

Confirmed live 2026-08-08: motion-triggered brightness churn
repeatedly power-cycled the zone overnight, and every single resume
was undone by the next tick's stale comparison — 10 spurious suspends
in one session, the zone stuck SUSPENDED at 100% by morning, and the
user's own manual changes getting steamrolled in real time while
working.

Adds _resume_locked(), used by all three trigger sites: resets
_obs_brightness/_obs_classified and opens _classify_grace_until for
one fade + settle window, same as the security-restore path, so the
daemon gets a real drive (or a clean drop to NIGHT_IDLE) before
judging anything again. A genuine override after the grace still
suspends normally (covered by a dedicated test).

Regression tests for all three paths, verified to fail on the
pre-fix code (reverted call sites, ran red, restored).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@cnewkirk
cnewkirk merged commit 06860a8 into main Aug 8, 2026
1 check passed
@cnewkirk
cnewkirk deleted the fix/manual-resume-stale-reference-v2 branch August 8, 2026 12:46
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