Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions integrations/tms/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .tms_connector import READ_ROUTE_CAPABILITY, TMSReadOnlyConnector

__all__ = ["READ_ROUTE_CAPABILITY", "TMSReadOnlyConnector"]
99 changes: 99 additions & 0 deletions integrations/tms/tms_connector.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
"""Read-only, governance-gated adapter for TMS route analysis."""

from dataclasses import dataclass
from numbers import Real
from typing import Any, Mapping

from services.agents.governance.agent_governance import (
AgentGovernanceEngine,
)
from services.guardian.tms_intelligence.runtime import TMSIntelligence


READ_ROUTE_CAPABILITY = "tms.route.analyze.read"


@dataclass(frozen=True)
class _ConnectorIdentity:
name: str = "adk_tms_readonly_connector"
capabilities: frozenset[str] = frozenset({READ_ROUTE_CAPABILITY})


class TMSReadOnlyConnector:
"""Expose TMS route analysis without transactional operations."""

def __init__(
self,
intelligence: TMSIntelligence | None = None,
governance: AgentGovernanceEngine | None = None,
):
self._intelligence = intelligence or TMSIntelligence()
self._governance = governance or AgentGovernanceEngine()
self._identity = _ConnectorIdentity()

def analyze_route(
self,
route: Mapping[str, Any],
) -> dict[str, Any]:
task = {
"capability": READ_ROUTE_CAPABILITY,
"critical": False,
"operation": "analyze_route",
"mode": "READ_ONLY",
}
decision = self._governance.authorize_execution(
self._identity,
task,
)
audit = dict(self._governance.audit_log[-1])

if decision != "ALLOW":
return {
"status": "BLOCKED",
"mode": "READ_ONLY",
"executed": False,
"reason": "governance_denied",
"audit": audit,
}

if not isinstance(route, Mapping):
return self._no_decision(
"route_mapping_required",
audit,
)

distance = route.get("distance")
if (
isinstance(distance, bool)
or not isinstance(distance, Real)
or distance <= 0
):
return self._no_decision(
"positive_numeric_distance_required",
audit,
)

result = self._intelligence.analyze_route(
{"distance": float(distance)}
)
return {
"status": "OK",
"mode": "READ_ONLY",
"executed": True,
"result": result,
"audit": audit,
}

@staticmethod
def _no_decision(
reason: str,
audit: dict[str, Any],
) -> dict[str, Any]:
return {
"status": "NO_DECISION",
"mode": "READ_ONLY",
"executed": False,
"axiom": "No Evidence -> No Decision",
"reason": reason,
"audit": audit,
}
63 changes: 63 additions & 0 deletions tests/tms_intelligence/test_tms_connector.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
from integrations.tms import TMSReadOnlyConnector


def test_analyze_route_with_verified_distance():
result = TMSReadOnlyConnector().analyze_route(
{"distance": 100}
)

assert result["status"] == "OK"
assert result["mode"] == "READ_ONLY"
assert result["executed"] is True
assert result["result"] == {
"route_status": "optimized",
"distance": 100.0,
}
assert result["audit"]["decision"] == "ALLOW"


def test_missing_distance_produces_no_decision():
result = TMSReadOnlyConnector().analyze_route({})

assert result["status"] == "NO_DECISION"
assert result["executed"] is False
assert result["reason"] == "positive_numeric_distance_required"
assert result["axiom"] == "No Evidence -> No Decision"


def test_boolean_distance_is_rejected():
result = TMSReadOnlyConnector().analyze_route(
{"distance": True}
)

assert result["status"] == "NO_DECISION"
assert result["executed"] is False

def test_zero_distance_is_rejected():
result = TMSReadOnlyConnector().analyze_route({"distance": 0})

assert result["status"] == "NO_DECISION"
assert result["executed"] is False


def test_negative_distance_is_rejected():
result = TMSReadOnlyConnector().analyze_route({"distance": -10})

assert result["status"] == "NO_DECISION"
assert result["executed"] is False


def test_string_distance_is_rejected():
result = TMSReadOnlyConnector().analyze_route({"distance": "100"})

assert result["status"] == "NO_DECISION"
assert result["executed"] is False
assert result["reason"] == "positive_numeric_distance_required"


def test_non_mapping_route_is_rejected():
result = TMSReadOnlyConnector().analyze_route(None)

assert result["status"] == "NO_DECISION"
assert result["executed"] is False
assert result["reason"] == "route_mapping_required"
Loading