Skip to content

[AAASM-4856] ✨ (python-sdk): Expose public ENFORCEMENT_MODES parity surface#280

Merged
Chisanan232 merged 4 commits into
masterfrom
v0.0.1/AAASM-4856/enforcement_modes_public
Jul 18, 2026
Merged

[AAASM-4856] ✨ (python-sdk): Expose public ENFORCEMENT_MODES parity surface#280
Chisanan232 merged 4 commits into
masterfrom
v0.0.1/AAASM-4856/enforcement_modes_public

Conversation

@Chisanan232

@Chisanan232 Chisanan232 commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Description

The Python SDK did not expose a public ENFORCEMENT_MODES parity surface. The only
enforcement-mode collection was a private, unordered _VALID_ENFORCEMENT_MODES: frozenset[EnforcementMode] in agent_assembly/core/assembly.py — underscore-private,
a frozenset (unordered), and absent from agent_assembly.__all__. The cross-SDK
enforcement-mode parity conformance cross-check in e2e-public reads
getattr(agent_assembly, "ENFORCEMENT_MODES", None) and got None, so the Python leg
of cross-SDK enforcement-mode parity could not run.

This PR adds the public surface, additively and behavior-preserving:

  • ENFORCEMENT_MODES: tuple[EnforcementMode, ...] = ("enforce", "observe", "disabled")
    — a public, ordered, immutable canonical tuple in core/assembly.py, made the
    single source of truth: the private _VALID_ENFORCEMENT_MODES is now derived
    via frozenset(ENFORCEMENT_MODES), so the ordered public surface and the private
    validator can never drift.
  • Exposed as agent_assembly.ENFORCEMENT_MODES through the existing lazy-export
    mechanism (_LAZY_EXPORTS / _ALWAYS_EXPORTED + module __getattr__/__dir__ on
    the top-level package, and the matching __getattr__/__all__ on
    agent_assembly.core). It now appears in agent_assembly.__all__. Import stays
    lazy — import agent_assembly still does not eagerly pull in httpx/pydantic.

No validation behavior changed: _VALID_ENFORCEMENT_MODES still contains exactly
{"enforce", "observe", "disabled"} and the init_assembly membership check behaves
identically. EnforcementMode typing is intact.

Not re-exported from agent_assembly.types: that module is stdlib-only by design
(PEP 562 lazy-loading isolation, AAASM-1696) and defines its own event types rather
than re-exporting the runtime/config surface — where EnforcementMode itself already
lives in core.assembly, not types. Adding this constant there would drag
core.assembly's heavy dependency surface into a deliberately-light module. The
hard requirement — agent_assembly.ENFORCEMENT_MODES — is satisfied at the top level.

Type of Change

  • ✨ New feature
  • 🔧 Bug fix
  • ♻️ Refactoring
  • 🍀 Performance improvement
  • 📚 Documentation update
  • 🚀 Release

Breaking Changes

  • No
  • Yes (please describe below)

Purely additive — a new public export plus an internal single-source-of-truth
refactor. No existing behavior changes.

Related Issues

  • Related JIRA ticket: AAASM-4856
  • Unmasks the cross-SDK enforcement-mode parity cross-check re-pointed to this ticket
    by AAASM-4853 (previously masked behind the now-Done AAASM-3158).

Closes AAASM-4856

Testing

  • Unit tests added/updated
  • Integration tests added/updated
  • Manual testing performed
  • No tests required (explain why)

New regression test test/unit/test_enforcement_modes_export.py asserts:

  1. agent_assembly.ENFORCEMENT_MODES == ("enforce", "observe", "disabled") (exact order),
  2. "ENFORCEMENT_MODES" in agent_assembly.__all__,
  3. frozenset(agent_assembly.ENFORCEMENT_MODES) == agent_assembly.core.assembly._VALID_ENFORCEMENT_MODES
    (public constant and private validator stay in sync).

test/unit/core/test_core_lazy_exports.py extended to cover the new lazy core.__getattr__
branch and the extended core.__all__ set.

How to verify:

  • .venv/bin/python -m pytest test/ -q1184 passed, 16 skipped.
  • .venv/bin/ruff check / ruff format --check clean on all changed files.
  • .venv/bin/mypy agent_assembly adds no new errors (the pre-existing
    agent_assembly._core import-not-found notes are the un-built native shim, an
    environment limitation, not from this change).
  • Downstream: the e2e-public test_enforcement_mode_parity cross-check
    (getattr(agent_assembly, "ENFORCEMENT_MODES", None)) now resolves to the ordered
    tuple instead of None.

