Files
microdao-daarion/tests/test_stepan_doc_anchor_reset.py
Apple 129e4ea1fc feat(platform): add new services, tools, tests and crews modules
New router intelligence modules (26 files): alert_ingest/store, audit_store,
architecture_pressure, backlog_generator/store, cost_analyzer, data_governance,
dependency_scanner, drift_analyzer, incident_* (5 files), llm_enrichment,
platform_priority_digest, provider_budget, release_check_runner, risk_* (6 files),
signature_state_store, sofiia_auto_router, tool_governance

New services:
- sofiia-console: Dockerfile, adapters/, monitor/nodes/ops/voice modules, launchd, react static
- memory-service: integration_endpoints, integrations, voice_endpoints, static UI
- aurora-service: full app suite (analysis, job_store, orchestrator, reporting, schemas, subagents)
- sofiia-supervisor: new supervisor service
- aistalk-bridge-lite: Telegram bridge lite
- calendar-service: CalDAV calendar service with reminders
- mlx-stt-service / mlx-tts-service: Apple Silicon speech services
- binance-bot-monitor: market monitor service
- node-worker: STT/TTS memory providers

New tools (9): agent_email, browser_tool, contract_tool, observability_tool,
oncall_tool, pr_reviewer_tool, repo_tool, safe_code_executor, secure_vault

New crews: agromatrix_crew (10 modules: depth_classifier, doc_facts, doc_focus,
farm_state, light_reply, llm_factory, memory_manager, proactivity, reflection_engine,
session_context, style_adapter, telemetry)

Tests: 85+ test files for all new modules
Made-with: Cursor
2026-03-03 07:14:14 -08:00

