- scheduler: _events_digest() — содержательные события стора за ~90 мин (Message/Reply/Tasks/Escalations/AUM/MCP), шум (CycleTicked/Tool*/) отсечён; секция «СОБЫТИЯ ХАРНЕСА» в build_context по policy.events_context=on - commands/cli: policy --events-context on|off (переключатель, одобрен Alex) - tests/test_events_context.py: 9 hermetic-проверок (on/off/дефолт/пустой стор)
87 lines
3.9 KiB
Python
87 lines
3.9 KiB
Python
# -*- 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: все проверки прошли")
|