Repository navigation
feat(models): extend ModelExecutionProfile and ModelExecutionConflict for ProtocolConstraintValidator (OMN-1292) - #361
Conversation
… for ProtocolConstraintValidator (OMN-1292) Extend existing models to support OMN-1227 (ProtocolConstraintValidator for SPI): ModelExecutionProfile (models/contracts/): - Add nondeterministic_allowed_phases field for phases where nondeterminism is OK - Add phase_order computed property (dict[str, int] mapping phases to indices) - Add model_validator ensuring phases are unique and nondeterministic_allowed_phases is subset ModelExecutionConflict (models/execution/): - Add must_run_conflict to conflict_type Literal union This follows ONEX principles by extending existing models rather than creating duplicate models with naming conflicts. Blocks: OMN-1227
📝 WalkthroughWalkthroughConverted mutable lists to immutable tuples across execution models and resolver outputs, added coercion and strict validation for ModelExecutionProfile (including Changes
Sequence Diagram(s)(omitted) Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Comment |
Code Review: PR #361 - Extend ModelExecutionProfile and ModelExecutionConflict✅ Overall Assessment: LGTM with Minor SuggestionsThis PR implements clean, well-tested extensions to existing models following ONEX principles. The code quality is excellent with comprehensive test coverage and proper adherence to project conventions. Strengths🎯 Architecture & Design
📝 Code Quality
🧪 Testing Excellence
Code AnalysisModelExecutionProfile Changes (✅ Excellent)New Fields: nondeterministic_allowed_phases: list[str] = Field(default_factory=list)
Computed Property: @property
def phase_order(self) -> dict[str, int]:
return {phase: idx for idx, phase in enumerate(self.phases)}
Validation Logic: # Validate phases are unique
if len(self.phases) \!= len(set(self.phases)):
raise ValueError("phases must contain unique values")
ModelExecutionConflict Changes (✅ Perfect)New Conflict Type: conflict_type: Literal[..., "must_run_conflict"]
Suggestions (Non-Blocking)1. Performance: Consider Caching
|
| Convention | Status |
|---|---|
| ✅ File naming | Correct (model_*.py) |
| ✅ PEP 604 unions | Used (list[str], dict[str, int]) |
| ✅ Pydantic config | frozen=True, extra="forbid", from_attributes=True |
| ✅ Type annotations | Self return type, proper Literal usage |
| ✅ Docstrings | Comprehensive with examples and version notes |
| ✅ Exception handling | ValueError with clear messages |
| ✅ Test markers | @pytest.mark.unit applied |
| ✅ Test organization | Logical test classes by feature |
Final Recommendation
✅ APPROVE - Ready to Merge
Rationale:
- Code quality is excellent and follows all ONEX conventions
- Architecture decision (extend vs. create new) is sound
- Test coverage is comprehensive (44 tests covering all cases)
- No breaking changes - purely additive
- Blocks OMN-1227 as intended
- CI will validate mypy/pytest compliance
Suggested Actions Before Merge:
- ✅ Ensure all CI checks pass (mypy, pytest, pre-commit)
- 🤔 Consider
cached_propertyoptimization if OMN-1227 usesphase_orderheavily - ✅ Verify OMN-1227 integration (out of scope for this PR)
🏆 Excellent Work!
This PR demonstrates:
- Strong understanding of ONEX architecture
- Attention to edge cases and validation
- Comprehensive testing practices
- Clear documentation
The extensions are minimal, focused, and well-integrated into existing patterns.
Generated by Claude Sonnet 4.5 🤖
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In @src/omnibase_core/models/contracts/model_execution_profile.py:
- Around line 70-75: The Pydantic model uses shallow immutability with list[str]
fields; change any list-typed fields (e.g., phases,
nondeterministic_allowed_phases, phase_order if present) to tuple[str, ...] in
the ModelExecutionProfile model and update their type annotations and validators
to accept/return tuples so instances are truly immutable under model_config
frozen=True; also update any code paths that consume these fields to handle
tuples instead of lists. In the existing string validators (the ones that
currently reject empty/whitespace-only values), normalize input by stripping
whitespace (or reject if stripped value is empty) so phase identifiers are
stored in canonical form (no leading/trailing spaces) and validation logic
(subset checks, ordering) remains reliable.
🧹 Nitpick comments (4)
src/omnibase_core/models/contracts/model_execution_profile.py (2)
77-91:phase_orderlooks good; relies on validation to prevent duplicate-key overwrites.
Givenphase_orderuses phase strings as dict keys, consider also rejecting phases with leading/trailing whitespace (e.g., requirephase == phase.strip()), otherwise “visually identical” phases can diverge.
92-125: Tighten invariants: validatenondeterministic_allowed_phasesentries (non-empty/normalized/unique).
Right now you validate subset membership, but duplicates and whitespace-only entries innondeterministic_allowed_phasescan slip through (and lead to confusing behavior).Targeted validator tightening
# Validate phases are non-empty strings for phase in self.phases: if not phase or not phase.strip(): raise ValueError("phases must be non-empty strings") + if phase != phase.strip(): + raise ValueError("phases must not contain leading/trailing whitespace") + # Validate nondeterministic_allowed_phases entries + for phase in self.nondeterministic_allowed_phases: + if not phase or not phase.strip(): + raise ValueError("nondeterministic_allowed_phases must be non-empty strings") + if phase != phase.strip(): + raise ValueError( + "nondeterministic_allowed_phases must not contain leading/trailing whitespace" + ) + if len(self.nondeterministic_allowed_phases) != len(set(self.nondeterministic_allowed_phases)): + raise ValueError("nondeterministic_allowed_phases must contain unique values")tests/unit/models/contracts/test_model_execution_profile.py (1)
155-194: Tests miss two important realities: (1) in-place list mutation, (2) actualfrom_attributesinput.
If the model stayslist[...], consider explicitly testing (and documenting) whetherprofile.phases.append(...)is allowed. Also, the “from_attributes” test currently validates dict parsing, not attribute parsing.Example test additions (pick based on intended immutability contract)
class _Obj: def __init__(self) -> None: self.phases = ["init", "execute", "cleanup"] self.nondeterministic_allowed_phases = ["execute"] def test_from_attributes_object(self) -> None: profile = ModelExecutionProfile.model_validate(_Obj()) assert profile.phases == ["init", "execute", "cleanup"] def test_in_place_mutation_behavior_is_defined(self) -> None: profile = ModelExecutionProfile() # Decide expected behavior; currently this likely succeeds with list-typed fields: profile.phases.append("mutated") # should this be allowed?tests/unit/models/execution/test_model_execution_conflict.py (1)
228-280: Consider testing (or explicitly disclaiming) in-place mutation + realfrom_attributesinputs.
Right now these tests only verify assignment is blocked; they don’t guard againstconflict.handler_ids.append(...)mutating a “frozen” instance, and they don’t exercise attribute-based validation inputs.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
src/omnibase_core/models/contracts/model_execution_profile.pysrc/omnibase_core/models/execution/model_execution_conflict.pytests/unit/models/contracts/test_model_execution_profile.pytests/unit/models/execution/__init__.pytests/unit/models/execution/test_model_execution_conflict.py
🧰 Additional context used
📓 Path-based instructions (4)
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Always use Poetry for Python package management and task execution. Use 'poetry run' for all Python commands (pytest, mypy, python -m, etc.). Never use pip or direct python execution.
Always use protocol names for service resolution (e.g., 'ProtocolEventBus', 'ProtocolLogger'), never concrete class names. Use duck typing without isinstance checks.
Use structured error handling with ModelOnexError and EnumCoreErrorCode, never generic Exception. Include error context in the context parameter.
Use the @standard_error_handling decorator on async functions to eliminate 6+ lines of try/catch boilerplate in error handling.
Use PEP 604 union syntax (e.g., 'str | None') instead of legacy Optional/Union. Enforce via ruff rule UP007.
Use standardized exception comment markers (# fallback-ok:, # catch-all-ok:, # cleanup-resilience-ok:, # boundary-ok:, # init-errors-ok:, # tool-resilience-ok:) when using catch-all or broad exception handlers.
Order exception tuples alphabetically by exception class name (e.g., except (AttributeError, TypeError, ValidationError) not except (ValueError, TypeError, AttributeError)).
Use centralized exception constants from omnibase_core.errors.exception_groups (PYDANTIC_MODEL_ERRORS, VALIDATION_ERRORS, FILE_IO_ERRORS, etc.) instead of manually listing exceptions.
Maintain 100% mypy strict mode compliance (0 errors) across all source files using type annotations. Both mypy and pyright must pass in CI.
Format Python code with Black: poetry run black src/ tests/. Sort imports with isort: poetry run isort src/ tests/. Lint with ruff: poetry run ruff check src/ tests/
Do NOT use 'from future import annotations' when runtime type introspection is needed (Pydantic models, FastAPI endpoints). Use it when forward references are needed or to prevent circular imports.
Use EnumNodeKind for architectural role (EFFECT, COMPUTE, REDUCER, ORCHESTRATOR, RUNTIME_HOST) for pipeline routing. Use EnumNodeType for implementation type (COMPUTE_GENERIC, TRA...
Files:
tests/unit/models/execution/__init__.pytests/unit/models/contracts/test_model_execution_profile.pysrc/omnibase_core/models/execution/model_execution_conflict.pytests/unit/models/execution/test_model_execution_conflict.pysrc/omnibase_core/models/contracts/model_execution_profile.py
tests/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
tests/**/*.py: Maintain minimum 60% code coverage across test suite. Run tests with: poetry run pytest tests/ --cov=src/omnibase_core/
Run all tests with parallel workers: poetry run pytest tests/ uses 4 workers locally with 60s timeout and loadscope distribution. CI uses 20 parallel splits on GitHub Actions.
Use pytest markers for test categorization: @pytest.mark.unit, @pytest.mark.integration, @pytest.mark.slow, @pytest.mark.smoke, @pytest.mark.performance
Use pytest 8.4+ for testing. Use pytest fixtures, markers, and parallel execution with pytest-xdist.
Files:
tests/unit/models/execution/__init__.pytests/unit/models/contracts/test_model_execution_profile.pytests/unit/models/execution/test_model_execution_conflict.py
src/omnibase_core/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
src/omnibase_core/**/*.py: Follow directory-specific naming prefixes for Python files in src/omnibase_core/. Examples: cli_, constants_, container_, decorator_, enum_, error_, factory_, mixin_, model_, node_, etc.
Use FileRegistry for loading YAML contracts: registry = FileRegistry(); contract = registry.load(Path('config/runtime_host.yaml'))
Use ModelEventEnvelope for inter-service event communication. Structure events with proper envelope wrapping for consistency.
Files:
src/omnibase_core/models/execution/model_execution_conflict.pysrc/omnibase_core/models/contracts/model_execution_profile.py
src/omnibase_core/models/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
src/omnibase_core/models/**/*.py: Add 'from_attributes=True' to ConfigDict for immutable value objects nested in other Pydantic models used with pytest-xdist parallel execution.
Use Pydantic 2.11+ for all data models. Use Pydantic v2 syntax, ConfigDict, and model_validate methods.
Files:
src/omnibase_core/models/execution/model_execution_conflict.pysrc/omnibase_core/models/contracts/model_execution_profile.py
🧠 Learnings (1)
📚 Learning: 2026-01-08T14:36:08.342Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-08T14:36:08.342Z
Learning: Applies to src/omnibase_core/models/**/*.py : Add 'from_attributes=True' to ConfigDict for immutable value objects nested in other Pydantic models used with pytest-xdist parallel execution.
Applied to files:
tests/unit/models/contracts/test_model_execution_profile.pytests/unit/models/execution/test_model_execution_conflict.py
🧬 Code graph analysis (2)
tests/unit/models/contracts/test_model_execution_profile.py (1)
src/omnibase_core/models/contracts/model_execution_profile.py (2)
ModelExecutionProfile(34-125)phase_order(78-90)
tests/unit/models/execution/test_model_execution_conflict.py (1)
src/omnibase_core/models/execution/model_execution_conflict.py (5)
ModelExecutionConflict(28-233)is_blocking(176-183)is_cycle(185-192)involves_handler(194-208)get_cycle_length(210-220)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (21)
- GitHub Check: Tests (Split 3/20)
- GitHub Check: Tests (Split 8/20)
- GitHub Check: Tests (Split 14/20)
- GitHub Check: Tests (Split 11/20)
- GitHub Check: Tests (Split 6/20)
- GitHub Check: Tests (Split 20/20)
- GitHub Check: Tests (Split 17/20)
- GitHub Check: Tests (Split 10/20)
- GitHub Check: Tests (Split 16/20)
- GitHub Check: Tests (Split 19/20)
- GitHub Check: Tests (Split 5/20)
- GitHub Check: Tests (Split 15/20)
- GitHub Check: Tests (Split 9/20)
- GitHub Check: Tests (Split 12/20)
- GitHub Check: Tests (Split 7/20)
- GitHub Check: Tests (Split 18/20)
- GitHub Check: Tests (Split 13/20)
- GitHub Check: Tests (Split 2/20)
- GitHub Check: Tests (Split 4/20)
- GitHub Check: Tests (Split 1/20)
- GitHub Check: claude-review
🔇 Additional comments (2)
tests/unit/models/execution/__init__.py (1)
1-3: LGTM (simple test package initializer + SPDX headers).src/omnibase_core/models/execution/model_execution_conflict.py (1)
38-41: No downstream exhaustive matching exists forconflict_type. The codebase contains nomatch/casestatements or exhaustiveif/elifchains over this field. The only type-specific check isis_cycle()(line 192), which handles one case. Adding"must_run_conflict"poses no exhaustive matching risk.Note: The thread-safety claim about immutability (line 40-41, 96-98) should be revisited—
frozen=Trueprevents field reassignment buthandler_ids,constraint_refs, andcycle_pathare mutable list objects and can be modified in-place.
…review feedback (OMN-1292) - Convert list[str] fields to tuple[str, ...] in ModelExecutionProfile (phases, nondeterministic_allowed_phases) for true immutability - Convert list[str] fields to tuple[str, ...] in ModelExecutionConflict (handler_ids, constraint_refs, cycle_path) for true immutability - Cache phase_order property using @functools.cached_property - Add validation for nondeterministic_allowed_phases (non-empty, stripped, unique) - Add comprehensive docstrings for both models - Fix CI test to expect ValidationError at model creation for duplicate phases - Add multi-error aggregation tests - Add tuple immutability tests - Add from_attributes input tests - Update resolver_execution.py to use tuples - Fix all mypy type errors in test files
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In @src/omnibase_core/models/contracts/model_execution_profile.py:
- Around line 141-172: The docstring for coerce_nondeterministic_phases_to_tuple
incorrectly states it raises ValueError for empty phases; update the docstring
to reflect that this function only normalizes and deduplicates input (converts
lists to tuples, strips whitespace, preserves order) and that validation
(including raising for empty phases) is performed elsewhere (e.g.,
validate_profile). Mention the expected input types and returned tuple but
remove or reword the Raises section to avoid claiming this function raises
ValueError.
- Around line 117-139: The docstring for coerce_phases_to_tuple incorrectly
claims it raises ValueError for empty phases; update the docstring in the
coerce_phases_to_tuple method to remove the "Raises" section (or revise it to
state it only normalizes/strips and does not perform empty-string validation),
and optionally add a short note pointing to validate_profile as the place where
empty-phase validation occurs so readers know where that check lives.
🧹 Nitpick comments (2)
src/omnibase_core/models/contracts/model_execution_profile.py (2)
226-229: Redundant.strip()call—phases are already stripped.The
coerce_phases_to_tuplevalidator already strips whitespace from all phases (Line 138). The checkif not phase or not phase.strip()is redundant sincephase.strip()will always equalphaseat this point.♻️ Simplified validation
# Validate phases are non-empty strings for phase in self.phases: - if not phase or not phase.strip(): + if not phase: raise ValueError("phases must be non-empty strings")
231-236: Same redundant.strip()check for nondeterministic_allowed_phases.The
coerce_nondeterministic_phases_to_tuplevalidator already strips whitespace (Line 164).♻️ Simplified validation
# Validate nondeterministic_allowed_phases entries are non-empty strings for phase in self.nondeterministic_allowed_phases: - if not phase or not phase.strip(): + if not phase: raise ValueError( "nondeterministic_allowed_phases must be non-empty strings" )
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
src/omnibase_core/models/contracts/model_execution_profile.pysrc/omnibase_core/models/execution/model_execution_conflict.pysrc/omnibase_core/resolution/resolver_execution.pytests/unit/factories/test_contract_profile_factory.pytests/unit/infrastructure/execution/test_phase_sequencer.pytests/unit/models/contracts/test_model_execution_profile.pytests/unit/models/execution/test_model_execution_conflict.py
🧰 Additional context used
📓 Path-based instructions (4)
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Always use Poetry for Python package management and task execution. Use 'poetry run' for all Python commands (pytest, mypy, python -m, etc.). Never use pip or direct python execution.
Always use protocol names for service resolution (e.g., 'ProtocolEventBus', 'ProtocolLogger'), never concrete class names. Use duck typing without isinstance checks.
Use structured error handling with ModelOnexError and EnumCoreErrorCode, never generic Exception. Include error context in the context parameter.
Use the @standard_error_handling decorator on async functions to eliminate 6+ lines of try/catch boilerplate in error handling.
Use PEP 604 union syntax (e.g., 'str | None') instead of legacy Optional/Union. Enforce via ruff rule UP007.
Use standardized exception comment markers (# fallback-ok:, # catch-all-ok:, # cleanup-resilience-ok:, # boundary-ok:, # init-errors-ok:, # tool-resilience-ok:) when using catch-all or broad exception handlers.
Order exception tuples alphabetically by exception class name (e.g., except (AttributeError, TypeError, ValidationError) not except (ValueError, TypeError, AttributeError)).
Use centralized exception constants from omnibase_core.errors.exception_groups (PYDANTIC_MODEL_ERRORS, VALIDATION_ERRORS, FILE_IO_ERRORS, etc.) instead of manually listing exceptions.
Maintain 100% mypy strict mode compliance (0 errors) across all source files using type annotations. Both mypy and pyright must pass in CI.
Format Python code with Black: poetry run black src/ tests/. Sort imports with isort: poetry run isort src/ tests/. Lint with ruff: poetry run ruff check src/ tests/
Do NOT use 'from future import annotations' when runtime type introspection is needed (Pydantic models, FastAPI endpoints). Use it when forward references are needed or to prevent circular imports.
Use EnumNodeKind for architectural role (EFFECT, COMPUTE, REDUCER, ORCHESTRATOR, RUNTIME_HOST) for pipeline routing. Use EnumNodeType for implementation type (COMPUTE_GENERIC, TRA...
Files:
tests/unit/factories/test_contract_profile_factory.pytests/unit/models/execution/test_model_execution_conflict.pytests/unit/infrastructure/execution/test_phase_sequencer.pysrc/omnibase_core/models/execution/model_execution_conflict.pysrc/omnibase_core/resolution/resolver_execution.pytests/unit/models/contracts/test_model_execution_profile.pysrc/omnibase_core/models/contracts/model_execution_profile.py
tests/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
tests/**/*.py: Maintain minimum 60% code coverage across test suite. Run tests with: poetry run pytest tests/ --cov=src/omnibase_core/
Run all tests with parallel workers: poetry run pytest tests/ uses 4 workers locally with 60s timeout and loadscope distribution. CI uses 20 parallel splits on GitHub Actions.
Use pytest markers for test categorization: @pytest.mark.unit, @pytest.mark.integration, @pytest.mark.slow, @pytest.mark.smoke, @pytest.mark.performance
Use pytest 8.4+ for testing. Use pytest fixtures, markers, and parallel execution with pytest-xdist.
Files:
tests/unit/factories/test_contract_profile_factory.pytests/unit/models/execution/test_model_execution_conflict.pytests/unit/infrastructure/execution/test_phase_sequencer.pytests/unit/models/contracts/test_model_execution_profile.py
src/omnibase_core/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
src/omnibase_core/**/*.py: Follow directory-specific naming prefixes for Python files in src/omnibase_core/. Examples: cli_, constants_, container_, decorator_, enum_, error_, factory_, mixin_, model_, node_, etc.
Use FileRegistry for loading YAML contracts: registry = FileRegistry(); contract = registry.load(Path('config/runtime_host.yaml'))
Use ModelEventEnvelope for inter-service event communication. Structure events with proper envelope wrapping for consistency.
Files:
src/omnibase_core/models/execution/model_execution_conflict.pysrc/omnibase_core/resolution/resolver_execution.pysrc/omnibase_core/models/contracts/model_execution_profile.py
src/omnibase_core/models/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
src/omnibase_core/models/**/*.py: Add 'from_attributes=True' to ConfigDict for immutable value objects nested in other Pydantic models used with pytest-xdist parallel execution.
Use Pydantic 2.11+ for all data models. Use Pydantic v2 syntax, ConfigDict, and model_validate methods.
Files:
src/omnibase_core/models/execution/model_execution_conflict.pysrc/omnibase_core/models/contracts/model_execution_profile.py
🧠 Learnings (2)
📚 Learning: 2026-01-08T14:36:08.342Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-08T14:36:08.342Z
Learning: Applies to src/omnibase_core/models/**/*.py : Add 'from_attributes=True' to ConfigDict for immutable value objects nested in other Pydantic models used with pytest-xdist parallel execution.
Applied to files:
tests/unit/models/execution/test_model_execution_conflict.pysrc/omnibase_core/models/execution/model_execution_conflict.pytests/unit/models/contracts/test_model_execution_profile.pysrc/omnibase_core/models/contracts/model_execution_profile.py
📚 Learning: 2026-01-08T14:36:08.342Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-08T14:36:08.342Z
Learning: Applies to **/*.py : Use structured error handling with ModelOnexError and EnumCoreErrorCode, never generic Exception. Include error context in the context parameter.
Applied to files:
tests/unit/infrastructure/execution/test_phase_sequencer.py
🧬 Code graph analysis (5)
tests/unit/factories/test_contract_profile_factory.py (1)
src/omnibase_core/models/contracts/model_execution_profile.py (1)
ModelExecutionProfile(45-247)
tests/unit/models/execution/test_model_execution_conflict.py (1)
src/omnibase_core/models/execution/model_execution_conflict.py (5)
ModelExecutionConflict(28-247)is_blocking(190-197)is_cycle(199-206)involves_handler(208-222)get_cycle_length(224-234)
tests/unit/infrastructure/execution/test_phase_sequencer.py (2)
src/omnibase_core/infrastructure/execution/phase_sequencer.py (2)
validate_phase_list(80-124)validate_phase_list_strict(127-179)src/omnibase_core/models/contracts/model_execution_profile.py (1)
ModelExecutionProfile(45-247)
tests/unit/models/contracts/test_model_execution_profile.py (2)
src/omnibase_core/models/contracts/model_execution_profile.py (2)
ModelExecutionProfile(45-247)phase_order(175-198)src/omnibase_core/models/contracts/model_execution_ordering_policy.py (1)
ModelExecutionOrderingPolicy(13-54)
src/omnibase_core/models/contracts/model_execution_profile.py (1)
src/omnibase_core/models/contracts/model_execution_ordering_policy.py (1)
ModelExecutionOrderingPolicy(13-54)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: claude-review
🔇 Additional comments (22)
src/omnibase_core/models/contracts/model_execution_profile.py (3)
1-42: LGTM: Well-documented module with proper immutability setup.The module docstring clearly documents the immutability rationale and version history. The
DEFAULT_EXECUTION_PHASESconstant is correctly defined as a tuple for immutability, and imports are properly organized.
174-198: LGTM: Well-implemented cached property.The
phase_ordercached property correctly derives the phase-to-index mapping from the immutablephasestuple. Caching is safe since the model is frozen.
45-115: LGTM: Comprehensive class definition with proper immutability.The class correctly implements:
frozen=Truefor attribute immutabilityfrom_attributes=Truefor pytest-xdist compatibility (per coding guidelines)- Tuple fields for true content immutability
- Clear docstrings with examples and version history
src/omnibase_core/models/execution/model_execution_conflict.py (3)
103-121: LGTM: Proper model configuration with new conflict type.The
model_configcorrectly includesfrom_attributes=True(per coding guidelines),frozen=Truefor immutability, andvalidate_assignment=Truefor extra safety. Themust_run_conflictaddition to the Literal union is well-documented.
134-161: LGTM: Tuple fields ensure true immutability.The conversion from
list[str]totuple[str, ...]forhandler_ids,constraint_refs, andcycle_pathprovides true immutability. The field descriptions clearly document the immutability semantics and usage for each conflict type.
173-188: LGTM: Appropriate constraint validation.The model validator correctly enforces that
cycle_pathmust be provided for cycle conflicts, with a clear error message.tests/unit/factories/test_contract_profile_factory.py (1)
48-72: LGTM: Tests correctly updated for tuple-based phases.The tests properly reflect the immutability changes:
expected_phasesis now a tupletest_custom_phasespasses a tuple and verifies tuple output- Docstrings updated to document coercion behavior
tests/unit/models/contracts/test_model_execution_profile.py (4)
1-27: LGTM: Well-structured test module.Proper SPDX headers, comprehensive docstring with references to related tickets, and correct imports including the
@pytest.mark.unitmarker as per coding guidelines.
92-113: LGTM: Caching behavior tests are thorough.Tests correctly verify that
phase_orderis cached (same object returned) and that each instance maintains its own independent cache. The comment on Lines 111-112 appropriately notes the dict mutability caveat while acknowledging the model's immutability makes this acceptable.
297-335: LGTM: Multi-error aggregation tests.Good coverage of Pydantic's error aggregation behavior. The tests verify that multiple validation failures are reported together, which is important for user experience.
338-401: LGTM: Comprehensive tuple immutability tests.Excellent coverage verifying:
- Field reassignment is blocked by
frozen=True- Tuples lack mutation methods (
append, etc.)- Type assertions confirm tuple semantics
- Cache consistency for
phase_ordertests/unit/infrastructure/execution/test_phase_sequencer.py (3)
26-26: LGTM: Appropriate adaptations for tuple-based phases.The import of
ValidationErrorand the use oflist(DEFAULT_EXECUTION_PHASES)correctly adapts to the API where:
DEFAULT_EXECUTION_PHASESis now a tuplevalidate_phase_listexpects a list inputAlso applies to: 108-108, 157-157
715-726: LGTM: Correctly tests validation at model creation time.The test properly verifies that duplicate phases now raise
ValidationErrorduringModelExecutionProfileinstantiation (via Pydantic's model validator), rather than at runtime. The docstring clearly explains this behavioral change.
438-446: LGTM: Tests use tuple syntax for phases.Profile creation correctly uses tuple syntax
("execute", "before")and("preflight", "execute", "finalize"), aligning with the new API.Also applies to: 453-468
tests/unit/models/execution/test_model_execution_conflict.py (5)
1-24: LGTM: Well-organized test module with comprehensive scope.Proper SPDX headers, clear docstring outlining test coverage areas, and correct references to related tickets (OMN-1106, OMN-1227, OMN-1292).
58-109: LGTM: Thorough must_run_conflict type coverage.Tests comprehensively cover the new
must_run_conflicttype:
- Valid creation
- Blocking vs warning severity
- Not a cycle type
- Handler involvement checks
111-152: LGTM: Parametrized test covers all conflict types.The parametrized test elegantly handles all seven conflict types, with special handling for the
cycletype that requirescycle_path. This ensures the newmust_run_conflictis validated alongside existing types.
254-348: LGTM: Comprehensive from_attributes testing.Excellent coverage of Pydantic's
from_attributesfunctionality:
- Dict input with list-to-tuple coercion
- Extra fields rejection
- Object with attributes
- Partial attributes with defaults
- Verifies tuple types after coercion
390-469: LGTM: Complete tuple immutability verification.Tests thoroughly verify immutability for all tuple fields:
handler_idsreassignment blocked- Tuple lacks mutation methods
cycle_pathimmutabilityconstraint_refsimmutabilitysrc/omnibase_core/resolution/resolver_execution.py (3)
436-471: LGTM: Conflict construction uses tuples consistently.All
ModelExecutionConflictcreations for missing dependencies (handler, capability, tag) now correctly use tuple literals forhandler_idsandconstraint_refs, aligning with the immutable model definition.
548-559: LGTM: Cycle conflict uses tuples correctly.The cycle conflict construction now uses
tuple(cycle[:-1])forhandler_idsandtuple(cycle)forcycle_path, ensuring immutability consistent withModelExecutionConflict's updated field types.
692-696: LGTM: Type annotation updated for tuple-based phases.The
profile_phasesparameter correctly usestuple[str, ...]to matchModelExecutionProfile.phasesfield type.
PR Review: OMN-1292 - Core Models for ProtocolConstraintValidatorSummaryThis PR extends ModelExecutionProfile and ModelExecutionConflict with new fields and validations to support the upcoming ProtocolConstraintValidator (OMN-1227). The implementation is solid and production-ready with excellent test coverage and attention to immutability. ✅ Strengths1. Excellent Test Coverage (44 comprehensive tests)
2. True Immutability via TuplesThe migration from list[str] → tuple[str, ...] is a significant improvement providing:
3. Smart Field Validators
4. Performance OptimizationUsing @cached_property for phase_order is smart - avoids recomputing the dictionary on every access while maintaining consistency (safe because model is frozen). 5. Backward CompatibilityAll existing tests pass with updates to accommodate tuple types. The coercion validators ensure existing code passing lists will continue to work. 6. Comprehensive Documentation
🎯 Architecture & Design1. Subset Validation PatternThe validation ensuring nondeterministic_allowed_phases ⊆ phases is well-implemented. Providing sorted invalid phases in error messages is excellent UX. 2. Conflict Type ExtensionAdding must_run_conflict to the Literal union is clean and follows the existing pattern. The existing helper methods (is_blocking, is_cycle, involves_handler) work correctly with the new type. 3. Consistency with ONEX Patterns
🔒 Security & SafetyNo Security Concerns
🧪 Testing AssessmentCoverage BreakdownModelExecutionProfile (9 test classes, 30+ tests):
ModelExecutionConflict (11 test classes, 40+ tests):
🔄 Integration ImpactAll existing tests pass after updates, confirming backward compatibility:
📋 Checklist VerificationBased on PR description:
🏆 Final VerdictLGTM - Approve for Merge ✅ This is exemplary work that:
Great job on the attention to detail, especially the tuple migration for true immutability and the thorough test coverage! Review conducted following CLAUDE.md guidelines for omnibase_core |
…(OMN-1292) - Update validate_phase_list and validate_phase_list_strict to accept tuple[str, ...] | list[str] for compatibility with tuple-based phases - Fix create_default_execution_plan to pass tuple directly instead of converting to list - Remove misleading Raises sections from field validator docstrings - Remove redundant .strip() calls in validate_profile (already stripped by field validators) - Add comprehensive test coverage for tuple immutability, list-to-tuple coercion, and from_attributes behavior
PR Review: ModelExecutionProfile and ModelExecutionConflict Extensions (OMN-1292)Overall AssessmentStrong Approval ✅ - This PR demonstrates excellent engineering practices and aligns perfectly with ONEX principles. The implementation is well-designed, comprehensively tested, and properly documented. Strengths1. Architectural Decisions 🎯
2. True Immutability Implementation 🔒
3. Performance Optimization ⚡
4. Validation Excellence ✅
5. Test Coverage 🧪
6. Documentation Quality 📚
7. Backward Compatibility 🔄
Code Quality ObservationsValidation Logic (model_execution_profile.py:195-241)The # Current: Validates empty strings AFTER subset check
# Suggestion: Early exit for empty strings before subset validation
# (Minor - current code is correct and clear)Verdict: Current implementation is fine - clear and correct is better than micro-optimized. Whitespace Stripping (model_execution_profile.py:135, 158)Both field validators strip whitespace, which is excellent for robustness. The deduplication in Question for consideration: Should whitespace-only phases be caught in field validator vs model validator? Current approach (strip then validate non-empty in model validator) is clean. Verdict: Current approach is good - normalization in field validator, validation in model validator is the right separation. Test Naming and OrganizationTest classes are excellently organized:
Excellent separation of concerns. Security & Thread Safety✅ Thread-safe - All fields are immutable tuples, model is frozen Performance ConsiderationsCached Property Performance
Validation Performance
Alignment with ONEX Standards✅ File Naming: Suggested Improvements (Optional)1. Type Hint for
|
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/omnibase_core/models/contracts/model_execution_profile.py (1)
117-166: Verify intentional deduplication inconsistency between validators.The
coerce_phases_to_tuplevalidator normalizes but does not deduplicate, whilecoerce_nondeterministic_phases_to_tupleexplicitly deduplicates (lines 160-166). Combined with thevalidate_profilecheck that rejects duplicate phases (line 217-218), this creates asymmetric behavior:
- Duplicate phases → ValidationError
- Duplicate nondeterministic_allowed_phases → silently deduplicated
This may be intentional (nondeterministic_allowed_phases is semantically a set, phases is an ordered sequence), but confirm this design choice is deliberate and consider adding a clarifying note in the docstring.
Optional: Extract shared normalization logic
Both validators strip whitespace. If you expect to add more validators with similar normalization, consider extracting:
@staticmethod def _normalize_phase_names(phases: tuple[str, ...]) -> tuple[str, ...]: """Strip whitespace from phase names.""" return tuple(phase.strip() for phase in phases)However, with only two validators, the current inline approach is acceptable.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/omnibase_core/infrastructure/execution/phase_sequencer.pysrc/omnibase_core/models/contracts/model_execution_profile.pytests/unit/models/contracts/test_model_execution_profile.py
🚧 Files skipped from review as they are similar to previous changes (1)
- tests/unit/models/contracts/test_model_execution_profile.py
🧰 Additional context used
📓 Path-based instructions (3)
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Always use Poetry for Python package management and task execution. Use 'poetry run' for all Python commands (pytest, mypy, python -m, etc.). Never use pip or direct python execution.
Always use protocol names for service resolution (e.g., 'ProtocolEventBus', 'ProtocolLogger'), never concrete class names. Use duck typing without isinstance checks.
Use structured error handling with ModelOnexError and EnumCoreErrorCode, never generic Exception. Include error context in the context parameter.
Use the @standard_error_handling decorator on async functions to eliminate 6+ lines of try/catch boilerplate in error handling.
Use PEP 604 union syntax (e.g., 'str | None') instead of legacy Optional/Union. Enforce via ruff rule UP007.
Use standardized exception comment markers (# fallback-ok:, # catch-all-ok:, # cleanup-resilience-ok:, # boundary-ok:, # init-errors-ok:, # tool-resilience-ok:) when using catch-all or broad exception handlers.
Order exception tuples alphabetically by exception class name (e.g., except (AttributeError, TypeError, ValidationError) not except (ValueError, TypeError, AttributeError)).
Use centralized exception constants from omnibase_core.errors.exception_groups (PYDANTIC_MODEL_ERRORS, VALIDATION_ERRORS, FILE_IO_ERRORS, etc.) instead of manually listing exceptions.
Maintain 100% mypy strict mode compliance (0 errors) across all source files using type annotations. Both mypy and pyright must pass in CI.
Format Python code with Black: poetry run black src/ tests/. Sort imports with isort: poetry run isort src/ tests/. Lint with ruff: poetry run ruff check src/ tests/
Do NOT use 'from future import annotations' when runtime type introspection is needed (Pydantic models, FastAPI endpoints). Use it when forward references are needed or to prevent circular imports.
Use EnumNodeKind for architectural role (EFFECT, COMPUTE, REDUCER, ORCHESTRATOR, RUNTIME_HOST) for pipeline routing. Use EnumNodeType for implementation type (COMPUTE_GENERIC, TRA...
Files:
src/omnibase_core/infrastructure/execution/phase_sequencer.pysrc/omnibase_core/models/contracts/model_execution_profile.py
src/omnibase_core/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
src/omnibase_core/**/*.py: Follow directory-specific naming prefixes for Python files in src/omnibase_core/. Examples: cli_, constants_, container_, decorator_, enum_, error_, factory_, mixin_, model_, node_, etc.
Use FileRegistry for loading YAML contracts: registry = FileRegistry(); contract = registry.load(Path('config/runtime_host.yaml'))
Use ModelEventEnvelope for inter-service event communication. Structure events with proper envelope wrapping for consistency.
Files:
src/omnibase_core/infrastructure/execution/phase_sequencer.pysrc/omnibase_core/models/contracts/model_execution_profile.py
src/omnibase_core/models/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
src/omnibase_core/models/**/*.py: Add 'from_attributes=True' to ConfigDict for immutable value objects nested in other Pydantic models used with pytest-xdist parallel execution.
Use Pydantic 2.11+ for all data models. Use Pydantic v2 syntax, ConfigDict, and model_validate methods.
Files:
src/omnibase_core/models/contracts/model_execution_profile.py
🧠 Learnings (1)
📚 Learning: 2026-01-08T14:36:08.342Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-08T14:36:08.342Z
Learning: Applies to src/omnibase_core/models/**/*.py : Add 'from_attributes=True' to ConfigDict for immutable value objects nested in other Pydantic models used with pytest-xdist parallel execution.
Applied to files:
src/omnibase_core/models/contracts/model_execution_profile.py
🧬 Code graph analysis (1)
src/omnibase_core/models/contracts/model_execution_profile.py (1)
src/omnibase_core/models/contracts/model_execution_ordering_policy.py (1)
ModelExecutionOrderingPolicy(13-54)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: claude-review
🔇 Additional comments (4)
src/omnibase_core/models/contracts/model_execution_profile.py (3)
168-192: Excellent caching strategy for phase lookups.The
cached_propertyimplementation is optimal for this use case:
- Computed once per instance, avoiding repeated enumeration
- Thread-safe in Python 3.12+ (meets the project's target)
- Guaranteed consistency due to immutable
phasestuple andfrozen=True
194-241: Robust validation with clear error messages.The model-level validation correctly enforces all invariants:
- Phase uniqueness detection (line 217-218)
- Non-empty string checks prevent whitespace-only phases
- Subset validation ensures referential integrity
- Error messages include context (e.g.,
sorted(invalid_phases)at line 238)The validation ordering (field validators → model validator) ensures normalization happens before invariant checks.
24-27: LGTM: Immutability implementation is correct.The refactor successfully achieves true immutability:
- Tuple types (
tuple[str, ...]) prevent mutation beyondfrozen=True- DEFAULT_EXECUTION_PHASES as tuple prevents accidental modification of the default
- New
nondeterministic_allowed_phasesfield aligns with OMN-1292 requirementsfrom_attributes=Truein ConfigDict follows project learnings for pytest-xdist compatibilityBased on learnings:
from_attributes=Trueis correctly included for immutable value objects used with pytest-xdist.Also applies to: 35-42, 95-108, 110-115
src/omnibase_core/infrastructure/execution/phase_sequencer.py (1)
80-80: LGTM: Clean adaptation to tuple-based phases.The signature updates correctly support the tuple-based refactor:
- Lines 80, 127-129:
list[str] | tuple[str, ...]provides flexibility while maintaining backward compatibility- Line 476: Passing
DEFAULT_EXECUTION_PHASESdirectly (withoutlist()wrapper) correctly leverages the tuple default- All functions remain pure and thread-safe since tuples are immutable
The changes maintain consistent behavior while supporting the immutability improvements in ModelExecutionProfile.
Also applies to: 127-129, 476-476
… (OMN-1292) - Fix CI test failures: convert list comprehensions to tuple generators in test_enum_handler_execution_phase.py for proper tuple-to-tuple comparison - Fix all 9 mypy errors in test file with appropriate type: ignore comments - Add validation consistency: nondeterministic_allowed_phases now raises ValidationError on duplicates (consistent with phases field behavior) - Add comprehensive test coverage: - TestPhaseOrderCaching (5 tests) - TestMultipleValidationErrors (7 tests) - TestListMutationPrevention (4 tests) - TestFromAttributesExplicit (5 tests)
Code Review - PR #361Overall Assessment: ✅ EXCELLENT This PR demonstrates exceptional code quality with comprehensive testing, excellent documentation, and careful attention to immutability guarantees. The changes are well-architected and follow ONEX best practices. Strengths 🌟1. Immutability Design
2. Validation Architecture
3. Performance Optimization
4. Test Coverage (44 new tests!)
5. Documentation Quality
6. Backward Compatibility
7. Type Safety
Code Quality Observations 🔍ModelExecutionProfile (
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In @src/omnibase_core/models/contracts/model_execution_profile.py:
- Around line 117-167: Both coerce_phases_to_tuple and
coerce_nondeterministic_phases_to_tuple currently call .strip() on each element
without type-checking, causing AttributeError for non-str inputs; update both
validators to guard element types (ensure each element is an instance of str)
before calling .strip(), and on invalid types raise a proper validation error
(either ValueError with a clear message or the project-standard ModelOnexError
with EnumCoreErrorCode.VALIDATION_ERROR) so Pydantic surfaces a ValidationError
instead of propagating AttributeError.
🧹 Nitpick comments (3)
src/omnibase_core/models/contracts/model_execution_profile.py (2)
7-10:phase_orderbreaks the “fully immutable” contract (mutable dict + cached instance state).
cached_propertycaches into__dict__, and the returneddictcan be mutated by consumers—silently corrupting subsequent lookups on the same instance. Consider returning a read-only mapping (or at least a defensive copy) to match the docstring and immutability intent.Proposed fix (return a read-only mapping)
-from functools import cached_property +from functools import cached_property +from types import MappingProxyType @@ @cached_property def phase_order(self) -> dict[str, int]: @@ - return {phase: idx for idx, phase in enumerate(self.phases)} + # Prevent accidental mutation of cached mapping + return MappingProxyType({phase: idx for idx, phase in enumerate(self.phases)})Also applies to: 53-57, 168-193
194-268: Consider explicitly rejectingphases=()if downstream assumes at least one phase.
As written, an empty phases tuple passes (no empties, no duplicates). If any execution planning assumes ≥1 phase, fail fast here with a targeted error.Possible adjustment
# Validate phases are unique if len(self.phases) != len(set(self.phases)): raise ValueError("phases must contain unique values") + + if not self.phases: + raise ValueError("phases must not be empty")tests/unit/enums/test_enum_handler_execution_phase.py (1)
253-266: Test comments say “StrEnum” but the enum isstr, Enum; consider rewording (and possibly reducing ignores).
The runtime equality-to-string behavior comes from thestrmixin here, not necessarilyenum.StrEnum. If you want to avoidtype: ignore[comparison-overlap]noise, prefer.valuecomparisons for most assertions and reserve direct== "..."checks for a single dedicated runtime-behavior test.Also applies to: 381-401
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/omnibase_core/models/contracts/model_execution_profile.pytests/unit/enums/test_enum_handler_execution_phase.pytests/unit/models/contracts/test_model_execution_profile.pytests/unit/models/execution/test_model_execution_conflict.py
🚧 Files skipped from review as they are similar to previous changes (1)
- tests/unit/models/contracts/test_model_execution_profile.py
🧰 Additional context used
📓 Path-based instructions (4)
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Always use Poetry for Python package management and task execution. Use 'poetry run' for all Python commands (pytest, mypy, python -m, etc.). Never use pip or direct python execution.
Always use protocol names for service resolution (e.g., 'ProtocolEventBus', 'ProtocolLogger'), never concrete class names. Use duck typing without isinstance checks.
Use structured error handling with ModelOnexError and EnumCoreErrorCode, never generic Exception. Include error context in the context parameter.
Use the @standard_error_handling decorator on async functions to eliminate 6+ lines of try/catch boilerplate in error handling.
Use PEP 604 union syntax (e.g., 'str | None') instead of legacy Optional/Union. Enforce via ruff rule UP007.
Use standardized exception comment markers (# fallback-ok:, # catch-all-ok:, # cleanup-resilience-ok:, # boundary-ok:, # init-errors-ok:, # tool-resilience-ok:) when using catch-all or broad exception handlers.
Order exception tuples alphabetically by exception class name (e.g., except (AttributeError, TypeError, ValidationError) not except (ValueError, TypeError, AttributeError)).
Use centralized exception constants from omnibase_core.errors.exception_groups (PYDANTIC_MODEL_ERRORS, VALIDATION_ERRORS, FILE_IO_ERRORS, etc.) instead of manually listing exceptions.
Maintain 100% mypy strict mode compliance (0 errors) across all source files using type annotations. Both mypy and pyright must pass in CI.
Format Python code with Black: poetry run black src/ tests/. Sort imports with isort: poetry run isort src/ tests/. Lint with ruff: poetry run ruff check src/ tests/
Do NOT use 'from future import annotations' when runtime type introspection is needed (Pydantic models, FastAPI endpoints). Use it when forward references are needed or to prevent circular imports.
Use EnumNodeKind for architectural role (EFFECT, COMPUTE, REDUCER, ORCHESTRATOR, RUNTIME_HOST) for pipeline routing. Use EnumNodeType for implementation type (COMPUTE_GENERIC, TRA...
Files:
tests/unit/models/execution/test_model_execution_conflict.pytests/unit/enums/test_enum_handler_execution_phase.pysrc/omnibase_core/models/contracts/model_execution_profile.py
tests/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
tests/**/*.py: Maintain minimum 60% code coverage across test suite. Run tests with: poetry run pytest tests/ --cov=src/omnibase_core/
Run all tests with parallel workers: poetry run pytest tests/ uses 4 workers locally with 60s timeout and loadscope distribution. CI uses 20 parallel splits on GitHub Actions.
Use pytest markers for test categorization: @pytest.mark.unit, @pytest.mark.integration, @pytest.mark.slow, @pytest.mark.smoke, @pytest.mark.performance
Use pytest 8.4+ for testing. Use pytest fixtures, markers, and parallel execution with pytest-xdist.
Files:
tests/unit/models/execution/test_model_execution_conflict.pytests/unit/enums/test_enum_handler_execution_phase.py
src/omnibase_core/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
src/omnibase_core/**/*.py: Follow directory-specific naming prefixes for Python files in src/omnibase_core/. Examples: cli_, constants_, container_, decorator_, enum_, error_, factory_, mixin_, model_, node_, etc.
Use FileRegistry for loading YAML contracts: registry = FileRegistry(); contract = registry.load(Path('config/runtime_host.yaml'))
Use ModelEventEnvelope for inter-service event communication. Structure events with proper envelope wrapping for consistency.
Files:
src/omnibase_core/models/contracts/model_execution_profile.py
src/omnibase_core/models/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
src/omnibase_core/models/**/*.py: Add 'from_attributes=True' to ConfigDict for immutable value objects nested in other Pydantic models used with pytest-xdist parallel execution.
Use Pydantic 2.11+ for all data models. Use Pydantic v2 syntax, ConfigDict, and model_validate methods.
Files:
src/omnibase_core/models/contracts/model_execution_profile.py
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-08T14:36:08.342Z
Learning: Applies to src/omnibase_core/models/**/*.py : Use Pydantic 2.11+ for all data models. Use Pydantic v2 syntax, ConfigDict, and model_validate methods.
📚 Learning: 2026-01-08T14:36:08.342Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-08T14:36:08.342Z
Learning: Applies to src/omnibase_core/models/**/*.py : Add 'from_attributes=True' to ConfigDict for immutable value objects nested in other Pydantic models used with pytest-xdist parallel execution.
Applied to files:
tests/unit/models/execution/test_model_execution_conflict.pysrc/omnibase_core/models/contracts/model_execution_profile.py
🧬 Code graph analysis (2)
tests/unit/enums/test_enum_handler_execution_phase.py (1)
src/omnibase_core/enums/enum_handler_execution_phase.py (1)
EnumHandlerExecutionPhase(18-140)
src/omnibase_core/models/contracts/model_execution_profile.py (1)
src/omnibase_core/models/contracts/model_execution_ordering_policy.py (1)
ModelExecutionOrderingPolicy(13-54)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Code Quality
- GitHub Check: claude-review
🔇 Additional comments (4)
tests/unit/models/execution/test_model_execution_conflict.py (2)
1-24: LGTM! Clean imports and documentation.The module header, imports, and docstring are well-structured. The references to OMN tickets provide good traceability for the new must_run_conflict functionality.
26-667: Excellent test coverage and organization!This test suite provides comprehensive coverage of ModelExecutionConflict including the new must_run_conflict type (OMN-1292). Highlights:
- Thorough validation testing: All conflict types, error conditions, and edge cases
- Extensive immutability verification: Tests frozen model, tuple fields, and prevention of index mutation
- from_attributes compatibility: Multiple source types (dict, object, namedtuple, dataclass) with proper list-to-tuple coercion
- Multi-error aggregation: Validates that Pydantic reports multiple validation errors together
- Clear organization: 11 test classes logically grouped by feature area
- Proper pytest usage: Unit markers, parametrize, clear docstrings
The test logic is correct throughout, including cycle length calculation (line 179), tuple coercion verification (lines 275-276), and TypeError expectations for index mutation (lines 488-515).
tests/unit/enums/test_enum_handler_execution_phase.py (2)
91-98: Tuple alignment withDEFAULT_EXECUTION_PHASESis correct.
This matches the new immutability contract and avoids list/tuple assertion mismatches.Also applies to: 113-119
289-291: Pydantic coercion test is fine; keep the ignore narrowly scoped.
The# type: ignore[arg-type]is appropriately localized to the runtime-coercion case.
…ess (OMN-1292) - Add type validation in field validators before calling .strip() - Reject empty phases tuple with clear error message - Make phase_order truly immutable with MappingProxyType - Fix test comments (StrEnum -> str, Enum pattern) - Add TestTypeValidation class with 4 new tests
Code Review for PR #361Overall Assessment: ✅ ExcellentThis PR demonstrates exceptional code quality and adherence to ONEX best practices. The implementation is well-thought-out, thoroughly tested, and properly documented. Strengths1. Architecture & Design ✅
2. Code Quality ✅
3. Testing ✅ (44 new tests!)
4. Code Conventions ✅
Detailed Technical ReviewModelExecutionProfile (
|
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
tests/unit/models/contracts/test_model_execution_profile.py (2)
39-47: Consider removing duplicate test.
test_custom_phasesandtest_custom_phases_from_tupleare identical—both pass a tuple and verify the same result. Since the model now internally coerces lists to tuples, consider keeping only one test (perhaps the one that tests list coercion) or renaming to differentiate their purpose.
100-113: Outdated comment: phase_order is now immutable.The comment on lines 111-112 states "modification of the returned dict could affect cached value" but this is no longer accurate. Per the model implementation,
phase_orderreturns aMappingProxyType, which is immutable. Consider updating or removing this comment to avoid confusion.🔧 Suggested fix
# Different profiles have different phase orders assert order1 == {"init": 0, "execute": 1} assert order2 == {"alpha": 0, "beta": 1, "gamma": 2} - # But modification of the returned dict could affect cached value - # This is acceptable since the model is immutable
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/omnibase_core/models/contracts/model_execution_profile.pytests/unit/enums/test_enum_handler_execution_phase.pytests/unit/models/contracts/test_model_execution_profile.py
🧰 Additional context used
📓 Path-based instructions (4)
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Always use Poetry for Python package management and task execution. Use 'poetry run' for all Python commands (pytest, mypy, python -m, etc.). Never use pip or direct python execution.
Always use protocol names for service resolution (e.g., 'ProtocolEventBus', 'ProtocolLogger'), never concrete class names. Use duck typing without isinstance checks.
Use structured error handling with ModelOnexError and EnumCoreErrorCode, never generic Exception. Include error context in the context parameter.
Use the @standard_error_handling decorator on async functions to eliminate 6+ lines of try/catch boilerplate in error handling.
Use PEP 604 union syntax (e.g., 'str | None') instead of legacy Optional/Union. Enforce via ruff rule UP007.
Use standardized exception comment markers (# fallback-ok:, # catch-all-ok:, # cleanup-resilience-ok:, # boundary-ok:, # init-errors-ok:, # tool-resilience-ok:) when using catch-all or broad exception handlers.
Order exception tuples alphabetically by exception class name (e.g., except (AttributeError, TypeError, ValidationError) not except (ValueError, TypeError, AttributeError)).
Use centralized exception constants from omnibase_core.errors.exception_groups (PYDANTIC_MODEL_ERRORS, VALIDATION_ERRORS, FILE_IO_ERRORS, etc.) instead of manually listing exceptions.
Maintain 100% mypy strict mode compliance (0 errors) across all source files using type annotations. Both mypy and pyright must pass in CI.
Format Python code with Black: poetry run black src/ tests/. Sort imports with isort: poetry run isort src/ tests/. Lint with ruff: poetry run ruff check src/ tests/
Do NOT use 'from future import annotations' when runtime type introspection is needed (Pydantic models, FastAPI endpoints). Use it when forward references are needed or to prevent circular imports.
Use EnumNodeKind for architectural role (EFFECT, COMPUTE, REDUCER, ORCHESTRATOR, RUNTIME_HOST) for pipeline routing. Use EnumNodeType for implementation type (COMPUTE_GENERIC, TRA...
Files:
tests/unit/enums/test_enum_handler_execution_phase.pysrc/omnibase_core/models/contracts/model_execution_profile.pytests/unit/models/contracts/test_model_execution_profile.py
tests/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
tests/**/*.py: Maintain minimum 60% code coverage across test suite. Run tests with: poetry run pytest tests/ --cov=src/omnibase_core/
Run all tests with parallel workers: poetry run pytest tests/ uses 4 workers locally with 60s timeout and loadscope distribution. CI uses 20 parallel splits on GitHub Actions.
Use pytest markers for test categorization: @pytest.mark.unit, @pytest.mark.integration, @pytest.mark.slow, @pytest.mark.smoke, @pytest.mark.performance
Use pytest 8.4+ for testing. Use pytest fixtures, markers, and parallel execution with pytest-xdist.
Files:
tests/unit/enums/test_enum_handler_execution_phase.pytests/unit/models/contracts/test_model_execution_profile.py
src/omnibase_core/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
src/omnibase_core/**/*.py: Follow directory-specific naming prefixes for Python files in src/omnibase_core/. Examples: cli_, constants_, container_, decorator_, enum_, error_, factory_, mixin_, model_, node_, etc.
Use FileRegistry for loading YAML contracts: registry = FileRegistry(); contract = registry.load(Path('config/runtime_host.yaml'))
Use ModelEventEnvelope for inter-service event communication. Structure events with proper envelope wrapping for consistency.
Files:
src/omnibase_core/models/contracts/model_execution_profile.py
src/omnibase_core/models/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
src/omnibase_core/models/**/*.py: Add 'from_attributes=True' to ConfigDict for immutable value objects nested in other Pydantic models used with pytest-xdist parallel execution.
Use Pydantic 2.11+ for all data models. Use Pydantic v2 syntax, ConfigDict, and model_validate methods.
Files:
src/omnibase_core/models/contracts/model_execution_profile.py
🧠 Learnings (3)
📚 Learning: 2026-01-08T14:36:08.342Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-08T14:36:08.342Z
Learning: Applies to src/omnibase_core/models/**/*.py : Add 'from_attributes=True' to ConfigDict for immutable value objects nested in other Pydantic models used with pytest-xdist parallel execution.
Applied to files:
src/omnibase_core/models/contracts/model_execution_profile.pytests/unit/models/contracts/test_model_execution_profile.py
📚 Learning: 2026-01-08T14:36:08.342Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-08T14:36:08.342Z
Learning: Applies to **/*.py : Use structured error handling with ModelOnexError and EnumCoreErrorCode, never generic Exception. Include error context in the context parameter.
Applied to files:
src/omnibase_core/models/contracts/model_execution_profile.py
📚 Learning: 2026-01-08T14:36:08.342Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-08T14:36:08.342Z
Learning: Applies to src/omnibase_core/models/**/*.py : Use Pydantic 2.11+ for all data models. Use Pydantic v2 syntax, ConfigDict, and model_validate methods.
Applied to files:
src/omnibase_core/models/contracts/model_execution_profile.py
🧬 Code graph analysis (2)
tests/unit/enums/test_enum_handler_execution_phase.py (1)
src/omnibase_core/enums/enum_handler_execution_phase.py (1)
EnumHandlerExecutionPhase(18-140)
src/omnibase_core/models/contracts/model_execution_profile.py (1)
src/omnibase_core/models/contracts/model_execution_ordering_policy.py (1)
ModelExecutionOrderingPolicy(13-54)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Code Quality
- GitHub Check: claude-review
🔇 Additional comments (18)
tests/unit/models/contracts/test_model_execution_profile.py (4)
1-27: LGTM! Well-structured test module setup.The imports, docstring, and module-level configuration are correct. The test file follows project conventions with proper SPDX headers, comprehensive docstrings, and appropriate imports for the features being tested.
115-478: LGTM! Comprehensive validation and immutability tests.The test classes for validation (
TestNondeterministicPhasesValidation,TestPhasesValidation), immutability (TestImmutability,TestTupleImmutabilityBehavior), coercion (TestListToTupleCoercion), andfrom_attributescompatibility are well-structured and thoroughly cover edge cases. The tests correctly verify the model's behavior as per the implementation.
817-853: LGTM! Type validation and immutability tests.The
TestTypeValidationclass properly tests type validation for non-string elements, empty phases rejection, and verifies thatphase_orderreturns an immutableMappingProxyType. These tests align with the model's validation and immutability guarantees.
692-704: No changes needed—test expectation is correct.The test correctly expects
TypeErrorwhen passing a non-iterable value to thephasesfield. The field validator directly iterates over the input without exception handling (for i, phase in enumerate(v):), which raisesTypeError: 'int' object is not iterablefor int inputs. In Pydantic v2, such exceptions from field_validators propagate as-is rather than being wrapped inValidationError.tests/unit/enums/test_enum_handler_execution_phase.py (6)
93-98: LGTM! Tuple conversion for DEFAULT_EXECUTION_PHASES alignment.The change from list comprehension to tuple correctly aligns the test assertion with the updated
DEFAULT_EXECUTION_PHASEStype (now a tuple for immutability).
116-118: LGTM! Consistent tuple usage for phase comparison.Same pattern as above—correctly using tuple to match
DEFAULT_EXECUTION_PHASEStype.
253-266: LGTM! Well-documented runtime behavior for str/Enum comparisons.The updated docstring clearly explains why
type: ignore[comparison-overlap]is needed—mypy can't statically verify thatstr, Enummembers are equal to their string values at runtime. This is appropriate documentation for the pattern used.
382-401: LGTM! Proper type ignore annotations with context.The updated docstring and comments explain the runtime vs. compile-time behavior difference for enum identity and equality comparisons. The
type: ignoreannotations are correctly placed and documented.
290-291: LGTM! Type annotation for Pydantic string coercion.The
type: ignore[arg-type]is appropriate here since Pydantic coerces strings to enums at runtime, but the static type signature expectsEnumHandlerExecutionPhase.
411-417: LGTM! Improved docstring assertion handling.The assertions now properly handle the
Nonecase for the docstring with explicit error messaging, and verify expected content.src/omnibase_core/models/contracts/model_execution_profile.py (8)
24-28: LGTM! Appropriate imports for immutability features.The imports of
cached_property,MappingProxyType,Self, and Pydantic validators are correct for implementing the immutability and validation features.
34-43: LGTM! Immutable default phases constant.Converting
DEFAULT_EXECUTION_PHASESfrom a list to a tuple ensures immutability at the module level, preventing accidental modification.
46-94: LGTM! Comprehensive class documentation.The docstring thoroughly explains the immutability guarantees, attributes, properties, and provides a clear example. The version change notes help track evolution.
96-116: LGTM! Correct field definitions with immutability.The fields use tuples for immutability, and
model_configincludesfrozen=Trueandfrom_attributes=Trueas required by coding guidelines for immutable value objects in Pydantic models.
118-146: LGTM! Robust coercion with type checking.The validator properly handles list-to-tuple coercion, validates each element is a string before calling
.strip(), and provides clear error messages with the index of the failing element. This preventsAttributeErrorif non-strings are passed.
148-187: LGTM! Consistent validation with intentional design choice.The validator follows the same pattern as
coerce_phases_to_tupleand clearly documents that deduplication is intentionally deferred to themodel_validatorto raise errors for duplicate entries rather than silently correcting them.
216-298: LGTM! Comprehensive model validation.The
model_validatorthoroughly validates all invariants with clear, specific error messages. The validation order (empty check → uniqueness → content validation → subset check) is logical, and the use ofsorted()for error messages ensures consistent output. The docstring clearly documents all validation rules and error cases.
189-214: Verifycached_propertycompatibility with frozen Pydantic models.
cached_propertytypically stores its computed value in the instance's__dict__. However, Pydantic'sfrozen=Truemay restrict__dict__modifications after initialization. This could causeAttributeErroron first access. Pydantic 2.x models withfrozen=Truegenerally allowcached_propertyto work because the property access happens after model construction, but this should be verified.Does Pydantic 2.x frozen model support cached_property?
Summary
ModelExecutionProfilewithnondeterministic_allowed_phasesfield andphase_ordercomputed propertyModelExecutionConflictwithmust_run_conflicttypeContext
This PR implements OMN-1292, providing core models required by OMN-1227 (ProtocolConstraintValidator for SPI).
Decision: Extend Existing vs. Create New
Following ONEX principles, we extended existing models rather than creating new ones:
ModelExecutionProfilemodels/contracts/ModelExecutionConflictmust_run_conflictChanges
ModelExecutionProfile (
models/contracts/model_execution_profile.py):nondeterministic_allowed_phases: list[str]- phases where nondeterministic effects are permittedphase_orderproperty - computeddict[str, int]mapping phases to indices (DRY, no redundant storage)@model_validatorensuring:phasesare unique and non-empty stringsnondeterministic_allowed_phasesis a subset ofphasesModelExecutionConflict (
models/execution/model_execution_conflict.py):"must_run_conflict"toconflict_typeLiteral unionTest plan
Blocks
Summary by CodeRabbit
New Features
Behavior Changes
Tests
✏️ Tip: You can customize this high-level summary in your review settings.