Skip to content

refactor(types): reduce union complexity with type aliases [OMN-1358] - #157

Merged
jonahgabriel merged 5 commits into
mainfrom
jonah/omn-1358-reduce-union-complexity-across-omnibase_infra-codebase
Jan 16, 2026
Merged

jonahgabriel merged 5 commits into
mainfrom
jonah/omn-1358-reduce-union-complexity-across-omnibase_infra-codebase

Conversation

@jonahgabriel

@jonahgabriel jonahgabriel commented Jan 16, 2026 •

Copy link
Copy Markdown
Collaborator

Reduce non-optional unions from 122 to 63 (48% reduction) by introducing centralized type aliases that consolidate repeated union patterns.

New type aliases in types/type_infra_aliases.py:

  • MessageOutputCategory: EnumMessageCategory | EnumNodeOutputType (31 uses)
  • PathLike: Path | str (11 uses)
  • PolicyTypeInput: EnumPolicyType | str (11 uses)
  • ASTFunctionDef: ast.AsyncFunctionDef | ast.FunctionDef (10 uses)
  • VersionInput: ModelSemVer | str (available for future use)

Also applied PrimitiveValue from omnibase_core for float | int | str patterns.

Updated INFRA_MAX_UNIONS threshold from 122 to 70 to reflect the new baseline with appropriate buffer for minor growth.

Summary by CodeRabbit

  • Refactor

    • Standardized and simplified public type aliases across the library, unifying input/return types for validation and runtime APIs.
  • Bug Fix

    • Lowered the infra union threshold from 122 to 70 to reduce false positives in validators.
  • Tests

    • Updated test expectations for the new threshold and added coverage validating public type exports and module wiring.

✏️ Tip: You can customize this high-level summary in your review settings.

Reduce non-optional unions from 122 to 63 (48% reduction) by introducing
centralized type aliases that consolidate repeated union patterns.

New type aliases in types/type_infra_aliases.py:
- MessageOutputCategory: EnumMessageCategory | EnumNodeOutputType (31 uses)
- PathLike: Path | str (11 uses)
- PolicyTypeInput: EnumPolicyType | str (11 uses)
- ASTFunctionDef: ast.AsyncFunctionDef | ast.FunctionDef (10 uses)
- VersionInput: ModelSemVer | str (available for future use)

Also applied PrimitiveValue from omnibase_core for float | int | str patterns.

Updated INFRA_MAX_UNIONS threshold from 122 to 70 to reflect the new baseline
with appropriate buffer for minor growth.
@linear

linear Bot commented Jan 16, 2026

Copy link
Copy Markdown

OMN-1358

@coderabbitai

coderabbitai Bot commented Jan 16, 2026 •

Copy link
Copy Markdown

Warning

Rate limit exceeded

@jonahgabriel has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 10 minutes and 14 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between abfaa48 and 9d1f3bb.

📒 Files selected for processing (3)
  • src/omnibase_infra/models/validation/model_category_match_result.py
  • src/omnibase_infra/types/type_infra_aliases.py
  • tests/unit/types/test_types_module_exports.py
📝 Walkthrough

Walkthrough

Centralized repeated union types into new aliases (PolicyTypeInput, MessageOutputCategory, PathInput, ASTFunctionDef) and propagated those aliases across many modules; switched several log-context types to PrimitiveValue, lowered INFRA_MAX_UNIONS from 122 to 70, and added tests for the types export surface.

Changes

Cohort / File(s) Summary
Type Alias Foundation
src/omnibase_infra/types/type_infra_aliases.py, src/omnibase_infra/types/__init__.py
Introduced new type aliases: PolicyTypeInput, MessageOutputCategory, PathInput, ASTFunctionDef and re-exported them via package __init__.
Policy Type Consolidation
src/omnibase_infra/errors/error_policy_registry.py, src/omnibase_infra/runtime/models/model_policy_key.py, src/omnibase_infra/runtime/models/model_policy_registration.py, src/omnibase_infra/runtime/policy_registry.py
Replaced `str
Log Context Type Updates
src/omnibase_infra/models/dispatch/model_dispatch_log_context.py, src/omnibase_infra/models/logging/model_log_context.py, src/omnibase_infra/runtime/message_dispatch_engine.py
Switched log-context value typing from `str
Category Type Refactoring
src/omnibase_infra/models/validation/model_category_match_result.py, src/omnibase_infra/validation/execution_shape_validator.py, src/omnibase_infra/validation/routing_coverage_validator.py, src/omnibase_infra/validation/runtime_shape_validator.py, src/omnibase_infra/validation/topic_category_validator.py
Replaced `EnumMessageCategory
Path and AST Type Usage
src/omnibase_infra/validation/any_type_validator.py, src/omnibase_infra/validation/contract_linter.py, src/omnibase_infra/validation/execution_shape_validator.py, src/omnibase_infra/validation/infra_validators.py
Replaced path unions with PathInput and function-def unions with ASTFunctionDef in signatures and checks. Updated INFRA_MAX_UNIONS constant from 122 to 70.
Validators / Runtime Adjustments
src/omnibase_infra/validation/runtime_shape_validator.py, src/omnibase_infra/validation/topic_category_validator.py, src/omnibase_infra/validation/routing_coverage_validator.py
Extensive signature and mapping updates to adopt MessageOutputCategory (notable changes in detection, mapping, and public validator APIs).
Tests and Exports
tests/unit/validation/test_validator_defaults.py, tests/unit/types/*
Adjusted test to expect INFRA_MAX_UNIONS = 70; added tests validating omnibase_infra.types exports and a test package initializer.

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I nibble at unions, tidy their maze,

Policy and Path now hop into place.
Categories bundled, primitives in sight,
Small paws, big changes—types snug and light.


Comment @coderabbitai help to get the list of available commands and usage tips.

@claude

claude Bot commented Jan 16, 2026

Copy link
Copy Markdown

PR Review: Type Alias Union Reduction (OMN-1358)

Summary

This PR successfully reduces non-optional union complexity from 122 to 63 (48% reduction) by introducing centralized type aliases. The implementation aligns well with ONEX infrastructure guidelines and demonstrates strong adherence to code quality standards.


✅ Strengths

1. Excellent CLAUDE.md Compliance

  • PEP 604 unions: All type aliases correctly use X | Y syntax instead of Optional[X] ✓
  • Zero Any types: No violations found in new code ✓
  • Strong typing: All aliases use concrete types (enums, AST nodes, Path) ✓
  • Proper module structure: Follows type_<name>.py naming convention ✓

2. Well-Designed Type Aliases

The new aliases address real code duplication with clear semantic meaning:

Alias Occurrences Use Case Quality
MessageOutputCategory 31 Routing/validation ✓ Clear intent
PathLike 11 Filesystem operations ✓ Idiomatic
PolicyTypeInput 11 API flexibility ✓ Input pattern
ASTFunctionDef 10 AST traversal ✓ Precise scope
VersionInput 4 Version parsing ✓ Future-ready

3. Integration with omnibase_core

  • Correctly imports and uses PrimitiveValue from omnibase_core.types instead of recreating it
  • Demonstrates proper cross-module dependency management

4. Proper TYPE_CHECKING Guard

if TYPE_CHECKING:
    from omnibase_core.models.primitives.model_semver import ModelSemVer

Correctly uses runtime guard for ModelSemVer to avoid circular imports while preserving type safety.

5. Comprehensive __all__ Exports

Both type_infra_aliases.py and types/__init__.py properly declare exports, enabling clean imports.

6. Aggressive INFRA_MAX_UNIONS Reduction

Updating threshold from 122 → 70 (instead of conservative ~100) shows commitment to maintaining reduced complexity and preventing gradual drift.


🔍 Observations (Not Blocking)

1. PathLike Naming Collision

The alias PathLike conflicts with os.PathLike from stdlib:

# stdlib (protocol-based)
from os import PathLike  # Protocol for __fspath__() implementers

# ONEX (concrete union)
from omnibase_infra.types import PathLike  # Path | str

Recommendation: Consider renaming to PathInput or PathLikeInput to avoid:

  • Namespace confusion in modules that import both
  • Misleading developers familiar with os.PathLike protocol semantics

CLAUDE.md Context: File naming follows type_<name>.py pattern correctly, but alias naming flexibility isn't explicitly covered.

Not blocking: Current usage is internal to omnibase_infra validators where collision is unlikely.

2. Backward Compatibility Note

model_category_match_result.py:54 keeps CategoryType as alias to MessageOutputCategory:

# Note: CategoryType is kept for backward compatibility; prefer MessageOutputCategory for new code
type CategoryType = MessageOutputCategory

CLAUDE.md states: "NO backwards compatibility is maintained" and "Breaking changes are always acceptable."

Observation: This compatibility alias is technically unnecessary per policy, but pragmatic for gradual migration. Consider removing CategoryType entirely in a follow-up PR to fully align with zero-compatibility policy.

3. VersionInput - Unused Alias

PR description notes "VersionInput: available for future use" (only 4 occurrences replaced, may not be applied yet).

Recommendation: Verify VersionInput is actually used in changed files, or document why it's pre-declared for upcoming work.


🧪 Test Coverage

Not blocking, but consider adding:

  • Unit tests for type alias resolution (mypy static checks)
  • Validator tests confirming INFRA_MAX_UNIONS=70 threshold works correctly

🔒 Security

No security concerns. Changes are type-level refactoring with no runtime behavior modifications.


📊 Performance

Neutral impact. Type aliases are compile-time constructs - no runtime overhead.


✨ Final Assessment

Recommendation: ✅ APPROVE with minor naming suggestion

This is high-quality refactoring work that:

  • Reduces cognitive load (48% fewer repeated unions)
  • Improves maintainability via centralized definitions
  • Follows ONEX strong typing principles
  • Sets aggressive quality bar (70 union ceiling)

Optional follow-up:

  1. Rename PathLike → PathInput to avoid stdlib collision
  2. Remove CategoryType backward compatibility alias per CLAUDE.md policy
  3. Add static type tests for new aliases

Great work on this refactor! The union reduction significantly improves code clarity while maintaining strict type safety. 🎯

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/omnibase_infra/types/type_infra_aliases.py`:
- Around line 20-41: The VersionInput type alias currently uses ModelSemVer
which is only imported under TYPE_CHECKING causing a NameError at import; change
the definition to defer evaluation by using typing.TypeAlias with a string
forward reference or import ModelSemVer at runtime: keep the TYPE_CHECKING
import as-is, add "from typing import TypeAlias" (or import ModelSemVer
normally), and replace the current "type VersionInput = ModelSemVer | str" with
a string-based alias like VersionInput: TypeAlias = "ModelSemVer | str" so the
runtime import error is avoided while preserving the intended type.
♻️ Duplicate comments (1)
src/omnibase_infra/models/validation/model_category_match_result.py (1)

