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
This commit is contained in:
150
tests/test_release_check_platform_review.py
Normal file
150
tests/test_release_check_platform_review.py
Normal file
@@ -0,0 +1,150 @@
|
||||
"""
|
||||
tests/test_release_check_platform_review.py
|
||||
|
||||
Tests for platform_review_required release gate:
|
||||
- warn mode: always pass=True + recommendations when score >= warn_at
|
||||
- strict mode: should_fail=True when score >= fail_at
|
||||
- skipped gracefully when no service_name
|
||||
- non-fatal on errors
|
||||
"""
|
||||
import sys, os
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../services/router"))
|
||||
|
||||
import asyncio
|
||||
import pytest
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
from release_check_runner import _run_platform_review_required
|
||||
|
||||
|
||||
def _make_tool_manager(pressure_score: int, band: str,
|
||||
requires_review: bool = False,
|
||||
signals_summary=None,
|
||||
fail: bool = False) -> MagicMock:
|
||||
tm = MagicMock()
|
||||
if fail:
|
||||
result = MagicMock(success=False, result=None, error="test error")
|
||||
else:
|
||||
result = MagicMock(
|
||||
success=True,
|
||||
result={
|
||||
"score": pressure_score,
|
||||
"band": band,
|
||||
"requires_arch_review": requires_review,
|
||||
"signals_summary": signals_summary or [],
|
||||
"components": {},
|
||||
},
|
||||
)
|
||||
tm.execute_tool = AsyncMock(return_value=result)
|
||||
return tm
|
||||
|
||||
|
||||
class TestPlatformReviewRequiredGate:
|
||||
def test_warn_mode_pass_below_threshold(self):
|
||||
"""Score below warn_at → pass, no recommendations, no failure."""
|
||||
tm = _make_tool_manager(30, "medium")
|
||||
ok, gate = asyncio.run(
|
||||
_run_platform_review_required(tm, "agent_ops", "gateway", "prod")
|
||||
)
|
||||
assert ok is True
|
||||
assert gate["name"] == "platform_review_required"
|
||||
assert gate.get("skipped") is False
|
||||
assert gate.get("should_fail") is False
|
||||
assert gate.get("recommendations", []) == []
|
||||
|
||||
def test_warn_mode_adds_recommendation_above_warn_at(self):
|
||||
"""Score >= warn_at → pass=True but recommendation added."""
|
||||
tm = _make_tool_manager(
|
||||
65, "high",
|
||||
signals_summary=["High recurrence in 30d"]
|
||||
)
|
||||
ok, gate = asyncio.run(
|
||||
_run_platform_review_required(tm, "agent_ops", "router", "prod")
|
||||
)
|
||||
assert ok is True
|
||||
assert len(gate.get("recommendations", [])) >= 1
|
||||
assert gate.get("should_fail") is False
|
||||
|
||||
def test_fail_at_sets_should_fail_true(self):
|
||||
"""Score >= fail_at → should_fail=True (gate decides blocking in strict mode)."""
|
||||
tm = _make_tool_manager(90, "critical", requires_review=True)
|
||||
ok, gate = asyncio.run(
|
||||
_run_platform_review_required(tm, "agent_ops", "gateway", "prod")
|
||||
)
|
||||
assert ok is True
|
||||
assert gate.get("should_fail") is True
|
||||
# Always pass=True in warn mode (caller handles strict)
|
||||
|
||||
def test_arch_review_required_adds_recommendation(self):
|
||||
"""When requires_arch_review=True, an extra recommendation is added."""
|
||||
tm = _make_tool_manager(65, "high", requires_review=True)
|
||||
_, gate = asyncio.run(
|
||||
_run_platform_review_required(tm, "agent_ops", "svc", "prod")
|
||||
)
|
||||
recs = gate.get("recommendations", [])
|
||||
assert any("Architecture review" in r or "architecture" in r.lower() for r in recs)
|
||||
|
||||
def test_skipped_when_no_service_name(self):
|
||||
"""Gate skips gracefully when no service_name provided."""
|
||||
tm = _make_tool_manager(0, "low")
|
||||
ok, gate = asyncio.run(
|
||||
_run_platform_review_required(tm, "agent_ops", service_name="")
|
||||
)
|
||||
assert ok is True
|
||||
assert gate.get("skipped") is True
|
||||
|
||||
def test_non_fatal_on_tool_error(self):
|
||||
"""Tool failure → skip (never block release)."""
|
||||
tm = _make_tool_manager(0, "low", fail=True)
|
||||
ok, gate = asyncio.run(
|
||||
_run_platform_review_required(tm, "agent_ops", "svc", "prod")
|
||||
)
|
||||
assert ok is True
|
||||
assert gate.get("skipped") is True
|
||||
|
||||
def test_non_fatal_on_exception(self):
|
||||
"""Any exception in gate → skip."""
|
||||
tm = MagicMock()
|
||||
tm.execute_tool = AsyncMock(side_effect=RuntimeError("unexpected"))
|
||||
ok, gate = asyncio.run(
|
||||
_run_platform_review_required(tm, "agent_ops", "svc", "prod")
|
||||
)
|
||||
assert ok is True
|
||||
assert gate.get("skipped") is True
|
||||
|
||||
def test_gate_includes_score_and_band(self):
|
||||
tm = _make_tool_manager(55, "high")
|
||||
_, gate = asyncio.run(
|
||||
_run_platform_review_required(tm, "agent_ops", "svc", "prod")
|
||||
)
|
||||
assert gate.get("score") == 55
|
||||
assert gate.get("band") == "high"
|
||||
|
||||
def test_gate_includes_warn_fail_thresholds(self):
|
||||
tm = _make_tool_manager(50, "medium")
|
||||
_, gate = asyncio.run(
|
||||
_run_platform_review_required(tm, "agent_ops", "svc", "prod")
|
||||
)
|
||||
assert "warn_at" in gate
|
||||
assert "fail_at" in gate
|
||||
|
||||
def test_score_below_fail_at_should_fail_false(self):
|
||||
tm = _make_tool_manager(75, "critical", requires_review=True)
|
||||
_, gate = asyncio.run(
|
||||
_run_platform_review_required(tm, "agent_ops", "svc", "prod")
|
||||
)
|
||||
# 75 < fail_at (85) → should_fail = False
|
||||
assert gate.get("should_fail") is False
|
||||
|
||||
def test_score_exactly_at_fail_at_should_fail_true(self):
|
||||
tm = _make_tool_manager(85, "critical", requires_review=True)
|
||||
_, gate = asyncio.run(
|
||||
_run_platform_review_required(tm, "agent_ops", "svc", "prod")
|
||||
)
|
||||
assert gate.get("should_fail") is True
|
||||
|
||||
def test_note_includes_score(self):
|
||||
tm = _make_tool_manager(60, "high")
|
||||
_, gate = asyncio.run(
|
||||
_run_platform_review_required(tm, "agent_ops", "svc", "prod")
|
||||
)
|
||||
assert "60" in gate.get("note", "")
|
||||
Reference in New Issue
Block a user