Introduce vultron/enums/ as a Bottom-of-Stack Neutral Layer for Cross-Cutting Enumerations
Context and Problem Statement
vultron/config/ must be a neutral module — it must not import from
vultron/core/ or vultron/adapters/. However, ActorConfig (which will
live in vultron/config/actor.py) needs CVDRole to type the
default_case_roles field. CVDRole currently lives in
vultron/core/states/roles.py, which is inside the core domain layer.
If vultron/config/ imports CVDRole from vultron/core/, it violates the
neutral-module constraint: neutral modules must not import from core. The
import graph has no valid location for CVDRole that satisfies all three
layers (core, config, adapters) simultaneously — unless a new bottom-of-stack
layer is introduced that all other layers may import freely.
Concern #1334 and spec CFG-07-006 identified this gap.
Decision Drivers
vultron/config/must remain neutral (no imports fromvultron/core/orvultron/adapters/).ActorConfig.default_case_rolesrequiresCVDRoleat type-annotation time.CVDRoleis a pure enumeration with no domain-logic dependencies — it is appropriate as a shared primitive.- The fix must not create a circular import.
- The fix should generalise: other enumerations may need the same treatment.
Considered Options
- Introduce
vultron/enums/as a new bottom-of-stack neutral package containingCVDRoleand related helpers, importable by all layers. - Move
CVDRoleintovultron/config/directly, making it a config concern rather than a domain concern. - Keep
CVDRoleinvultron/core/and use aTYPE_CHECKINGguard invultron/config/actor.pyto avoid the runtime import. - Use
str/ plain string literals fordefault_case_roles, deferringCVDRolevalidation to a later layer.
Decision Outcome
Chosen option: Introduce vultron/enums/ as a new bottom-of-stack neutral
package, because it is the only option that preserves both the neutral-module
constraint on vultron/config/ and the domain-model status of CVDRole as a
shared primitive, without TYPE_CHECKING hacks or loss of type safety.
Consequences
- Good, because
vultron/config/,vultron/core/, andvultron/adapters/can all import fromvultron/enums/freely without layering violations. - Good, because
CVDRoleretains its identity as a domain primitive rather than being absorbed into config or stringly-typed. - Good, because
vultron/enums/can absorb other cross-cutting enumerations in the future (e.g.,RunMode) following the same pattern. - Bad, because it adds a new top-level package to the module hierarchy;
existing imports of
CVDRolefromvultron/core/states/roles.pymust be updated (tracked in #1342 / #1343). - Bad, because
vultron/enums/must be kept strictly free of imports fromvultron/core/,vultron/config/, orvultron/adapters/— a new invariant to enforce.
Pros and Cons of the Options
Option 1 — vultron/enums/ bottom-of-stack package
- Good, because it resolves the import cycle cleanly for all current and future neutral-module consumers.
- Good, because the constraint is enforceable via import-graph linting.
- Neutral, because the migration is mechanical (search-and-replace imports).
Option 2 — Move CVDRole into vultron/config/
- Bad, because
CVDRoleis used byvultron/core/BT nodes; placing it invultron/config/would make core depend on config — a layering violation.
Option 3 — TYPE_CHECKING guard
- Bad, because it breaks runtime isinstance checks and Pydantic validators that need the actual enum class at import time.
- Bad, because
TYPE_CHECKINGguards are fragile; they hide dependency structure rather than resolving it.
Option 4 — Plain strings
- Bad, because it removes the type safety that
CVDRoleprovides. - Bad, because it moves validation responsibility to runtime rather than model-construction time.
Validation
Import-graph tests in test/architecture/ (ARCH-01 series) must be extended
to assert:
vultron.enumsdoes NOT import fromvultron.core,vultron.config, orvultron.adapters.vultron.configdoes NOT import fromvultron.coreorvultron.adapters.
More Information
Generated spec requirements: specs/configuration.yaml CFG-07-006.
Related:
- Concern #1334 — original bug report (SeedConfig in production adapter)
- PR #1341 — docs: plan concern #1334 (this ADR drafted as follow-up)
- Issues #1342 / #1343 — implementation of the config sub-package
notes/configuration.md§ "Target Architecture" — full sub-package layout and import-graph constraints