Repository navigation
feat(contracts): implement ModelContractVersion with typed semver fields [OMN-154] - #116
Conversation
…lds [OMN-154] Add typed semver model for contract versioning with downgrade protection. - Create ModelContractVersion with major/minor/patch int fields - Implement full comparison operators (__eq__, __lt__, __le__, __gt__, __ge__) - Add version bumping methods (bump_major, bump_minor, bump_patch) - Add downgrade protection via validate_progression(allow_downgrade=False) - Add factory methods from_string() and from_tuple() - Ensure immutability with frozen=True, extra="forbid", strict=True - Add comprehensive TDD tests (86 tests, 88% coverage) - Export from omnibase_core.models.contracts Implements CONTRACT_STABILITY_SPEC.md semver requirements.
WalkthroughAdds an immutable ModelContractVersion semantic-version model with parsing, comparisons, bump/progression helpers and downgrade validation; exposes it from the contracts package; updates several import paths (mixins and transformation types), tightens protocol-location validation whitelist, adds unit tests, and adjusts pre-commit hook stages. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (6)
🚧 Files skipped from review as they are similar to previous changes (3)
🧰 Additional context used📓 Path-based instructions (4)**/*.py📄 CodeRabbit inference engine (CLAUDE.md)
Files:
src/omnibase_core/**/*.py📄 CodeRabbit inference engine (CLAUDE.md)
Files:
src/omnibase_core/models/**/*.py📄 CodeRabbit inference engine (CLAUDE.md)
Files:
src/omnibase_core/mixins/**/*.py📄 CodeRabbit inference engine (CLAUDE.md)
Files:
🧠 Learnings (3)📚 Learning: 2025-12-06T23:34:11.788ZApplied to files:
📚 Learning: 2025-12-06T23:34:11.788ZApplied to files:
📚 Learning: 2025-12-06T23:34:11.788ZApplied to files:
🧬 Code graph analysis (3)src/omnibase_core/models/contracts/model_contract_compute.py (1)
src/omnibase_core/mixins/__init__.py (1)
src/omnibase_core/models/contracts/model_contract_effect.py (1)
⏰ 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)
🔇 Additional comments (3)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (5)
src/omnibase_core/models/contracts/__init__.py (1)
10-11: Import organization could be improved.The new relative import at line 10 is placed between absolute imports. For consistency, consider grouping it with other relative imports starting at line 16.
from omnibase_core.models.core.model_workflow import ModelWorkflow """ Contract Models Models for validating various contract formats and subcontract compositions. """ from omnibase_core.models.discovery.model_event_descriptor import ModelEventDescriptor -from .model_contract_version import ModelContractVersion from omnibase_core.models.security.model_condition_value import ModelConditionValue from omnibase_core.models.service.model_external_service_config import ( ModelExternalServiceConfig, ) from . import subcontracts +from .model_contract_version import ModelContractVersion from .mixin_node_type_validator import MixinNodeTypeValidatortests/unit/models/contracts/test_model_contract_version.py (2)
35-36: Add pytest markers as per coding guidelines.Per the coding guidelines, tests should use
@pytest.mark.unitfor unit tests and@pytest.mark.timeout()to prevent hangs. Consider adding the class-level markers.+import pytest + +@pytest.mark.unit +@pytest.mark.timeout(30) class TestModelContractVersionBasicConstruction: """Tests for ModelContractVersion basic construction and initialization."""Apply similar markers to all test classes in this file.
667-689: Tests for prerelease/build metadata could be more explicit.The try/except pattern here silently passes if the feature isn't supported. Since the implementation does support prerelease/build suffixes (per the regex in
from_string), these tests should assert success rather than allowing silent failure.def test_from_string_with_prerelease_suffix_may_be_ignored(self) -> None: """Test from_string() with prerelease suffix (if supported).""" - # Based on ModelSemVer, prerelease suffixes may be parsed but ignored - try: - version = ModelContractVersion.from_string("1.2.3-alpha") - assert version.major == 1 - assert version.minor == 2 - assert version.patch == 3 - except Exception: - # If prerelease is not supported, that's also acceptable - pass + # Prerelease suffixes are parsed but ignored per implementation + version = ModelContractVersion.from_string("1.2.3-alpha") + assert version.major == 1 + assert version.minor == 2 + assert version.patch == 3 def test_from_string_with_build_metadata_may_be_ignored(self) -> None: """Test from_string() with build metadata (if supported).""" - try: - version = ModelContractVersion.from_string("1.2.3+build") - assert version.major == 1 - assert version.minor == 2 - assert version.patch == 3 - except Exception: - # If build metadata is not supported, that's also acceptable - pass + # Build metadata is parsed but ignored per implementation + version = ModelContractVersion.from_string("1.2.3+build") + assert version.major == 1 + assert version.minor == 2 + assert version.patch == 3src/omnibase_core/models/contracts/model_contract_version.py (2)
14-14: Remove unused import.
Anyis imported fromtypingbut never used in this module.-from typing import Any
258-263: Consider usingModelOnexErrorfor consistency.Per coding guidelines, structured error handling with
ModelOnexErrorandEnumCoreErrorCodeis preferred. Thefrom_stringmethod usesModelOnexError, butvalidate_progressionraises a plainValueError. Consider usingModelOnexErrorwith an appropriate error code (e.g.,VALIDATION_ERRORorCONTRACT_VIOLATION) for consistency.if self.is_downgrade_from(from_version) and not allow_downgrade: - raise ValueError( - f"Version downgrade detected: {from_version} -> {self}. " - f"Downgrades are not allowed without explicit allow_downgrade=True. " - f"See CONTRACT_STABILITY_SPEC.md for versioning rules." + raise ModelOnexError( + error_code=EnumCoreErrorCode.CONTRACT_VIOLATION, + message=( + f"Version downgrade detected: {from_version} -> {self}. " + f"Downgrades are not allowed without explicit allow_downgrade=True. " + f"See CONTRACT_STABILITY_SPEC.md for versioning rules." + ), )Note: This would require updating the tests to catch
ModelOnexErrorinstead ofValueError.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/omnibase_core/models/contracts/__init__.py(2 hunks)src/omnibase_core/models/contracts/model_contract_version.py(1 hunks)tests/unit/models/contracts/test_model_contract_version.py(1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Always use Poetry for Python package management and task execution. Usepoetry runfor pytest, mypy, black, isort, and other tools. Never use pip directly or execute python commands without the poetry run prefix.
Enforce 100% strict mypy compliance. All functions must have complete type annotations. Usepoetry run mypy src/omnibase_core/to verify strict mode compliance with no errors.
Format code with black, sort imports with isort, and lint with ruff. Runpoetry run black src/ tests/,poetry run isort src/ tests/, andpoetry run ruff check --fix src/ tests/
Files:
src/omnibase_core/models/contracts/__init__.pysrc/omnibase_core/models/contracts/model_contract_version.pytests/unit/models/contracts/test_model_contract_version.py
src/omnibase_core/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
src/omnibase_core/**/*.py: Use protocol names withcontainer.get_service()for dependency injection, never resolve services by concrete class names. Example:container.get_service('ProtocolEventBus')instead ofcontainer.get_service('EventBusService')
Always use ModelONEXContainer for dependency injection in node constructors and service resolution. Never confuse it with ModelContainer[T], which is a generic value wrapper, not a DI container.
Use structured error handling with ModelOnexError and EnumCoreErrorCode, never raise generic Exception. Always chain exceptions withfrom ewhen catching and re-raising.
Use the @standard_error_handling decorator on methods to eliminate 6+ lines of try/catch boilerplate. Example:@standard_error_handlingabove async methods.
Respect thread safety constraints: Do NOT share node instances (NodeCompute, NodeEffect), cache, or circuit breaker instances across threads without synchronization. Use thread-local instances or locks.
Use duck typing with protocols. Do not use isinstance checks with protocol types. Rely on the protocol interface directly.
Use EnumNodeKind for high-level architectural classification (EFFECT, COMPUTE, REDUCER, ORCHESTRATOR) when routing data through the ONEX pipeline. Use EnumNodeType for specific implementation discovery and capability matching.
Use ModelEventEnvelope for inter-service event-driven communication. Process events through the envelope pattern for consistent event handling.
Files:
src/omnibase_core/models/contracts/__init__.pysrc/omnibase_core/models/contracts/model_contract_version.py
src/omnibase_core/models/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Use Pydantic 2.11+ models for all data validation and serialization. Ensure models are immutable after creation for thread safety.
Files:
src/omnibase_core/models/contracts/__init__.pysrc/omnibase_core/models/contracts/model_contract_version.py
tests/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
tests/**/*.py: Write tests using pytest with async support via pytest-asyncio. Maintain minimum 60% code coverage. Use pytest markers: @pytest.mark.unit, @pytest.mark.integration, @pytest.mark.slow
Add @pytest.mark.timeout() to prevent test hangs. Run tests withpoetry run pytest tests/ --timeout=60for 60-second timeout protection.
Files:
tests/unit/models/contracts/test_model_contract_version.py
🧠 Learnings (2)
📚 Learning: 2025-12-06T23:34:11.788Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T23:34:11.788Z
Learning: Applies to src/omnibase_core/**/*.py : Use ModelEventEnvelope for inter-service event-driven communication. Process events through the envelope pattern for consistent event handling.
Applied to files:
src/omnibase_core/models/contracts/__init__.py
📚 Learning: 2025-12-06T23:34:11.788Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T23:34:11.788Z
Learning: Applies to src/omnibase_core/models/**/*.py : Use Pydantic 2.11+ models for all data validation and serialization. Ensure models are immutable after creation for thread safety.
Applied to files:
src/omnibase_core/models/contracts/model_contract_version.py
🧬 Code graph analysis (3)
src/omnibase_core/models/contracts/__init__.py (1)
src/omnibase_core/models/contracts/model_contract_version.py (1)
ModelContractVersion(22-263)
src/omnibase_core/models/contracts/model_contract_version.py (1)
src/omnibase_core/enums/enum_core_error_code.py (1)
EnumCoreErrorCode(9-154)
tests/unit/models/contracts/test_model_contract_version.py (1)
src/omnibase_core/models/contracts/model_contract_version.py (9)
ModelContractVersion(22-263)from_string(70-104)is_upgrade_from(196-214)is_downgrade_from(216-234)bump_major(157-168)bump_minor(170-181)bump_patch(183-194)validate_progression(236-263)to_string(61-63)
⏰ 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: Smoke Tests
🔇 Additional comments (8)
src/omnibase_core/models/contracts/__init__.py (1)
60-62: LGTM!
ModelContractVersionis correctly exported in the__all__list under the "Foundation models" section, making it publicly importable fromomnibase_core.models.contracts.tests/unit/models/contracts/test_model_contract_version.py (1)
1-33: Well-structured test module with comprehensive coverage.The test file provides excellent coverage for
ModelContractVersionwith clear test categories matching the acceptance criteria. The docstring clearly documents the test categories and requirements from CONTRACT_STABILITY_SPEC.md.src/omnibase_core/models/contracts/model_contract_version.py (6)
46-51: LGTM!The model configuration correctly enforces immutability (
frozen=True), strict typing (strict=True), and no extra fields (extra="forbid"), aligning with the coding guidelines for thread-safe Pydantic models. Based on learnings, this ensures models are immutable after creation.
69-104: LGTM!The
from_stringmethod correctly usesModelOnexErrorwithEnumCoreErrorCode.VALIDATION_ERRORfor invalid format handling, following the structured error handling guideline. The regex properly validates semver format including optional prerelease/build suffixes.
123-155: LGTM!The comparison operators correctly return
NotImplementedfor type mismatches, following Python's comparison protocol. The tuple-based comparison ensures proper lexicographic ordering (major > minor > patch).
157-194: LGTM!The bump methods correctly implement semantic versioning semantics:
bump_majorresets minor/patch,bump_minorresets patch, and all return new instances to preserve immutability.
196-234: LGTM!The
is_upgrade_fromandis_downgrade_fromhelper methods provide clear semantic intent by delegating to the comparison operators.
1-20: Well-implemented semantic versioning model.The
ModelContractVersionclass is well-documented with clear docstrings, examples, and references to the specification. The implementation correctly follows Pydantic 2.x patterns with immutability for thread safety.
…OMN-154] - Use ModelOnexError instead of ValueError in validate_progression() - Remove unused import (typing.Any) - Add @pytest.mark.unit markers to all test classes - Make prerelease/build metadata tests explicit (remove try/except pass) - Update tests to use ModelOnexError instead of generic Exception
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (5)
src/omnibase_core/models/contracts/model_contract_version.py (1)
105-122: Harden from_tuple against invalid tuple shapes
from_tupleblindly indexesversion_tuple[0..2]. For tuples of incorrect length, this will surface as a genericIndexErrorrather than a domain-specific validation error.Consider validating the length (and optionally the element types) and raising a
ModelOnexErrorwith an appropriateEnumCoreErrorCode(e.g.,VALIDATION_ERRORor a contract-specific code) when the tuple is not exactly three integers. This keeps error handling consistent withfrom_stringand the rest of the model.tests/unit/models/contracts/test_model_contract_version.py (4)
119-133: Tighten exception expectations to avoid masking regressionsSeveral tests use broad exception tuples, e.g.:
- Lines 121–123:
with pytest.raises((ValidationError, Exception))- Lines 126–127, 131–132: similar patterns
- Lines 136–137, 141–142, 146–147, 151–152, 156–157
- Lines 485–487, 491–492, 497–498
Given we standardize on Pydantic 2.x and strict models, these cases should deterministically raise
ValidationErrororTypeError(for type mismatches or frozen-field assignments). Including bareExceptionmakes it easier for unrelated bugs to pass silently.I’d suggest narrowing these to the concrete expected exceptions, e.g.:
- Negative/invalid field values:
pytest.raises(ValidationError)- Type mismatches/frozen assignments:
pytest.raises((ValidationError, TypeError))if you need to cover bothThis keeps the tests strict while still robust to minor internal changes in Pydantic’s error type mix.
Also applies to: 134-158, 482-499
34-37: Add timeout markers per test module or class to match testing guidelinesPer the project testing guidelines, tests should use
@pytest.mark.timeout()to guard against hangs, alongside running with--timeout=60. Currently, the test classes are marked only with@pytest.mark.unit.Consider adding a reasonable timeout marker at the class or module level, e.g.:
@pytest.mark.unit @pytest.mark.timeout(5) class TestModelContractVersionBasicConstruction: ...or a module-level
pytestmark = pytest.mark.timeout(5)near the top. This aligns the suite with the recommended timeout safeguards. As per coding guidelines.Also applies to: 399-402, 462-465, 578-581, 629-643, 676-679
28-32: Prefer importing from the public contracts package APIThe tests currently import:
from omnibase_core.models.contracts.model_contract_version import ( ModelContractVersion, )Since the PR exposes
ModelContractVersionvia theomnibase_core.models.contractspackage__init__, consider switching to:from omnibase_core.models.contracts import ModelContractVersionThis exercises the intended public API surface and will catch any future regressions in the package export configuration.
710-711: Remove direct pytest.main invocation in test moduleThe
if __name__ == "__main__": pytest.main([__file__, "-v"])block is unnecessary in a pytest-managed suite and diverges from the documented workflow (poetry run pytest tests/ ...). Keeping this can create confusion about the supported way to run tests and is not typically used in pytest test modules.I recommend removing this block and relying solely on the standard pytest entrypoint.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/omnibase_core/models/contracts/model_contract_version.py(1 hunks)tests/unit/models/contracts/test_model_contract_version.py(1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Always use Poetry for Python package management and task execution. Usepoetry runfor pytest, mypy, black, isort, and other tools. Never use pip directly or execute python commands without the poetry run prefix.
Enforce 100% strict mypy compliance. All functions must have complete type annotations. Usepoetry run mypy src/omnibase_core/to verify strict mode compliance with no errors.
Format code with black, sort imports with isort, and lint with ruff. Runpoetry run black src/ tests/,poetry run isort src/ tests/, andpoetry run ruff check --fix src/ tests/
Files:
tests/unit/models/contracts/test_model_contract_version.pysrc/omnibase_core/models/contracts/model_contract_version.py
tests/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
tests/**/*.py: Write tests using pytest with async support via pytest-asyncio. Maintain minimum 60% code coverage. Use pytest markers: @pytest.mark.unit, @pytest.mark.integration, @pytest.mark.slow
Add @pytest.mark.timeout() to prevent test hangs. Run tests withpoetry run pytest tests/ --timeout=60for 60-second timeout protection.
Files:
tests/unit/models/contracts/test_model_contract_version.py
src/omnibase_core/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
src/omnibase_core/**/*.py: Use protocol names withcontainer.get_service()for dependency injection, never resolve services by concrete class names. Example:container.get_service('ProtocolEventBus')instead ofcontainer.get_service('EventBusService')
Always use ModelONEXContainer for dependency injection in node constructors and service resolution. Never confuse it with ModelContainer[T], which is a generic value wrapper, not a DI container.
Use structured error handling with ModelOnexError and EnumCoreErrorCode, never raise generic Exception. Always chain exceptions withfrom ewhen catching and re-raising.
Use the @standard_error_handling decorator on methods to eliminate 6+ lines of try/catch boilerplate. Example:@standard_error_handlingabove async methods.
Respect thread safety constraints: Do NOT share node instances (NodeCompute, NodeEffect), cache, or circuit breaker instances across threads without synchronization. Use thread-local instances or locks.
Use duck typing with protocols. Do not use isinstance checks with protocol types. Rely on the protocol interface directly.
Use EnumNodeKind for high-level architectural classification (EFFECT, COMPUTE, REDUCER, ORCHESTRATOR) when routing data through the ONEX pipeline. Use EnumNodeType for specific implementation discovery and capability matching.
Use ModelEventEnvelope for inter-service event-driven communication. Process events through the envelope pattern for consistent event handling.
Files:
src/omnibase_core/models/contracts/model_contract_version.py
src/omnibase_core/models/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Use Pydantic 2.11+ models for all data validation and serialization. Ensure models are immutable after creation for thread safety.
Files:
src/omnibase_core/models/contracts/model_contract_version.py
🧠 Learnings (1)
📚 Learning: 2025-12-06T23:34:11.788Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T23:34:11.788Z
Learning: Applies to src/omnibase_core/models/**/*.py : Use Pydantic 2.11+ models for all data validation and serialization. Ensure models are immutable after creation for thread safety.
Applied to files:
src/omnibase_core/models/contracts/model_contract_version.py
🧬 Code graph analysis (2)
tests/unit/models/contracts/test_model_contract_version.py (1)
src/omnibase_core/models/contracts/model_contract_version.py (9)
ModelContractVersion(21-269)from_string(69-103)is_upgrade_from(199-217)is_downgrade_from(219-237)bump_major(158-169)bump_minor(171-182)bump_patch(184-197)validate_progression(239-269)to_string(60-62)
src/omnibase_core/models/contracts/model_contract_version.py (1)
src/omnibase_core/enums/enum_core_error_code.py (1)
EnumCoreErrorCode(9-154)
⏰ 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: Smoke Tests
- GitHub Check: claude-review
Pull Request Review: ModelContractVersion ImplementationSummary: This PR implements ModelContractVersion with typed semver fields. The implementation is well-structured and production-ready with excellent test coverage (88.16 percent, 86 tests). STRENGTHS:
AREAS FOR CONSIDERATION:
SECURITY & PERFORMANCE:
TEST COVERAGE: ACCEPTANCE CRITERIA (OMN-154):
FINAL VERDICT: LGTM - Approve with Minor Suggestions This is high-quality, production-ready code. The suggested improvements are non-blocking and can be addressed in follow-up PRs. Review Confidence: 95 percent |
Update deprecated `stages: [commit]` to `stages: [pre-commit]` as recommended by pre-commit 4.x. This ensures ruff format and check hooks run automatically on every commit.
|
Code Review - PR 116: ModelContractVersion Implementation - Overall Assessment: EXCELLENT - This is a high-quality implementation with comprehensive test coverage (86 tests, 88% coverage) and excellent documentation. - Strengths: Architecture & Design (5/5), Error Handling (5/5), Test Coverage (5/5), Documentation (5/5), Code Quality (5/5). - Issues Found: 2 minor documentation inconsistencies in docstrings (lines 83 and 259) - both say ValueError but should say ModelOnexError. - Security & Performance: Excellent (no concerns). - CLAUDE.md Compliance: Full compliance with all requirements. - Final Verdict: APPROVED (recommend fixing 2 minor docstring inconsistencies before merge). Great work! - Reviewed by: Claude Code, Date: 2025-12-07 |
Detailed Code Review AnalysisArchitecture & Design ExcellenceThe implementation demonstrates mastery of Python and Pydantic patterns:
The regex pattern in from_string() correctly enforces no leading zeros per semver 2.0.0 spec and supports optional prerelease/build metadata for forward compatibility. Error Handling: CLAUDE.md CompliantAll error handling follows ONEX Core patterns:
Test Coverage: Comprehensive86 tests organized into 10 test classes:
88.16% coverage exceeds the 60% requirement and approaches the 90% target. Security AnalysisNo security concerns identified:
Performance AnalysisExcellent performance characteristics:
This model will have negligible overhead in production. |
Specific RecommendationsCritical (Must Fix): NoneThe code is production-ready as-is. Minor (Should Fix Before Merge):1. Fix from_string() docstring (model_contract_version.py:83) Current: Raises:
ValueError: If version string format is invalidShould be: Raises:
ModelOnexError: If version string format is invalid2. Fix validate_progression() docstring (model_contract_version.py:259) Current: >>> v1.validate_progression(from_version=v2) # Raises ValueErrorShould be: >>> v1.validate_progression(from_version=v2) # Raises ModelOnexErrorOptional (Nice to Have):
Pre-commit Config ChangesThe changes to .pre-commit-config.yaml are cosmetic improvements:
These are good housekeeping changes with zero risk. |
|
Review Summary - Overall Grade: A+ (Excellent) - What Makes This Code Excellent: (1) Deep ONEX Understanding - follows all CLAUDE.md patterns perfectly, (2) Software Engineering Fundamentals - DRY principle, single responsibility, immutability, (3) Production Readiness - 86 comprehensive tests, security considered, performance optimized, (4) Maintainability - clear structure, excellent docs, follows existing patterns, (5) Attention to Detail - boundary conditions tested, proper Pydantic usage, semver 2.0.0 compliant. - What Needs Fixing: Just 2 minor docstring inconsistencies (ValueError should be ModelOnexError) - documentation-only issues. - CI Expectations: All checks should pass (86 tests, mypy strict 0 errors, 88% coverage). - Bottom Line: Exemplary code that other developers should use as a reference. Approve and merge after fixing 2 docstring issues. Great work! |
…ion issues PR Review Fixes (ModelContractVersion): - Use ModelOnexError instead of ValueError in validate_progression() - Fix docstrings to reference ModelOnexError (not ValueError) - Harden from_tuple() with length validation - Remove unused typing.Any import - Add @pytest.mark.unit markers to all test classes - Add @pytest.mark.timeout(30) to test module - Make prerelease/build metadata tests explicit - Tighten exception expectations (ValidationError not generic Exception) - Import from public API (from omnibase_core.models.contracts import) - Remove pytest.main invocation - Add 6 new tests for from_tuple() validation ONEX Validation Fixes: - Rename types.py -> model_types.py (naming convention) - Rename mixin_node_type_validator.py -> model_mixin_node_type_validator.py - Update validate_structure.py to allow protocols in omnibase_core - Remove empty tests/unit/models/workflow directories [OMN-154]
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
src/omnibase_core/models/contracts/__init__.py (1)
1-7: Consider moving module docstring before imports.The module docstring (lines 3-7) appears after the first import (line 1). Per PEP 257, the module docstring should be the first statement in the module. This is a minor style issue.
+""" +Contract Models + +Models for validating various contract formats and subcontract compositions. +""" + from omnibase_core.models.core.model_workflow import ModelWorkflow -""" -Contract Models - -Models for validating various contract formats and subcontract compositions. -""" - from omnibase_core.models.discovery.model_event_descriptor import ModelEventDescriptortests/unit/models/contracts/test_model_contract_version.py (1)
32-34: Consider adding@pytest.mark.timeoutto all test classes for consistency.Only
TestModelContractVersionBasicConstructionhas the@pytest.mark.timeout(30)decorator. Per coding guidelines, tests should have timeout markers to prevent hangs. Consider adding timeout markers to the remaining test classes for consistency.src/omnibase_core/models/contracts/model_contract_version.py (1)
269-277: Consider usingCONTRACT_VALIDATION_ERRORfor better error specificity.The current implementation uses
EnumCoreErrorCode.VALIDATION_ERROR. Since this specifically validates contract version progression, usingEnumCoreErrorCode.CONTRACT_VALIDATION_ERRORwould make it easier to distinguish contract-version failures from other validation errors, improving observability and error triage.if self.is_downgrade_from(from_version) and not allow_downgrade: raise ModelOnexError( - error_code=EnumCoreErrorCode.VALIDATION_ERROR, + error_code=EnumCoreErrorCode.CONTRACT_VALIDATION_ERROR, message=( f"Version downgrade detected: {from_version} -> {self}. " f"Downgrades are not allowed without explicit allow_downgrade=True. " f"See CONTRACT_STABILITY_SPEC.md for versioning rules." ), )
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
scripts/validation/validate_structure.py(1 hunks)src/omnibase_core/models/contracts/__init__.py(2 hunks)src/omnibase_core/models/contracts/model_contract_compute.py(1 hunks)src/omnibase_core/models/contracts/model_contract_effect.py(1 hunks)src/omnibase_core/models/contracts/model_contract_orchestrator.py(1 hunks)src/omnibase_core/models/contracts/model_contract_reducer.py(1 hunks)src/omnibase_core/models/contracts/model_contract_version.py(1 hunks)src/omnibase_core/models/contracts/subcontracts/model_compute_pipeline_step.py(1 hunks)src/omnibase_core/models/transformations/__init__.py(1 hunks)src/omnibase_core/utils/compute_transformations.py(1 hunks)tests/unit/models/contracts/test_model_contract_version.py(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- src/omnibase_core/models/contracts/model_contract_orchestrator.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. Usepoetry runfor pytest, mypy, black, isort, and other tools. Never use pip directly or execute python commands without the poetry run prefix.
Enforce 100% strict mypy compliance. All functions must have complete type annotations. Usepoetry run mypy src/omnibase_core/to verify strict mode compliance with no errors.
Format code with black, sort imports with isort, and lint with ruff. Runpoetry run black src/ tests/,poetry run isort src/ tests/, andpoetry run ruff check --fix src/ tests/
Files:
src/omnibase_core/models/contracts/model_contract_reducer.pysrc/omnibase_core/models/contracts/model_contract_compute.pysrc/omnibase_core/models/transformations/__init__.pysrc/omnibase_core/models/contracts/model_contract_effect.pyscripts/validation/validate_structure.pysrc/omnibase_core/models/contracts/model_contract_version.pysrc/omnibase_core/models/contracts/__init__.pysrc/omnibase_core/utils/compute_transformations.pysrc/omnibase_core/models/contracts/subcontracts/model_compute_pipeline_step.pytests/unit/models/contracts/test_model_contract_version.py
src/omnibase_core/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
src/omnibase_core/**/*.py: Use protocol names withcontainer.get_service()for dependency injection, never resolve services by concrete class names. Example:container.get_service('ProtocolEventBus')instead ofcontainer.get_service('EventBusService')
Always use ModelONEXContainer for dependency injection in node constructors and service resolution. Never confuse it with ModelContainer[T], which is a generic value wrapper, not a DI container.
Use structured error handling with ModelOnexError and EnumCoreErrorCode, never raise generic Exception. Always chain exceptions withfrom ewhen catching and re-raising.
Use the @standard_error_handling decorator on methods to eliminate 6+ lines of try/catch boilerplate. Example:@standard_error_handlingabove async methods.
Respect thread safety constraints: Do NOT share node instances (NodeCompute, NodeEffect), cache, or circuit breaker instances across threads without synchronization. Use thread-local instances or locks.
Use duck typing with protocols. Do not use isinstance checks with protocol types. Rely on the protocol interface directly.
Use EnumNodeKind for high-level architectural classification (EFFECT, COMPUTE, REDUCER, ORCHESTRATOR) when routing data through the ONEX pipeline. Use EnumNodeType for specific implementation discovery and capability matching.
Use ModelEventEnvelope for inter-service event-driven communication. Process events through the envelope pattern for consistent event handling.
Files:
src/omnibase_core/models/contracts/model_contract_reducer.pysrc/omnibase_core/models/contracts/model_contract_compute.pysrc/omnibase_core/models/transformations/__init__.pysrc/omnibase_core/models/contracts/model_contract_effect.pysrc/omnibase_core/models/contracts/model_contract_version.pysrc/omnibase_core/models/contracts/__init__.pysrc/omnibase_core/utils/compute_transformations.pysrc/omnibase_core/models/contracts/subcontracts/model_compute_pipeline_step.py
src/omnibase_core/models/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Use Pydantic 2.11+ models for all data validation and serialization. Ensure models are immutable after creation for thread safety.
Files:
src/omnibase_core/models/contracts/model_contract_reducer.pysrc/omnibase_core/models/contracts/model_contract_compute.pysrc/omnibase_core/models/transformations/__init__.pysrc/omnibase_core/models/contracts/model_contract_effect.pysrc/omnibase_core/models/contracts/model_contract_version.pysrc/omnibase_core/models/contracts/__init__.pysrc/omnibase_core/models/contracts/subcontracts/model_compute_pipeline_step.py
tests/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
tests/**/*.py: Write tests using pytest with async support via pytest-asyncio. Maintain minimum 60% code coverage. Use pytest markers: @pytest.mark.unit, @pytest.mark.integration, @pytest.mark.slow
Add @pytest.mark.timeout() to prevent test hangs. Run tests withpoetry run pytest tests/ --timeout=60for 60-second timeout protection.
Files:
tests/unit/models/contracts/test_model_contract_version.py
🧠 Learnings (8)
📚 Learning: 2025-12-06T23:34:11.788Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T23:34:11.788Z
Learning: Applies to src/omnibase_core/nodes/node_reducer.py : NodeReducer is for FSM-driven state aggregation and management. Use ModelIntent for state transitions. This is the PRIMARY implementation as of v0.4.0 (replaces NodeReducerDeclarative).
Applied to files:
src/omnibase_core/models/contracts/model_contract_reducer.py
📚 Learning: 2025-12-06T23:34:11.788Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T23:34:11.788Z
Learning: Applies to src/omnibase_core/**/*.py : Use structured error handling with ModelOnexError and EnumCoreErrorCode, never raise generic Exception. Always chain exceptions with `from e` when catching and re-raising.
Applied to files:
src/omnibase_core/models/contracts/model_contract_reducer.pysrc/omnibase_core/models/contracts/model_contract_compute.pysrc/omnibase_core/models/contracts/model_contract_effect.pysrc/omnibase_core/models/contracts/model_contract_version.py
📚 Learning: 2025-12-06T23:34:11.788Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T23:34:11.788Z
Learning: Applies to src/omnibase_core/mixins/**/*.py : Mixin classes should be composed into node classes for specific capabilities. Available mixins include: MixinDiscoveryResponder, MixinEventHandler, MixinEventListener, MixinNodeExecutor, MixinNodeLifecycle, MixinRequestResponseIntrospection, MixinWorkflowSupport.
Applied to files:
src/omnibase_core/models/contracts/model_contract_reducer.pysrc/omnibase_core/models/contracts/model_contract_compute.pysrc/omnibase_core/models/contracts/model_contract_effect.pysrc/omnibase_core/models/contracts/__init__.py
📚 Learning: 2025-12-06T23:34:11.788Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T23:34:11.788Z
Learning: Applies to src/omnibase_core/**/*.py : Use EnumNodeKind for high-level architectural classification (EFFECT, COMPUTE, REDUCER, ORCHESTRATOR) when routing data through the ONEX pipeline. Use EnumNodeType for specific implementation discovery and capability matching.
Applied to files:
src/omnibase_core/models/contracts/model_contract_reducer.pysrc/omnibase_core/models/contracts/model_contract_compute.pysrc/omnibase_core/models/contracts/model_contract_effect.py
📚 Learning: 2025-12-06T23:34:11.788Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T23:34:11.788Z
Learning: Applies to src/omnibase_core/**/*.py : Use duck typing with protocols. Do not use isinstance checks with protocol types. Rely on the protocol interface directly.
Applied to files:
scripts/validation/validate_structure.py
📚 Learning: 2025-12-06T23:34:11.788Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T23:34:11.788Z
Learning: Applies to src/omnibase_core/models/**/*.py : Use Pydantic 2.11+ models for all data validation and serialization. Ensure models are immutable after creation for thread safety.
Applied to files:
src/omnibase_core/models/contracts/model_contract_version.py
📚 Learning: 2025-12-06T23:34:11.788Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T23:34:11.788Z
Learning: Applies to src/omnibase_core/**/*.py : Use ModelEventEnvelope for inter-service event-driven communication. Process events through the envelope pattern for consistent event handling.
Applied to files:
src/omnibase_core/models/contracts/__init__.py
📚 Learning: 2025-12-06T23:34:11.788Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T23:34:11.788Z
Learning: Applies to src/omnibase_core/**/*.py : Always use ModelONEXContainer for dependency injection in node constructors and service resolution. Never confuse it with ModelContainer[T], which is a generic value wrapper, not a DI container.
Applied to files:
src/omnibase_core/models/contracts/__init__.py
🧬 Code graph analysis (2)
src/omnibase_core/models/contracts/model_contract_version.py (1)
src/omnibase_core/enums/enum_core_error_code.py (1)
EnumCoreErrorCode(9-154)
tests/unit/models/contracts/test_model_contract_version.py (1)
src/omnibase_core/models/contracts/model_contract_version.py (10)
ModelContractVersion(21-277)from_string(69-103)is_upgrade_from(207-225)is_downgrade_from(227-245)bump_major(166-177)bump_minor(179-190)bump_patch(192-205)validate_progression(247-277)to_string(60-62)from_tuple(106-130)
⏰ 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: Smoke Tests
- GitHub Check: claude-review
🔇 Additional comments (15)
src/omnibase_core/models/contracts/model_contract_effect.py (1)
38-40: LGTM!The import path update from
mixin_node_type_validatortomodel_mixin_node_type_validatorcorrectly follows the project'smodel_prefix naming convention for files in the models directory.src/omnibase_core/models/contracts/model_contract_compute.py (1)
29-31: LGTM!Consistent import path update matching the refactoring in other contract modules.
src/omnibase_core/utils/compute_transformations.py (1)
74-74: LGTM!Import path updated to use
model_typesmodule, consistent with the broader refactoring to follow themodel_prefix naming convention for type definition files.src/omnibase_core/models/contracts/subcontracts/model_compute_pipeline_step.py (1)
78-78: LGTM!Import path updated consistently with other modules in this PR.
src/omnibase_core/models/transformations/__init__.py (1)
29-29: LGTM!The import path change from
.typesto.model_typesforModelTransformationConfigaligns with the broader refactoring pattern in this PR to relocate imports to dedicatedmodel_*modules. The public API remains unchanged.src/omnibase_core/models/contracts/model_contract_reducer.py (1)
39-41: LGTM!The import path change for
MixinNodeTypeValidatorfrom.mixin_node_type_validatorto.model_mixin_node_type_validatoris consistent with the broader refactoring pattern across contract model files in this PR.src/omnibase_core/models/contracts/__init__.py (2)
10-17: LGTM!The new
ModelContractVersionimport and the updatedMixinNodeTypeValidatorimport path are correctly added, makingModelContractVersionpublicly importable fromomnibase_core.models.contracts.
61-61: LGTM!
ModelContractVersionis appropriately placed under "Foundation models" in__all__, reflecting its role as a core versioning primitive for contracts.tests/unit/models/contracts/test_model_contract_version.py (3)
28-29: Good use of public API import path.Importing
ModelContractVersionfromomnibase_core.models.contracts(the package) rather than the direct module path validates that the__init__.pyexports are correctly configured.
509-516: LGTM!The tests correctly verify that comparisons with non-
ModelContractVersiontypes returnFalse(viaNotImplemented), covering strings, integers, andNone. This validates the__eq__implementation's type checking.
719-750: LGTM!Excellent coverage of semver prerelease (
-alpha,-beta.1) and build metadata (+build,+build.456) parsing. These tests validate thatfrom_string()correctly extracts the baseX.Y.Zversion while ignoring optional suffixes.src/omnibase_core/models/contracts/model_contract_version.py (4)
41-50: LGTM!The model configuration follows Pydantic best practices with
frozen=Truefor immutability (per coding guidelines for thread safety),extra="forbid"for strict validation, andstrict=Trueto prevent type coercion. Thege=0constraint on all fields ensures non-negative version components.
89-103: LGTM!The regex pattern correctly implements semver parsing rules:
- Disallows leading zeros (e.g., rejects
01.02.03)- Allows optional prerelease (
-alpha) and build metadata (+build) suffixes- Properly extracts the numeric components while ignoring extensions
132-164: LGTM!The comparison operators are correctly implemented:
- Using
to_tuple()provides correct lexicographic ordering (major > minor > patch)- Returning
NotImplementedfor type mismatches allows Python to handle comparison fallback correctly__hash__is consistent with__eq__(equal objects have equal hashes)
166-205: LGTM!The bump methods correctly implement semver semantics:
bump_major(): increments major, resets minor and patch to 0bump_minor(): increments minor, resets patch to 0bump_patch(): increments only patchAll methods return new instances, preserving immutability of the frozen model.
| # Protocol directories are allowed in: | ||
| # - omnibase_spi: Higher-level protocol abstractions | ||
| # - omnibase_core: Core-native protocols for self-contained operation (v0.3.6+) | ||
| # See CLAUDE.md: "dependency inversion - SPI now depends on Core, not vice versa" | ||
| PROTOCOL_ALLOWED_REPOS = {"omnibase_spi", "omnibase_core"} | ||
|
|
||
| if self.repo_name not in PROTOCOL_ALLOWED_REPOS and protocols_path.exists(): | ||
| self.violations.append( | ||
| StructureViolation( | ||
| level=ViolationLevel.ERROR, | ||
| category="Protocol Location", | ||
| message="Only omnibase_spi should contain protocols directory", | ||
| message="Only omnibase_spi and omnibase_core should contain protocols directory", | ||
| path=f"src/{self.repo_name}/protocols/", | ||
| suggestion="Remove local protocols, import from omnibase_spi instead", | ||
| suggestion="Remove local protocols, import from omnibase_spi or omnibase_core instead", | ||
| ) | ||
| ) | ||
|
|
||
| # Count protocol files in non-SPI repositories | ||
| if self.repo_name != "omnibase_spi": | ||
| # Count protocol files in repositories that don't have explicit protocol allowance | ||
| if self.repo_name not in PROTOCOL_ALLOWED_REPOS: |
There was a problem hiding this comment.
Logical inconsistency: omnibase_core special handling at line 406 is now dead code.
Since omnibase_core is now in PROTOCOL_ALLOWED_REPOS (line 368), the protocol counting block (lines 382-417) is entirely skipped for omnibase_core. This makes the special case at line 406 (max_protocols = 7 if self.repo_name == "omnibase_core" else 3) unreachable.
If this is intentional (protocol counting should not apply to allowed repos), consider removing the dead code for clarity. If protocol counting should still apply to omnibase_core, the condition needs adjustment.
- # Count protocol files in repositories that don't have explicit protocol allowance
- if self.repo_name not in PROTOCOL_ALLOWED_REPOS:
+ # Count protocol files in repositories that don't have explicit protocol allowance
+ # Note: omnibase_core has a temporary allowance for up to 7 protocols during migration
+ if self.repo_name not in PROTOCOL_ALLOWED_REPOS or self.repo_name == "omnibase_core":Alternatively, if protocol counting should be completely disabled for allowed repos, remove lines 396-417 (the omnibase_core special case comment and handling).
- Fix import sorting in contract models (I001 violations): - model_contract_compute.py - model_contract_effect.py - model_contract_orchestrator.py - model_contract_reducer.py - subcontracts/model_compute_pipeline_step.py - Fix import order in __init__.py files: - models/contracts/__init__.py - models/transformations/__init__.py - Update test_protocol_location_validation_non_spi test: - Test was outdated - expected omnibase_core to NOT have protocols - v0.3.6+ allows both omnibase_spi AND omnibase_core to have protocols - Changed test to use 'omnibase_other' as the non-allowed repo - Added test_protocol_location_validation_core_repo to verify core is allowed - Update pre-commit config to use modern stage names (pre-commit 4.x)
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (3)
src/omnibase_core/models/contracts/subcontracts/model_compute_pipeline_step.py (1)
72-78: Import path update forModelTransformationConfiglooks goodSwitching to
omnibase_core.models.transformations.model_typeskeeps the type usage intact and matches the new module layout. SinceModelTransformationConfigis also re-exported from thetransformationspackage, you could optionally import viafrom omnibase_core.models.transformations import ModelTransformationConfigto decouple this contract from the internal module structure, but the current import is perfectly valid if you prefer explicit module paths.tests/unit/validation/test_validate_structure.py (2)
180-200: Test logic correctly validates the updated protocol location rules.The test properly creates a non-whitelisted repository and verifies that a violation is raised. The updated docstring clearly explains the v0.3.6+ behavior change.
Optional: Consider verifying both allowed repositories in the message.
The assertion at line 199 only checks for "omnibase_spi" in the violation message. Since the validation logic references both
omnibase_spiandomnibase_coreas allowed repositories, you could make the assertion more comprehensive:- assert "omnibase_spi" in protocol_violations[0].message + assert "omnibase_spi" in protocol_violations[0].message + assert "omnibase_core" in protocol_violations[0].message
66-227: Consider adding pytest markers per coding guidelines.As per coding guidelines, unit tests should include
@pytest.mark.unitdecorators and@pytest.mark.timeout()for hang prevention. This helps with test categorization and adds timeout protection.Example for the modified tests:
@pytest.mark.unit @pytest.mark.timeout(60) def test_protocol_location_validation_non_spi(self, temp_repo): """Test that non-SPI/non-core repositories shouldn't have protocols directory. ... """@pytest.mark.unit @pytest.mark.timeout(60) def test_protocol_location_validation_core_repo(self, temp_repo): """Test that omnibase_core repository is allowed to have protocols (v0.3.6+)."""This pattern should be applied to all test methods in the file.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
.pre-commit-config.yaml(4 hunks)src/omnibase_core/models/contracts/__init__.py(4 hunks)src/omnibase_core/models/contracts/model_contract_compute.py(1 hunks)src/omnibase_core/models/contracts/model_contract_effect.py(1 hunks)src/omnibase_core/models/contracts/model_contract_orchestrator.py(1 hunks)src/omnibase_core/models/contracts/model_contract_reducer.py(1 hunks)src/omnibase_core/models/contracts/subcontracts/model_compute_pipeline_step.py(1 hunks)src/omnibase_core/models/transformations/__init__.py(1 hunks)tests/unit/validation/test_validate_structure.py(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
- .pre-commit-config.yaml
- src/omnibase_core/models/contracts/init.py
- src/omnibase_core/models/contracts/model_contract_reducer.py
- src/omnibase_core/models/contracts/model_contract_effect.py
- src/omnibase_core/models/contracts/model_contract_compute.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. Usepoetry runfor pytest, mypy, black, isort, and other tools. Never use pip directly or execute python commands without the poetry run prefix.
Enforce 100% strict mypy compliance. All functions must have complete type annotations. Usepoetry run mypy src/omnibase_core/to verify strict mode compliance with no errors.
Format code with black, sort imports with isort, and lint with ruff. Runpoetry run black src/ tests/,poetry run isort src/ tests/, andpoetry run ruff check --fix src/ tests/
Files:
src/omnibase_core/models/contracts/subcontracts/model_compute_pipeline_step.pytests/unit/validation/test_validate_structure.pysrc/omnibase_core/models/contracts/model_contract_orchestrator.pysrc/omnibase_core/models/transformations/__init__.py
src/omnibase_core/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
src/omnibase_core/**/*.py: Use protocol names withcontainer.get_service()for dependency injection, never resolve services by concrete class names. Example:container.get_service('ProtocolEventBus')instead ofcontainer.get_service('EventBusService')
Always use ModelONEXContainer for dependency injection in node constructors and service resolution. Never confuse it with ModelContainer[T], which is a generic value wrapper, not a DI container.
Use structured error handling with ModelOnexError and EnumCoreErrorCode, never raise generic Exception. Always chain exceptions withfrom ewhen catching and re-raising.
Use the @standard_error_handling decorator on methods to eliminate 6+ lines of try/catch boilerplate. Example:@standard_error_handlingabove async methods.
Respect thread safety constraints: Do NOT share node instances (NodeCompute, NodeEffect), cache, or circuit breaker instances across threads without synchronization. Use thread-local instances or locks.
Use duck typing with protocols. Do not use isinstance checks with protocol types. Rely on the protocol interface directly.
Use EnumNodeKind for high-level architectural classification (EFFECT, COMPUTE, REDUCER, ORCHESTRATOR) when routing data through the ONEX pipeline. Use EnumNodeType for specific implementation discovery and capability matching.
Use ModelEventEnvelope for inter-service event-driven communication. Process events through the envelope pattern for consistent event handling.
Files:
src/omnibase_core/models/contracts/subcontracts/model_compute_pipeline_step.pysrc/omnibase_core/models/contracts/model_contract_orchestrator.pysrc/omnibase_core/models/transformations/__init__.py
src/omnibase_core/models/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Use Pydantic 2.11+ models for all data validation and serialization. Ensure models are immutable after creation for thread safety.
Files:
src/omnibase_core/models/contracts/subcontracts/model_compute_pipeline_step.pysrc/omnibase_core/models/contracts/model_contract_orchestrator.pysrc/omnibase_core/models/transformations/__init__.py
tests/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
tests/**/*.py: Write tests using pytest with async support via pytest-asyncio. Maintain minimum 60% code coverage. Use pytest markers: @pytest.mark.unit, @pytest.mark.integration, @pytest.mark.slow
Add @pytest.mark.timeout() to prevent test hangs. Run tests withpoetry run pytest tests/ --timeout=60for 60-second timeout protection.
Files:
tests/unit/validation/test_validate_structure.py
🧠 Learnings (5)
📚 Learning: 2025-12-06T23:34:11.788Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T23:34:11.788Z
Learning: Applies to src/omnibase_core/mixins/**/*.py : Mixin classes should be composed into node classes for specific capabilities. Available mixins include: MixinDiscoveryResponder, MixinEventHandler, MixinEventListener, MixinNodeExecutor, MixinNodeLifecycle, MixinRequestResponseIntrospection, MixinWorkflowSupport.
Applied to files:
src/omnibase_core/models/contracts/model_contract_orchestrator.py
📚 Learning: 2025-12-06T23:34:11.788Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T23:34:11.788Z
Learning: Applies to src/omnibase_core/**/*.py : Use EnumNodeKind for high-level architectural classification (EFFECT, COMPUTE, REDUCER, ORCHESTRATOR) when routing data through the ONEX pipeline. Use EnumNodeType for specific implementation discovery and capability matching.
Applied to files:
src/omnibase_core/models/contracts/model_contract_orchestrator.py
📚 Learning: 2025-12-06T23:34:11.788Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T23:34:11.788Z
Learning: Applies to src/omnibase_core/**/*.py : Use structured error handling with ModelOnexError and EnumCoreErrorCode, never raise generic Exception. Always chain exceptions with `from e` when catching and re-raising.
Applied to files:
src/omnibase_core/models/contracts/model_contract_orchestrator.py
📚 Learning: 2025-12-06T23:34:11.788Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T23:34:11.788Z
Learning: Applies to src/omnibase_core/**/*.py : Always use ModelONEXContainer for dependency injection in node constructors and service resolution. Never confuse it with ModelContainer[T], which is a generic value wrapper, not a DI container.
Applied to files:
src/omnibase_core/models/contracts/model_contract_orchestrator.py
📚 Learning: 2025-12-06T23:34:11.788Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T23:34:11.788Z
Learning: Applies to src/omnibase_core/**/*.py : Use ModelEventEnvelope for inter-service event-driven communication. Process events through the envelope pattern for consistent event handling.
Applied to files:
src/omnibase_core/models/contracts/model_contract_orchestrator.py
🧬 Code graph analysis (1)
tests/unit/validation/test_validate_structure.py (1)
scripts/validation/validate_structure.py (1)
OmniStructureValidator(43-542)
⏰ 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: claude-review
- GitHub Check: Smoke Tests
🔇 Additional comments (3)
src/omnibase_core/models/contracts/model_contract_orchestrator.py (1)
42-44: Import relocation forMixinNodeTypeValidatorlooks correctThe updated import path matches the new module name while preserving the same mixin symbol, and remains consistent with how
_DEFAULT_NODE_TYPEis used in this model. No further changes needed here.src/omnibase_core/models/transformations/__init__.py (1)
22-40: Public re‑export ofModelTransformationConfigis consistent and usefulImporting
ModelTransformationConfigfrom.model_typesand adding it to__all__cleanly exposes the discriminated union via the package API, matching the docstring and allowing callers to depend on a stableomnibase_core.models.transformationsimport surface. No further changes needed here.tests/unit/validation/test_validate_structure.py (1)
201-212: LGTM! New test correctly validates omnibase_core protocol allowance.The test properly verifies that
omnibase_coreis whitelisted and can contain a protocols directory without triggering violations, matching the v0.3.6+ behavior described in the PR objectives.
PR Review: ModelContractVersion ImplementationThis PR implements ModelContractVersion with typed semver fields. The implementation is well-structured and follows ONEX best practices with 88% test coverage. Strengths
Recommendations
Security & Performance
Final VerdictAPPROVE with minor recommendations This is a high-quality PR demonstrating excellent software engineering. The implementation is robust and well-tested. The recommendations above are nice-to-have improvements, not blockers. Great work! |
Move mixin from models/contracts/ to mixins/ directory per ONEX architecture principles: - Mixins belong in src/omnibase_core/mixins/ - Models belong in src/omnibase_core/models/ Changes: - Move model_mixin_node_type_validator.py → mixin_node_type_validator.py - Update imports in all contract models - Export from mixins/__init__.py - Maintain re-export from contracts/__init__.py for compatibility
Code Review - PR #116: ModelContractVersion ImplementationI have thoroughly reviewed this pull request implementing ModelContractVersion with typed semver fields. ✅ Strengths1. Excellent Code Quality
2. Comprehensive Testing (750 lines!)
3. Strong Design Patterns
🔍 Issues and Recommendations1. CRITICAL: Pre-commit Configuration Change 2. Documentation: from_string() Prerelease Behavior 3. Optional Performance Optimization 📊 Test Coverage: 88.16% (exceeds 60% requirement) ✅🔧 Refactoring ChangesGood: Mixin Relocation - Moving MixinNodeTypeValidator to mixins/ is correct. ✅ Final VerdictAPPROVED with minor recommendations This is high-quality work with excellent implementation, comprehensive testing, and strong adherence to project conventions. Suggested next steps:
Great work! The implementation is solid and well-tested. Reviewed by: Claude Code (Sonnet 4.5) |
Summary
Implements
ModelContractVersionwith typed semver fields per CONTRACT_STABILITY_SPEC.md requirements.ModelContractVersionPydantic model withmajor,minor,patchint fields__eq__,__lt__,__le__,__gt__,__ge__)bump_major,bump_minor,bump_patch)validate_progression(allow_downgrade=False)from_string()andfrom_tuple()frozen=True,extra="forbid",strict=Trueomnibase_core.models.contractsTest plan
ModelSemVerpatternsAcceptance Criteria (OMN-154)
ModelContractVersioncreated with typed semver fields (major,minor,patch)ALLOW_DOWNGRADE=true(future work)Closes OMN-154
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.