50-56: Same PEP 695 compatibility concern as other new aliases.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Lite

📥 Commits

Reviewing files that changed from the base of the PR and between fafe200 and 6db5940.

📒 Files selected for processing (17)
  • src/omnibase_infra/errors/error_policy_registry.py
  • src/omnibase_infra/models/dispatch/model_dispatch_log_context.py
  • src/omnibase_infra/models/logging/model_log_context.py
  • src/omnibase_infra/models/validation/model_category_match_result.py
  • src/omnibase_infra/runtime/message_dispatch_engine.py
  • src/omnibase_infra/runtime/models/model_policy_key.py
  • src/omnibase_infra/runtime/models/model_policy_registration.py
  • src/omnibase_infra/runtime/policy_registry.py
  • src/omnibase_infra/types/__init__.py
  • src/omnibase_infra/types/type_infra_aliases.py
  • src/omnibase_infra/validation/any_type_validator.py
  • src/omnibase_infra/validation/contract_linter.py
  • src/omnibase_infra/validation/execution_shape_validator.py
  • src/omnibase_infra/validation/infra_validators.py
  • src/omnibase_infra/validation/routing_coverage_validator.py
  • src/omnibase_infra/validation/runtime_shape_validator.py
  • src/omnibase_infra/validation/topic_category_validator.py
🧰 Additional context used
📓 Path-based instructions (4)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Never use Any type - use object for generic payloads in function parameters and return types
Use X | None (PEP 604) instead of Optional[X] for nullable types
All services must use ModelONEXContainer for dependency injection via __init__(self, container: ModelONEXContainer)
Use @allow_any decorator with documented reason as exemption mechanism for Any type violations
Use JsonType from omnibase_core.types as the canonical type alias for JSON-compatible values
Use ModelEventEnvelope[object] for generic dispatcher interfaces and object for generic payloads
Infrastructure error handling must use OnexError base class and never expose passwords, API keys, PII, or connection strings with credentials in error messages
Use InfraConnectionError, InfraTimeoutError, InfraAuthenticationError, InfraUnavailableError for transport failures with proper ModelInfraErrorContext
Correlation IDs must be propagated from incoming requests, auto-generated with uuid4() if missing, and included in all error contexts
External service adapters must implement MixinAsyncCircuitBreaker with appropriate threshold and reset_timeout configuration
Protocol resolution must use duck typing via protocols, never use isinstance checks

Files:

  • src/omnibase_infra/models/validation/model_category_match_result.py
  • src/omnibase_infra/validation/any_type_validator.py
  • src/omnibase_infra/runtime/models/model_policy_registration.py
  • src/omnibase_infra/runtime/message_dispatch_engine.py
  • src/omnibase_infra/runtime/policy_registry.py
  • src/omnibase_infra/types/__init__.py
  • src/omnibase_infra/models/dispatch/model_dispatch_log_context.py
  • src/omnibase_infra/types/type_infra_aliases.py
  • src/omnibase_infra/validation/routing_coverage_validator.py
  • src/omnibase_infra/validation/infra_validators.py
  • src/omnibase_infra/validation/execution_shape_validator.py
  • src/omnibase_infra/validation/runtime_shape_validator.py
  • src/omnibase_infra/runtime/models/model_policy_key.py
  • src/omnibase_infra/models/logging/model_log_context.py
  • src/omnibase_infra/errors/error_policy_registry.py
  • src/omnibase_infra/validation/contract_linter.py
  • src/omnibase_infra/validation/topic_category_validator.py
**/model_*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/model_*.py: File naming convention: Models must use model_<name>.py with class name Model<Name>
Each model file must contain exactly one Model* class
Pydantic workaround for Any type must include # NOTE: comment documenting the reason when technically required
Use SerializeAsAny type wrapper for Pydantic fields containing complex nested models to preserve subclass fields during serialization

Files:

  • src/omnibase_infra/models/validation/model_category_match_result.py
  • src/omnibase_infra/runtime/models/model_policy_registration.py
  • src/omnibase_infra/models/dispatch/model_dispatch_log_context.py
  • src/omnibase_infra/runtime/models/model_policy_key.py
  • src/omnibase_infra/models/logging/model_log_context.py
**/model_*result*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Result models may override __bool__ to enable idiomatic conditional checks, with required Warning section in docstring explaining non-standard behavior

Files:

  • src/omnibase_infra/models/validation/model_category_match_result.py
