Skip to content

feat(daemon): night-guide — motion-triggered path lighting with a clean hand-back - #11

Merged
cnewkirk merged 1 commit into
mainfrom
feat/night-guide-v2
Aug 8, 2026
Merged

feat(daemon): night-guide — motion-triggered path lighting with a clean hand-back#11
cnewkirk merged 1 commit into
mainfrom
feat/night-guide-v2

Conversation

@cnewkirk

@cnewkirk cnewkirk commented Aug 8, 2026

Copy link
Copy Markdown
Owner

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

Adds circadian_daemon.night_guide (optional): while the driven zone is out
of the circadian window (parked at night_look, or off), motion on a
configured MotionAware area briefly raises it to a soft guide look, then
hands control back once timeout elapses with no further motion. Repeated
motion extends the episode from the latest event, not the first.

Closes the actual product gap behind the 2026-08-08 incident: the resume-race
fix (#10) stopped the daemon from fighting itself, but neither the bridge's
native convenience-motion feature nor hueman's own (bridge-native)
night_motion automation has any concept of "restore whatever was there
before" — both only know a fixed configured fallback. Built daemon-native
instead, sharing the recompute-when-possible hand-back shape
_restore_after_security already established:

  • A real manual override showing when the guide engages (SUSPENDED) is
    snapshotted (a raw grouped_light GET) before the guide look overwrites it,
    and restored verbatim on hand-back.
  • Otherwise hand-back recomputes the current authoritative target fresh: the
    curve if the window reopened mid-episode, otherwise the normal resting
    state.

New: nightguide_control.py (pure IDLE/GUIDING timing, 7 tests),
NightGuideSpec, full daemon wiring + 10 integration tests. Spot-verified the
snapshot-restore test fails without the restore branch (temporarily
disabled, ran red, restored).

…an hand-back

Adds circadian_daemon.night_guide (optional): while the driven zone is
out of the circadian window (parked at night_look, or off), motion on
a configured MotionAware area briefly raises it to a soft guide look
(e.g. dim red, for a night trip to the bathroom/kitchen), then hands
control back once `timeout` elapses with no further motion. Repeated
motion extends the episode from the latest event, not the first.

This closes the actual product gap behind the 2026-08-08 incident: the
daemon's resume-race fix (86f8d93) stopped the daemon from fighting
itself, but neither the bridge's native convenience-motion feature nor
hueman's own (bridge-native) night_motion automation has any concept
of "restore whatever was there before" — both only know a fixed
configured fallback, which is what made native motion recalls fight
manual overrides and the daemon's resume logic in the first place.
Built daemon-native instead, sharing the same recompute-when-possible
hand-back shape _restore_after_security already established:

- A real manual override showing when the guide engages (SUSPENDED)
  is snapshotted (a raw grouped_light GET) before the guide look
  overwrites it, and restored verbatim on hand-back -- a manual look
  is arbitrary, not derivable from anything else.
- Otherwise (ordinary circadian/night_look was showing) hand-back
  recomputes the current authoritative target fresh instead of
  replaying a snapshot: the curve if the window reopened mid-episode,
  otherwise the normal resting state. Hold alone would leave the
  guide look showing forever, since Hold assumes nothing changed
  underneath it -- false here, the guide write is what changed it.

Consumes the same MotionAware SSE events `rhythm` already reads
(independent consumers of one event, _handle_event restructured so
neither requires the other to be configured) -- no new sensor
plumbing. Never fights the operator (an override suspends and stays
suspended straight through a guide episode) or the curve (circadian
reclaims the zone the instant its window opens).

New: nightguide_control.py (pure IDLE/GUIDING timing, 7 tests),
NightGuideSpec (config.py), full daemon wiring + 10 integration tests
covering: gating to out-of-window only, snapshot-vs-recompute on
hand-back both ways, mid-episode window reopen, repeated-motion
extension, unrelated-area/motion-false rejection, and rhythm
coexistence. Spot-verified the snapshot-restore test fails without the
restore branch (temporarily disabled, ran red, restored). Full suite
(393 tests) + mypy clean.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@cnewkirk
cnewkirk merged commit c075e26 into main Aug 8, 2026
1 check passed
@cnewkirk
cnewkirk deleted the feat/night-guide-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