Skip to content
Merged
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 agent_assembly/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
_LAZY_EXPORTS: dict[str, str] = {
"init_assembly": _MODULE_CORE,
"AssemblyContext": _MODULE_CORE,
"ENFORCEMENT_MODES": _MODULE_CORE,
"GovernanceInterceptor": _MODULE_ADAPTERS,
"FrameworkAdapter": _MODULE_ADAPTERS,
"AssemblyError": _MODULE_EXCEPTIONS,
Expand All @@ -44,6 +45,7 @@
"__version__",
"init_assembly",
"AssemblyContext",
"ENFORCEMENT_MODES",
"GovernanceInterceptor",
"FrameworkAdapter",
"AssemblyError",
Expand Down Expand Up @@ -103,6 +105,7 @@ def __dir__() -> list[str]:
if TYPE_CHECKING:
from agent_assembly.adapters import FrameworkAdapter as FrameworkAdapter
from agent_assembly.adapters import GovernanceInterceptor as GovernanceInterceptor
from agent_assembly.core import ENFORCEMENT_MODES as ENFORCEMENT_MODES
from agent_assembly.core import AssemblyContext as AssemblyContext
from agent_assembly.core import init_assembly as init_assembly
from agent_assembly.exceptions import (
Expand Down
12 changes: 9 additions & 3 deletions agent_assembly/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,27 @@
from typing import TYPE_CHECKING, Any

if TYPE_CHECKING:
from agent_assembly.core.assembly import AssemblyContext, init_assembly
from agent_assembly.core.assembly import (
ENFORCEMENT_MODES,
AssemblyContext,
init_assembly,
)
from agent_assembly.core.lineage import LineageRegistry

__all__ = ["init_assembly", "AssemblyContext", "LineageRegistry"]
__all__ = ["init_assembly", "AssemblyContext", "ENFORCEMENT_MODES", "LineageRegistry"]


def __getattr__(name: str) -> Any:
if name in ("AssemblyContext", "init_assembly"):
if name in ("AssemblyContext", "init_assembly", "ENFORCEMENT_MODES"):
from agent_assembly.core.assembly import ( # noqa: PLC0415
ENFORCEMENT_MODES,
AssemblyContext,
init_assembly,
)

globals()["AssemblyContext"] = AssemblyContext
globals()["init_assembly"] = init_assembly
globals()["ENFORCEMENT_MODES"] = ENFORCEMENT_MODES
return globals()[name]
if name == "LineageRegistry":
from agent_assembly.core.lineage import LineageRegistry # noqa: PLC0415
Expand Down
12 changes: 11 additions & 1 deletion agent_assembly/core/assembly.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,23 @@
Mirrors ``aa_core::EnforcementMode`` on the wire; uses the same snake_case
tokens the gateway expects in the registration body."""

ENFORCEMENT_MODES: tuple[EnforcementMode, ...] = ("enforce", "observe", "disabled")
"""Canonical, ordered enforcement-mode tokens — the public parity surface.

Single source of truth for the enforcement-mode set: the private
``_VALID_ENFORCEMENT_MODES`` membership validator is derived from this tuple
(``frozenset(ENFORCEMENT_MODES)``) so the two can never drift. Ordering is
significant — the cross-SDK conformance cross-check (AAASM-4856) asserts the
Python/Node/Go SDKs each expose this exact sequence, matching the canonical
``aa_core::EnforcementMode`` order on the wire."""

ENV_GATEWAY_URL = "AA_GATEWAY_URL"
ENV_CONTROL_PLANE_URL = "AA_CONTROL_PLANE_URL"

_DEFAULT_AGENT_ID = "agent-assembly-default"
_AGENT_ID_RE = re.compile(r"^[A-Za-z0-9_.-]{1,128}$")
_VALID_RUNTIME_MODES = {"auto", "ebpf", "proxy", "sdk-only"}
_VALID_ENFORCEMENT_MODES: frozenset[EnforcementMode] = frozenset({"enforce", "observe", "disabled"})
_VALID_ENFORCEMENT_MODES: frozenset[EnforcementMode] = frozenset(ENFORCEMENT_MODES)
_INIT_LOCK = Lock()
_ACTIVE_CONTEXT: AssemblyContext | None = None

Expand Down
13 changes: 12 additions & 1 deletion test/unit/core/test_core_lazy_exports.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ def test_lazy_getattr_resolves_init_assembly_and_assembly_context() -> None:
assert core.AssemblyContext is AssemblyContext


def test_lazy_getattr_resolves_enforcement_modes() -> None:
from agent_assembly.core.assembly import ENFORCEMENT_MODES

assert core.ENFORCEMENT_MODES is ENFORCEMENT_MODES


def test_lazy_getattr_resolves_lineage_registry() -> None:
from agent_assembly.core.lineage import LineageRegistry

Expand All @@ -32,4 +38,9 @@ def test_lazy_getattr_raises_attribute_error_for_unknown_symbol() -> None:


def test_all_lists_the_public_lazy_exports() -> None:
assert set(core.__all__) == {"init_assembly", "AssemblyContext", "LineageRegistry"}
assert set(core.__all__) == {
"init_assembly",
"AssemblyContext",
"ENFORCEMENT_MODES",
"LineageRegistry",
}
29 changes: 29 additions & 0 deletions test/unit/test_enforcement_modes_export.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""AAASM-4856: `agent_assembly.ENFORCEMENT_MODES` public parity surface.

The cross-SDK enforcement-mode parity conformance cross-check in e2e-public
reads ``getattr(agent_assembly, "ENFORCEMENT_MODES", None)`` to assert the
installed Python SDK against the canonical ordered set. These tests pin that
surface: it must resolve, be publicly discoverable via ``__all__``, carry the
exact canonical order, and stay in sync with the private membership validator
it is the single source of truth for.
"""

from __future__ import annotations

import agent_assembly
import agent_assembly.core.assembly as assembly


def test_enforcement_modes_is_the_canonical_ordered_tuple() -> None:
# Order is significant — the cross-SDK cross-check compares sequences.
assert agent_assembly.ENFORCEMENT_MODES == ("enforce", "observe", "disabled")


def test_enforcement_modes_is_a_public_export() -> None:
assert "ENFORCEMENT_MODES" in agent_assembly.__all__


def test_enforcement_modes_stays_in_sync_with_private_validator() -> None:
# The public constant is the single source of truth; the private validator
# is derived from it, so the two can never drift.
assert frozenset(agent_assembly.ENFORCEMENT_MODES) == assembly._VALID_ENFORCEMENT_MODES