**/errors/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Error classes must follow naming pattern <Domain><Type>Error and be located in errors/ directory

Files:

  • src/omnibase_infra/errors/error_policy_registry.py
🧠 Learnings (23)
📓 Common learnings
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-28T18:58:53.781Z
Learning: Applies to **/*.py : Use proper union type definitions and discriminated unions where appropriate
📚 Learning: 2025-11-28T18:58:53.781Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-28T18:58:53.781Z
Learning: Applies to **/*.py : Use `EnumCoreErrorCode` with `ModelOnexError` for proper error code usage

Applied to files:

  • src/omnibase_infra/runtime/message_dispatch_engine.py
  • src/omnibase_infra/models/dispatch/model_dispatch_log_context.py
📚 Learning: 2026-01-15T23:08:36.545Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T23:08:36.545Z
Learning: Applies to **/*.py : Use `ModelOnexError` with error codes for ONEX-specific domain errors that need serialization or cross-service communication

Applied to files:

  • src/omnibase_infra/runtime/message_dispatch_engine.py
📚 Learning: 2025-11-24T16:33:32.747Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T16:33:32.747Z
Learning: Applies to **/*.py : Import enums from `omnibase.enums` package

Applied to files:

  • src/omnibase_infra/runtime/message_dispatch_engine.py
📚 Learning: 2025-11-24T17:22:32.195Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-24T17:22:32.195Z
Learning: Applies to **/*.py : All error handling must use OnexError exception class with specific error codes from error enum, never raise generic Exception or ValueError

Applied to files:

  • src/omnibase_infra/runtime/message_dispatch_engine.py
📚 Learning: 2025-11-24T17:24:41.687Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T17:24:41.687Z
Learning: Applies to **/*.py : Import enums from `omnibase.enums` module

Applied to files:

  • src/omnibase_infra/runtime/message_dispatch_engine.py
📚 Learning: 2026-01-15T23:08:36.545Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T23:08:36.545Z
Learning: Applies to **/*.py : Use `EnumSeverity` from omnibase_core.enums for all general severity classifications (not custom severity enums)

Applied to files:

  • src/omnibase_infra/runtime/message_dispatch_engine.py
  • src/omnibase_infra/validation/contract_linter.py
📚 Learning: 2026-01-16T14:05:23.806Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_spi PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-16T14:05:23.806Z
Learning: Applies to src/omnibase_spi/**/*.py : SPI modules may import from `omnibase_core` at runtime for type hints and model references

Applied to files:

  • src/omnibase_infra/types/__init__.py
📚 Learning: 2025-09-23T22:28:00.333Z
Learnt from: jonahgabriel
Repo: OmniNode-ai/omnibase_core PR: 32
File: examples/practical_migration_example.py:125-134
Timestamp: 2025-09-23T22:28:00.333Z
Learning: The omnibase_core codebase extensively uses constrained TypeVars for primitive types with the pattern `T = TypeVar("T", str, int, float, bool)` across multiple models including ModelTypedMetrics, ModelGenericMetadata, and ModelExecutionResult. This is the preferred approach over hardcoded union types like `str | int | bool | float | None`.

Applied to files:

  • src/omnibase_infra/types/__init__.py
  • src/omnibase_infra/types/type_infra_aliases.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/*.py : Use `JsonType` from `omnibase_core.types` as the canonical type alias for JSON-compatible values

Applied to files:

  • src/omnibase_infra/types/__init__.py
  • src/omnibase_infra/types/type_infra_aliases.py
📚 Learning: 2025-11-28T18:58:53.781Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-28T18:58:53.781Z
Learning: Applies to **/*.py : Use proper union type definitions and discriminated unions where appropriate

Applied to files:

  • src/omnibase_infra/types/type_infra_aliases.py
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Deviations from omnibase_core standards are only acceptable for: (1) Orchestrator/Reducer nodes (ModelService* disabled), (2) Experimental features being prototyped for upstream, (3) Performance-critical optimizations with benchmark proof, (4) Bridge-specific unique patterns. All deviations require explicit documentation and justification.

Applied to files:

  • src/omnibase_infra/validation/infra_validators.py
📚 Learning: 2025-11-24T16:32:55.606Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T16:32:55.606Z
Learning: Applies to **/*contract*.yaml : All ONEX nodes must have validated YAML contracts following the contract-driven development pattern with input_state and output_state schema definitions

Applied to files:

  • src/omnibase_infra/validation/infra_validators.py
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contracts/contract_*.yaml : All ONEX node subcontracts must be organized in a `contracts/` subdirectory within the versioned implementation directory with separate files for contract_actions.yaml, contract_models.yaml, contract_validation.yaml, contract_cli.yaml (optional), and contract_capabilities.yaml (optional)

Applied to files:

  • src/omnibase_infra/validation/infra_validators.py
📚 Learning: 2025-12-07T17:50:13.678Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T17:50:13.678Z
Learning: Applies to **/*.py : Use file prefix naming conventions in Python files: model_* for Pydantic models, enum_* for enumerations, protocol_* for protocol interfaces, service_* for service implementations, node_* for ONEX nodes

Applied to files:

  • src/omnibase_infra/validation/execution_shape_validator.py
📚 Learning: 2025-11-24T17:24:41.687Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T17:24:41.687Z
Learning: Applies to **/models/model_*.py : Model class names must follow the pattern `Model<Name>` (e.g., `ModelNodeGeneratorInputState`)

Applied to files:

  • src/omnibase_infra/validation/execution_shape_validator.py
📚 Learning: 2026-01-15T23:08:36.545Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T23:08:36.545Z
Learning: Applies to src/omnibase_core/**/*.py : File naming in `src/omnibase_core/` must follow directory-specific prefix convention (e.g., `decorator_*.py` in decorators/, `model_*.py` in models/, `enum_*.py` in enums/)

Applied to files:

  • src/omnibase_infra/validation/execution_shape_validator.py
📚 Learning: 2025-12-06T22:21:32.649Z
Learnt from: CR
Repo: OmniNode-ai/omniagent PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T22:21:32.649Z
Learning: Applies to shared/models/model_*.py : Use `model_*` prefix for Pydantic models in `shared/models/` directory

Applied to files:

  • src/omnibase_infra/validation/execution_shape_validator.py
📚 Learning: 2025-12-06T22:21:32.649Z
Learnt from: CR
Repo: OmniNode-ai/omniagent PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T22:21:32.649Z
Learning: Applies to nodes/**/node_*.py : Use `node_*` prefix for ONEX node implementation files in `nodes/{type}/` directory

Applied to files:

  • src/omnibase_infra/validation/execution_shape_validator.py
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/models/model_contract_*.py : All ONEX node auto-generated Pydantic models must be organized in a `models/` directory with files for state.py, model_contract_actions.py, model_contract_models.py, model_contract_validation.py, model_contract_cli.py (optional), model_contract_capabilities.py (optional), and error_codes.py, generated from the corresponding contract definitions

Applied to files:

  • src/omnibase_infra/validation/execution_shape_validator.py
📚 Learning: 2025-11-24T16:33:32.747Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T16:33:32.747Z
Learning: Applies to **/{models,protocols}/{model_*,protocol_*}.py : Avoid using Any, dict, or primitive types in model and protocol definitions; use strongest typing possible