Checklist

  • Code follows project style guidelines
  • Self-review completed
  • Comments added for complex logic
  • Documentation updated if needed
  • All tests passing

Cross-SDK parity (informational — no changes here)

  • node-sdk: already exposes public ordered ENFORCEMENT_MODES
    (src/types/enforcement-mode.ts, re-exported from src/index.ts). Parity present.
  • go-sdk: exposes the EnforcementMode type + individual constants
    (EnforcementModeEnforce/Observe/Disabled) + a Valid() method, but no exported
    ordered collection
    equivalent to ENFORCEMENT_MODES. Potential follow-up gap if
    the conformance harness expects an ordered public slice — to be filed separately.

🤖 Generated with Claude Code

Introduce a public, ordered canonical enforcement-mode tuple
("enforce", "observe", "disabled") as the parity surface the cross-SDK
conformance cross-check reads. Ordered + immutable, unlike the private
unordered _VALID_ENFORCEMENT_MODES frozenset.

Refs AAASM-4856
Make ENFORCEMENT_MODES the single source of truth: build the private
membership validator via frozenset(ENFORCEMENT_MODES) so the public
ordered surface and the private validator can never drift. Set membership
is unchanged — still {enforce, observe, disabled}.

Refs AAASM-4856
Wire the public constant through the lazy-export mechanism so
agent_assembly.ENFORCEMENT_MODES resolves and appears in __all__, via
both agent_assembly.core and the top-level package __getattr__. Import
stays lazy — no eager httpx/pydantic pull-in.

This is what the e2e-public cross-SDK conformance cross-check reads
(getattr(agent_assembly, "ENFORCEMENT_MODES", None)); it previously
returned None.

Refs AAASM-4856
Pin the AAASM-4856 contract: agent_assembly.ENFORCEMENT_MODES resolves
to the exact canonical order, is discoverable via __all__, resolves
lazily through core.__getattr__, and stays in sync with the private
_VALID_ENFORCEMENT_MODES validator it derives. Extend the core lazy-export
set assertion to cover the new public export.

Refs AAASM-4856
@codecov

codecov Bot commented Jul 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@sonarqubecloud

Copy link
Copy Markdown

@Chisanan232

Copy link
Copy Markdown
Contributor Author

Review — Claude Code

CI: ✅ green — full test matrix + CodeQL + SonarCloud + codecov/patch all pass. The skipping rows are conditional e2e / deploy / manual-republish lanes (expected on a PR), not failures.
SonarCloud: 0 open issues.

Scope vs AAASM-4856: ✅ complete.

  • Public ordered ENFORCEMENT_MODES: tuple = ("enforce","observe","disabled") added in core/assembly.py as the single source of truth; _VALID_ENFORCEMENT_MODES now frozenset(ENFORCEMENT_MODES) so the two can never drift.
  • Exposed at top-level agent_assembly.ENFORCEMENT_MODES + __all__ through the existing lazy mechanism (_LAZY_EXPORTS + core.__getattr__), which is exactly what the e2e conformance cross-check reads.
  • Correctly not re-exported from agent_assembly.types (stdlib-only by PEP 562 isolation, AAASM-1696 — re-exporting would drag core.assembly's heavy deps into a deliberately-light module). Rationale documented in the PR.
  • Regression test asserts exact order, __all__ membership, and public↔private sync.

Side-effects: none. The membership validator is byte-equivalent (frozenset of the same 3 tokens); the assembly.py:333 check behaves identically. Lazy loading is preserved — import agent_assembly stays light; the constant is imported only on access, same path as init_assembly. pytest test/ → 1184 passed / 16 skipped; ruff clean on changed files; mypy no new errors (the _core/grpc notes are the pre-existing native-shim env limitation).

Front-end: none (SDK library) → no Playwright needed.

Verdict: ✅ ready to approve + merge — closes the Python leg of the cross-SDK ENFORCEMENT_MODES parity the harness had masked since AAASM-3158 (via AAASM-4853). node-sdk already exposes the equivalent; go-sdk parity is under separate read-only verification.

@Chisanan232
Chisanan232 merged commit 9b7d4d0 into master Jul 18, 2026
30 checks passed
@Chisanan232
Chisanan232 deleted the v0.0.1/AAASM-4856/enforcement_modes_public branch July 18, 2026 11:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant