Skip to content

Core engine: visibility, plant-day budget, decisions - #2

Merged
leiklier merged 3 commits into
mainfrom
feat/core
Jul 23, 2026
Merged

Core engine: visibility, plant-day budget, decisions#2
leiklier merged 3 commits into
mainfrom
feat/core

Conversation

@leiklier

Copy link
Copy Markdown
Owner

What

The pure scheduling core (custom_components/grow_conductor/core/, zero homeassistant imports — ruff TID251 + poisoned-import test):

  • model.pyInputSnapshot (tri-state signals), Decision(want_on, state, reason, next_review), display enums.
  • visibility.py — the §1 priority chain: veto > viewer activity/clear-hold > asleep > away > confirmed refuge > observed. Hold counts from the falling edge of viewer activity; refuge confirmation survives unrelated snapshot churn.
  • budget.pyPlantDayLedger: accrues from reported physical state (manual light counts), splits open blocks at the anchor (2.4), seed/restore per rule 5.1.
  • engine.py — event-driven, clock-injected; every decision carries the exact next_review instant so the adapter needs one timer, no polling.

Tests

33 scenario tests citing rule numbers: full nominal workday (sleep block → wake cut → away block → cap → anchor reset), night movement with cooldown recovery, WFH via refuge incl. lunch-break flicker handling, veto without release hold, cap exactness, min-block guard, standby accounting, restore seeding (current vs stale day), idempotence.

Part 2 of 3, stacked on #1.

🤖 Generated with Claude Code

@leiklier

Copy link
Copy Markdown
Owner Author

Follow-up commit: Engine.activity_pulse(now) implementing rule 1.3b, with scenario tests (night pulse cut + hold extension by repeated pulses; a pulse while awake arming the hold across the sleep transition). 35 core tests.

leiklier and others added 3 commits July 23, 2026 19:22
Pure, event-driven, clock-injected core (no homeassistant imports —
ruff TID251 plus a poisoned-import test enforce it). PlantDayLedger
accrues from reported truth and splits open blocks at the anchor;
visibility.assess implements the §1 priority chain (veto > viewer/hold >
asleep > away > refuge); Engine folds snapshots/reports/settings into
Decisions with next_review instants so the adapter needs exactly one
timer. 33 scenario tests cite spec rules: nominal workday, night
movement, WFH refuge, cap exactness, min-block guard, standby
accounting, restore seeding, anchor splits.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Stamps the viewer-activity clock without sustaining activity: instant
cut, normal clear-hold recovery, level never read. Tests: night pulse
cut + hold extension by repeated pulses; a pulse while awake arming the
hold across a sleep transition.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Viewer memory now tracks episodes edge-to-edge (active_since, last_end,
sustained_end); during confirmed refuge, activity cuts only once
continuously active for exposure_grace, short episodes and pulses
impose no hold, and only grace-exceeding episodes carry clear_hold.
Refuge confirmation is a latch: unconfirmed engagements restart on any
dropout, confirmed refuge survives evidence gaps up to refuge_hold
(falling edges stamp last-active; the lapse instant is a scheduled
review). Asleep/away contexts unchanged. 43 core tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@leiklier

Copy link
Copy Markdown
Owner Author

Follow-up commit for rules 1.3c/1.7: viewer memory tracks episodes edge-to-edge (active_since / last_end / sustained_end), refuge confirmation is a latch with hold-across-gaps (falling edges stamp last-active; lapse instants are scheduled reviews). New scenarios: coffee run never toggles, sustained exposure cuts exactly at grace, hold/release/re-confirm, unconfirmed dropout resets, pulse ignored during refuge. 43 core tests.

@leiklier
leiklier deleted the branch main July 23, 2026 19:34
@leiklier leiklier closed this Jul 23, 2026
@leiklier leiklier reopened this Jul 23, 2026
@leiklier
leiklier changed the base branch from docs/design to main July 23, 2026 19:35
@leiklier
leiklier merged commit 35577c3 into main Jul 23, 2026
12 checks passed
@leiklier
leiklier deleted the feat/core branch July 23, 2026 19:36
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