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
256 lines
9.5 KiB
Python
256 lines
9.5 KiB
Python
"""
|
|
tests/test_architecture_pressure_engine.py
|
|
|
|
Unit tests for architecture_pressure.py:
|
|
- compute_pressure scoring
|
|
- band classification
|
|
- requires_arch_review flag
|
|
- signal scoring (count-based diminishing + boolean)
|
|
- signals_summary generation
|
|
"""
|
|
import sys, os
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../services/router"))
|
|
|
|
import pytest
|
|
from architecture_pressure import (
|
|
compute_pressure,
|
|
classify_pressure_band,
|
|
load_pressure_policy,
|
|
_reload_pressure_policy,
|
|
_score_signals,
|
|
_signals_summary,
|
|
_builtin_pressure_defaults,
|
|
)
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def reset_policy():
|
|
_reload_pressure_policy()
|
|
yield
|
|
_reload_pressure_policy()
|
|
|
|
|
|
@pytest.fixture
|
|
def policy():
|
|
return _builtin_pressure_defaults()
|
|
|
|
|
|
class TestClassifyBand:
|
|
def test_score_0_is_low(self, policy):
|
|
assert classify_pressure_band(0, policy) == "low"
|
|
|
|
def test_score_at_low_max_is_low(self, policy):
|
|
assert classify_pressure_band(20, policy) == "low"
|
|
|
|
def test_score_21_is_medium(self, policy):
|
|
assert classify_pressure_band(21, policy) == "medium"
|
|
|
|
def test_score_at_medium_max_is_medium(self, policy):
|
|
assert classify_pressure_band(45, policy) == "medium"
|
|
|
|
def test_score_46_is_high(self, policy):
|
|
assert classify_pressure_band(46, policy) == "high"
|
|
|
|
def test_score_at_high_max_is_high(self, policy):
|
|
assert classify_pressure_band(70, policy) == "high"
|
|
|
|
def test_score_71_is_critical(self, policy):
|
|
assert classify_pressure_band(71, policy) == "critical"
|
|
|
|
def test_score_200_is_critical(self, policy):
|
|
assert classify_pressure_band(200, policy) == "critical"
|
|
|
|
|
|
class TestScoreSignals:
|
|
def test_no_signals_zero_score(self, policy):
|
|
components = {
|
|
"recurrence_high_30d": 0, "recurrence_warn_30d": 0,
|
|
"regressions_30d": 0, "escalations_30d": 0,
|
|
"followups_created_30d": 0, "followups_overdue": 0,
|
|
"drift_failures_30d": 0, "dependency_high_30d": 0,
|
|
}
|
|
assert _score_signals(components, policy) == 0
|
|
|
|
def test_recurrence_high_boolean(self, policy):
|
|
components = {
|
|
"recurrence_high_30d": 1, "recurrence_warn_30d": 0,
|
|
"regressions_30d": 0, "escalations_30d": 0,
|
|
"followups_created_30d": 0, "followups_overdue": 0,
|
|
"drift_failures_30d": 0, "dependency_high_30d": 0,
|
|
}
|
|
score = _score_signals(components, policy)
|
|
assert score == 20 # weight = 20
|
|
|
|
def test_recurrence_high_multiple_times_still_one_weight(self, policy):
|
|
"""recurrence_high_30d is a boolean — count > 1 does not multiply."""
|
|
components = {
|
|
"recurrence_high_30d": 5, "recurrence_warn_30d": 0,
|
|
"regressions_30d": 0, "escalations_30d": 0,
|
|
"followups_created_30d": 0, "followups_overdue": 0,
|
|
"drift_failures_30d": 0, "dependency_high_30d": 0,
|
|
}
|
|
score_5 = _score_signals(components, policy)
|
|
components["recurrence_high_30d"] = 1
|
|
score_1 = _score_signals(components, policy)
|
|
assert score_5 == score_1
|
|
|
|
def test_regressions_count_increases_score(self, policy):
|
|
base = {"recurrence_high_30d": 0, "recurrence_warn_30d": 0,
|
|
"regressions_30d": 1, "escalations_30d": 0,
|
|
"followups_created_30d": 0, "followups_overdue": 0,
|
|
"drift_failures_30d": 0, "dependency_high_30d": 0}
|
|
s1 = _score_signals(base, policy)
|
|
base["regressions_30d"] = 3
|
|
s3 = _score_signals(base, policy)
|
|
assert s3 > s1
|
|
|
|
def test_followups_overdue_adds_score(self, policy):
|
|
components = {
|
|
"recurrence_high_30d": 0, "recurrence_warn_30d": 0,
|
|
"regressions_30d": 0, "escalations_30d": 0,
|
|
"followups_created_30d": 0, "followups_overdue": 2,
|
|
"drift_failures_30d": 0, "dependency_high_30d": 0,
|
|
}
|
|
score = _score_signals(components, policy)
|
|
# weight=15, first unit = 15, second = 15//2 = 7
|
|
expected = 15 + 7
|
|
assert score == expected
|
|
|
|
def test_all_signals_present(self, policy):
|
|
components = {
|
|
"recurrence_high_30d": 1, "recurrence_warn_30d": 1,
|
|
"regressions_30d": 2, "escalations_30d": 2,
|
|
"followups_created_30d": 2, "followups_overdue": 2,
|
|
"drift_failures_30d": 2, "dependency_high_30d": 2,
|
|
}
|
|
score = _score_signals(components, policy)
|
|
assert score > 0
|
|
|
|
|
|
class TestSignalsSummary:
|
|
def test_empty_components_no_summary(self, policy):
|
|
comp = {k: 0 for k in [
|
|
"recurrence_high_30d", "recurrence_warn_30d", "regressions_30d",
|
|
"escalations_30d", "followups_created_30d", "followups_overdue",
|
|
"drift_failures_30d", "dependency_high_30d",
|
|
]}
|
|
assert _signals_summary(comp, policy) == []
|
|
|
|
def test_recurrence_high_summary(self, policy):
|
|
comp = {"recurrence_high_30d": 1, "recurrence_warn_30d": 0,
|
|
"regressions_30d": 0, "escalations_30d": 0,
|
|
"followups_created_30d": 0, "followups_overdue": 0,
|
|
"drift_failures_30d": 0, "dependency_high_30d": 0}
|
|
summaries = _signals_summary(comp, policy)
|
|
assert any("High-recurrence" in s for s in summaries)
|
|
|
|
def test_followups_overdue_in_summary(self, policy):
|
|
comp = {"recurrence_high_30d": 0, "recurrence_warn_30d": 0,
|
|
"regressions_30d": 0, "escalations_30d": 0,
|
|
"followups_created_30d": 0, "followups_overdue": 3,
|
|
"drift_failures_30d": 0, "dependency_high_30d": 0}
|
|
summaries = _signals_summary(comp, policy)
|
|
assert any("Overdue follow-ups" in s for s in summaries)
|
|
|
|
|
|
class TestComputePressure:
|
|
def test_no_signals_returns_low(self, policy):
|
|
report = compute_pressure(
|
|
"gateway", "prod",
|
|
components={
|
|
"recurrence_high_30d": 0, "recurrence_warn_30d": 0,
|
|
"regressions_30d": 0, "escalations_30d": 0,
|
|
"followups_created_30d": 0, "followups_overdue": 0,
|
|
"drift_failures_30d": 0, "dependency_high_30d": 0,
|
|
},
|
|
policy=policy,
|
|
)
|
|
assert report["score"] == 0
|
|
assert report["band"] == "low"
|
|
assert report["requires_arch_review"] is False
|
|
|
|
def test_high_pressure_sets_requires_arch_review(self, policy):
|
|
report = compute_pressure(
|
|
"gateway", "prod",
|
|
components={
|
|
"recurrence_high_30d": 1,
|
|
"regressions_30d": 3,
|
|
"escalations_30d": 3,
|
|
"followups_overdue": 2,
|
|
"recurrence_warn_30d": 1,
|
|
"followups_created_30d": 2,
|
|
"drift_failures_30d": 2,
|
|
"dependency_high_30d": 2,
|
|
},
|
|
policy=policy,
|
|
)
|
|
assert report["requires_arch_review"] is True
|
|
assert report["band"] in ("high", "critical")
|
|
|
|
def test_report_includes_service_and_env(self, policy):
|
|
report = compute_pressure(
|
|
"router", "staging",
|
|
components={k: 0 for k in [
|
|
"recurrence_high_30d", "recurrence_warn_30d", "regressions_30d",
|
|
"escalations_30d", "followups_created_30d", "followups_overdue",
|
|
"drift_failures_30d", "dependency_high_30d",
|
|
]},
|
|
policy=policy,
|
|
)
|
|
assert report["service"] == "router"
|
|
assert report["env"] == "staging"
|
|
|
|
def test_report_has_computed_at(self, policy):
|
|
report = compute_pressure("svc", "prod", components={}, policy=policy)
|
|
assert "computed_at" in report
|
|
|
|
def test_missing_components_default_to_zero(self, policy):
|
|
"""If components dict is incomplete, missing keys default to 0."""
|
|
report = compute_pressure(
|
|
"svc", "prod",
|
|
components={"recurrence_high_30d": 1},
|
|
policy=policy,
|
|
)
|
|
assert report["score"] >= 0 # no KeyError
|
|
|
|
def test_score_is_non_negative(self, policy):
|
|
report = compute_pressure("svc", "prod", components={}, policy=policy)
|
|
assert report["score"] >= 0
|
|
|
|
def test_signals_summary_populated_when_signals_active(self, policy):
|
|
report = compute_pressure(
|
|
"svc", "prod",
|
|
components={
|
|
"recurrence_high_30d": 1, "regressions_30d": 2,
|
|
"escalations_30d": 0, "recurrence_warn_30d": 0,
|
|
"followups_created_30d": 0, "followups_overdue": 0,
|
|
"drift_failures_30d": 0, "dependency_high_30d": 0,
|
|
},
|
|
policy=policy,
|
|
)
|
|
assert len(report["signals_summary"]) > 0
|
|
|
|
def test_band_critical_above_70(self, policy):
|
|
report = compute_pressure(
|
|
"svc", "prod",
|
|
components={
|
|
"recurrence_high_30d": 1,
|
|
"regressions_30d": 5,
|
|
"escalations_30d": 5,
|
|
"followups_overdue": 5,
|
|
"recurrence_warn_30d": 1,
|
|
"followups_created_30d": 5,
|
|
"drift_failures_30d": 5,
|
|
"dependency_high_30d": 5,
|
|
},
|
|
policy=policy,
|
|
)
|
|
assert report["band"] == "critical"
|
|
assert report["requires_arch_review"] is True
|
|
|
|
def test_no_stores_with_none_components_returns_report(self, policy):
|
|
"""When no stores, fallback to zeros — should not raise."""
|
|
report = compute_pressure("svc", "prod", policy=policy)
|
|
assert "score" in report
|
|
assert "band" in report
|