# -*- coding: utf-8 -*- """t-261017110430: подача событий EventStore в контекст тика (hermetic, без LLM). Запуск: ./venv/bin/python tests/test_events_context.py Проверяет: policy.events_context=on — в контексте мин/час/день появляется секция «СОБЫТИЯ ХАРНЕСА» с содержательными событиями (MessageReceived, TaskClaimed, …) и БЕЗ механического шума (CycleTicked/ToolCalled/…); policy off (и дефолт) — секции нет. Выжимка не валит контекст при пустом сторе. """ import os import sys sys.path.insert(0, "/root/simbiot-harness") # изоляция стора (как test_gate.py): тест не пишет в боевой стор import tempfile as _iso_tf # noqa: E402 os.environ["SIMBIOT_DB"] = os.path.join( _iso_tf.mkdtemp(prefix="simbiot_test_evt_"), "harness.db") from harness import es, scheduler # noqa: E402 from harness.levels import LEVELS # noqa: E402 fails = [] def check(name, cond, extra=""): print(("PASS" if cond else "FAIL"), name, ("| " + extra) if not cond else "") if not cond: fails.append(name) es.init_db() es.append_event("tg", "m-1", "MessageReceived", {"text": "привет, как дела?"}) es.append_event("tg", "m-1", "ReplySent", {"text": "привет! всё ровно"}) es.append_event("harness", "t-1", "TaskClaimed", {"level": "min"}) # механический шум — его в контексте быть не должно es.append_event("cycle", "x", "CycleTicked", {"level": "min"}) es.append_event("trace", "y", "ToolCalled", {"tool": "shell"}) def ctx(policy): model = {"tasks": {}, "inbox": {}, "escalations": {}, "digests": {}, "policy": policy if policy is not None else {}} return scheduler.build_context(LEVELS["min"], model, batch=[]) on = ctx({"events_context": "on"}) check("on: секция СОБЫТИЯ ХАРНЕСА в контексте", "СОБЫТИЯ ХАРНЕСА" in on) check("on: входящее с текстом", "входящее [m-1]: привет, как дела?" in on) check("on: ответ в чат", "ответ в чат [m-1]: привет! всё ровно" in on) check("on: задача взята с уровнем", "задача взята [t-1]: уровнем min" in on) check("on: шум CycleTicked/ToolCalled отсечён", "CycleTicked" not in on and "ToolCalled" not in on) off = ctx({"events_context": "off"}) check("off: секции нет", "СОБЫТИЯ ХАРНЕСА" not in off) default = ctx(None) check("дефолт (нет policy): секции нет", "СОБЫТИЯ ХАРНЕСА" not in default) # пустой стор (lookback 90 мин): не падает и не добавляет секцию. # es.DB_PATH кешируется на импорте — смена SIMBIOT_DB после импорта не # действует, поэтому патчим модульный глобал напрямую (с возвратом). _db_backup, es.DB_PATH = es.DB_PATH, os.path.join( _iso_tf.mkdtemp(prefix="simbiot_test_evt2_"), "harness.db") try: es.init_db() empty = ctx({"events_context": "on"}) check("пустой стор: контекст собран, секции нет", isinstance(empty, str) and "СОБЫТИЯ ХАРНЕСА" not in empty) finally: es.DB_PATH = _db_backup # часовой уровень: секция там тоже (тот же build_context) on_hour = scheduler.build_context( LEVELS["hour"], {"tasks": {}, "inbox": {}, "escalations": {}, "digests": {}, "policy": {"events_context": "on"}}, batch=[]) check("hour: секция в контексте", "СОБЫТИЯ ХАРНЕСА" in on_hour) print() if fails: print("FAILED:", len(fails), fails) sys.exit(1) print("OK: все проверки прошли")