209 lines
7.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Tests for Doc Anchor Reset (PROMPT 27, v3.3)."""
import sys
import os
import time
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
from crews.agromatrix_crew import session_context as sc
from crews.agromatrix_crew.doc_facts import build_self_correction
FACTS_DOC_A = {
"profit_uah": 5_972_016.0,
"fertilizer_uah": 1_521_084.0,
"area_ha": 497.0,
}
def _make_session(active_doc_id: str, doc_facts: dict, fact_claims: list | None = None) -> dict:
sess = sc._default_session()
sess["active_doc_id"] = active_doc_id
sess["doc_facts"] = dict(doc_facts)
sess["fact_claims"] = list(fact_claims or [])
sess["updated_at"] = time.time()
return sess
def _store_session(chat_id: str, sess: dict):
sc._STORE[chat_id] = sess
# ── Основний сценарій: зміна doc_id → reset ──────────────────────────────────
def test_anchor_reset_clears_doc_facts():
"""При зміні doc_id — doc_facts скидаються."""
chat_id = "anchor_test_1"
sess = _make_session("docA", FACTS_DOC_A)
_store_session(chat_id, sess)
loaded = sc.load_session(chat_id)
assert loaded["doc_facts"] == FACTS_DOC_A
# Симулюємо логіку з run.py: новий doc_id != старий
current_doc_id = "docB"
prev_doc_id = loaded.get("active_doc_id")
if prev_doc_id and prev_doc_id != current_doc_id:
loaded["doc_facts"] = {}
loaded["fact_claims"] = []
assert loaded["doc_facts"] == {}
assert loaded["fact_claims"] == []
def test_anchor_reset_clears_fact_claims():
"""При зміні doc_id — fact_claims також скидаються."""
chat_id = "anchor_test_2"
claims = [{"key": "profit_present", "value": True, "ts": time.time()}]
sess = _make_session("docA", FACTS_DOC_A, fact_claims=claims)
_store_session(chat_id, sess)
loaded = sc.load_session(chat_id)
assert len(loaded["fact_claims"]) == 1
# Зміна doc_id
current_doc_id = "docB"
prev_doc_id = loaded.get("active_doc_id")
if prev_doc_id and prev_doc_id != current_doc_id:
loaded["doc_facts"] = {}
loaded["fact_claims"] = []
assert loaded["fact_claims"] == []
def test_anchor_reset_updates_active_doc_id():
"""Після reset active_doc_id має оновитися через update_session."""
chat_id = "anchor_test_3"
sess = _make_session("docA", FACTS_DOC_A)
_store_session(chat_id, sess)
# Виконуємо update_session з новим active_doc_id
sc.update_session(chat_id, "текст", depth="deep", agents=[],
active_doc_id="docB", doc_facts={}, fact_claims=[])
updated = sc.load_session(chat_id)
assert updated["active_doc_id"] == "docB"
assert updated["doc_facts"] == {}
# ── Fail-safe: якщо current_doc_id None → нічого не скидаємо ────────────────
def test_no_reset_when_current_doc_id_is_none():
"""Якщо current_doc_id не визначений — doc_facts НЕ скидаються."""
chat_id = "anchor_test_failsafe"
sess = _make_session("docA", FACTS_DOC_A)
_store_session(chat_id, sess)
loaded = sc.load_session(chat_id)
current_doc_id = None # невідомий
# Логіка з run.py: якщо current_doc_id None — нічого не робимо
if current_doc_id:
prev = loaded.get("active_doc_id")
if prev and prev != current_doc_id:
loaded["doc_facts"] = {}
loaded["fact_claims"] = []
# doc_facts мають залишитись
assert loaded["doc_facts"] == FACTS_DOC_A
def test_no_reset_when_same_doc_id():
"""Якщо doc_id той самий — doc_facts НЕ скидаються."""
chat_id = "anchor_test_same"
sess = _make_session("docA", FACTS_DOC_A)
_store_session(chat_id, sess)
loaded = sc.load_session(chat_id)
current_doc_id = "docA" # той самий
prev = loaded.get("active_doc_id")
if prev and prev != current_doc_id:
loaded["doc_facts"] = {}
loaded["fact_claims"] = []
assert loaded["doc_facts"] == FACTS_DOC_A
def test_no_reset_when_no_previous_doc_id():
"""Якщо попереднього active_doc_id нема — reset не спрацьовує."""
chat_id = "anchor_test_noprev"
sess = sc._default_session()
sess["doc_facts"] = FACTS_DOC_A
sess["active_doc_id"] = None # нема попереднього
sess["updated_at"] = time.time()
_store_session(chat_id, sess)
loaded = sc.load_session(chat_id)
current_doc_id = "docB"
prev = loaded.get("active_doc_id")
if prev and prev != current_doc_id:
loaded["doc_facts"] = {}
loaded["fact_claims"] = []
# Нема попереднього — нічого не скинули
assert loaded["doc_facts"] == FACTS_DOC_A
# ── Self-correction: тільки в межах одного doc_id ────────────────────────────
def test_self_correction_blocked_on_different_doc():
"""Self-correction НЕ спрацьовує при зміні doc_id."""
sess = _make_session("docA", FACTS_DOC_A)
sess["fact_claims"] = [{"key": "profit_present", "value": False, "ts": time.time()}]
response = "У звіті є прибуток — 5 972 016 грн."
# current_doc_id = docB (новий) → correction заблокована
correction = build_self_correction(response, FACTS_DOC_A, sess, current_doc_id="docB")
assert correction == "", f"Expected no correction, got: {correction!r}"
def test_self_correction_works_same_doc():
"""Self-correction спрацьовує в межах того самого doc_id."""
sess = _make_session("docA", FACTS_DOC_A)
sess["fact_claims"] = [{"key": "profit_present", "value": False, "ts": time.time()}]
response = "У звіті є прибуток — 5 972 016 грн."
correction = build_self_correction(response, FACTS_DOC_A, sess, current_doc_id="docA")
assert correction, f"Expected correction prefix, got empty"
assert "неточно" in correction.lower() or "написав" in correction.lower()
def test_self_correction_works_when_no_current_doc_id():
"""Self-correction не блокується якщо current_doc_id=None (backward-compat)."""
sess = _make_session("docA", FACTS_DOC_A)
sess["fact_claims"] = [{"key": "profit_present", "value": False, "ts": time.time()}]
response = "У звіті є прибуток — 5 972 016 грн."
# current_doc_id=None → anchor guard не спрацьовує → correction дозволена
correction = build_self_correction(response, FACTS_DOC_A, sess, current_doc_id=None)
assert correction, "Expected correction when current_doc_id is None"
# ── update_session: active_doc_id персистується ───────────────────────────────
def test_update_session_persists_active_doc_id():
"""update_session зберігає active_doc_id."""
chat_id = "anchor_persist_test"
sc.clear_session(chat_id)
sc.update_session(chat_id, "запит", depth="deep", agents=[],
active_doc_id="doc_xyz123")
sess = sc.load_session(chat_id)
assert sess["active_doc_id"] == "doc_xyz123"
def test_update_session_preserves_doc_id_if_not_provided():
"""update_session зберігає існуючий active_doc_id якщо новий не передано."""
chat_id = "anchor_preserve_test"
sc.clear_session(chat_id)
sc.update_session(chat_id, "перший", depth="deep", agents=[],
active_doc_id="docA")
sc.update_session(chat_id, "другий", depth="light", agents=[])
sess = sc.load_session(chat_id)
# active_doc_id має залишитись "docA" (None не перезаписує)
assert sess["active_doc_id"] == "docA"