Bootstrap SillyHome Future v2 core

This commit is contained in:
2026-06-18 12:16:54 +02:00
commit 549f87523a
15 changed files with 729 additions and 0 deletions

93
tests/test_future_core.py Normal file
View File

@@ -0,0 +1,93 @@
from __future__ import annotations
from pathlib import Path
from app.core.event_core import EventCore
from app.core.handoff import HandoffMatrix
from app.core.models import (
BehaviorPatternV2,
ControlProfile,
EntityState,
HandoffMode,
LearningProfile,
LearningState,
RuntimeState,
SafetyStage,
StateEvent,
)
from app.core.stores import FutureStores
def test_event_core_routes_state_event_to_decision(tmp_path: Path) -> None:
stores = FutureStores(tmp_path)
stores.save_runtime(
RuntimeState(
entities={
"light.storage": EntityState(
entity_id="light.storage",
domain="light",
state="off",
)
}
)
)
stores.save_learning(
LearningState(
profiles={
"light.storage": LearningProfile(
actuator_entity_id="light.storage",
patterns=[
BehaviorPatternV2(
actuator_entity_id="light.storage",
target_state="on",
trigger_entity_id="binary_sensor.storage_door",
trigger_state="on",
support=3,
confidence=0.95,
)
],
)
}
)
)
stores.save_control(
stores.control().model_copy(
update={
"profiles": {
"light.storage": ControlProfile(
actuator_entity_id="light.storage",
stage=SafetyStage.DRY_RUN,
min_confidence=0.8,
)
}
}
)
)
core = EventCore(stores)
audit = core.process_state_event(
StateEvent(entity_id="binary_sensor.storage_door", new_state="on")
)
decisions = [item for item in audit if item.kind == "decision"]
assert decisions
assert decisions[0].decision is not None
assert decisions[0].decision.target_state == "on"
assert decisions[0].decision.allowed is True
assert decisions[0].decision.dry_run is True
def test_handoff_matrix_detects_conflict_and_rollback() -> None:
matrix = HandoffMatrix()
profile = ControlProfile(
actuator_entity_id="light.storage",
handoff_mode=HandoffMode.CONTROLLED,
related_automation_ids=["automation.storage"],
)
assert matrix.classify(profile) is HandoffMode.CONFLICT
controlled = matrix.assume_control(profile)
assert controlled.paused_automation_ids == ["automation.storage"]
rolled_back = matrix.rollback(controlled)
assert rolled_back.handoff_mode is HandoffMode.ROLLBACK
assert rolled_back.paused_automation_ids == []