Applied to files:

  • src/omnibase_infra/models/logging/model_log_context.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/*.py : Use `InfraConnectionError`, `InfraTimeoutError`, `InfraAuthenticationError`, `InfraUnavailableError` for transport failures with proper `ModelInfraErrorContext`

Applied to files:

  • src/omnibase_infra/errors/error_policy_registry.py
📚 Learning: 2025-12-07T17:50:13.678Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T17:50:13.678Z
Learning: Applies to **/contracts/*.yaml : Validate contracts using the contract linter tool: python -m omniintelligence.tools.contract_linter for YAML contract definitions

Applied to files:

  • src/omnibase_infra/validation/contract_linter.py
🧬 Code graph analysis (9)
src/omnibase_infra/runtime/models/model_policy_registration.py (2)
src/omnibase_infra/runtime/protocol_policy.py (1)
  • policy_type (254-286)
src/omnibase_infra/runtime/models/model_policy_key.py (1)
  • validate_policy_type (96-114)
src/omnibase_infra/types/type_infra_aliases.py (3)
src/omnibase_infra/enums/enum_message_category.py (1)
  • EnumMessageCategory (34-196)
src/omnibase_infra/enums/enum_node_output_type.py (1)
  • EnumNodeOutputType (40-182)
src/omnibase_infra/enums/enum_policy_type.py (1)
  • EnumPolicyType (12-29)
src/omnibase_infra/validation/routing_coverage_validator.py (3)
src/omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_node_heartbeat.py (1)
  • category (169-171)
src/omnibase_infra/protocols/protocol_message_dispatcher.py (1)
  • category (164-176)
tests/unit/runtime/test_dispatcher_registry.py (1)
  • category (59-60)
src/omnibase_infra/validation/execution_shape_validator.py (2)
src/omnibase_infra/enums/enum_node_output_type.py (4)
  • is_event (86-88)
  • EnumNodeOutputType (40-182)
  • is_intent (94-96)
  • is_projection (98-100)
src/omnibase_infra/enums/enum_message_category.py (3)
  • is_event (186-188)
  • EnumMessageCategory (34-196)
  • is_intent (194-196)
src/omnibase_infra/validation/runtime_shape_validator.py (4)
src/omnibase_infra/enums/enum_node_archetype.py (1)
  • EnumNodeArchetype (41-71)
src/omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_node_heartbeat.py (1)
  • category (169-171)
src/omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_node_introspected.py (1)
  • category (214-216)
src/omnibase_infra/protocols/protocol_message_dispatcher.py (1)
  • category (164-176)
src/omnibase_infra/runtime/models/model_policy_key.py (2)
src/omnibase_infra/runtime/protocol_policy.py (1)
  • policy_type (254-286)
src/omnibase_infra/runtime/models/model_policy_registration.py (1)
  • validate_policy_type (120-138)
src/omnibase_infra/models/logging/model_log_context.py (4)
src/omnibase_infra/models/dispatch/model_dispatch_log_context.py (1)
  • to_dict (208-267)
src/omnibase_infra/models/validation/model_coverage_metrics.py (1)
  • to_dict (240-273)
src/omnibase_infra/models/dispatch/model_dispatcher_metrics.py (1)
  • to_dict (251-272)
src/omnibase_infra/models/registration/model_introspection_metrics.py (1)
  • to_dict (147-184)
src/omnibase_infra/errors/error_policy_registry.py (4)
tests/unit/runtime/test_policy_registry_performance.py (4)
  • policy_type (45-47)
  • policy_type (356-357)
  • policy_type (371-372)
  • policy_type (386-387)
tests/unit/runtime/test_policy_registry.py (8)
  • policy_type (48-49)
  • policy_type (66-67)
  • policy_type (84-85)
  • policy_type (102-103)
  • policy_type (123-124)
  • policy_type (144-145)
  • policy_type (162-163)
  • policy_type (180-181)
src/omnibase_infra/runtime/protocol_policy.py (1)
  • policy_type (254-286)
tests/integration/runtime/test_policy_registry_container_integration.py (3)
  • policy_type (133-134)
  • policy_type (202-203)
  • policy_type (216-217)
src/omnibase_infra/validation/topic_category_validator.py (4)
src/omnibase_infra/enums/enum_node_archetype.py (1)
  • EnumNodeArchetype (41-71)
src/omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_node_heartbeat.py (1)
  • category (169-171)
src/omnibase_infra/protocols/protocol_message_dispatcher.py (1)
  • category (164-176)
tests/unit/runtime/test_dispatcher_registry.py (1)
  • category (59-60)
🔇 Additional comments (24)
src/omnibase_infra/types/type_infra_aliases.py (1)

43-49: Export list matches the new aliases.

src/omnibase_infra/types/__init__.py (1)

31-46: Re-exports are consistent and clear.

src/omnibase_infra/validation/contract_linter.py (3)

71-75: Good consolidation on PathLike for public APIs.


929-949: LGTM: PathLike boundary is handled cleanly.


952-1004: Consistent PathLike usage across directory/CI helpers.

src/omnibase_infra/validation/any_type_validator.py (1)

58-175: Nice alignment with centralized ASTFunctionDef alias.

src/omnibase_infra/validation/routing_coverage_validator.py (2)

65-175: Type-alias propagation looks consistent.
The MessageOutputCategory typing is applied uniformly across discovery helpers and discovery output.

Also applies to: 189-192, 293-297, 341-392


714-715: Cache typing aligned with discovery output.
The cached discovered types now match the new MessageOutputCategory alias.

src/omnibase_infra/errors/error_policy_registry.py (1)

13-13: PolicyTypeInput adoption is clean.
Signature now matches the centralized alias while keeping EnumPolicyType/string handling intact.

Also applies to: 73-78

src/omnibase_infra/models/dispatch/model_dispatch_log_context.py (1)

35-35: LogContextDict typing update is consistent.
The alias now reflects the centralized primitive value type without affecting behavior.

Also applies to: 47-47

src/omnibase_infra/models/logging/model_log_context.py (1)

89-89: to_dict typing update is consistent.
Return typing now aligns with the shared primitive value alias used across log contexts.

Also applies to: 235-261

src/omnibase_infra/runtime/message_dispatch_engine.py (1)

147-147: Structured log context typing updated consistently.
Return typing now matches the centralized primitive value alias used elsewhere.

Also applies to: 767-770

src/omnibase_infra/runtime/models/model_policy_registration.py (2)

15-18: Policy type alias adoption looks consistent.
Nice consolidation of the policy_type input shape on the model field using the shared alias.

Also applies to: 71-74


118-138: Validator signature aligns with PolicyTypeInput.
Typing now matches the alias while keeping the validation behavior intact.

src/omnibase_infra/runtime/models/model_policy_key.py (2)

13-16: Policy key now matches shared policy_type input shape.
Good alignment with the centralized PolicyTypeInput alias.

Also applies to: 46-50


94-114: Validator signature update is clean.
No behavior change, just consistent typing for policy_type validation.

src/omnibase_infra/validation/infra_validators.py (2)

51-53: PathLike standardized across validator entry points.
Consistent path typing across the infra validators reads well and keeps call sites uniform.

Also applies to: 420-423, 460-461, 477-479, 684-686, 1034-1038, 1132-1134, 1152-1155


388-402: Confirm the new union threshold baseline (70) still passes.
Please re-run the union usage validation to ensure the reduced cap is aligned with the current non-optional union count.

src/omnibase_infra/runtime/policy_registry.py (1)

93-98: PolicyTypeInput adoption across registry APIs is consistent.
The normalization path and public method signatures now share the same policy_type input shape, which should reduce call-site variance.

Also applies to: 595-598, 769-775, 851-855, 1298-1301, 1374-1378, 1423-1427

src/omnibase_infra/validation/runtime_shape_validator.py (2)

174-178: MessageOutputCategory integration is cohesive in helpers and mappings.
The mapping and category-detection utilities now consistently operate on the unified category type.

Also applies to: 206-208, 311-313, 366-369, 425-430


551-555: Runtime validator APIs now consistently use MessageOutputCategory.
Public validation methods align with the consolidated category type, keeping call sites uniform.

Also applies to: 604-609, 706-711

src/omnibase_infra/validation/execution_shape_validator.py (2)

99-100: ASTFunctionDef alias applied consistently across handler discovery and validation.
Keeps node typing consistent end‑to‑end and removes duplicated unions.

Also applies to: 275-279, 462-473, 512-513, 645-652, 673-676, 1009-1013, 1058-1062


717-758: MessageOutputCategory integration in return‑type detection is clean.
Normalization and PROJECTION handling remain explicit and easy to follow.

Also applies to: 810-908, 910-947

src/omnibase_infra/validation/topic_category_validator.py (1)

49-50: MessageOutputCategory usage is consistently applied across constants and APIs.
Unifies routing and output-type expectations while keeping PROJECTION handling centralized.

Also applies to: 86-91, 102-111, 170-174, 244-249, 362-366, 1009-1013

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment thread src/omnibase_infra/types/type_infra_aliases.py Outdated
- Move ModelSemVer import to runtime (was in TYPE_CHECKING block)
- Rename PathLike to PathInput to avoid stdlib os.PathLike collision
- Update INFRA_MAX_UNIONS test to expect 70 (reduced from 122)
@claude

claude Bot commented Jan 16, 2026

Copy link
Copy Markdown

Code Review: Type Alias Refactoring (OMN-1358)

Summary

This PR successfully reduces union complexity from 122 to 70 non-optional unions (48% reduction) by introducing centralized type aliases. The implementation follows ONEX patterns and the approach is sound.


✅ Strengths

1. Excellent Type Alias Design

  • All aliases follow PEP 695 syntax (type X = Y)
  • Comprehensive documentation with usage counts
  • Clear naming that avoids stdlib collisions (PathInput vs PathLike)
  • Proper __all__ exports for public API

2. Strong ONEX Compliance

  • Zero Any types introduced ✓
  • Follows omnibase_core.types pattern (like PrimitiveValue)
  • Consistent with CLAUDE.md type annotation conventions
  • Uses PEP 604 unions (X | Y)

3. Thorough Testing

  • Updated test constants to reflect new baseline (70)
  • Maintained threshold documentation history
  • Tests verify the reduction actually works

4. Clean Import Hygiene

  • Re-exports through types/__init__.py for public API
  • Consistent import patterns across all modified files
  • No circular dependencies introduced

🔍 Issues & Recommendations

1. CRITICAL: Incomplete Type Alias Adoption

The PR description claims reduction from 122 to 70, but there may be additional opportunities for using the new aliases:

# VERIFY: Are there remaining instances of these patterns?
# - Path | str  (should use PathInput)
# - EnumPolicyType | str  (should use PolicyTypeInput)  
# - EnumMessageCategory | EnumNodeOutputType  (should use MessageOutputCategory)
# - ast.AsyncFunctionDef | ast.FunctionDef  (should use ASTFunctionDef)

Action Required: Run a grep audit to ensure all applicable locations now use the aliases:

# Check for remaining raw patterns
rg "Path \| str" src/omnibase_infra/
rg "EnumPolicyType \| str" src/omnibase_infra/
rg "AsyncFunctionDef \| ast\.FunctionDef" src/omnibase_infra/

2. MINOR: Type Alias Documentation Gap

File: src/omnibase_infra/types/type_infra_aliases.py

The module docstring mentions occurrence counts but these will become stale:

# Replaces 24 occurrences of: EnumMessageCategory | EnumNodeOutputType
type MessageOutputCategory = EnumMessageCategory | EnumNodeOutputType

Recommendation: Remove numeric counts from comments (or make them historical):

# Message category or node output type (for routing and validation)
# Historically replaced 24 direct union occurrences (OMN-1358)
type MessageOutputCategory = EnumMessageCategory | EnumNodeOutputType

3. MINOR: Inconsistent Usage of PrimitiveValue

Files:

  • model_dispatch_log_context.py:47
  • model_log_context.py:235,260
  • message_dispatch_engine.py:769

Good adoption of PrimitiveValue from omnibase_core.types, BUT:

Question: Why is this type alias defined locally in model_dispatch_log_context.py?

type LogContextDict = dict[str, PrimitiveValue]

Recommendation: If LogContextDict is used in multiple files, promote it to type_infra_aliases.py. If it's truly local, keep it in the file but add a comment explaining why it's not in the central aliases file.


4. MINOR: Backward Compatibility Note Missing

File: src/omnibase_infra/models/validation/model_category_match_result.py:54-55

# Type alias for the category union - improves readability
# Note: CategoryType is kept for backward compatibility; prefer MessageOutputCategory for new code
type CategoryType = MessageOutputCategory

CONTRADICTION: CLAUDE.md explicitly states:

NO backwards compatibility is maintained. ALL changes are breaking changes.

Action Required: Either:

  1. Remove the backward compatibility alias (CategoryType) entirely, OR
  2. Add a comment explaining this is an internal alias for code clarity (not public API backward compatibility)

5. OBSERVATION: Threshold Reduction Assumptions

File: tests/unit/validation/test_validator_defaults.py:70

The new threshold of 70 assumes no growth buffer. The previous 122 had ~20-unit buffer above baseline. Consider:

# Current: 63 actual unions, threshold 70 (7-unit buffer)
# Previous: 100 actual unions, threshold 122 (22-unit buffer)

Question: Is a 7-unit buffer sufficient for ongoing development? Should INFRA_MAX_UNIONS = 75 to maintain ~10% buffer?

Recommendation: Document the rationale for the smaller buffer, or adjust to 75 if growth is expected.


🧪 Test Coverage Assessment

✅ Well-Tested:

  • Threshold constants updated correctly
  • Test documentation reflects the 122→70 reduction
  • Metadata validation tests confirm non-optional union count

⚠️ Missing Test Coverage:

  • No tests verifying the new type aliases are actually used
  • No import tests for the new types module exports

Suggested Test Addition:

def test_type_alias_adoption():
    """Verify type aliases are used instead of raw unions."""
    from omnibase_infra.types import MessageOutputCategory, PathInput
    
    # Import should work
    assert MessageOutputCategory is not None
    
    # Verify no raw patterns remain in key files
    # (use AST inspection or grep-based checks)

🔒 Security Considerations

✅ No Security Issues:

  • Type aliases don't introduce runtime behavior
  • No Any types that could bypass validation
  • No dynamic imports or reflection

🏗️ Architecture & Design

✅ Excellent Architectural Decisions:

  1. Centralized Type Definitions: Single source of truth in type_infra_aliases.py
  2. Layered Abstraction: Core types (PrimitiveValue) → Infra types (MessageOutputCategory)
  3. Import Hierarchy: Proper re-export through __init__.py
  4. Naming Consistency: All aliases use *Input or descriptive names

⚠️ Minor Concern: The VersionInput alias is defined but not used in this PR:

# Version input flexibility
# Replaces 4 occurrences of: ModelSemVer | str
type VersionInput = ModelSemVer | str

Action Required: Either:

  1. Apply VersionInput in this PR to realize the 4-occurrence reduction, OR
  2. Remove it and add in a future PR when actually needed

📊 Performance Considerations

✅ No Performance Impact:

  • Type aliases are compile-time only (zero runtime cost)
  • No changes to runtime behavior
  • Union type checking performance unchanged

🎯 Recommendations Summary

Priority Issue Action
HIGH Verify complete adoption Grep audit for remaining raw union patterns
MEDIUM VersionInput unused Apply in this PR or remove
MEDIUM Backward compat contradiction Remove CategoryType or clarify internal use
LOW Stale occurrence counts Make comments historical or remove counts
LOW LogContextDict placement Document why local vs central
LOW Threshold buffer Document 7-unit buffer rationale

✅ Approval Recommendation

APPROVE with minor revisions

This PR delivers significant value (48% union reduction) with clean implementation. The issues identified are non-blocking but should be addressed before merge:

  1. Must Fix: Verify complete type alias adoption (grep audit)
  2. Should Fix: Resolve VersionInput unused type and CategoryType backward compat note
  3. Nice to Have: Address documentation and testing gaps

Great work on this refactoring! 🎉


📋 Checklist for Merge

  • Grep audit confirms no remaining raw Path | str, EnumPolicyType | str, etc.
  • VersionInput either used or removed
  • CategoryType backward compat note clarified per CLAUDE.md
  • CI passes (ONEX validators, any_type check, union threshold)
  • Consider adding import test for new types module exports

Add comprehensive test coverage for the new types module to verify
all exports are importable at runtime. Addresses PR review feedback.
@claude

claude Bot commented Jan 16, 2026

Copy link
Copy Markdown

PR Review: Union Complexity Reduction with Type Aliases [OMN-1358]

Summary

This PR successfully reduces non-optional union complexity from 122 to 63 instances (48% reduction) by introducing centralized type aliases. The implementation is clean, well-tested, and follows ONEX architectural principles.


✅ Strengths

1. Excellent Design Pattern

  • Follows the same pattern as omnibase_core.types.type_json for consistency
  • Type aliases are semantically meaningful (MessageOutputCategory, PolicyTypeInput, PathInput, etc.)
  • Proper separation in dedicated module (type_infra_aliases.py)

2. Comprehensive Test Coverage

The new test file test_types_module_exports.py is exceptionally thorough:

  • ✅ Module import validation
  • ✅ Export consistency checks (__all__ completeness)
  • ✅ Direct import verification from submodules
  • ✅ Cross-module identity validation (ensures top-level exports match submodule definitions)
  • ✅ Export count verification (guards against accidental additions/removals)

3. Strong Type Safety

  • All type aliases properly defined using PEP 695 type statement
  • Clear documentation of what each alias replaces (e.g., "Replaces 24 occurrences")
  • No Any types introduced (maintains zero-tolerance policy)
  • Proper __all__ exports for explicit public API

4. Validation Threshold Update

  • INFRA_MAX_UNIONS correctly updated from 122 to 70
  • Test expectations updated in test_validator_defaults.py:71
  • Threshold history properly documented with rationale

5. Documentation Quality

  • Clear docstrings explaining purpose and usage
  • OMN-1358 ticket reference for traceability
  • Comments explaining naming choices (e.g., PathInput vs PathLike to avoid stdlib collision)

📋 Code Quality Observations

Import Pattern Consistency

File: src/omnibase_infra/types/__init__.py

The centralized export pattern is excellent:

from omnibase_infra.types.type_infra_aliases import (
    ASTFunctionDef,
    MessageOutputCategory,
    PathInput,
    PolicyTypeInput,
    VersionInput,
)

__all__: list[str] = [
    "ASTFunctionDef",
    "MessageOutputCategory",
    # ... etc
]

This provides both direct imports (from omnibase_infra.types import PathInput) and submodule access, with validation to ensure they're the same object.

Type Alias Usage Patterns

MessageOutputCategory (44 occurrences across 7 files):

  • Most frequent type alias
  • Used consistently in validators and routing logic
  • Properly replaces EnumMessageCategory | EnumNodeOutputType pattern

PolicyTypeInput (20 occurrences across 6 files):

  • Correctly applied in policy registry and error handling
  • Maintains API flexibility with EnumPolicyType | str pattern

PrimitiveValue Usage (from omnibase_core.types):

  • Good reuse of existing type from core: float | int | str
  • Applied in model_dispatch_log_context.py:47 and model_log_context.py:235

Backward Compatibility Note

File: src/omnibase_infra/models/validation/model_category_match_result.py:53-55

# Type alias for the category union - improves readability
# Note: CategoryType is kept for backward compatibility; prefer MessageOutputCategory for new code
type CategoryType = MessageOutputCategory

⚠️ Consideration: Per CLAUDE.md "No Backwards Compatibility" policy:

Breaking changes are always acceptable and encouraged. Remove old patterns immediately.

Question: Is CategoryType still used elsewhere in the codebase, or can it be removed entirely in favor of MessageOutputCategory?


🔍 Potential Issues

1. ⚠️ Missing Union Pattern Verification

I don't see evidence that all 122 → 63 replacements were verified. Consider running a validation to ensure no EnumMessageCategory | EnumNodeOutputType patterns remain outside of the type alias definition itself.

Suggested verification:

# Should only find the definition in type_infra_aliases.py and the docstring comment
rg "EnumMessageCategory \| EnumNodeOutputType" src/omnibase_infra --type py

Based on my earlier grep, only 2 files contain this pattern (both in types/ directory), which is correct.

2. 📝 Minor: Type Alias Naming Convention

File: src/omnibase_infra/types/type_infra_aliases.py:28

# Note: Named PathInput (not PathLike) to avoid collision with stdlib os.PathLike
type PathInput = Path | str

Good decision documented, but consider if PathLike → PathInput naming pattern should be applied to others:

  • PolicyTypeInput ✅ (already uses Input suffix)
  • VersionInput ✅ (already uses Input suffix)
  • MessageOutputCategory - Could this be MessageCategoryInput for consistency?

Not a blocker, but worth considering for future standardization.

3. ⚠️ ASTFunctionDef Usage Pattern

File: src/omnibase_infra/validation/any_type_validator.py:174

def _check_function_def(self, node: ASTFunctionDef) -> None:

The type alias is used in the method signature, but the visitor methods still check isinstance(node, (ast.AsyncFunctionDef, ast.FunctionDef)) in some places. Verify that all AST node type checks are updated consistently.

Example from execution_shape_validator.py:462:

elif isinstance(node, (ast.AsyncFunctionDef, ast.FunctionDef)):

This is correct (can't use type alias in isinstance checks), but ensure the pattern is consistent.


🛡️ Security & Performance

Security

  • ✅ No new external dependencies
  • ✅ No Any types introduced
  • ✅ Type aliases maintain same constraints as original unions
  • ✅ No path traversal or injection risks

Performance

  • ✅ Type aliases have zero runtime overhead (compile-time only)
  • ✅ Reduced AST complexity may slightly improve type checker performance
  • ✅ Union count validation now runs against smaller baseline (faster CI)

🧪 Testing

Test Coverage Assessment

Excellent - The test suite covers:

  1. ✅ Import validation for all exports
  2. ✅ Direct and indirect import paths
  3. ✅ Export consistency between top-level and submodules
  4. ✅ Correct count of exports (guards against regressions)
  5. ✅ Proper TypedDict structure validation
  6. ✅ Pydantic model instantiation

Missing Test Coverage (Suggestions)

Consider adding integration tests that verify type aliases work correctly in:

  • Pydantic model validation (e.g., ModelPolicyKey with PolicyTypeInput)
  • Function signatures that use the aliases
  • Runtime isinstance checks (where applicable)

Not critical for this PR, but valuable for future-proofing.


📊 Metrics

Metric Before After Change
Non-optional unions 122 63 -48% ✅
Union threshold 122 70 Conservative buffer
Type alias definitions 0 5 New abstractions
Test coverage N/A 100% Comprehensive

✅ ONEX Compliance Checklist

Requirement Status Notes
No Any types ✅ PASS Zero Any usage
PEP 604 unions (X | Y) ✅ PASS All unions use PEP 604 syntax
Strong typing ✅ PASS Type aliases maintain strict typing
One model per file ✅ PASS N/A - no new models
File naming conventions ✅ PASS type_infra_aliases.py follows pattern
Test coverage ✅ PASS Comprehensive test suite added
Documentation ✅ PASS Clear docstrings and comments
CI validation update ✅ PASS INFRA_MAX_UNIONS threshold updated

🎯 Recommendations

Critical (Before Merge)

  1. ✅ VERIFIED: Ensure no remaining EnumMessageCategory | EnumNodeOutputType patterns outside type definitions
  2. ⚠️ DECISION NEEDED: Remove CategoryType backward compatibility alias per ONEX policy (unless actively used)

Nice-to-Have (Future PRs)

  1. Consider standardizing Input suffix across all type aliases (MessageCategoryInput?)
  2. Add runtime validation tests for Pydantic models using these aliases
  3. Document type alias usage patterns in CLAUDE.md or ADR

🏁 Verdict

APPROVED ✅

This is a well-executed refactoring that:

  • Reduces complexity measurably (48% reduction)
  • Follows ONEX architectural patterns
  • Includes excellent test coverage
  • Updates validation thresholds correctly
  • Maintains type safety throughout

Minor Action Items

  1. Verify CategoryType backward compatibility alias is needed (or remove per ONEX policy)
  2. Consider naming convention standardization in future work

Excellent work on this refactoring! The type alias pattern is a clean solution to union complexity, and the comprehensive testing gives confidence in the changes.


Review completed by: Claude Code
CLAUDE.md compliance: ✅ Verified
Test coverage: ✅ Comprehensive
Security: ✅ No concerns
Performance: ✅ No degradation

…N-1358]

Address PR #157 review feedback:
- Remove unused VersionInput type alias and ModelSemVer import
- Enhance PathInput documentation to clarify os.PathLike distinction
- Update tests to reflect 7 exports (was 8)
@claude

claude Bot commented Jan 16, 2026

Copy link
Copy Markdown

PR Review: Union Complexity Reduction with Type Aliases

Summary

This PR successfully reduces non-optional union complexity from 122 to 70 (48% reduction) by introducing centralized type aliases. The implementation is clean, well-tested, and aligns with ONEX coding standards.


✅ Strengths

1. Excellent Type Alias Design

  • Naming clarity: PathInput cleverly avoids collision with stdlib os.PathLike while maintaining semantic meaning
  • Comprehensive documentation: Each alias includes usage count and rationale in comments
  • Proper exports: Type aliases properly exposed via __all__ in both submodule and top-level types/__init__.py

2. Strong Test Coverage

The test suite (test_types_module_exports.py) is exemplary:

  • Runtime import verification (prevents TYPE_CHECKING-only exports)
  • Export consistency validation (top-level vs submodule)
  • Practical usage examples (e.g., ModelParsedDSN instantiation)
  • Export count validation (7 exports expected and verified)

3. Threshold Adjustment Well-Documented

  • Clear history in INFRA_MAX_UNIONS comments (122 → 70)
  • Test expectations updated appropriately (test_validator_defaults.py:71)
  • Buffer maintained for minor growth (70 vs 63 actual)

4. Backward Compatibility Consideration

Line 54-55 in model_category_match_result.py:

# Note: CategoryType is kept for backward compatibility; prefer MessageOutputCategory for new code
type CategoryType = MessageOutputCategory

Despite the "no backwards compatibility" policy in CLAUDE.md, this transitional alias is acceptable as it's within the same PR and helps gradual migration.


🔍 Code Quality Observations

Consistent Application

The type aliases are applied consistently across:

  • Error contexts (PolicyRegistryError)
  • Validation models (ModelCategoryMatchResult)
  • Validators (execution_shape_validator.py, routing_coverage_validator.py)
  • Runtime modules (policy_registry.py, message_dispatch_engine.py)

Proper Import Patterns

All imports follow ONEX conventions:

from omnibase_infra.types import MessageOutputCategory, PathInput, PolicyTypeInput, ASTFunctionDef

PrimitiveValue Reuse

Smart reuse of omnibase_core.types.PrimitiveValue for float | int | str patterns (lines in model_log_context.py, model_dispatch_log_context.py) demonstrates good cross-layer coordination.


🐛 Potential Issues

1. VersionInput Removal - Verification Needed

Commit abfaa48 removes VersionInput type alias and ModelSemVer import as "unused".

Question: Was this based on static analysis or manual review? If static analysis, ensure no dynamic usage exists (e.g., getattr(), string-based imports).

Recommendation: Run grep to confirm zero usage:

rg "VersionInput" src/

2. isinstance() Usage with Type Aliases

Line 462 in execution_shape_validator.py:

elif isinstance(node, (ast.AsyncFunctionDef, ast.FunctionDef)):

While the type alias ASTFunctionDef is used for annotations, isinstance() still uses the tuple form. This is correct (type aliases aren't runtime types), but consider adding a comment:

# Note: isinstance requires concrete types, not type alias
elif isinstance(node, (ast.AsyncFunctionDef, ast.FunctionDef)):

3. Union Threshold Buffer Analysis

Current state: 63 actual non-optional unions, threshold set to 70 (buffer of 7).

Question: Is a 10% buffer sufficient? Previous threshold (122) had a ~20 buffer above baseline (~100).

Recommendation: Document the rationale for the tighter buffer in infra_validators.py comments.


🔒 Security Considerations

No security concerns identified. The changes are purely type system refactoring with no:

  • Input validation changes
  • Authentication/authorization modifications
  • External system interactions
  • Data exposure risks

📊 Performance Considerations

Positive impact:

  • Type aliases are compile-time constructs (no runtime overhead)
  • AST parsing remains unchanged (same underlying types)
  • Validator performance unaffected (threshold lowered but logic identical)

No performance regressions expected.


🧪 Test Coverage Assessment

What's Covered ✅

  • Module import tests (runtime availability)
  • Export consistency tests (top-level vs submodule)
  • Validator threshold tests (INFRA_MAX_UNIONS = 70)
  • Edge cases (zero unions, empty directories)

Potential Gaps 🤔

  1. No explicit tests for type alias usage in validators
    Consider adding a test that verifies validators accept both:

    • EnumMessageCategory | EnumNodeOutputType (legacy)
    • MessageOutputCategory (new alias)
  2. No mypy verification in tests
    Consider a static type check test:

    def test_type_alias_mypy_compatibility():
        # Verify type aliases work with strict mypy
        from omnibase_infra.types import PathInput
        from pathlib import Path
        
        def accepts_path(p: PathInput) -> None: ...
        
        accepts_path(Path("/tmp"))  # Should pass
        accepts_path("/tmp")  # Should pass

📝 Documentation Quality

Excellent Documentation ✅

  • Type alias comments explain usage count and rationale
  • PathInput has clear disambiguation from os.PathLike
  • INFRA_MAX_UNIONS threshold history is comprehensive
  • Test docstrings explain validation behavior

Minor Improvement Opportunity

Consider adding a docstring to type_infra_aliases.py explaining when to use each alias:

"""
When to use these aliases:
- MessageOutputCategory: When accepting either message categories or node output types
- PathInput: When accepting filesystem paths flexibly (Path or str)
- PolicyTypeInput: When accepting policy types with string fallback
- ASTFunctionDef: When processing both sync and async function definitions
"""

🎯 CLAUDE.md Compliance

✅ Compliant

  • Strong typing: No Any types introduced
  • PEP 604 unions: Uses X | Y syntax (not Union[X, Y])
  • File naming: type_infra_aliases.py follows conventions
  • Module exports: Proper __all__ definition

⚠️ Minor Deviation

Line 54-55 in model_category_match_result.py keeps CategoryType for "backward compatibility", which contradicts the "No Backwards Compatibility" policy in CLAUDE.md.

Recommendation: Remove CategoryType alias or document why this exception is necessary. If it's only used within the PR scope, it's acceptable.


🚀 Recommendations

High Priority

  1. Verify VersionInput removal: Confirm no dynamic usage exists
  2. Tighten buffer rationale: Document why 7 is sufficient (vs previous 20)

Medium Priority

  1. Add isinstance() comment: Clarify why tuple form is needed
  2. Remove CategoryType alias: Unless there's external usage justification

Low Priority

  1. Add mypy verification test: Ensure type aliases work with strict type checking
  2. Enhance module docstring: Add "when to use" guidance

🎉 Final Verdict

LGTM with minor suggestions. This PR is production-ready.

Impact:

  • ✅ 48% reduction in union complexity
  • ✅ Improved code readability
  • ✅ Comprehensive test coverage
  • ✅ No breaking changes
  • ✅ Proper documentation

Merge confidence: High (9/10)

The implementation is solid, tests are thorough, and the approach aligns with ONEX best practices. The minor items listed above are suggestions for polish, not blockers.


Reviewed by: Claude Sonnet 4.5
Review date: 2026-01-16
PR: #157
Commit: abfaa48

…N-1358]

- Remove CategoryType backward compat alias (violates no-compat policy)
- Replace with MessageOutputCategory in model_category_match_result.py
- Add isinstance() clarity comment explaining single-type check
- Enhance type_infra_aliases.py docstring with "when to use" guidance
- Add TestTypeAliasMyPyCompatibility class with 8 mypy verification tests
@claude

claude Bot commented Jan 16, 2026

Copy link
Copy Markdown

Pull Request Review: Type Alias Union Complexity Reduction

Summary

This PR successfully reduces union complexity from 122 to 63 non-optional unions (48% reduction) by introducing well-designed type aliases. The changes align with ONEX infrastructure patterns and demonstrate excellent engineering discipline.

✅ Strengths

1. Excellent Type Alias Design

  • Clear naming conventions: MessageOutputCategory, PathInput, PolicyTypeInput, ASTFunctionDef are all self-documenting
  • Proper namespace separation: Avoided collision with stdlib os.PathLike by naming it PathInput
  • Comprehensive documentation: Each alias includes usage guidance and rationale

2. Outstanding Test Coverage (366 lines of new tests!)

The test suite in test_types_module_exports.py is exceptionally thorough:

  • Export verification: Tests that all aliases are properly exported
  • Runtime compatibility: Validates type aliases work correctly at runtime
  • Type identity preservation: Ensures enum values maintain their type identity
  • Collection type compatibility: Tests aliases in list[] and dict[] contexts
  • Submodule consistency: Verifies top-level and submodule exports match

This level of testing sets a strong precedent for type infrastructure changes.

3. Significant Complexity Reduction

  • MessageOutputCategory: Replaces 31 occurrences of EnumMessageCategory | EnumNodeOutputType
  • PathInput: Replaces 11 occurrences of Path | str
  • PolicyTypeInput: Replaces 11 occurrences of EnumPolicyType | str
  • ASTFunctionDef: Replaces 10 occurrences of ast.AsyncFunctionDef | ast.FunctionDef

4. Appropriate Threshold Adjustment

The INFRA_MAX_UNIONS reduction from 122 to 70 is well-justified:

  • Leaves ~7 unions buffer above the actual count (63)
  • Documented in threshold history with clear rationale
  • Comment mentions type aliases that were applied

5. Consistent Application

Changes are applied systematically across:

  • Error handling (error_policy_registry.py)
  • Model definitions (model_category_match_result.py)
  • Validation infrastructure (execution_shape_validator.py, routing_coverage_validator.py)
  • Runtime components (policy_registry.py, message_dispatch_engine.py)

🔍 Observations & Minor Suggestions

1. Documentation Comment Discrepancy (line 389)

# - 70 (2026-01-16): OMN-1358 type alias replacements reduced from 122 to 63 non-optional unions
#                    Applied HandlerMap, NodeId, PayloadDict, EventMetadata, MetadataDict type aliases

The comment mentions HandlerMap, NodeId, PayloadDict, EventMetadata, MetadataDict type aliases, but the PR actually introduces:

  • MessageOutputCategory
  • PathInput
  • PolicyTypeInput
  • ASTFunctionDef

Recommendation: Update the comment to reflect the actual type aliases introduced, or clarify if those other aliases were applied in a separate commit.

2. PrimitiveValue Usage

The PR also applies PrimitiveValue from omnibase_core in a few places (e.g., model_log_context.py:235). This is excellent reuse of core infrastructure types.

Suggestion: Consider documenting this in the PR description alongside the new type aliases, as it contributes to the union reduction.

3. isinstance() Pattern in model_category_match_result.py

Line 196 has a good comment explaining why a single isinstance() check is sufficient:

# Single type check is sufficient - EnumMessageCategory is the only message
# category enum. EnumNodeOutputType contains PROJECTION which is NOT a
# routable message category (it's for reducer state aggregation outputs).
return isinstance(self.category, EnumMessageCategory)

This demonstrates excellent defensive coding with clear rationale.

🛡️ Security & Best Practices

✅ No security concerns - Type aliases are compile-time constructs with no runtime security implications

✅ Follows ONEX patterns:

  • Strong typing (no Any types introduced)
  • PEP 604 unions (X | Y syntax)
  • Comprehensive docstrings
  • Clear module structure

✅ Backward compatibility: Not a concern per ONEX policy ("No Backwards Compatibility" - all changes are breaking)

📊 Code Quality Metrics

Metric Status
Type safety ✅ No Any types introduced
Test coverage ✅ 366 lines of comprehensive tests
Documentation ✅ Excellent inline docs and usage guidance
Naming conventions ✅ Clear, self-documenting names
CLAUDE.md compliance ✅ Follows strong typing principles

🎯 Final Verdict

APPROVE with minor documentation update suggestion

This PR represents excellent engineering work:

  • Significant complexity reduction (48% union reduction)
  • Exceptional test coverage (comprehensive type compatibility tests)
  • Well-designed type aliases with clear usage guidance
  • Systematic application across the codebase

The only minor issue is the documentation comment discrepancy in infra_validators.py:389 which mentions type aliases that don't appear to be in this PR.

Recommendation

✅ Safe to merge after addressing the documentation comment discrepancy (or clarifying if those aliases were applied elsewhere)


Review performed by Claude Code following ONEX infrastructure patterns and CLAUDE.md guidelines

@jonahgabriel
jonahgabriel merged commit 2882fa9 into main Jan 16, 2026
11 checks passed
jonahgabriel added a commit that referenced this pull request Jan 16, 2026
Merge PR #157 (OMN-1358 type alias changes) into PR #158 (OMN-1181 structured errors).

Changes:
- Resolve merge conflicts in model_policy_key.py, model_policy_registration.py, infra_validators.py
- Update INFRA_MAX_UNIONS from 122 to 66 (actual count: 64 after type alias cleanup)
- Fix defensive pattern in mixin_vault_token.py: RuntimeHostError → InfraVaultError
- Update test expectation in test_validator_defaults.py

The type alias changes from OMN-1358 reduced union count from 122 to ~64.
OMN-1181 adds 2 unions for EnumPolicyType | str validators, setting threshold to 66.
@jonahgabriel
jonahgabriel deleted the jonah/omn-1358-reduce-union-complexity-across-omnibase_infra-codebase branch April 4, 2026 02:06
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