Skip to content

feat(context): add ApplicationContext for thread-safe container management - #92

Merged
jonahgabriel merged 6 commits into
mainfrom
feature/pytest-xdist-scope-optimization
Nov 27, 2025
Merged

jonahgabriel merged 6 commits into
mainfrom
feature/pytest-xdist-scope-optimization

Conversation

@jonahgabriel

@jonahgabriel jonahgabriel commented Nov 27, 2025 •

Copy link
Copy Markdown
Contributor

Summary

  • Introduces contextvars-based container management (ApplicationContext) to replace the legacy singleton holder pattern
  • Provides proper isolation between async tasks and threads during parallel test execution with pytest-xdist
  • Adds isolation fixtures (reset_all_singletons, reset_container_singleton) for test isolation

Key Changes

  • New src/omnibase_core/context/ module: Thread-safe container management using Python's contextvars
  • Migration from global singletons: Replaced util_container_holder.py with ApplicationContext
  • Updated registries: model_action_registry.py, model_cli_command_registry.py, model_event_type_registry.py use lru_cache patterns
  • Test isolation fixtures: New tests/fixtures/isolation.py with comprehensive test isolation support
  • Updated conftest.py: Improved cleanup and isolation for parallel test execution

Why This Matters

The previous singleton holder pattern caused test isolation issues in parallel execution (pytest-xdist). Each parallel worker could interfere with others through shared global state. The new contextvars-based approach ensures:

  • Each thread has its own copy of context variables
  • Async tasks inherit context at creation time
  • Modifications in one task/thread don't affect others

Test Plan

  • All pre-commit hooks pass (mypy, ruff, black, isort, ONEX validations)
  • Unit tests pass (poetry run pytest tests/unit/)
  • Integration tests pass
  • CI pipeline passes with parallel test execution

Summary by CodeRabbit

Release Notes

  • New Features

    • Context-based container management with thread-safe and async-safe operations
    • Logger caching with optional TTL-based protocol services lookup
  • Bug Fixes

    • Improved test resilience with automatic retry (2 reruns, 1-second delay) for flaky tests
  • Refactor

    • Reorganized service wrapper modules to new models.service structure
    • Transitioned container management from global singleton to context-based approach
    • Updated test distribution strategy from loadscope to loadgroup for finer control
  • Chores

    • Updated import paths across documentation
    • Removed legacy migration and analysis scripts
    • Updated CI validation script paths

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

…ement

Introduces contextvars-based container management to replace the legacy
singleton holder pattern. This provides proper isolation between async
tasks and threads during parallel test execution with pytest-xdist.

Key changes:
- Add ApplicationContext class with sync/async context managers
- Add isolation fixtures for parallel-safe test execution
- Migrate registries and caches to use lru_cache patterns
- Remove util_container_holder.py (replaced by contextvars)
- Update conftest.py with improved cleanup and isolation
@coderabbitai

coderabbitai Bot commented Nov 27, 2025 •

Copy link
Copy Markdown
Contributor

Walkthrough

Introduces context-based container management replacing global singleton access, adds logger caching with TTL-based protocol service lookups, reorganizes service wrapper import paths from node_services to service module, removes ~80 legacy migration and analysis scripts, updates pytest to use loadgroup distribution with test retry logic, and cleans up events module exports. Documentation and configuration updated accordingly.

Changes

Cohort / File(s) Summary
Context Management - New src/omnibase_core/context/__init__.py, src/omnibase_core/context/application_context.py
Container Refactoring src/omnibase_core/models/container/model_onex_container.py
Logging Improvements src/omnibase_core/logging/core_logging.py, src/omnibase_core/logging/emit.py
Import Path Reorganization src/omnibase_core/infrastructure/infrastructure_bases.py, docs/architecture/*.md, docs/guides/*.md, docs/reference/*.md
Events Module Cleanup src/omnibase_core/events/__init__.py
Test Configuration pyproject.toml, .github/workflows/test.yml, .pre-commit-config.yaml
Documentation Metadata docs/architecture/ECOSYSTEM_DIRECTORY_STRUCTURE.md, docs/architecture/architecture-research/RESEARCH_REPORT_4_NODE_ARCHITECTURE.md, docs/guides/VERSION_FIELD_AUTOMATION_STRATEGY.md, docs/guides/node-building/*.md, docs/reference/SERVICE_WRAPPERS.md, docs/reference/api/nodes.md, docs/guides/INTENT_PUBLISHER_TESTING_DOCUMENTATION.md, docs/testing/CI_TEST_STRATEGY.md, docs/conventions/VERSION_SEMANTICS.md, docs/ci/CI_MONITORING_GUIDE.md
Report and Documentation Artifacts PR88_GROUP_1A_VERIFICATION_REPORT.md, VERIFICATION_REPORT.md, scripts/PROTOCOL_IMPLEMENTATION_REPORT.md, scripts/README_PYDANTIC_FIXERS.md, scripts/TYPE_SAFETY_README.md
Script Removals - Fixers & Analyzers scripts/fix_*.py (~30 files), scripts/analyze_*.py (~5 files), scripts/batch_*.py (~3 files), scripts/comprehensive_*.py (1 file), scripts/migrate_*.py (5 files)
Script Removals - High-Level Tools scripts/add_*.py (2 files), scripts/execute_duplicate_resolution.sh, scripts/generate_all_exports.py, scripts/implement_protocols.py, scripts/intelligence/*.py (2 files), scripts/performance/*.py (3 files), scripts/apply_fixer_to_models.sh, scripts/audit_naming_conventions.py, scripts/auto_fix_type_annotations.py

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Areas requiring extra attention:

  • Context management implementation (src/omnibase_core/context/application_context.py): Verify thread-safety and async-safety of ContextVar usage, token reset semantics, and proper cleanup in edge cases (exceptions during context execution).
  • Container refactoring logic (src/omnibase_core/models/container/model_onex_container.py): Ensure context-based retrieval maintains backward compatibility, verify no race conditions between context checks and container creation, validate sync wrapper behavior when asyncio.run() creates new event loop.
  • Logging cache TTL mechanism (src/omnibase_core/logging/emit.py): Review time-based cache invalidation logic, verify lru_cache(maxsize=1) + TTL state tracking doesn't introduce stale data issues, confirm fallback behavior when protocol services unavailable.
  • Large volume of import path changes: While mechanical, verify all 40+ documentation and code import updates correctly reflect new service module locations, no lingering references to old paths.
  • Script removal scope: Confirm no active pipelines or user workflows depend on removed scripts; verify migration tools are no longer needed (stages marked complete).

Possibly related PRs

  • PR #71: Introduces container-related changes and ModelONEXContainer import/export; directly related to this PR's context-based container management refactoring.
  • PR #80: Large-scale repository reorganization (services, enums, mixins relocation); overlaps with import path reorganizations in this PR.
  • PR #88: Model refactoring with ModelSemVer version field updates; shares model surface modifications with this PR's documentation and cleanup activities.

Poem

🐰 Hop, skip, and context jump!

Containers dance in variables now,
Scripts retire with grateful bow,
Paths reorganized, caches gleam—
A cleaner, swifter, safer dream! ✨

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 clearly summarizes the main change: introducing ApplicationContext for thread-safe container management using contextvars instead of singletons.
Docstring Coverage ✅ Passed Docstring coverage is 89.23% 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 feature/pytest-xdist-scope-optimization

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

@claude

claude Bot commented Nov 27, 2025

Copy link
Copy Markdown

Code Review: ApplicationContext for Thread-Safe Container Management

I've completed a thorough review of this PR following the project's architecture patterns and conventions outlined in CLAUDE.md. Overall, this is excellent architectural work that addresses real test isolation issues with a clean, modern solution.


🎯 Summary

This PR successfully migrates from a legacy singleton holder pattern to contextvars-based container management, providing proper isolation for parallel test execution with pytest-xdist. The implementation is well-architected, thoroughly tested, and aligns with Python best practices.

Recommendation: ✅ Approve with minor suggestions


✅ Strengths

1. Excellent Architecture ⭐

  • contextvars is the correct solution for async/thread-safe container isolation
  • Clean separation of concerns: ApplicationContext for containers, lru_cache for other singletons
  • Proper token-based reset pattern enables nested contexts and rollback
  • Both sync and async context managers provided

2. Comprehensive Testing ⭐

  • 391 lines of tests in test_application_context.py
  • Tests cover thread isolation, async task isolation, nested contexts, and edge cases
  • 311 lines of tests for isolation fixtures
  • Good test structure following pytest best practices

3. Documentation ⭐

  • Extensive docstrings with clear examples
  • Good migration notes in deprecated util_singleton_holders.py
  • Proper __all__ exports and module documentation

4. Type Safety ⭐

  • Proper type annotations throughout
  • Uses TYPE_CHECKING to avoid circular imports
  • Token types correctly specified

5. Backward Compatibility

  • Legacy holder keys still accepted in isolation fixtures
  • Graceful fallbacks for missing modules
  • Tests can migrate incrementally

🔍 Issues & Recommendations

🔴 CRITICAL: Missing Test Pre-Conditions

Location: pyproject.toml:306-308

"--reruns=2",  # Auto-retry failed tests twice (handles flaky tests)
"--reruns-delay=1",  # 1 second delay between reruns

Issue: Adding automatic test retries masks real race conditions and flakiness instead of fixing them. If tests are flaky, the root cause should be addressed, not hidden.

Recommendation:

  1. Remove auto-retry from default config - flaky tests should fail loudly
  2. Use retries only for known external dependencies (network, etc.) with explicit markers:
    @pytest.mark.flaky(reruns=2, reruns_delay=1)
    def test_external_api_call():
        pass
  3. Investigate and fix any flaky tests revealed by removing auto-retry

References:

  • Project requires 60%+ coverage with deterministic tests (CLAUDE.md)
  • Pytest best practices: retries hide bugs (pytest-rerunfailures docs)

🟡 MODERATE: Error Handling Inconsistencies

1. Silent Fallback in get_model_onex_container_sync()

Location: src/omnibase_core/models/container/model_onex_container.py:778-779

container = get_current_container()
if container is not None:
    return container

# No container exists - create one
container = asyncio.run(create_model_onex_container())

Issue: Creating a container silently when none exists can hide initialization bugs. This differs from the async version's explicit "get or create" semantics.

Recommendation: Add logging or make the creation explicit:

from omnibase_core.logging import core_logging

container = get_current_container()
if container is not None:
    return container

# No container exists - create and log for debugging
core_logging.debug(
    "No container in current context - creating new instance",
    correlation_id=core_logging._get_correlation_id()
)
container = asyncio.run(create_model_onex_container())
set_current_container(container)
return container

2. Registry Access Error Handling

Location: src/omnibase_core/models/core/model_action_registry.py:241-267

Good: Registries now raise ModelOnexError when container not initialized ✅

Issue: The error message says "Initialize the container first" but doesn't provide guidance on how to initialize it.

Recommendation: Improve error messages with actionable guidance:

raise ModelOnexError(
    message="DI container not initialized - cannot get action registry. "
    "Initialize with: container = await create_model_onex_container() or "
    "use ApplicationContext(container).",
    error_code=EnumCoreErrorCode.CONFIGURATION_ERROR,
) from e

🟡 MODERATE: Test Configuration Concerns

Location: pyproject.toml:305

"--dist=loadgroup",  # Group tests by @pytest.mark.xdist_group for better control

Issue: Changing from loadscope to loadgroup requires tests to use @pytest.mark.xdist_group markers. Without these markers, tests may not be properly distributed.

Questions:

  1. Have existing tests been audited for appropriate xdist_group markers?
  2. What happens to unmarked tests - do they fall back to loadscope behavior?
  3. Is there documentation guiding developers on when to use xdist_group?

Recommendation:

  • Document the xdist_group marker strategy in CLAUDE.md
  • Add examples of when to use grouping (e.g., database tests, registry tests)
  • Consider a hybrid approach: --dist=loadscope as default, loadgroup for specific test suites

🟢 MINOR: Code Quality Improvements

1. Cache Clear Functions Could Return Status

Location: src/omnibase_core/logging/core_logging.py:119-121

def clear_logger_cache() -> None:
    """Clear the logger cache (for testing)."""
    _get_cached_logger.cache_clear()

Suggestion: Return cache info for debugging:

def clear_logger_cache() -> dict[str, int]:
    """Clear the logger cache (for testing).
    
    Returns:
        Cache statistics before clearing (hits, misses, size).
    """
    info = _get_cached_logger.cache_info()
    _get_cached_logger.cache_clear()
    return {
        "hits": info.hits,
        "misses": info.misses,
        "size": info.currsize,
    }

This helps diagnose cache effectiveness in tests.

2. Magic Number in TTL

Location: src/omnibase_core/logging/emit.py:44

_PROTOCOL_CACHE_TTL = 300.0

Suggestion: Document the rationale for 5 minutes:

# TTL for protocol services cache
# 300s (5 minutes) balances:
# - Enough time to avoid repeated container lookups during normal operation
# - Short enough to pick up container reinitialization in long-running processes
_PROTOCOL_CACHE_TTL = 300.0

3. Unused Imports

Location: src/omnibase_core/models/core/model_event_type_registry.py:1-8

The diff shows imports were reordered but Generic and Any may now be unused. Run:

poetry run ruff check --select F401 src/omnibase_core/models/core/model_event_type_registry.py

🟢 MINOR: Documentation Gaps

1. CLAUDE.md Should Mention ApplicationContext

The project's CLAUDE.md extensively documents architecture but doesn't mention the new ApplicationContext pattern.

Recommendation: Add a section to CLAUDE.md:

### Application Context (v0.2.0+)

**contextvars-based container management** for thread-safe and async-safe isolation:

```python
from omnibase_core.context import ApplicationContext, get_current_container

# Set container for current context
async with ApplicationContext(container):
    current = get_current_container()
    # Use container...

# Or sync version
with ApplicationContext(container):
    current = get_current_container()

Benefits:

  • Proper isolation between asyncio tasks and threads
  • Essential for pytest-xdist parallel test execution
  • Replaces legacy singleton holder pattern

#### 2. **Testing Guide Should Reference Isolation Fixtures**

Add to docs/testing/ directory:
- When to use `reset_all_singletons` vs `reset_container_singleton`
- How to diagnose test isolation issues
- Examples of proper fixture usage

---

## 🔒 Security Review

✅ **No security concerns identified**

- No credential handling in changed code
- No external API calls introduced
- Thread safety properly handled via contextvars (inherently safe)
- No SQL injection or XSS vectors

---

## ⚡ Performance Review

### Positive:
- ✅ `lru_cache` with TTL reduces container lookups
- ✅ contextvars have minimal overhead (C-level implementation)
- ✅ Reduced lock contention vs singleton pattern

### Concerns:
- ⚠️ **`get_model_onex_container_sync()` creates new event loop every call** if no container exists
  - Each `asyncio.run()` creates and destroys an event loop (~1ms overhead)
  - Recommendation: Cache result or document that this is for initialization only

---

## 📊 Test Coverage Analysis

Based on PR changes:

| File | Lines Added | Test Coverage | Status |
|------|-------------|---------------|--------|
| `application_context.py` | 262 | 391 test lines | ✅ Excellent |
| `isolation.py` | 536 | 311 test lines | ✅ Good |
| `model_action_registry.py` | Changes | Existing suite | ✅ Covered |
| `model_onex_container.py` | Changes | Existing suite | ✅ Covered |

**Overall: Test coverage meets project's 60%+ requirement** ✅

---

## 🧪 Test Plan Checklist

From PR description:

- ✅ **All pre-commit hooks pass** (mypy, ruff, black, isort)
- ⏳ **Unit tests pass** - `poetry run pytest tests/unit/` (needs verification)
- ⏳ **Integration tests pass** (needs verification)
- ⏳ **CI pipeline passes with parallel execution** (needs verification)

**Action Required:** Verify all CI checks pass before merge.

---

## 📝 Suggested Next Steps (Post-Merge)

1. **Monitor CI Performance**
   - Track if `loadgroup` distribution improves split balance
   - Refer to CI_MONITORING_GUIDE.md for baseline timings

2. **Audit Flaky Tests**
   - Remove `--reruns=2` default
   - Mark specific flaky tests with explicit retry markers
   - Document flakiness in issue tracker

3. **Update Documentation**
   - Add ApplicationContext to CLAUDE.md
   - Create testing guide for isolation fixtures
   - Update migration guide for v0.2.0

4. **Performance Testing**
   - Benchmark `get_model_onex_container_sync()` in production
   - Consider caching if called frequently

---

## 🎓 Learning & Best Practices

This PR demonstrates excellent engineering:

1. ✅ **Right tool for the job**: contextvars over global state
2. ✅ **Comprehensive testing**: Thread isolation, async isolation, edge cases
3. ✅ **Type safety**: Full mypy strict compliance
4. ✅ **Documentation**: Clear migration path and examples
5. ✅ **Backward compatibility**: Graceful migration path

**Kudos to @jonahgabriel for a well-architected solution\!** 🎉

---

## 🏁 Final Recommendation

**✅ Approve after addressing:**

1. **CRITICAL:** Remove default test auto-retry (`--reruns=2`)
2. **MODERATE:** Document `xdist_group` marker strategy
3. **MODERATE:** Improve error messages in registry access

**Nice-to-have (non-blocking):**
- Add ApplicationContext to CLAUDE.md
- Return cache stats from clear functions
- Document TTL rationale

This is a significant improvement to test reliability and follows ONEX architectural principles. Well done\!

---

**Reviewed by:** Claude Code  
**Review Date:** 2025-11-27  
**Branch:** `feature/pytest-xdist-scope-optimization`  
**Target:** `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: 6

Caution

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

⚠️ Outside diff range comments (1)
pyproject.toml (1)

320-328: Stale comment references outdated distribution strategy.

The comment at Line 323 mentions --dist=loadscope but the actual configuration now uses --dist=loadgroup. Consider updating the comment to avoid confusion.

 # Memory optimization notes:
 # - Limited to 4 workers to prevent OOM on machines with 16GB RAM
 # - Use --timeout to prevent hanging tests accumulating memory
-# - Use --dist=loadscope to group tests by module (reduces import overhead)
+# - Use --dist=loadgroup to group tests by @pytest.mark.xdist_group (enables finer control)
 # Test execution strategies:
🧹 Nitpick comments (7)
tests/unit/mixins/test_mixin_hybrid_execution.py (1)

117-135: Improved log verification logic looks good.

The more robust verification approach that scans all log calls for the MIXIN_INIT message is better than the previous simplistic assertion.

Minor nit: The unpacked kwargs at Line 126 is unused. Consider using _ to indicate it's intentionally ignored.

             for call in mock_log.call_args_list:
-                args, kwargs = call
+                args, _ = call
                 # Message is the second positional argument
                 if len(args) >= 2 and "MIXIN_INIT" in str(args[1]):
                     mixin_init_found = True
                     break
src/omnibase_core/models/core/model_action_registry.py (1)

280-286: Consider logging the exception for debugging test failures.

While the silent no-op is intentional for the case where the container isn't initialized, catching all exceptions silently can hide unexpected errors during test debugging.

     try:
         container = get_model_onex_container_sync()
         registry = cast(ModelActionRegistry, container.action_registry())
         registry.clear()
-    except Exception:
+    except Exception:  # noqa: BLE001 - intentional no-op for testing
         # If container is not initialized, nothing to reset
         pass

Alternatively, add debug logging:

except Exception as e:
    # If container is not initialized, nothing to reset
    import logging
    logging.debug(f"reset_action_registry no-op: {e}")
tests/unit/models/core/test_model_cli_command_registry.py (1)

654-670: Consider using public reset API instead of accessing internal _current_container.

The fixture directly accesses _current_container, which is an internal implementation detail. The PR introduces public reset utilities in tests/fixtures/isolation.py (e.g., reset_container_singleton) that would be more appropriate here.

     @pytest.fixture(autouse=True)
     def reset_global_registry(self):
         """Reset global registry state before and after each test.
-
-        The new pattern uses ApplicationContext (contextvars), so we reset
-        the context variable to ensure a fresh container is created for each test.
         """
-        from omnibase_core.context.application_context import _current_container
-
-        # Reset context variable to None (clear any existing container)
-        # This ensures a fresh container will be created
-        context_token = _current_container.set(None)
-
-        yield
-
-        # Restore original context variable state
-        _current_container.reset(context_token)
+        from tests.fixtures.isolation import SingletonResetContext
+
+        with SingletonResetContext(holder_keys=["container"], clear_caches=True):
+            yield

Alternatively, since the reset_container_singleton fixture is now globally available via conftest.py, you could simply use it:

@pytest.fixture(autouse=True)
def reset_global_registry(self, reset_container_singleton):
    """Reset global registry state before and after each test."""
    yield
src/omnibase_core/context/__init__.py (1)

50-57: Consider sorting __all__ alphabetically for consistency.

Static analysis suggests sorting the exports. This is a minor style improvement.

 __all__ = [
     "ApplicationContext",
     "get_current_container",
-    "set_current_container",
     "reset_container",
     "run_with_container",
     "run_with_container_sync",
+    "set_current_container",
 ]
tests/fixtures/isolation.py (1)

72-77: Accessing private _current_container directly.

The function imports _current_container (a private module variable with underscore prefix) directly from application_context. While this works, consider whether the public set_current_container(None) API should be used instead, or if a dedicated clear_current_container() function should be exposed from the module for test utilities.

 def reset_application_context() -> contextvars.Token[Any] | None:
     try:
-        from omnibase_core.context.application_context import _current_container
+        from omnibase_core.context.application_context import (
+            _current_container,
+        )
 
         return _current_container.set(None)

Alternatively, expose a public API in application_context.py:

def clear_current_container() -> contextvars.Token[ModelONEXContainer | None]:
    """Clear the current container, returning a token for restore."""
    return _current_container.set(None)
tests/unit/enums/test_enum_scenario_status.py (2)

19-19: Add @pytest.mark.unit decorator for test categorization.

Per coding guidelines, test classes should use pytest.mark decorators to categorize tests appropriately. Since this is in tests/unit/, add the unit marker.

Based on coding guidelines: "Use @pytest.mark decorators (unit, integration, slow, smoke, performance) to categorize tests appropriately"

+@pytest.mark.unit
 class TestEnumScenarioStatus:

245-245: Add @pytest.mark.unit decorator for test categorization.

Same as the previous test class - add the unit marker for proper test categorization.

+@pytest.mark.unit
 class TestEnumScenarioStatusEdgeCases:
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a0e53e2 and 5738066.

📒 Files selected for processing (22)
  • pyproject.toml (1 hunks)
  • src/omnibase_core/context/__init__.py (1 hunks)
  • src/omnibase_core/context/application_context.py (1 hunks)
  • src/omnibase_core/logging/core_logging.py (2 hunks)
  • src/omnibase_core/logging/emit.py (2 hunks)
  • src/omnibase_core/models/container/model_onex_container.py (2 hunks)
  • src/omnibase_core/models/core/model_action_registry.py (2 hunks)
  • src/omnibase_core/models/core/model_cli_command_registry.py (3 hunks)
  • src/omnibase_core/models/core/model_event_type_registry.py (2 hunks)
  • src/omnibase_core/models/security/model_secret_manager.py (1 hunks)
  • src/omnibase_core/utils/util_container_holder.py (0 hunks)
  • src/omnibase_core/utils/util_singleton_holders.py (1 hunks)
  • tests/conftest.py (2 hunks)
  • tests/fixtures/isolation.py (1 hunks)
  • tests/unit/context/__init__.py (1 hunks)
  • tests/unit/context/test_application_context.py (1 hunks)
  • tests/unit/enums/test_enum_scenario_status.py (1 hunks)
  • tests/unit/fixtures/__init__.py (1 hunks)
  • tests/unit/fixtures/test_isolation_fixtures.py (1 hunks)
  • tests/unit/logging/test_core_logging.py (1 hunks)
  • tests/unit/mixins/test_mixin_hybrid_execution.py (1 hunks)
  • tests/unit/models/core/test_model_cli_command_registry.py (2 hunks)
💤 Files with no reviewable changes (1)
  • src/omnibase_core/utils/util_container_holder.py
🧰 Additional context used
📓 Path-based instructions (4)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Always use Poetry for Python package management and task execution - never use pip or python directly
Always use ModelOnexError with EnumCoreErrorCode for structured error handling, never raise generic Exception
Use @standard_error_handling decorator on async functions to eliminate boilerplate try/catch logic
Use duck typing with protocols instead of isinstance checks - protocols define contracts through interfaces, not runtime type checking
Always use 100% strict mypy type checking - all functions must have type annotations and no untyped definitions are allowed
Run code through black formatter, isort for import sorting, and ruff linter before committing
Use async/await pattern with asyncio for asynchronous operations - never use threading for I/O operations
Use ModelEventEnvelope for inter-service event-driven communication and process event payloads through envelope pattern

Files:

  • tests/unit/fixtures/__init__.py
  • tests/unit/enums/test_enum_scenario_status.py
  • tests/unit/context/test_application_context.py
  • tests/unit/fixtures/test_isolation_fixtures.py
  • tests/unit/logging/test_core_logging.py
  • tests/conftest.py
  • tests/unit/mixins/test_mixin_hybrid_execution.py
  • src/omnibase_core/models/security/model_secret_manager.py
  • src/omnibase_core/models/core/model_event_type_registry.py
  • src/omnibase_core/models/core/model_action_registry.py
  • src/omnibase_core/logging/core_logging.py
  • src/omnibase_core/models/core/model_cli_command_registry.py
  • src/omnibase_core/models/container/model_onex_container.py
  • tests/unit/context/__init__.py
  • src/omnibase_core/context/application_context.py
  • src/omnibase_core/context/__init__.py
  • src/omnibase_core/utils/util_singleton_holders.py
  • tests/unit/models/core/test_model_cli_command_registry.py
  • tests/fixtures/isolation.py
  • src/omnibase_core/logging/emit.py
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

tests/**/*.py: Maintain minimum 60% code coverage with pytest tests - unit tests go in tests/unit/, integration tests in tests/integration/
Run pytest tests with parallelization disabled (-n 0 -xvs) for debugging and use standard pytest run for CI
Use @pytest.mark decorators (unit, integration, slow, smoke, performance) to categorize tests appropriately

Files:

  • tests/unit/fixtures/__init__.py
  • tests/unit/enums/test_enum_scenario_status.py
  • tests/unit/context/test_application_context.py
  • tests/unit/fixtures/test_isolation_fixtures.py
  • tests/unit/logging/test_core_logging.py
  • tests/conftest.py
  • tests/unit/mixins/test_mixin_hybrid_execution.py
  • tests/unit/context/__init__.py
  • tests/unit/models/core/test_model_cli_command_registry.py
  • tests/fixtures/isolation.py
src/omnibase_core/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Use container.get_service('ProtocolName') for dependency resolution by protocol name, never by concrete class name

Files:

  • src/omnibase_core/models/security/model_secret_manager.py
  • src/omnibase_core/models/core/model_event_type_registry.py
  • src/omnibase_core/models/core/model_action_registry.py
  • src/omnibase_core/logging/core_logging.py
  • src/omnibase_core/models/core/model_cli_command_registry.py
  • src/omnibase_core/models/container/model_onex_container.py
  • src/omnibase_core/context/application_context.py
  • src/omnibase_core/context/__init__.py
  • src/omnibase_core/utils/util_singleton_holders.py
  • src/omnibase_core/logging/emit.py
src/omnibase_core/models/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Use Pydantic models for data validation and serialization - leverage Pydantic 2.11+ features for type safety

Files:

  • src/omnibase_core/models/security/model_secret_manager.py
  • src/omnibase_core/models/core/model_event_type_registry.py
  • src/omnibase_core/models/core/model_action_registry.py
  • src/omnibase_core/models/core/model_cli_command_registry.py
  • src/omnibase_core/models/container/model_onex_container.py
🧠 Learnings (6)
📚 Learning: 2025-11-25T21:48:22.841Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T21:48:22.841Z
Learning: Applies to tests/**/*.py : Run pytest tests with parallelization disabled (-n 0 -xvs) for debugging and use standard pytest run for CI

Applied to files:

  • pyproject.toml
📚 Learning: 2025-11-25T21:48:22.841Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T21:48:22.841Z
Learning: Applies to tests/**/*.py : Use pytest.mark decorators (unit, integration, slow, smoke, performance) to categorize tests appropriately

Applied to files:

  • tests/conftest.py
📚 Learning: 2025-11-25T21:48:22.841Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T21:48:22.841Z
Learning: Applies to src/omnibase_core/nodes/**/*.py : Use ModelONEXContainer for dependency injection in node constructors, never use ModelContainer[T]

Applied to files:

  • src/omnibase_core/models/security/model_secret_manager.py
  • src/omnibase_core/models/core/model_event_type_registry.py
  • src/omnibase_core/models/core/model_action_registry.py
  • src/omnibase_core/models/core/model_cli_command_registry.py
  • src/omnibase_core/models/container/model_onex_container.py
  • src/omnibase_core/context/application_context.py
📚 Learning: 2025-11-25T21:48:22.841Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T21:48:22.841Z
Learning: Applies to **/*.py : Always use ModelOnexError with EnumCoreErrorCode for structured error handling, never raise generic Exception

Applied to files:

  • src/omnibase_core/models/security/model_secret_manager.py
  • src/omnibase_core/models/core/model_event_type_registry.py
  • src/omnibase_core/models/core/model_cli_command_registry.py
📚 Learning: 2025-11-25T21:48:22.841Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T21:48:22.841Z
Learning: Applies to src/omnibase_core/models/**/*.py : Use Pydantic models for data validation and serialization - leverage Pydantic 2.11+ features for type safety

Applied to files:

  • src/omnibase_core/models/core/model_event_type_registry.py
📚 Learning: 2025-11-25T21:48:22.841Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T21:48:22.841Z
Learning: Applies to src/omnibase_core/**/*.py : Use container.get_service('ProtocolName') for dependency resolution by protocol name, never by concrete class name

Applied to files:

  • src/omnibase_core/logging/emit.py
🧬 Code graph analysis (12)
tests/unit/context/test_application_context.py (1)
src/omnibase_core/context/application_context.py (8)
  • ApplicationContext (39-143)
  • get_current_container (146-161)
  • reset_container (191-208)
  • run_with_container (212-235)
  • run_with_container_sync (239-262)
  • set_current_container (164-188)
  • sync (131-143)
  • container (74-76)
tests/unit/logging/test_core_logging.py (1)
tests/fixtures/isolation.py (1)
  • isolated_correlation_context (342-374)
tests/conftest.py (1)
tests/fixtures/isolation.py (5)
  • clear_caches_fixture (327-338)
  • isolated_correlation_context (342-374)
  • reset_all_singletons (265-284)
  • reset_container_singleton (288-298)
  • reset_registries (302-323)
src/omnibase_core/models/security/model_secret_manager.py (4)
src/omnibase_core/context/application_context.py (1)
  • container (74-76)
src/omnibase_core/infrastructure/node_base.py (1)
  • container (752-760)
src/omnibase_core/models/container/model_onex_container.py (3)
  • get_model_onex_container_sync (761-787)
  • secret_manager (219-221)
  • config (184-186)
src/omnibase_core/container/service_registry.py (1)
  • config (104-106)
src/omnibase_core/models/core/model_action_registry.py (3)
src/omnibase_core/context/application_context.py (1)
  • container (74-76)
src/omnibase_core/infrastructure/node_base.py (1)
  • container (752-760)
src/omnibase_core/models/container/model_onex_container.py (2)
  • get_model_onex_container_sync (761-787)
  • action_registry (204-206)
src/omnibase_core/logging/core_logging.py (4)
src/omnibase_core/context/application_context.py (1)
  • container (74-76)
src/omnibase_core/models/container/model_onex_container.py (2)
  • get_model_onex_container_sync (761-787)
  • get_service (478-484)
src/omnibase_core/utils/util_bootstrap.py (1)
  • get_service (68-96)
src/omnibase_core/utils/util_simple_fallback_logger.py (1)
  • _SimpleFallbackLogger (12-27)
src/omnibase_core/models/container/model_onex_container.py (2)
src/omnibase_core/context/application_context.py (3)
  • get_current_container (146-161)
  • set_current_container (164-188)
  • container (74-76)
src/omnibase_core/infrastructure/node_base.py (2)
  • container (752-760)
  • run (588-602)
src/omnibase_core/context/application_context.py (1)
src/omnibase_core/models/container/model_onex_container.py (1)
  • ModelONEXContainer (81-651)
src/omnibase_core/context/__init__.py (1)
src/omnibase_core/context/application_context.py (6)
  • ApplicationContext (39-143)
  • get_current_container (146-161)
  • reset_container (191-208)
  • run_with_container (212-235)
  • run_with_container_sync (239-262)
  • set_current_container (164-188)
tests/unit/models/core/test_model_cli_command_registry.py (2)
src/omnibase_core/context/application_context.py (1)
  • get_current_container (146-161)
src/omnibase_core/models/core/model_cli_command_registry.py (2)
  • get_global_command_registry (270-289)
  • ModelCliCommandRegistry (27-267)
tests/fixtures/isolation.py (3)
src/omnibase_core/context/application_context.py (2)
  • container (74-76)
  • get_current_container (146-161)
src/omnibase_core/logging/core_logging.py (2)
  • clear_logger_cache (119-121)
  • emit (74-83)
src/omnibase_core/logging/emit.py (1)
  • clear_protocol_cache (484-487)
src/omnibase_core/logging/emit.py (5)
src/omnibase_core/context/application_context.py (1)
  • container (74-76)
src/omnibase_core/infrastructure/node_base.py (1)
  • container (752-760)
src/omnibase_core/models/container/model_onex_container.py (2)
  • ModelONEXContainer (81-651)
  • get_service (478-484)
src/omnibase_core/container/container_service_resolver.py (1)
  • get_service (60-150)
src/omnibase_core/utils/util_bootstrap.py (1)
  • get_service (68-96)
🪛 Ruff (0.14.6)
tests/unit/enums/test_enum_scenario_status.py

278-278: pickle and modules that wrap it can be unsafe when used to deserialize untrusted data, possible security issue

(S301)

tests/unit/context/test_application_context.py

154-154: Avoid specifying long messages outside the exception class

(TRY003)


221-221: Avoid specifying long messages outside the exception class

(TRY003)


275-275: Avoid specifying long messages outside the exception class

(TRY003)

tests/unit/fixtures/test_isolation_fixtures.py

109-109: Unused method argument: reset_container_singleton

(ARG002)


113-113: Unused method argument: reset_all_singletons

(ARG002)


120-120: Unused method argument: isolated_correlation_context

(ARG002)


127-127: Unused method argument: reset_registries

(ARG002)


300-300: Unused method argument: reset_container_singleton

(ARG002)


307-307: Unused method argument: reset_all_singletons

(ARG002)

tests/unit/logging/test_core_logging.py

102-102: Unused method argument: isolated_correlation_context

(ARG002)

tests/conftest.py

234-234: Unused function argument: config

(ARG001)

tests/unit/mixins/test_mixin_hybrid_execution.py

126-126: Unpacked variable kwargs is never used

Prefix it with an underscore or any other dummy variable pattern

(RUF059)

src/omnibase_core/models/core/model_event_type_registry.py

223-223: Consider moving this statement to an else block

(TRY300)


246-248: try-except-pass detected, consider logging the exception

(S110)


246-246: Do not catch blind exception: Exception

(BLE001)

src/omnibase_core/models/core/model_action_registry.py

261-261: Consider moving this statement to an else block

(TRY300)


284-286: try-except-pass detected, consider logging the exception

(S110)


284-284: Do not catch blind exception: Exception

(BLE001)

src/omnibase_core/logging/core_logging.py

113-113: Do not catch blind exception: Exception

(BLE001)


115-115: Do not catch blind exception: Exception

(BLE001)

src/omnibase_core/context/__init__.py

50-57: __all__ is not sorted

Apply an isort-style sorting to __all__

(RUF022)

tests/fixtures/isolation.py

421-423: try-except-pass detected, consider logging the exception

(S110)


421-421: Do not catch blind exception: Exception

(BLE001)


429-430: try-except-pass detected, consider logging the exception

(S110)


429-429: Do not catch blind exception: Exception

(BLE001)

src/omnibase_core/logging/emit.py

472-472: Consider moving this statement to an else block

(TRY300)


473-473: Do not catch blind exception: Exception

(BLE001)

⏰ 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). (3)
  • GitHub Check: claude-review
  • GitHub Check: Code Quality
  • GitHub Check: Smoke Tests
🔇 Additional comments (44)
tests/unit/context/__init__.py (1)

1-1: LGTM!

Standard package initializer for the new context test module.

pyproject.toml (1)

306-309: Approve the test distribution and rerun configuration changes.

The switch to --dist=loadgroup for pytest-xdist and the addition of --reruns=2 with delay aligns well with the PR's goal of improving test isolation during parallel execution.

src/omnibase_core/utils/util_singleton_holders.py (1)

1-49: Well-documented deprecation with clear migration guidance.

The comprehensive docstring provides excellent migration examples from legacy singleton holders to the new ApplicationContext-based patterns. Exporting nothing via __all__ = [] ensures consumers cannot accidentally use deprecated patterns while the module remains discoverable for documentation purposes.

src/omnibase_core/models/core/model_event_type_registry.py (2)

205-229: Container-based registry access with proper error handling.

The migration from singleton fallback to explicit DI container access with ModelOnexError follows coding guidelines. The auto-bootstrap behavior when the registry is empty maintains backward compatibility while enforcing proper initialization.


232-248: Silent no-op behavior in reset is appropriate for testing.

The try-except-pass pattern here is intentional per the docstring ("Does nothing if container is not initialized"). This is a reasonable design for a reset function primarily used in test cleanup—failing silently when there's nothing to reset avoids test setup complexity.

tests/unit/logging/test_core_logging.py (1)

101-109: Correct use of fixture for test isolation.

The isolated_correlation_context fixture parameter is intentionally "unused" in the function body—this is a standard pytest pattern where including the fixture as a parameter triggers its setup/teardown side effects. The Ruff ARG002 warning is a false positive in this context. The fixture ensures proper isolation by clearing any correlation ID from previous tests.

src/omnibase_core/models/core/model_cli_command_registry.py (1)

270-289: Container-based registry access with structured error handling.

The migration from singleton fallback to strict DI container access follows the coding guidelines—using ModelOnexError with EnumCoreErrorCode.CONFIGURATION_ERROR instead of generic exceptions. The exception chaining (from e) preserves debugging context.

This strict behavior (raise on failure rather than fallback) is appropriate for a registry access function where the consumer needs the registry to function correctly.

tests/unit/fixtures/__init__.py (1)

1-1: Minor typo in docstring.

The docstring has a double period at the end: "Unit tests for fixtures.." → should be "Unit tests for fixtures."

-"""Unit tests for fixtures."""
+"""Unit tests for fixtures."""

Wait, looking more closely, the issue is the extra period. Let me correct:

-"""Unit tests for fixtures.."""
+"""Unit tests for fixtures."""

Likely an incorrect or invalid review comment.

src/omnibase_core/logging/core_logging.py (3)

119-121: LGTM!

The clear_logger_cache() function is a clean addition for test isolation, allowing tests to reset the cached logger state.


124-126: LGTM!

Clean simplification - the delegation to _get_cached_logger() removes the previous double-checked locking complexity.


97-117: Based on my comprehensive investigation, I can now provide the verified review comment. The original review comment correctly identifies a real design flaw in how the logger caching interacts with the contextvars-based container isolation system.

Do not use lru_cache with context-variable container—it defeats per-context isolation.

The @lru_cache(maxsize=1) decorator caches the logger instance globally (process-wide), but get_model_onex_container_sync() explicitly uses contextvars to provide per-context containers. Different execution contexts (via run_with_container() or ApplicationContext) can have different containers, but the cached logger will always return the one from the first context, breaking isolation.

The docstring claims "without global state," but lru_cache is exactly that—global state that ignores context boundaries.

Recommended fixes:

  1. Remove the cache and accept minor performance cost—contexts need independent loggers
  2. Use a context-aware cache mechanism (e.g., dict keyed by container ID)
  3. If logger must be truly global (intentional singleton), remove the misleading docstring and add a clear comment explaining why context isolation is disabled

The existing clear_logger_cache() function hints that this limitation is known; document it explicitly if global caching is intentional.

src/omnibase_core/models/core/model_action_registry.py (1)

241-267: LGTM - Clean migration to DI container pattern.

The change from fallback-to-singleton to raising ModelOnexError when the container isn't initialized is a good design decision. It makes failures explicit rather than silently returning a potentially inconsistent registry.

Minor note: The static analyzer suggests moving line 261 (return registry) to an else block, but the current structure is clear and readable.

tests/unit/context/test_application_context.py (7)

1-25: LGTM - Comprehensive test suite for ApplicationContext.

Well-organized test module covering all aspects of the contextvars-based container management:

  • Basic get/set/reset operations
  • Sync and async context managers
  • Exception handling and cleanup
  • Nested contexts
  • Thread isolation
  • Async task inheritance and isolation

The imports are clean and the test structure follows good practices.


27-86: LGTM!

Clean test implementation with proper context isolation using contextvars.copy_context(). The reset pattern with token ensures no test pollution.


88-188: LGTM!

Excellent coverage of sync context manager behavior including:

  • Reset to previous value verification
  • Normal exit cleanup
  • Exception cleanup (critical for proper resource management)
  • Nested context manager behavior
  • The sync() class method test

190-242: LGTM!

Async context manager tests mirror the sync tests appropriately, with proper @pytest.mark.asyncio decorators. Good coverage of async-specific behavior.


244-309: LGTM!

Good tests for the run_with_container and run_with_container_sync helper functions, verifying both the yielded value and cleanup behavior.


311-382: LGTM - Critical isolation tests.

These tests verify the core PR objective: thread-safe and async-safe container isolation. The thread isolation test using threading.Barrier for synchronization is well-designed, and the async task tests correctly verify that child tasks inherit context but modifications don't propagate back to parents.


384-391: LGTM!

Simple but necessary test for the container property accessor.

tests/unit/models/core/test_model_cli_command_registry.py (3)

672-687: LGTM - Good verification of container-based registry access.

The test correctly verifies that:

  1. Container is None after fixture reset
  2. Getting the global registry creates a container
  3. Container is set in context after registry access

This validates the migration from singleton to DI container pattern.


688-694: LGTM!

Simple but important test verifying that repeated calls return the same registry instance (singleton behavior within a context).


696-742: LGTM!

Good integration tests verifying that module-level functions (discover_commands_from_contracts, get_command_definition) properly use the container-based global registry.

tests/conftest.py (3)

210-230: LGTM - Well-documented pytest markers for test isolation.

The new markers provide clear semantics for test categorization:

  • isolated: fresh module state
  • no_shared_state: sensitive to global pollution
  • singleton_sensitive: touches specific singletons
  • fresh_event_loop: needs isolated asyncio loop
  • serial: runs after parallel tests complete

Good documentation in the marker descriptions.


233-272: LGTM - Critical for parallel test execution.

The separation of serial-marked tests to run last is essential for pytest-xdist compatibility. This ensures:

  1. Parallel tests run first without global state interference
  2. Serial tests run after parallel tests complete
  3. Consistent, deterministic test ordering within each group

The docstring clearly explains the rationale.


504-517: LGTM - Global fixture imports for test isolation.

Importing these fixtures at the conftest level makes them available to all tests without explicit imports. This is the standard pytest pattern and aligns with the PR's goal of providing comprehensive test isolation support.

The imported fixtures cover:

  • Cache clearing (clear_caches_fixture)
  • Event loop isolation (fresh_asyncio_loop)
  • Logging context isolation (isolated_correlation_context)
  • Singleton/container reset (reset_all_singletons, reset_container_singleton, reset_registries)
src/omnibase_core/models/container/model_onex_container.py (3)

41-46: LGTM - Import of context management utilities.

The imports correctly bring in the context-based container management functions that replace the legacy singleton holder pattern.


727-758: LGTM - Context-based async container access.

The implementation correctly checks for an existing container in the current context before creating a new one. The comprehensive docstring explains the context isolation benefits across asyncio tasks, threads, and nested contexts.


761-787: LGTM - Well-documented sync container access with context awareness.

The implementation correctly handles the nuance that asyncio.run() creates a fresh context (line 780-781 comment). The solution of capturing the container and setting it in the caller's context after asyncio.run() returns is the right approach to ensure context propagation works correctly.

src/omnibase_core/logging/emit.py (2)

477-487: LGTM - TTL-based cache refresh mechanism.

The TTL refresh logic is correct: when TTL is exceeded, the cache is cleared before calling the cached function, which then sets a fresh timestamp. The clear_protocol_cache() function properly resets both the timestamp and the lru_cache for testing purposes.


765-766: LGTM - Clean integration of cached protocol services.

The change simplifies the routing logic by delegating caching concerns to get_protocol_services().

src/omnibase_core/context/__init__.py (1)

1-39: LGTM - Well-documented module docstring with usage examples.

The docstring provides clear examples for common use cases including token-based reset, async context managers, and sync context managers. This will help developers adopt the new context-based approach.

tests/unit/fixtures/test_isolation_fixtures.py (5)

5-9: Note: Test imports private _current_container for cleanup.

Importing _current_container (a private contextvar) is acceptable for test cleanup purposes, allowing tests to properly reset state via _current_container.reset(token) in finally blocks. This is a reasonable testing pattern.


26-88: LGTM - Comprehensive tests for SingletonResetContext.

Tests cover the key scenarios: container reset to None inside context, legacy key filtering, proper restoration on exit, and the clear_caches parameter. The consistent use of try/finally with token-based cleanup is a good pattern.


106-135: LGTM - Fixture tests use standard pytest pattern.

The unused method argument warnings (ARG002) are false positives. The fixture parameters (reset_container_singleton, reset_all_singletons, etc.) trigger pytest to execute those fixtures before the test runs. The tests then verify the expected state after fixture execution.


137-217: LGTM - Good coverage of utility functions and legacy key handling.

Tests properly verify:

  • get_all_holder_classes() returns empty dict (confirming migration)
  • reset_singleton_by_key() works for container and returns True for legacy keys
  • is_legacy_holder_key() correctly identifies all legacy keys
  • LEGACY_HOLDER_KEYS contains all expected keys

220-311: LGTM - Thorough application context tests.

The TestApplicationContext class covers:

  • Basic reset functionality
  • Idempotent reset behavior
  • SingletonResetContext integration
  • Proper restoration on context exit
  • clear_all_caches effect on context
  • Fixture integration tests

As per coding guidelines, these tests properly use pytest fixtures and markers for unit tests.

src/omnibase_core/context/application_context.py (3)

1-36: Well-structured module with proper contextvars usage.

The module docstring clearly documents the thread-safety guarantees and benefits of the contextvars approach. The TYPE_CHECKING guard for the ModelONEXContainer import avoids circular dependencies while maintaining type safety.


39-143: Solid dual-protocol context manager implementation.

The class correctly implements both sync and async context manager protocols with proper token-based cleanup. The sync() classmethod is semantically redundant (since the instance already supports __enter__/__exit__), but it provides clear API intent for users and aligns with the documented usage pattern.


211-262: Context manager helpers provide convenient functional API.

The run_with_container and run_with_container_sync functions correctly use try/finally to ensure cleanup. They provide a functional alternative to the class-based ApplicationContext, which is useful for simpler use cases.

tests/fixtures/isolation.py (4)

97-126: Cache clearing implementation looks correct.

The function appropriately uses try/except to handle cases where modules may not be available. The discarded token from reset_application_context() is intentional since this function is meant for one-way clearing, not save/restore semantics.


341-374: Correlation context isolation uses internal API.

The fixture correctly saves and restores the correlation ID state. Accessing core_logging._context directly is necessary for test isolation but couples this fixture to internal implementation details.

Consider adding a comment noting this dependency, so maintainers know to update this fixture if the logging internals change.


264-339: Well-designed pytest fixtures with clear documentation.

The fixtures are appropriately scoped and documented with usage examples. The reset_registries fixture correctly notes the migration from individual holder resets to container-based access.


465-536: Utility functions provide clean backward compatibility.

The get_all_holder_classes() returning an empty dict and is_legacy_holder_key() checking against the frozen set provide backward compatibility while documenting the migration away from singleton holders.

tests/unit/enums/test_enum_scenario_status.py (1)

268-282: The importlib workaround appears unnecessary for the actual test behavior.

Standard Python enums are singletons within a process, and pickle.dumps()/pickle.loads() automatically preserves enum identity without any special handling. The importlib.import_module() call returns the cached module from sys.modules—the same object reference as the top-level EnumScenarioStatus import—so it provides no functional difference.

Additionally, the test has no isolation markers or fixtures applied to it (confirmed in conftest.py), so no module reloading occurs that would require this workaround. The comment about fixing "pytest-xdist worker process module caching" misrepresents how the code works: importlib.import_module() within one worker's process cannot affect another worker's separate sys.modules.

Recommendation:

  • Remove the importlib workaround and verify the test still passes with direct iteration over EnumScenarioStatus
  • Update the comment if the workaround is retained for defensive purposes, clarifying that it doesn't actually address cross-worker pytest-xdist issues
  • The identity assertion on line 281 is correct and should be kept—it validates that pickle preserves enum singleton semantics

Note on static analysis: The Ruff warning about pickle.loads() on line 278 is acceptable in unit tests with controlled input data.

Comment on lines +453 to +474
@lru_cache(maxsize=1)
def _get_protocol_services_cached() -> tuple[Any, Any]:
"""Get formatter and output handler with caching."""
_protocol_cache_state[0] = time.time()

try:
from omnibase_core.models.container.model_onex_container import (
ModelONEXContainer,
)
from omnibase_core.nodes.node_logger.protocols.protocol_context_aware_output_handler import (
ProtocolContextAwareOutputHandler,
)
from omnibase_core.nodes.node_logger.protocols.protocol_smart_log_formatter import (
ProtocolSmartLogFormatter,
)

container = ModelONEXContainer()
formatter = container.get_service(ProtocolSmartLogFormatter)
output_handler = container.get_service(ProtocolContextAwareOutputHandler)
return (formatter, output_handler)
except Exception: # fallback-ok: protocol services init must never fail
return (None, None)

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

Use context-based container accessor instead of creating new container.

Line 469 creates a new ModelONEXContainer() directly, bypassing the context-based container management that this PR introduces. This could lead to inconsistent container instances across the codebase.

Apply this diff to use the context-based accessor:

 @lru_cache(maxsize=1)
 def _get_protocol_services_cached() -> tuple[Any, Any]:
     """Get formatter and output handler with caching."""
     _protocol_cache_state[0] = time.time()
 
     try:
         from omnibase_core.models.container.model_onex_container import (
-            ModelONEXContainer,
+            get_model_onex_container_sync,
         )
         from omnibase_core.nodes.node_logger.protocols.protocol_context_aware_output_handler import (
             ProtocolContextAwareOutputHandler,
         )
         from omnibase_core.nodes.node_logger.protocols.protocol_smart_log_formatter import (
             ProtocolSmartLogFormatter,
         )
 
-        container = ModelONEXContainer()
+        container = get_model_onex_container_sync()
         formatter = container.get_service(ProtocolSmartLogFormatter)
         output_handler = container.get_service(ProtocolContextAwareOutputHandler)
         return (formatter, output_handler)
     except Exception:  # fallback-ok: protocol services init must never fail
         return (None, None)
🧰 Tools
🪛 Ruff (0.14.6)

472-472: Consider moving this statement to an else block

(TRY300)


473-473: Do not catch blind exception: Exception

(BLE001)

🤖 Prompt for AI Agents
In src/omnibase_core/logging/emit.py around lines 453 to 474, the code currently
instantiates ModelONEXContainer() directly which bypasses the PR-introduced
context-based container management; replace the direct instantiation with the
context-based container accessor introduced in this PR (import the accessor
function that returns the current ModelONEXContainer from the appropriate
module) and use that returned container to call get_service for
ProtocolSmartLogFormatter and ProtocolContextAwareOutputHandler, keeping the
existing try/except fallback behavior if the accessor returns None or raises.

Comment on lines 392 to +403
try:
container = get_model_onex_container_sync()
return cast(ModelSecretManager, container.secret_manager())
except (
Exception
): # fallback-ok: DI container unavailable during bootstrap or circular dependency scenarios
# Fallback to singleton holder
manager = _SecretManagerHolder.get()
if manager is None:
manager = ModelSecretManager()
_SecretManagerHolder.set(manager)
return manager
# Type narrowing: manager is now guaranteed to be ModelSecretManager
return cast(ModelSecretManager, manager)
except Exception as e:
raise ModelOnexError(
message="DI container not initialized - cannot get secret manager. "
"Call init_secret_manager() first.",
error_code=EnumCoreErrorCode.CONFIGURATION_ERROR,
) from e

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

Verify secret_manager access pattern - property vs method call.

Line 397 calls container.secret_manager() as a method, but the relevant code snippet at src/omnibase_core/models/container/model_onex_container.py:218-220 shows secret_manager is a property, not a method.

Apply this diff to fix the property access:

     try:
         container = get_model_onex_container_sync()
-        return cast(ModelSecretManager, container.secret_manager())
+        return cast(ModelSecretManager, container.secret_manager)
     except Exception as e:
🤖 Prompt for AI Agents
In src/omnibase_core/models/security/model_secret_manager.py around lines 395 to
403, the code calls container.secret_manager() but secret_manager is defined as
a property in model_onex_container.py; change the call to access the property
(container.secret_manager) instead of invoking it, keep the cast to
ModelSecretManager and preserve the existing exception handling and error
message.

Comment on lines 408 to +432
def init_secret_manager(config: ModelSecretConfig) -> ModelSecretManager:
"""Initialize global secret manager with custom config (now via DI container)."""
"""Initialize global secret manager with custom config via DI container.

Args:
config: The secret management configuration

Returns:
The initialized ModelSecretManager instance

Raises:
ModelOnexError: If DI container is not initialized
"""
from omnibase_core.models.container.model_onex_container import (
get_model_onex_container_sync,
)

manager = ModelSecretManager(config=config)
# Create the manager instance (for validation and potential future use)
_ = ModelSecretManager(config=config)

try:
# Try to set in container
container = get_model_onex_container_sync()
# Container manages its own instance, but we update holder as fallback
_SecretManagerHolder.set(manager)
result: ModelSecretManager = container.secret_manager()
return result
except (
Exception
): # fallback-ok: DI container unavailable during bootstrap or circular dependency scenarios
# Fallback to singleton holder
_SecretManagerHolder.set(manager)
return manager
return cast(ModelSecretManager, container.secret_manager())
except Exception as e:
raise ModelOnexError(
message="DI container not initialized - cannot initialize secret manager.",
error_code=EnumCoreErrorCode.CONFIGURATION_ERROR,
) from e

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

Provided config is validated but never used - API behavior is misleading.

The function creates a ModelSecretManager with the provided config (line 423) for validation purposes only, then discards it and returns the container's own secret manager instance. The caller's config is never actually applied to the container's secret manager.

This makes the function signature misleading - callers expect their config to be used. Consider either:

  1. Documenting that the config is only validated (not applied), or
  2. Actually using the config to configure the container's secret manager
🤖 Prompt for AI Agents
In src/omnibase_core/models/security/model_secret_manager.py around lines 406 to
432, the function currently constructs a ModelSecretManager with the provided
config only for validation and then returns the container's existing
secret_manager, so the caller's config is never applied; instead instantiate the
ModelSecretManager with the provided config and register/override that instance
in the DI container before returning it (or, if the container only supports
providers, update the container binding/provider to return a ModelSecretManager
constructed with the given config), preserving the existing try/except behavior
and raising ModelOnexError on DI initialization failures.

Comment on lines 431 to +464
def init_secret_manager_from_manager(manager: ModelSecretManager) -> ModelSecretManager:
"""Initialize global secret manager from existing manager instance (now via DI container)."""
"""Initialize global secret manager from existing manager instance via DI container.

Note: The provided manager is validated but the DI container manages its own singleton.
The container's secret_manager instance is returned.

Args:
manager: An existing ModelSecretManager instance (used for validation)

Returns:
The DI container's ModelSecretManager instance

Raises:
ModelOnexError: If DI container is not initialized
"""
from omnibase_core.models.container.model_onex_container import (
get_model_onex_container_sync,
)

# Validate the manager by accessing it (ensures it's a valid instance)
_ = manager.config

try:
# Try to set in container
container = get_model_onex_container_sync()
# Container manages its own instance, but we update holder as fallback
_SecretManagerHolder.set(manager)
result: ModelSecretManager = container.secret_manager()
return result
except (
Exception
): # fallback-ok: DI container unavailable during bootstrap or circular dependency scenarios
# Fallback to singleton holder
_SecretManagerHolder.set(manager)
return manager
return cast(ModelSecretManager, container.secret_manager())
except Exception as e:
raise ModelOnexError(
message="DI container not initialized - cannot initialize secret manager.",
error_code=EnumCoreErrorCode.CONFIGURATION_ERROR,
) from e

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

Same issues: property access and misleading API.

This function has the same two issues as init_secret_manager:

  1. Line 459 calls container.secret_manager() as a method instead of property access
  2. The provided manager is only validated but never used - the container's own instance is returned
     try:
         container = get_model_onex_container_sync()
-        return cast(ModelSecretManager, container.secret_manager())
+        return cast(ModelSecretManager, container.secret_manager)
     except Exception as e:
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def init_secret_manager_from_manager(manager: ModelSecretManager) -> ModelSecretManager:
"""Initialize global secret manager from existing manager instance (now via DI container)."""
"""Initialize global secret manager from existing manager instance via DI container.
Note: The provided manager is validated but the DI container manages its own singleton.
The container's secret_manager instance is returned.
Args:
manager: An existing ModelSecretManager instance (used for validation)
Returns:
The DI container's ModelSecretManager instance
Raises:
ModelOnexError: If DI container is not initialized
"""
from omnibase_core.models.container.model_onex_container import (
get_model_onex_container_sync,
)
# Validate the manager by accessing it (ensures it's a valid instance)
_ = manager.config
try:
# Try to set in container
container = get_model_onex_container_sync()
# Container manages its own instance, but we update holder as fallback
_SecretManagerHolder.set(manager)
result: ModelSecretManager = container.secret_manager()
return result
except (
Exception
): # fallback-ok: DI container unavailable during bootstrap or circular dependency scenarios
# Fallback to singleton holder
_SecretManagerHolder.set(manager)
return manager
return cast(ModelSecretManager, container.secret_manager())
except Exception as e:
raise ModelOnexError(
message="DI container not initialized - cannot initialize secret manager.",
error_code=EnumCoreErrorCode.CONFIGURATION_ERROR,
) from e
def init_secret_manager_from_manager(manager: ModelSecretManager) -> ModelSecretManager:
"""Initialize global secret manager from existing manager instance via DI container.
Note: The provided manager is validated but the DI container manages its own singleton.
The container's secret_manager instance is returned.
Args:
manager: An existing ModelSecretManager instance (used for validation)
Returns:
The DI container's ModelSecretManager instance
Raises:
ModelOnexError: If DI container is not initialized
"""
from omnibase_core.models.container.model_onex_container import (
get_model_onex_container_sync,
)
# Validate the manager by accessing it (ensures it's a valid instance)
_ = manager.config
try:
container = get_model_onex_container_sync()
return cast(ModelSecretManager, container.secret_manager)
except Exception as e:
raise ModelOnexError(
message="DI container not initialized - cannot initialize secret manager.",
error_code=EnumCoreErrorCode.CONFIGURATION_ERROR,
) from e
🤖 Prompt for AI Agents
In src/omnibase_core/models/security/model_secret_manager.py around lines
435-464, fix two issues: (1) stop calling container.secret_manager() as a method
and access it as a property (container.secret_manager) and (2) make the
function’s behavior explicit about the provided manager — either register the
passed-in manager into the DI container before returning (e.g., use the
container's setter/registration API or assign container.secret_manager = manager
if supported) or, if the intended behavior is only validation, change the
API/name to reflect that and return the validated manager; implement the chosen
approach consistently and preserve the existing exception handling.

Comment on lines +236 to +246
def __enter__(self) -> SingletonResetContext:
"""Enter context: save state, reset context, and clear caches."""
# Save and reset container context
if self._should_reset_container:
self._save_and_reset_context()

# Clear lru_cache caches if requested
if self._clear_caches:
clear_all_caches()

return self

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

Potential double reset of application context.

When _should_reset_container=True and clear_caches=True (the defaults), _save_and_reset_context() resets the container, then clear_all_caches() also calls reset_application_context(). This results in two resets, discarding the first token.

This doesn't cause incorrect behavior, but the first token (saved in _saved_state) becomes invalid for restoration since clear_all_caches() creates a new token that's discarded.

Consider reordering or conditionally skipping the reset in clear_all_caches:

     def __enter__(self) -> SingletonResetContext:
         """Enter context: save state, reset context, and clear caches."""
+        # Clear caches first (without resetting container context)
+        if self._clear_caches:
+            # Only clear logger and protocol caches, not container
+            try:
+                from omnibase_core.logging.core_logging import clear_logger_cache
+                clear_logger_cache()
+            except ImportError:
+                pass
+            try:
+                from omnibase_core.logging.emit import clear_protocol_cache
+                clear_protocol_cache()
+            except ImportError:
+                pass
+
         # Save and reset container context
         if self._should_reset_container:
             self._save_and_reset_context()
-
-        # Clear lru_cache caches if requested
-        if self._clear_caches:
-            clear_all_caches()

Or modify clear_all_caches to accept a skip_context_reset parameter.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In tests/fixtures/isolation.py around lines 236–246: currently __enter__ calls
_save_and_reset_context() and then clear_all_caches(), which causes
reset_application_context() to run twice and discards the first saved token;
change the logic to avoid the double reset by either (A) calling
clear_all_caches(skip_context_reset=True) when _should_reset_container is true
(add the skip_context_reset parameter to clear_all_caches and have it bypass
reset_application_context), or (B) reorder operations to call clear_all_caches()
before _save_and_reset_context(), ensuring only a single reset occurs; implement
one of these two fixes and update the clear_all_caches signature/usages if you
choose option A.

Comment on lines +392 to +430
# Save the current event loop if any
try:
old_loop = asyncio.get_event_loop()
old_loop_running = old_loop.is_running()
except RuntimeError:
old_loop = None
old_loop_running = False

# Create fresh loop
new_loop = asyncio.new_event_loop()
asyncio.set_event_loop(new_loop)

try:
yield new_loop
finally:
# Clean up the new loop
try:
# Cancel all pending tasks
pending = asyncio.all_tasks(new_loop)
for task in pending:
task.cancel()

# Give tasks a chance to handle cancellation
if pending:
new_loop.run_until_complete(
asyncio.gather(*pending, return_exceptions=True)
)

new_loop.close()
except Exception:
# Best effort cleanup
pass

# Restore old loop if it wasn't running
if old_loop is not None and not old_loop_running:
try:
asyncio.set_event_loop(old_loop)
except Exception:
pass

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

Address deprecated asyncio API and bare exception handling.

  1. asyncio.get_event_loop() without a running loop is deprecated since Python 3.10. Consider using asyncio.get_running_loop() with appropriate fallback.

  2. The bare except Exception blocks (lines 421, 429) flagged by static analysis should at minimum log the exception for debugging parallel test issues.

     # Save the current event loop if any
     try:
-        old_loop = asyncio.get_event_loop()
-        old_loop_running = old_loop.is_running()
+        old_loop = asyncio.get_running_loop()
+        old_loop_running = True
     except RuntimeError:
-        old_loop = None
-        old_loop_running = False
+        try:
+            old_loop = asyncio.get_event_loop_policy().get_event_loop()
+            old_loop_running = old_loop.is_running()
+        except RuntimeError:
+            old_loop = None
+            old_loop_running = False

For the cleanup blocks:

-        except Exception:
-            # Best effort cleanup
-            pass
+        except Exception as e:
+            # Best effort cleanup - log for debugging
+            import logging
+            logging.getLogger(__name__).debug(f"Event loop cleanup error: {e}")
🧰 Tools
🪛 Ruff (0.14.6)

421-423: try-except-pass detected, consider logging the exception

(S110)


421-421: Do not catch blind exception: Exception

(BLE001)


429-430: try-except-pass detected, consider logging the exception

(S110)


429-429: Do not catch blind exception: Exception

(BLE001)

🤖 Prompt for AI Agents
In tests/fixtures/isolation.py around lines 392 to 430, replace the deprecated
use of asyncio.get_event_loop() with a call to asyncio.get_running_loop() inside
a try/except to detect a running loop and fall back to setting old_loop to None
if no running loop exists; also stop using bare "except Exception" in the two
cleanup blocks — catch Exception as e and record the error using the module
logger (or a test logger) so failures are visible (ensure you import or obtain a
logger); keep the existing best-effort cleanup behavior but log the exception
details before continuing.

- Remove primitives/ re-export module (use models.primitives directly)
- Remove events/ re-export module (use models.events directly)
- Remove models/nodes/ re-export module (use models.core directly)
- Move service models from node_services/ to service/
- Remove ephemeral docs from project root
- Update all imports to use direct paths
- Add generics support to ModelMetricValue
@claude

claude Bot commented Nov 27, 2025

Copy link
Copy Markdown

Pull Request Review: Context-Based Container Management

Overall Assessment: Strong architectural improvement with excellent test coverage and documentation. A few items need addressing before merge.


Summary

This PR migrates from a singleton holder pattern to contextvars-based container management, providing proper isolation for parallel test execution with pytest-xdist. This is a solid architectural improvement that addresses real test isolation issues.

Changes: 67 files (+2,148 / -951 lines)
Key Addition: New ApplicationContext module using Python's contextvars


Strengths

1. Excellent Architecture

  • contextvars-based isolation: Proper solution for thread/async safety
  • Token-based reset: Clean API for test isolation
  • Clear migration path: From singleton holders to dependency injection
  • Well-documented: Comprehensive docstrings and inline comments

2. Comprehensive Test Coverage

  • 391 lines of tests for ApplicationContext alone
  • 311 lines for isolation fixtures
  • Tests cover threading, async, nested contexts, and error handling
  • Good test organization with descriptive class names

3. Proper Error Handling

  • Uses ModelOnexError with EnumCoreErrorCode (follows ONEX standards)
  • Graceful fallbacks when container not initialized
  • Clear error messages with context

4. Test Infrastructure Improvements

  • Added --reruns=2 with 1s delay for flaky tests
  • Changed from loadscope to loadgroup for better test distribution
  • New isolation fixtures

Critical Issues

1. Incomplete Event Loop Cleanup

File: tests/fixtures/isolation.py:408-420

Silent exception swallowing in cleanup can mask serious issues. Recommend at minimum logging the exception rather than silent pass.

2. Import Cycle Risk

File: src/omnibase_core/models/core/model_action_registry.py:247-267

The get_action_registry() function imports from container. If container initialization depends on registries, this could create a circular dependency.

Recommendation: Add explicit documentation about initialization order.

3. Missing CI Status Verification

Before merging, verify all CI checks pass, especially:

  • 20 parallel test splits (target: <3m30s per split per CLAUDE.md)
  • mypy strict mode (should still be 0 errors)
  • Coverage requirement (60%+ per CLAUDE.md)

Code Quality Concerns

1. Deletion of Verification Reports

Files Deleted:

  • PR88_GROUP_1A_VERIFICATION_REPORT.md (-188 lines)
  • VERIFICATION_REPORT.md (-211 lines)

Question: Were these temporary artifacts or important audit trails? If audit records, consider moving to docs/decisions/ or docs/archive/ instead of deleting.

2. Large Fixture File

File: tests/fixtures/isolation.py (536 lines)

While well-organized, consider splitting into:

  • fixtures/context_isolation.py - Context/container fixtures
  • fixtures/cache_isolation.py - Cache clearing fixtures
  • fixtures/async_isolation.py - Event loop fixtures

3. Documentation Path Changes

Multiple doc files updated import paths. Is this a breaking change for external users? Verify backward compatibility or update CHANGELOG.md


Security & Performance

Security: No Issues Detected

  • No credential leaks
  • No unsafe deserialization
  • Proper error boundaries

Performance: Improvements Expected

  • contextvars are lightweight (native Python)
  • lru_cache reduces repeated lookups
  • Fire-and-forget logging
  • Proper task cleanup prevents memory leaks

Thread Safety: Properly Addressed

  • contextvars provide inherent thread isolation
  • lru_cache is thread-safe by default
  • Threading tests included

Testing Recommendations

1. Verify CI Performance

Per CLAUDE.md benchmarks:

  • Average runtime per split: 2m30s - 3m30s (target)
  • No splits > 4m30s (warning threshold)
  • Total CI time: ~3 minutes

2. Run Full Test Suite Locally

poetry run pytest tests/ --cov=src/omnibase_core --cov-report=term-missing
poetry run pytest tests/ -n 4
poetry run pytest tests/ -n 4 -p no:rerunfailures

3. Verify mypy Compliance

poetry run mypy src/omnibase_core/

4. Test Isolation Verification

poetry run pytest tests/unit/context/ --random-order
poetry run pytest tests/unit/fixtures/ --random-order

Documentation Needs

1. Update CLAUDE.md

Add section on ApplicationContext usage patterns

2. Migration Guide

Create docs/migrations/SINGLETON_TO_CONTEXTVAR.md:

  • Why the change was made
  • How to migrate existing code
  • Common pitfalls
  • Testing strategies

3. CHANGELOG.md Entry

Document breaking changes, additions, and fixes


Best Practices Followed

ONEX Standards Compliance:

  • Uses ModelOnexError instead of generic Exception
  • Proper error codes
  • Poetry for all dependencies
  • Type annotations throughout
  • Comprehensive docstrings

Python Best Practices:

  • contextvars for context management (PEP 567)
  • Type hints with TYPE_CHECKING guard
  • Context managers for resource cleanup
  • lru_cache for performance

Testing Best Practices:

  • Isolated test fixtures
  • Mocking where appropriate
  • Descriptive test names
  • Good test organization

Metrics

Metric Value Status
Files Changed 67 Reasonable for refactor
Lines Added +2,148 Good test/doc coverage
Lines Deleted -951 Net positive (removing boilerplate)
New Module context/ Well-scoped
Test Files 2 new Comprehensive

Recommendation

Status: APPROVE WITH CONDITIONS

Before Merge:

  1. Resolve the 3 critical issues above
  2. Verify all CI checks pass (especially parallel tests)
  3. Confirm no breaking changes or update CHANGELOG
  4. Add migration guide documentation
  5. Run full test suite with -n4 locally

After Merge:

  1. Monitor CI performance for regressions
  2. Watch for test isolation issues in production
  3. Update downstream repositories if needed

Future Enhancements (Optional)

  1. Performance monitoring for context switch overhead
  2. Debug mode to trace context propagation
  3. Consider splitting large isolation.py file
  4. Add architecture decision record (ADR)

Great work on this refactor! The architecture is solid and addresses real problems. Just need to verify CI status and address the critical items above.

@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

Caution

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

⚠️ Outside diff range comments (2)
src/omnibase_core/models/discovery/model_custommetrics.py (1)

28-41: Potential UnboundLocalError if value type is unexpected.

If value somehow doesn't match any of the isinstance checks (e.g., None at runtime despite type hints), metric_type will be unbound when constructing ModelMetricValue. Consider adding a fallback or raising a clear error.

             elif isinstance(value, float):
                 metric_type = "float"
+            else:
+                raise TypeError(f"Unsupported metric value type: {type(value).__name__}")

             metrics.append(
docs/architecture/architecture-research/RESEARCH_REPORT_4_NODE_ARCHITECTURE.md (1)

176-188: Update the import statement to use the full module path

The example import is incorrect. Throughout the codebase, ModelServiceEffect is imported using the full module path:

from omnibase_core.models.service.model_service_effect import ModelServiceEffect

The package-level import shown in the example does not work since ModelServiceEffect is not re-exported in omnibase_core.models.service.__init__.py. Update line 184 to match the correct import pattern used consistently across all tests and source files.

🧹 Nitpick comments (2)
src/omnibase_core/models/discovery/model_custom_metrics.py (1)

18-18: Sort __all__ for consistency.

Static analysis (ruff RUF022) flags that __all__ is not sorted. Apply isort-style sorting for consistency with project conventions.

-__all__ = ["ModelCustomMetrics", "ModelMetricValue", "AnyMetricValue", "MetricValueT"]
+__all__ = ["AnyMetricValue", "MetricValueT", "ModelCustomMetrics", "ModelMetricValue"]
docs/reference/api/nodes.md (1)

149-197: Add language identifiers to service wrapper code fences to satisfy markdownlint

markdownlint is flagging these fenced blocks for missing languages (MD040):

  • The four service wrapper examples under “ModelServiceCompute/Effect/Reducer/Orchestrator”.

Recommend marking them as Python:

-```
+```python
 from omnibase_core.models.service.model_service_compute import ModelServiceCompute
 ...
-```
+```python
 from omnibase_core.models.service.model_service_effect import ModelServiceEffect
 ...
-```
+```python
 from omnibase_core.models.service.model_service_reducer import ModelServiceReducer
 ...
-```
+```python
 from omnibase_core.models.service.model_service_orchestrator import ModelServiceOrchestrator
 ...
-```

This will clear the MD040 warnings and improves syntax highlighting without changing content.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5738066 and 10e4d3a.

📒 Files selected for processing (45)
  • PR88_GROUP_1A_VERIFICATION_REPORT.md (0 hunks)
  • VERIFICATION_REPORT.md (0 hunks)
  • docs/architecture/ECOSYSTEM_DIRECTORY_STRUCTURE.md (1 hunks)
  • docs/architecture/architecture-research/RESEARCH_REPORT_4_NODE_ARCHITECTURE.md (1 hunks)
  • docs/architecture/overview.md (1 hunks)
  • docs/guides/VERSION_FIELD_AUTOMATION_STRATEGY.md (3 hunks)
  • docs/guides/node-building/01_WHAT_IS_A_NODE.md (1 hunks)
  • docs/guides/node-building/02_NODE_TYPES.md (1 hunks)
  • docs/reference/SERVICE_WRAPPERS.md (7 hunks)
  • docs/reference/api/nodes.md (5 hunks)
  • scripts/fix_string_id_violations.py (1 hunks)
  • scripts/fix_version_field_pattern1.sh (2 hunks)
  • src/omnibase_core/events/__init__.py (0 hunks)
  • src/omnibase_core/infrastructure/infrastructure_bases.py (1 hunks)
  • src/omnibase_core/models/core/__init__.py (1 hunks)
  • src/omnibase_core/models/core/model_monitoring_metrics.py (2 hunks)
  • src/omnibase_core/models/discovery/model_custom_metrics.py (1 hunks)
  • src/omnibase_core/models/discovery/model_custommetrics.py (2 hunks)
  • src/omnibase_core/models/discovery/model_metric_value.py (2 hunks)
  • src/omnibase_core/models/nodes/__init__.py (0 hunks)
  • src/omnibase_core/models/nodes/node_services/__init__.py (0 hunks)
  • src/omnibase_core/models/registry/model_registry_health_report.py (1 hunks)
  • src/omnibase_core/models/service/model_service_compute.py (1 hunks)
  • src/omnibase_core/models/service/model_service_effect.py (1 hunks)
  • src/omnibase_core/models/service/model_service_orchestrator.py (1 hunks)
  • src/omnibase_core/models/service/model_service_reducer.py (1 hunks)
  • src/omnibase_core/primitives/__init__.py (0 hunks)
  • tests/unit/models/nodes/node_services/test_model_service_compute_health.py (1 hunks)
  • tests/unit/models/nodes/node_services/test_model_service_compute_integration.py (1 hunks)
  • tests/unit/models/nodes/node_services/test_model_service_compute_invocation.py (1 hunks)
  • tests/unit/models/nodes/node_services/test_model_service_compute_lifecycle.py (1 hunks)
  • tests/unit/models/nodes/node_services/test_model_service_effect_health.py (1 hunks)
  • tests/unit/models/nodes/node_services/test_model_service_effect_integration.py (1 hunks)
  • tests/unit/models/nodes/node_services/test_model_service_effect_invocation.py (1 hunks)
  • tests/unit/models/nodes/node_services/test_model_service_effect_lifecycle.py (1 hunks)
  • tests/unit/models/nodes/node_services/test_model_service_orchestrator_health.py (1 hunks)
  • tests/unit/models/nodes/node_services/test_model_service_orchestrator_integration.py (1 hunks)
  • tests/unit/models/nodes/node_services/test_model_service_orchestrator_invocation.py (1 hunks)
  • tests/unit/models/nodes/node_services/test_model_service_orchestrator_lifecycle.py (1 hunks)
  • tests/unit/models/nodes/node_services/test_model_service_reducer_health.py (1 hunks)
  • tests/unit/models/nodes/node_services/test_model_service_reducer_integration.py (1 hunks)
  • tests/unit/models/nodes/node_services/test_model_service_reducer_invocation.py (1 hunks)
  • tests/unit/models/nodes/node_services/test_model_service_reducer_lifecycle.py (1 hunks)
  • tests/unit/nodes/test_retry_count_tracking.py (1 hunks)
  • tests/unit/primitives/test_model_semver.py (1 hunks)
💤 Files with no reviewable changes (6)
  • src/omnibase_core/events/init.py
  • VERIFICATION_REPORT.md
  • src/omnibase_core/models/nodes/init.py
  • src/omnibase_core/primitives/init.py
  • src/omnibase_core/models/nodes/node_services/init.py
  • PR88_GROUP_1A_VERIFICATION_REPORT.md
✅ Files skipped from review due to trivial changes (6)
  • tests/unit/models/nodes/node_services/test_model_service_orchestrator_health.py
  • scripts/fix_string_id_violations.py
  • tests/unit/models/nodes/node_services/test_model_service_reducer_integration.py
  • tests/unit/models/nodes/node_services/test_model_service_effect_health.py
  • tests/unit/models/nodes/node_services/test_model_service_effect_lifecycle.py
  • docs/guides/node-building/02_NODE_TYPES.md
🧰 Additional context used
📓 Path-based instructions (4)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Always use Poetry for Python package management and task execution - never use pip or python directly
Always use ModelOnexError with EnumCoreErrorCode for structured error handling, never raise generic Exception
Use @standard_error_handling decorator on async functions to eliminate boilerplate try/catch logic
Use duck typing with protocols instead of isinstance checks - protocols define contracts through interfaces, not runtime type checking
Always use 100% strict mypy type checking - all functions must have type annotations and no untyped definitions are allowed
Run code through black formatter, isort for import sorting, and ruff linter before committing
Use async/await pattern with asyncio for asynchronous operations - never use threading for I/O operations
Use ModelEventEnvelope for inter-service event-driven communication and process event payloads through envelope pattern

Files:

  • tests/unit/models/nodes/node_services/test_model_service_orchestrator_integration.py
  • tests/unit/models/nodes/node_services/test_model_service_effect_integration.py
  • tests/unit/models/nodes/node_services/test_model_service_compute_health.py
  • src/omnibase_core/models/core/__init__.py
  • tests/unit/models/nodes/node_services/test_model_service_compute_integration.py
  • src/omnibase_core/models/core/model_monitoring_metrics.py
  • tests/unit/models/nodes/node_services/test_model_service_reducer_health.py
  • src/omnibase_core/models/service/model_service_compute.py
  • src/omnibase_core/models/service/model_service_orchestrator.py
  • src/omnibase_core/infrastructure/infrastructure_bases.py
  • src/omnibase_core/models/registry/model_registry_health_report.py
  • tests/unit/models/nodes/node_services/test_model_service_reducer_invocation.py
  • tests/unit/nodes/test_retry_count_tracking.py
  • tests/unit/models/nodes/node_services/test_model_service_compute_lifecycle.py
  • tests/unit/primitives/test_model_semver.py
  • tests/unit/models/nodes/node_services/test_model_service_effect_invocation.py
  • tests/unit/models/nodes/node_services/test_model_service_reducer_lifecycle.py
  • src/omnibase_core/models/discovery/model_custom_metrics.py
  • src/omnibase_core/models/service/model_service_reducer.py
  • src/omnibase_core/models/discovery/model_custommetrics.py
  • src/omnibase_core/models/service/model_service_effect.py
  • tests/unit/models/nodes/node_services/test_model_service_compute_invocation.py
  • tests/unit/models/nodes/node_services/test_model_service_orchestrator_lifecycle.py
  • tests/unit/models/nodes/node_services/test_model_service_orchestrator_invocation.py
  • src/omnibase_core/models/discovery/model_metric_value.py
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

tests/**/*.py: Maintain minimum 60% code coverage with pytest tests - unit tests go in tests/unit/, integration tests in tests/integration/
Run pytest tests with parallelization disabled (-n 0 -xvs) for debugging and use standard pytest run for CI
Use @pytest.mark decorators (unit, integration, slow, smoke, performance) to categorize tests appropriately

Files:

  • tests/unit/models/nodes/node_services/test_model_service_orchestrator_integration.py
  • tests/unit/models/nodes/node_services/test_model_service_effect_integration.py
  • tests/unit/models/nodes/node_services/test_model_service_compute_health.py
  • tests/unit/models/nodes/node_services/test_model_service_compute_integration.py
  • tests/unit/models/nodes/node_services/test_model_service_reducer_health.py
  • tests/unit/models/nodes/node_services/test_model_service_reducer_invocation.py
  • tests/unit/nodes/test_retry_count_tracking.py
  • tests/unit/models/nodes/node_services/test_model_service_compute_lifecycle.py
  • tests/unit/primitives/test_model_semver.py
  • tests/unit/models/nodes/node_services/test_model_service_effect_invocation.py
  • tests/unit/models/nodes/node_services/test_model_service_reducer_lifecycle.py
  • tests/unit/models/nodes/node_services/test_model_service_compute_invocation.py
  • tests/unit/models/nodes/node_services/test_model_service_orchestrator_lifecycle.py
  • tests/unit/models/nodes/node_services/test_model_service_orchestrator_invocation.py
src/omnibase_core/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Use container.get_service('ProtocolName') for dependency resolution by protocol name, never by concrete class name

Files:

  • src/omnibase_core/models/core/__init__.py
  • src/omnibase_core/models/core/model_monitoring_metrics.py
  • src/omnibase_core/models/service/model_service_compute.py
  • src/omnibase_core/models/service/model_service_orchestrator.py
  • src/omnibase_core/infrastructure/infrastructure_bases.py
  • src/omnibase_core/models/registry/model_registry_health_report.py
  • src/omnibase_core/models/discovery/model_custom_metrics.py
  • src/omnibase_core/models/service/model_service_reducer.py
  • src/omnibase_core/models/discovery/model_custommetrics.py
  • src/omnibase_core/models/service/model_service_effect.py
  • src/omnibase_core/models/discovery/model_metric_value.py
src/omnibase_core/models/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Use Pydantic models for data validation and serialization - leverage Pydantic 2.11+ features for type safety

Files:

  • src/omnibase_core/models/core/__init__.py
  • src/omnibase_core/models/core/model_monitoring_metrics.py
  • src/omnibase_core/models/service/model_service_compute.py
  • src/omnibase_core/models/service/model_service_orchestrator.py
  • src/omnibase_core/models/registry/model_registry_health_report.py
  • src/omnibase_core/models/discovery/model_custom_metrics.py
  • src/omnibase_core/models/service/model_service_reducer.py
  • src/omnibase_core/models/discovery/model_custommetrics.py
  • src/omnibase_core/models/service/model_service_effect.py
  • src/omnibase_core/models/discovery/model_metric_value.py
🧠 Learnings (7)
📚 Learning: 2025-11-25T21:48:22.841Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T21:48:22.841Z
Learning: Applies to src/omnibase_core/nodes/**/*.py : Use ModelONEXContainer for dependency injection in node constructors, never use ModelContainer[T]

Applied to files:

  • tests/unit/models/nodes/node_services/test_model_service_orchestrator_integration.py
  • docs/guides/node-building/01_WHAT_IS_A_NODE.md
  • docs/architecture/overview.md
  • docs/architecture/ECOSYSTEM_DIRECTORY_STRUCTURE.md
  • tests/unit/models/nodes/node_services/test_model_service_compute_health.py
  • tests/unit/models/nodes/node_services/test_model_service_compute_integration.py
  • tests/unit/models/nodes/node_services/test_model_service_reducer_health.py
  • src/omnibase_core/models/service/model_service_compute.py
  • src/omnibase_core/models/service/model_service_orchestrator.py
  • src/omnibase_core/infrastructure/infrastructure_bases.py
  • tests/unit/nodes/test_retry_count_tracking.py
  • tests/unit/models/nodes/node_services/test_model_service_compute_lifecycle.py
  • docs/reference/api/nodes.md
  • tests/unit/models/nodes/node_services/test_model_service_reducer_lifecycle.py
  • src/omnibase_core/models/service/model_service_reducer.py
  • src/omnibase_core/models/service/model_service_effect.py
  • tests/unit/models/nodes/node_services/test_model_service_orchestrator_lifecycle.py
  • tests/unit/models/nodes/node_services/test_model_service_orchestrator_invocation.py
  • docs/reference/SERVICE_WRAPPERS.md
📚 Learning: 2025-11-25T21:48:22.841Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T21:48:22.841Z
Learning: Applies to src/omnibase_core/nodes/**/*.py : Use mixin classes (MixinDiscoveryResponder, MixinEventHandler, etc.) to add reusable behavior to nodes

Applied to files:

  • docs/architecture/overview.md
  • tests/unit/models/nodes/node_services/test_model_service_reducer_health.py
  • src/omnibase_core/infrastructure/infrastructure_bases.py
  • docs/reference/api/nodes.md
  • tests/unit/models/nodes/node_services/test_model_service_orchestrator_lifecycle.py
  • tests/unit/models/nodes/node_services/test_model_service_orchestrator_invocation.py
📚 Learning: 2025-11-25T21:48:22.841Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T21:48:22.841Z
Learning: Applies to src/omnibase_core/nodes/**/*.py : Implement EFFECT, COMPUTE, REDUCER, or ORCHESTRATOR node types following the four-node architecture pattern - data flows unidirectionally left to right

Applied to files:

  • docs/architecture/overview.md
  • tests/unit/models/nodes/node_services/test_model_service_effect_integration.py
  • docs/architecture/architecture-research/RESEARCH_REPORT_4_NODE_ARCHITECTURE.md
  • src/omnibase_core/infrastructure/infrastructure_bases.py
  • docs/reference/api/nodes.md
  • src/omnibase_core/models/service/model_service_effect.py
  • docs/reference/SERVICE_WRAPPERS.md
📚 Learning: 2025-11-25T21:48:22.841Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T21:48:22.841Z
Learning: Applies to src/omnibase_core/models/**/*.py : Use Pydantic models for data validation and serialization - leverage Pydantic 2.11+ features for type safety

Applied to files:

  • src/omnibase_core/models/core/__init__.py
  • src/omnibase_core/models/core/model_monitoring_metrics.py
  • src/omnibase_core/models/discovery/model_custommetrics.py
📚 Learning: 2025-11-25T21:48:22.841Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T21:48:22.841Z
Learning: Applies to src/omnibase_core/**/*.py : Use container.get_service('ProtocolName') for dependency resolution by protocol name, never by concrete class name

Applied to files:

  • src/omnibase_core/models/service/model_service_compute.py
  • src/omnibase_core/models/service/model_service_orchestrator.py
📚 Learning: 2025-11-25T21:48:22.841Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T21:48:22.841Z
Learning: Applies to **/*.py : Always use ModelOnexError with EnumCoreErrorCode for structured error handling, never raise generic Exception

Applied to files:

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

Applied to files:

  • src/omnibase_core/models/discovery/model_custom_metrics.py
  • src/omnibase_core/models/discovery/model_custommetrics.py
  • src/omnibase_core/models/discovery/model_metric_value.py
🧬 Code graph analysis (15)
tests/unit/models/nodes/node_services/test_model_service_effect_integration.py (1)
src/omnibase_core/models/service/model_service_effect.py (1)
  • ModelServiceEffect (74-133)
tests/unit/models/nodes/node_services/test_model_service_compute_health.py (1)
src/omnibase_core/models/service/model_service_compute.py (1)
  • ModelServiceCompute (61-118)
tests/unit/models/nodes/node_services/test_model_service_compute_integration.py (1)
src/omnibase_core/models/service/model_service_compute.py (1)
  • ModelServiceCompute (61-118)
src/omnibase_core/models/core/model_monitoring_metrics.py (1)
src/omnibase_core/models/discovery/model_metric_value.py (1)
  • ModelMetricValue (34-75)
tests/unit/models/nodes/node_services/test_model_service_reducer_health.py (1)
src/omnibase_core/models/service/model_service_reducer.py (1)
  • ModelServiceReducer (61-116)
src/omnibase_core/infrastructure/infrastructure_bases.py (2)
src/omnibase_core/models/service/model_service_compute.py (1)
  • ModelServiceCompute (61-118)
src/omnibase_core/models/service/model_service_effect.py (1)
  • ModelServiceEffect (74-133)
src/omnibase_core/models/registry/model_registry_health_report.py (1)
src/omnibase_core/models/discovery/model_metric_value.py (1)
  • ModelMetricValue (34-75)
tests/unit/models/nodes/node_services/test_model_service_reducer_invocation.py (1)
src/omnibase_core/models/service/model_service_reducer.py (1)
  • ModelServiceReducer (61-116)
tests/unit/nodes/test_retry_count_tracking.py (1)
src/omnibase_core/models/service/model_service_effect.py (1)
  • ModelServiceEffect (74-133)
tests/unit/models/nodes/node_services/test_model_service_compute_lifecycle.py (1)
src/omnibase_core/models/service/model_service_compute.py (1)
  • ModelServiceCompute (61-118)
tests/unit/models/nodes/node_services/test_model_service_effect_invocation.py (1)
src/omnibase_core/models/service/model_service_effect.py (1)
  • ModelServiceEffect (74-133)
tests/unit/models/nodes/node_services/test_model_service_reducer_lifecycle.py (1)
src/omnibase_core/models/service/model_service_reducer.py (1)
  • ModelServiceReducer (61-116)
src/omnibase_core/models/discovery/model_custom_metrics.py (2)
src/omnibase_core/models/discovery/model_custommetrics.py (1)
  • ModelCustomMetrics (9-43)
src/omnibase_core/models/discovery/model_metric_value.py (1)
  • ModelMetricValue (34-75)
src/omnibase_core/models/discovery/model_custommetrics.py (1)
src/omnibase_core/models/discovery/model_metric_value.py (1)
  • ModelMetricValue (34-75)
tests/unit/models/nodes/node_services/test_model_service_compute_invocation.py (1)
src/omnibase_core/models/service/model_service_compute.py (1)
  • ModelServiceCompute (61-118)
🪛 markdownlint-cli2 (0.18.1)
docs/reference/api/nodes.md

149-149: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


163-163: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


177-177: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


191-191: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🪛 Ruff (0.14.6)
src/omnibase_core/models/discovery/model_custom_metrics.py

18-18: __all__ is not sorted

Apply an isort-style sorting to __all__

(RUF022)

⏰ 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 (34)
src/omnibase_core/models/discovery/model_metric_value.py (3)

29-31: Good rationale for using bound= over constraints.

The comment correctly explains why bound=Union[...] is used instead of the typical constrained TypeVar pattern (TypeVar("T", str, int, float, bool)). This allows AnyMetricValue to be typed as ModelMetricValue[Union[str, int, float, bool]], which wouldn't work with discrete constraints.


34-52: LGTM!

The generic ModelMetricValue[MetricValueT] implementation is well-documented and correctly uses Pydantic 2.x generic model patterns. The value field properly uses the generic type parameter.


78-79: LGTM!

The AnyMetricValue type alias provides a clean way to handle collections with mixed metric value types, which is the practical use case for most metric containers.

src/omnibase_core/models/discovery/model_custommetrics.py (1)

3-6: LGTM!

The import updates correctly bring in AnyMetricValue alongside ModelMetricValue, aligning with the generic typing changes in the source module.

src/omnibase_core/models/service/model_service_compute.py (1)

14-18: LGTM!

The usage example import path correctly reflects the new module location (omnibase_core.models.service.model_service_compute), ensuring documentation stays consistent with the actual module structure after the migration.

tests/unit/models/nodes/node_services/test_model_service_reducer_health.py (1)

39-39: LGTM!

The import path update aligns with the broader module migration from omnibase_core.models.nodes.node_services to omnibase_core.models.service. The test file correctly imports ModelServiceReducer from its new location.

tests/unit/models/nodes/node_services/test_model_service_compute_health.py (1)

43-43: Import path updated to new service module is correct

Using omnibase_core.models.service.model_service_compute keeps this test aligned with the refactored service wrapper location; no further changes needed here.

tests/unit/models/nodes/node_services/test_model_service_orchestrator_lifecycle.py (1)

32-34: Orchestrator import refactor is consistent with new module layout

Importing ModelServiceOrchestrator from omnibase_core.models.service.model_service_orchestrator matches the service-wrapper relocation and keeps these lifecycle tests targeting the correct class.

docs/reference/SERVICE_WRAPPERS.md (1)

35-35: Documentation imports now match the consolidated models.service API

All service-wrapper examples (Effect, Compute, Orchestrator, Reducer, and testing snippets) now import from omnibase_core.models.service, which reflects the refactor and avoids stale paths in user-facing docs.

Also applies to: 80-80, 131-131, 185-185, 375-375, 399-399, 427-427

src/omnibase_core/models/service/model_service_reducer.py (1)

16-16: Reducer usage example import updated correctly

The docstring example now imports ModelServiceReducer from omnibase_core.models.service.model_service_reducer, matching the actual implementation location.

src/omnibase_core/models/service/model_service_effect.py (1)

16-16: Effect service usage example correctly references models.service

The import in the usage example now matches the real module path for ModelServiceEffect, preventing confusion for consumers.

tests/unit/models/nodes/node_services/test_model_service_compute_lifecycle.py (1)

30-30: Compute service lifecycle tests now target the relocated class

Switching to omnibase_core.models.service.model_service_compute keeps these lifecycle tests wired to the canonical ModelServiceCompute definition after the namespace move.

tests/unit/models/nodes/node_services/test_model_service_orchestrator_integration.py (1)

45-46: Integration tests correctly reference ModelServiceOrchestrator from models.service

Updating the import to omnibase_core.models.service.model_service_orchestrator aligns these MRO and integration tests with the new orchestrator module location without affecting behavior.

src/omnibase_core/models/service/model_service_orchestrator.py (1)

16-16: Orchestrator usage example import now matches public module path

The example correctly imports ModelServiceOrchestrator from omnibase_core.models.service.model_service_orchestrator, consistent with the refactor and other docs/tests.

tests/unit/nodes/test_retry_count_tracking.py (1)

10-10: LGTM! Import path updated to reflect module reorganization.

The import path correctly reflects the migration of service wrappers from omnibase_core.models.nodes.node_services to omnibase_core.models.service. No behavioral changes.

docs/guides/node-building/01_WHAT_IS_A_NODE.md (1)

379-379: LGTM! Documentation updated to reflect new module structure.

The import path in the Quick Reference example correctly reflects the migration of service wrappers to the omnibase_core.models.service namespace.

docs/architecture/overview.md (1)

267-267: LGTM! Documentation synchronized with module restructuring.

The example import path correctly reflects the service wrapper relocation to omnibase_core.models.service.

src/omnibase_core/models/registry/model_registry_health_report.py (1)

430-440: LGTM! Explicit typing improves mypy strict checking compliance.

The addition of explicit type annotation dict[str, AnyMetricValue] for custom_metrics correctly captures the heterogeneous metric value types (str, bool, int, float) used throughout the dictionary. This aligns with the coding guideline requiring 100% strict mypy type checking.

docs/architecture/ECOSYSTEM_DIRECTORY_STRUCTURE.md (1)

267-267: LGTM! Documentation reflects updated module organization.

The import path update aligns with the service wrapper migration to omnibase_core.models.service.

tests/unit/models/nodes/node_services/test_model_service_compute_integration.py (1)

32-32: LGTM! Test import updated to new service module location.

The import path correctly reflects the ModelServiceCompute relocation. Test coverage and assertions remain unchanged.

tests/unit/models/nodes/node_services/test_model_service_reducer_lifecycle.py (1)

22-22: LGTM! Test import path updated for service wrapper relocation.

The import correctly references ModelServiceReducer at its new location in omnibase_core.models.service. Test functionality unchanged.

tests/unit/models/nodes/node_services/test_model_service_orchestrator_invocation.py (1)

31-33: LGTM! Test import reflects service wrapper module migration.

The import path correctly references ModelServiceOrchestrator at its new location in omnibase_core.models.service. Test coverage for tool invocation and workflow coordination remains unchanged.

tests/unit/models/nodes/node_services/test_model_service_compute_invocation.py (1)

25-35: ModelServiceCompute import path update looks correct

Importing ModelServiceCompute from omnibase_core.models.service.model_service_compute aligns with the new service wrapper location and matches the class definition module. No further changes needed.

tests/unit/models/nodes/node_services/test_model_service_reducer_invocation.py (1)

33-52: ModelServiceReducer import path matches new service wrapper location

The updated import from omnibase_core.models.service.model_service_reducer matches the service module and keeps the test logic intact.

tests/unit/models/nodes/node_services/test_model_service_effect_integration.py (1)

37-47: ModelServiceEffect import path aligned with service module

Importing ModelServiceEffect from omnibase_core.models.service.model_service_effect is consistent with the new service namespace and other references.

src/omnibase_core/models/core/model_monitoring_metrics.py (1)

12-15: custom_metrics now correctly uses AnyMetricValue for generic metric typing

Bringing in AnyMetricValue and updating custom_metrics to dict[str, AnyMetricValue] | None matches the new generic metric value model and keeps the default behavior ({} via default_factory) while still accepting None for compatibility. No issues spotted.

Also applies to: 91-94

tests/unit/models/nodes/node_services/test_model_service_effect_invocation.py (1)

16-27: ModelServiceEffect import path updated consistently

The import now points to omnibase_core.models.service.model_service_effect, which matches the service wrapper module and keeps the test behavior unchanged.

src/omnibase_core/infrastructure/infrastructure_bases.py (1)

29-40: Infrastructure service wrapper imports now aligned with service modules

Using:

from omnibase_core.models.service.model_service_compute import ModelServiceCompute
from omnibase_core.models.service.model_service_effect import ModelServiceEffect
# ...
# from omnibase_core.models.service.model_service_orchestrator import ModelServiceOrchestrator
# from omnibase_core.models.service.model_service_reducer import ModelServiceReducer

keeps this infra module in sync with the new service wrapper locations and the usage examples in the docstring. __all__ remains accurate.

docs/reference/api/nodes.md (2)

143-197: Service wrapper API docs now point to the correct modules

The “Location” strings and example imports for:

  • ModelServiceCompute
  • ModelServiceEffect
  • ModelServiceReducer
  • ModelServiceOrchestrator

now consistently use the omnibase_core.models.service.model_service_* paths, which matches the service wrapper modules and the rest of the repo. Examples remain accurate with respect to constructor signatures and mixin composition.


331-337: Thread-safety section import updated consistently

The thread-safety example now imports ModelServiceCompute from omnibase_core.models.service.model_service_compute, which matches the rest of the documentation and the infrastructure base module.

src/omnibase_core/models/core/__init__.py (1)

10-11: LGTM! Documentation clearly guides developers to the new location.

The updated note provides clear guidance on where to import ModelSemVer from after the module restructuring.

docs/guides/VERSION_FIELD_AUTOMATION_STRATEGY.md (1)

161-161: LGTM! Command examples consistently updated throughout the guide.

All bash command examples have been updated to use the new import path omnibase_core.models.primitives.model_semver. The changes are consistent across both the Phase 1 section and the Execution Order section.

Also applies to: 177-180, 647-649

scripts/fix_version_field_pattern1.sh (1)

194-194: Import path verification complete — no issues found.

The import path omnibase_core.models.primitives.model_semver is correct and valid. ModelSemVer is properly defined at src/omnibase_core/models/primitives/model_semver.py and is widely used throughout the codebase with this exact import path. No lingering references to the old incorrect path remain. The script will work as intended.

tests/unit/primitives/test_model_semver.py (1)

18-23: Import path and symbol exports are correct — all four symbols properly defined and module-level.

Verification confirms the import statement is valid:

  • ModelSemVer: class defined at line 15
  • SemVerField: type alias at line 117 (SemVerField = ModelSemVer)
  • parse_semver_from_string: function at line 136
  • parse_input_state_version: function at line 181

All symbols are defined at module level in ./src/omnibase_core/models/primitives/model_semver.py and will be properly exported. The import path is consistent with the module restructuring.

Note: The test execution verification cannot be completed in the sandbox environment (Poetry is unavailable), but static analysis confirms no import errors will occur when the tests are run locally.

Scripts cleanup:
- Remove ~70 one-time migration/fix scripts
- Move validation scripts to scripts/validation/
- Remove empty directories (intelligence/, performance/, migration/, spi-copy/, templates/)
- Update validate-doc-links.py references in CI and pre-commit

Code cleanup:
- Remove 1,658 unused imports across src/ and tests/
- Update ECOSYSTEM_DIRECTORY_STRUCTURE.md for removed modules
- Fix stale script references in 5 documentation files
- Remove stale TODO and update version refs in model_onex_container.py

Impact: 1,071 files changed, -27,472 lines of dead code

@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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 10e4d3a and 1c76484.

📒 Files selected for processing (86)
  • .github/workflows/test.yml (1 hunks)
  • .pre-commit-config.yaml (1 hunks)
  • docs/architecture/ECOSYSTEM_DIRECTORY_STRUCTURE.md (4 hunks)
  • docs/ci/CI_MONITORING_GUIDE.md (1 hunks)
  • docs/conventions/VERSION_SEMANTICS.md (1 hunks)
  • docs/guides/INTENT_PUBLISHER_TESTING_DOCUMENTATION.md (1 hunks)
  • docs/guides/VERSION_FIELD_AUTOMATION_STRATEGY.md (6 hunks)
  • docs/testing/CI_TEST_STRATEGY.md (1 hunks)
  • scripts/PROTOCOL_IMPLEMENTATION_REPORT.md (0 hunks)
  • scripts/README_PYDANTIC_FIXERS.md (0 hunks)
  • scripts/TYPE_SAFETY_README.md (0 hunks)
  • scripts/add_missing_imports.py (0 hunks)
  • scripts/add_modelonexerror_import.py (0 hunks)
  • scripts/analyze-to-dict-methods.py (0 hunks)
  • scripts/analyze_exception_handling.py (0 hunks)
  • scripts/analyze_multi_enum_files.py (0 hunks)
  • scripts/analyze_mypy_errors.py (0 hunks)
  • scripts/analyze_name_errors.py (0 hunks)
  • scripts/analyze_pydantic_errors.py (0 hunks)
  • scripts/apply_fixer_to_models.sh (0 hunks)
  • scripts/audit_naming_conventions.py (0 hunks)
  • scripts/auto_fix_type_annotations.py (0 hunks)
  • scripts/batch_fix_all_models.py (0 hunks)
  • scripts/batch_fix_name_errors.py (0 hunks)
  • scripts/batch_fix_string_versions.sh (0 hunks)
  • scripts/comprehensive_arg_type_fix.py (0 hunks)
  • scripts/execute_duplicate_resolution.sh (0 hunks)
  • scripts/fix-import-patterns.py (0 hunks)
  • scripts/fix-imports.py (0 hunks)
  • scripts/fix-semi-redundant-to-dict.py (0 hunks)
  • scripts/fix_all_precommit_errors.py (0 hunks)
  • scripts/fix_all_string_id_version_violations.py (0 hunks)
  • scripts/fix_all_syntax_errors.sh (0 hunks)
  • scripts/fix_arg_type_errors.py (0 hunks)
  • scripts/fix_attr_defined_errors.py (0 hunks)
  • scripts/fix_computation_type_enum.py (0 hunks)
  • scripts/fix_default_factory.py (0 hunks)
  • scripts/fix_documentation_links.py (0 hunks)
  • scripts/fix_enum_naming.py (0 hunks)
  • scripts/fix_error_raising_violations.py (0 hunks)
  • scripts/fix_field_positional_defaults.py (0 hunks)
  • scripts/fix_final_precommit_errors.py (0 hunks)
  • scripts/fix_id_fallbacks.py (0 hunks)
  • scripts/fix_import_syntax_errors.py (0 hunks)
  • scripts/fix_incomplete_imports.py (0 hunks)
  • scripts/fix_misplaced_imports.py (0 hunks)
  • scripts/fix_missing_imports.py (0 hunks)
  • scripts/fix_missing_self_comprehensive.py (0 hunks)
  • scripts/fix_mypy_errors_batch.py (0 hunks)
  • scripts/fix_mypy_type_annotations.py (0 hunks)
  • scripts/fix_name_defined_errors.py (0 hunks)
  • scripts/fix_no_any_return_errors.py (0 hunks)
  • scripts/fix_no_redef_errors.py (0 hunks)
  • scripts/fix_pydantic_field_syntax.py (0 hunks)
  • scripts/fix_pydantic_missing_fields.py (0 hunks)
  • scripts/fix_remaining_id_version_violations.py (0 hunks)
  • scripts/fix_self_multiline.py (0 hunks)
  • scripts/fix_simple_enum_renames.py (0 hunks)
  • scripts/fix_string_id_violations.py (0 hunks)
  • scripts/fix_string_version_violations.py (0 hunks)
  • scripts/fix_string_version_violations_v2.py (0 hunks)
  • scripts/fix_string_versions_ast.py (0 hunks)
  • scripts/fix_string_versions_regex.py (0 hunks)
  • scripts/fix_syntax_errors.py (0 hunks)
  • scripts/fix_syntax_errors_v2.py (0 hunks)
  • scripts/fix_type_annotations.py (0 hunks)
  • scripts/fix_type_annotations_batch2.py (0 hunks)
  • scripts/fix_uuid_errors.py (0 hunks)
  • scripts/fix_valueerror_to_onexerror.py (0 hunks)
  • scripts/fix_version_field_pattern1.sh (0 hunks)
  • scripts/fix_version_field_pattern2.py (0 hunks)
  • scripts/generate_all_exports.py (0 hunks)
  • scripts/implement_protocols.py (0 hunks)
  • scripts/intelligence/comprehensive_any_type_detector.py (0 hunks)
  • scripts/intelligence/enhanced_type_system_validator.py (0 hunks)
  • scripts/intelligence/intelligence_hook.py (0 hunks)
  • scripts/migrate-pydantic-dict-calls.py (0 hunks)
  • scripts/migrate_modelschemavalue.py (0 hunks)
  • scripts/migrate_onex_error.py (0 hunks)
  • scripts/migration/fix_version_defaults.py (0 hunks)
  • scripts/migration/fix_version_defaults_v2.py (0 hunks)
  • scripts/migration/migrate_protocols_safe.py (0 hunks)
  • scripts/migration/remove_version_default_factory.py (0 hunks)
  • scripts/performance/analyze_imports.py (0 hunks)
  • scripts/performance/benchmark_serialization.py (0 hunks)
  • scripts/performance/memory_usage_analysis.py (0 hunks)
💤 Files with no reviewable changes (78)
  • scripts/fix_valueerror_to_onexerror.py
  • scripts/PROTOCOL_IMPLEMENTATION_REPORT.md
  • scripts/batch_fix_string_versions.sh
  • scripts/execute_duplicate_resolution.sh
  • scripts/add_missing_imports.py
  • scripts/fix_uuid_errors.py
  • scripts/README_PYDANTIC_FIXERS.md
  • scripts/fix_all_syntax_errors.sh
  • scripts/apply_fixer_to_models.sh
  • scripts/fix_import_syntax_errors.py
  • scripts/fix_mypy_errors_batch.py
  • scripts/analyze_exception_handling.py
  • scripts/fix_syntax_errors.py
  • scripts/fix_pydantic_field_syntax.py
  • scripts/fix_id_fallbacks.py
  • scripts/fix-import-patterns.py
  • scripts/analyze_name_errors.py
  • scripts/audit_naming_conventions.py
  • scripts/fix_mypy_type_annotations.py
  • scripts/fix_version_field_pattern2.py
  • scripts/batch_fix_all_models.py
  • scripts/analyze_multi_enum_files.py
  • scripts/fix_type_annotations_batch2.py
  • scripts/auto_fix_type_annotations.py
  • scripts/add_modelonexerror_import.py
  • scripts/migration/fix_version_defaults_v2.py
  • scripts/fix_attr_defined_errors.py
  • scripts/fix_version_field_pattern1.sh
  • scripts/fix_string_version_violations_v2.py
  • scripts/fix_incomplete_imports.py
  • scripts/fix-semi-redundant-to-dict.py
  • scripts/fix_arg_type_errors.py
  • scripts/generate_all_exports.py
  • scripts/TYPE_SAFETY_README.md
  • scripts/fix_remaining_id_version_violations.py
  • scripts/batch_fix_name_errors.py
  • scripts/intelligence/intelligence_hook.py
  • scripts/fix_pydantic_missing_fields.py
  • scripts/fix_missing_imports.py
  • scripts/intelligence/comprehensive_any_type_detector.py
  • scripts/fix_self_multiline.py
  • scripts/migrate_modelschemavalue.py
  • scripts/performance/memory_usage_analysis.py
  • scripts/fix_final_precommit_errors.py
  • scripts/analyze-to-dict-methods.py
  • scripts/analyze_pydantic_errors.py
  • scripts/fix_name_defined_errors.py
  • scripts/fix_no_any_return_errors.py
  • scripts/fix_enum_naming.py
  • scripts/performance/analyze_imports.py
  • scripts/migrate_onex_error.py
  • scripts/fix-imports.py
  • scripts/fix_all_precommit_errors.py
  • scripts/fix_string_versions_ast.py
  • scripts/fix_simple_enum_renames.py
  • scripts/fix_error_raising_violations.py
  • scripts/fix_field_positional_defaults.py
  • scripts/fix_string_versions_regex.py
  • scripts/migration/fix_version_defaults.py
  • scripts/fix_computation_type_enum.py
  • scripts/fix_type_annotations.py
  • scripts/migration/migrate_protocols_safe.py
  • scripts/comprehensive_arg_type_fix.py
  • scripts/fix_no_redef_errors.py
  • scripts/fix_syntax_errors_v2.py
  • scripts/fix_misplaced_imports.py
  • scripts/analyze_mypy_errors.py
  • scripts/fix_missing_self_comprehensive.py
  • scripts/fix_documentation_links.py
  • scripts/intelligence/enhanced_type_system_validator.py
  • scripts/fix_all_string_id_version_violations.py
  • scripts/migration/remove_version_default_factory.py
  • scripts/migrate-pydantic-dict-calls.py
  • scripts/implement_protocols.py
  • scripts/fix_default_factory.py
  • scripts/performance/benchmark_serialization.py
  • scripts/fix_string_version_violations.py
  • scripts/fix_string_id_violations.py
✅ Files skipped from review due to trivial changes (2)
  • docs/guides/INTENT_PUBLISHER_TESTING_DOCUMENTATION.md
  • docs/ci/CI_MONITORING_GUIDE.md
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-11-25T21:48:22.841Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T21:48:22.841Z
Learning: Applies to **/*.py : Always use Poetry for Python package management and task execution - never use pip or python directly

Applied to files:

  • docs/guides/VERSION_FIELD_AUTOMATION_STRATEGY.md
📚 Learning: 2025-11-25T21:48:22.841Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T21:48:22.841Z
Learning: Applies to src/omnibase_core/nodes/**/*.py : Use ModelONEXContainer for dependency injection in node constructors, never use ModelContainer[T]

Applied to files:

  • docs/architecture/ECOSYSTEM_DIRECTORY_STRUCTURE.md
🪛 LanguageTool
docs/guides/VERSION_FIELD_AUTOMATION_STRATEGY.md

[style] ~331-~331: Consider replacing this word to strengthen your wording.
Context: ...is script was a one-time migration tool and has been removed after the migration wa...

(AND_THAT)

🪛 markdownlint-cli2 (0.18.1)
docs/architecture/ECOSYSTEM_DIRECTORY_STRUCTURE.md

265-265: 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). (3)
  • GitHub Check: Code Quality
  • GitHub Check: Smoke Tests
  • GitHub Check: claude-review
🔇 Additional comments (7)
docs/conventions/VERSION_SEMANTICS.md (1)

659-673: Documentation clarification is well-executed.

The updated pre-commit validation section appropriately distinguishes between proposed enhancements and current enforcement mechanisms. Commenting out the example validation commands prevents users from attempting to run scripts that don't exist, and the explanatory note clearly states that compliance is currently enforced through code review and type checking (mypy strict mode).

docs/architecture/ECOSYSTEM_DIRECTORY_STRUCTURE.md (1)

41-46: Documentation correctly reflects service wrapper module reorganization.

The updates to paths (models/nodes/node_services/ → models/service/), import statements (from omnibase_core.models.service import), and service wrapper examples align well with the PR's core objective of reorganizing service wrappers. The documentation is internally consistent and properly guides developers to the new module locations.

Also applies to: 263-263, 266-266

.github/workflows/test.yml (1)

232-235: Consistent path migration across configs and workflows.

Both .pre-commit-config.yaml (line 327) and .github/workflows/test.yml (line 234) have been updated consistently to reflect the script relocation. The changes align with the PR's validation script reorganization objective.

Use the verification script provided in the .pre-commit-config.yaml review to confirm the script path migration is complete and all references have been updated.

.pre-commit-config.yaml (1)

325-333: Script relocation is complete and consistent.

The verification confirms:

  • ✓ New path scripts/validation/validate-doc-links.py exists
  • ✓ Old path has been cleaned up (no orphaned script)
  • ✓ No dangling references to the old path pattern

The path update in .pre-commit-config.yaml (line 327) correctly reflects the reorganization, and the file has been properly moved rather than copied.

docs/guides/VERSION_FIELD_AUTOMATION_STRATEGY.md (3)

230-288: Document appropriately marks removed migration scripts as historical reference.

The annotations marking scripts/fix_version_field_pattern1.sh (line 238) and scripts/fix_version_field_pattern2.py (line 329) as "REMOVED" with supporting notes (lines 232, 331) are clear and appropriately contextualize the preserved code examples as historical reference. This maintains the document's value as a record of how the migration was accomplished.


661-689: Verify phase completion markers align with actual PR scope.

The document marks Phase 1–3 migration steps as "COMPLETED" (lines 661, 676) and transitions command examples to "Historical Reference" (lines 563, 663, 678). Confirm these phases were indeed completed as part of the current PR or in prior work, and that users should not attempt to run these removed scripts. If the migration was completed in an earlier PR, consider adding a note explaining when/where it was done.


160-183: Import path migration verified and accurately documented.

All verification points confirm the documentation is correct:

  • omnibase_core.models.primitives.model_semver exists and is the canonical location for ModelSemVer
  • ModelSemVer class is properly defined and accessible at line 15 of the module
  • Old import path (omnibase_core.primitives.model_semver) no longer exists in the codebase
  • Active code consistently uses the new import path across 15+ test files and throughout the codebase

The documentation accurately reflects the completed migration.

**Location**: `omnibase_core/src/omnibase_core/models/nodes/node_services/`
**Location**: `omnibase_core/src/omnibase_core/models/service/`

```

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

Add language specifications to fenced code blocks.

Markdown linting requires fenced code blocks to specify a language for syntax highlighting. Three code blocks are missing language specifications.

Apply these diffs to add python language specifications:

 **Location**: `omnibase_core/src/omnibase_core/models/service/`
 
-```
+```python
 from omnibase_core.models.service import ModelServiceCompute
 **Location**: `omninode_bridge/src/omninode_bridge/nodes/`
 
-```
+```python
 from omnibase_core.nodes.node_effect import NodeEffect
 **Location**: `omnibase_infra/src/omnibase_infra/nodes/`
 
-```
+```python
 from omnibase_core.infrastructure.infrastructure_bases import ModelServiceEffect

Also applies to: 284-285, 301-302

🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

265-265: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
In docs/architecture/ECOSYSTEM_DIRECTORY_STRUCTURE.md around lines 265 (and
similarly for 284-285 and 301-302), several fenced code blocks are missing
language identifiers; update each opening triple-backtick for the listed blocks
to ```python so the blocks read as Python code fences (i.e., replace ``` with
```python at the start of each of the three code blocks referenced).

**Configuration**:
```
python3 scripts/validate-doc-links.py --fix-case
python3 scripts/validation/validate-doc-links.py --fix-case

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
# Verify script path update and search for orphaned references

echo "=== Checking new script path ==="
if [ -f "scripts/validation/validate-doc-links.py" ]; then
  echo "✓ New script path found: scripts/validation/validate-doc-links.py"
else
  echo "✗ New script path NOT found"
fi

echo ""
echo "=== Checking old script path ==="
if [ -f "scripts/validate-doc-links.py" ]; then
  echo "⚠ Old script path still exists: scripts/validate-doc-links.py"
else
  echo "✓ Old script path removed"
fi

echo ""
echo "=== Searching for references to old path ==="
rg -n "scripts/validate-doc-links\.py" --type=md --type=py --type=yaml --type=toml 2>/dev/null | head -20
if [ $? -eq 1 ]; then
  echo "✓ No references to old path found in docs/code"
fi

echo ""
echo "=== Checking if scripts/validation directory exists ==="
if [ -d "scripts/validation" ]; then
  echo "✓ Directory scripts/validation exists"
  echo "Contents:"
  ls -la scripts/validation/ 2>/dev/null | head -10
else
  echo "✗ Directory scripts/validation does NOT exist"
fi

Repository: OmniNode-ai/omnibase_core

Length of output: 1203


Update inline documentation within the script to reflect the new path location.

The path update in the documentation is correct—scripts/validation/validate-doc-links.py exists and the old path has been removed. However, the script's own inline documentation still references the old path. Lines 12–13 in scripts/validation/validate-doc-links.py contain stale references:

poetry run python scripts/validate-doc-links.py
poetry run python scripts/validate-doc-links.py --fix-case

These should be updated to:

poetry run python scripts/validation/validate-doc-links.py
poetry run python scripts/validation/validate-doc-links.py --fix-case
🤖 Prompt for AI Agents
In scripts/validation/validate-doc-links.py around lines 12–13, the script's
inline documentation/docstring still references the old path
(scripts/validate-doc-links.py); update those two lines to use the new path
scripts/validation/validate-doc-links.py (i.e., replace both occurrences of
"poetry run python scripts/validate-doc-links.py" and the "--fix-case" variant
with the new path) and ensure any other examples or usage strings in the file
reflect the new location.

@claude

claude Bot commented Nov 27, 2025

Copy link
Copy Markdown

PR #92 Code Review: ApplicationContext for Thread-Safe Container Management

Executive Summary

This PR introduces a contextvars-based container management system to replace the legacy singleton holder pattern. The implementation is well-designed but has two critical issues that must be fixed before merging.


🚨 Critical Issues (Must Fix)

1. Container Creation Bypasses ApplicationContext - BLOCKING

Location: src/omnibase_core/logging/emit.py:467

_get_protocol_services_cached() creates a new container directly instead of using context:

container = ModelONEXContainer()  # Creates NEW container, ignoring context\!

Fix: Use get_model_onex_container_sync() to get context-managed container.


2. Race Condition in TTL Cache Clearing - BLOCKING

Location: src/omnibase_core/logging/emit.py:451-479

The TTL cache clearing is NOT thread-safe. Multiple pytest-xdist workers can simultaneously check TTL and call cache_clear().

Fix: Add threading.Lock around the TTL check-and-clear operation.


⚠️ High Priority

3. asyncio.run() Context Isolation

Location: src/omnibase_core/models/container/model_onex_container.py:771

Add comment explaining asyncio.run() creates isolated context and contextvars don't propagate back.

4. Registry Holders May Be Redundant

Verify if util_*_registry_holder.py files are still needed given ApplicationContext.


✅ What's Great

  1. Solid Architecture using contextvars
  2. Comprehensive test isolation fixtures
  3. Massive cleanup (28k+ lines removed)
  4. Follows ONEX patterns in CLAUDE.md
  5. Good documentation

📊 Overall Assessment

Rating: ⚠️ Approve with Required Changes

Excellent architectural direction. Issues #1 and #2 must be fixed before merging.


🎯 Required Actions

  • Fix emit.py:467 to use get_model_onex_container_sync()
  • Add threading.Lock to emit.py TTL cache clearing
  • Run poetry run mypy src/omnibase_core/context/ --strict
  • Run poetry run pytest tests/unit/ -n 4

Review Date: 2025-11-27 | Reviewer: Claude (Sonnet 4.5)

@claude

claude Bot commented Nov 27, 2025

Copy link
Copy Markdown

Pull Request Review - PR #92: ApplicationContext Migration

Overview

This is an excellent architectural improvement that migrates from singleton holders to Python's contextvars for thread-safe container management. The implementation is well-designed, thoroughly tested, and addresses critical test isolation issues in parallel execution.

Summary

✅ Approved - This PR represents a significant quality improvement with proper migration strategy, comprehensive testing, and solid architectural foundation.


Strengths

1. Solid Architecture ⭐⭐⭐⭐⭐

The use of contextvars is the right solution for this problem:

  • ✅ Inherent thread safety (no manual locks needed)
  • ✅ Proper async task isolation (child tasks inherit parent context)
  • ✅ No global mutable state
  • ✅ Clean, Pythonic API
  • ✅ Follows standard library best practices

Example of clean design (application_context.py:146-161):

def get_current_container() -> ModelONEXContainer | None:
    """Get the container from the current context."""
    return _current_container.get()

Simple, clear, and thread-safe.

2. Comprehensive Test Isolation ⭐⭐⭐⭐⭐

The new tests/fixtures/isolation.py provides excellent test isolation support:

  • ✅ Multiple fixtures for different isolation needs (reset_all_singletons, reset_container_singleton, etc.)
  • ✅ Context manager pattern for cleanup
  • ✅ Token-based state restoration
  • ✅ Backward compatibility with existing test suite
  • ✅ Fresh event loop fixture for async test isolation

Particularly good: SingletonResetContext class with proper state management and exception safety.

3. Backward Compatibility ⭐⭐⭐⭐⭐

Migration is handled exceptionally well:

  • ✅ Existing fixture names unchanged
  • ✅ Registry access functions maintain same API
  • ✅ Deprecated code includes clear migration guide
  • ✅ Legacy keys still accepted where appropriate

Example (util_singleton_holders.py):
The deprecation notice provides clear migration path with before/after examples.

4. Thorough Testing

The test_application_context.py test suite covers:

  • ✅ Basic operations (get, set, reset)
  • ✅ Sync and async context managers
  • ✅ Thread isolation
  • ✅ Async task inheritance
  • ✅ Nested contexts
  • ✅ Exception safety

5. Clean Implementation

  • ✅ Type hints throughout (mypy strict compliance expected)
  • ✅ Comprehensive docstrings
  • ✅ Clear separation of concerns
  • ✅ No code duplication

Issues & Recommendations

🟡 Minor Issue #1: Potential Performance Cost in get_model_onex_container_sync()

Location: model_onex_container.py (likely around container creation)

Issue: The sync container getter uses asyncio.run() which creates a new event loop each time there's no cached container. While this only happens once per context, it's still a relatively expensive operation.

Current Pattern:

def get_model_onex_container_sync() -> ModelONEXContainer:
    container = get_current_container()
    if container is not None:
        return container
    
    # Creates NEW event loop each time\!
    container = asyncio.run(create_model_onex_container())
    set_current_container(container)
    return container

Recommendation:

  • Document this behavior clearly (may already be done)
  • Consider adding a warning if called frequently
  • Consider lazy initialization strategy for sync contexts

Severity: Low - Mitigated by caching after first creation


🟡 Minor Issue #2: Context Propagation Awareness

Issue: Developers need to understand that asyncio.run() creates a new context that doesn't propagate back to the parent automatically.

Example from code:

container = asyncio.run(create_model_onex_container())  # New context
set_current_container(container)  # Must explicitly set in current context

Recommendation:

  • Add documentation about context propagation rules
  • Include examples in docstrings showing when explicit set_current_container() is needed
  • Consider adding to docs/guides/THREADING.md or similar

Severity: Low - Code handles it correctly, just needs documentation


🟢 Suggestion #1: Add Debug Utilities

Recommendation: Consider adding debug utilities for development:

def get_container_debug_info() -> dict[str, Any]:
    """Get debug information about current container state."""
    return {
        "has_container": get_current_container() is not None,
        "container_id": id(get_current_container()) if get_current_container() else None,
        "thread_id": threading.get_ident(),
    }

This would help developers debug context isolation issues during development.


🟢 Suggestion #2: Performance Monitoring

Recommendation: Consider adding metrics/logging for:

  • Number of times asyncio.run() is called in get_model_onex_container_sync()
  • Container creation frequency
  • Context switches

This would help identify if the event loop creation becomes a bottleneck.


🟢 Suggestion #3: Update CLAUDE.md

Recommendation: The CLAUDE.md file should be updated to:

  • Document the new ApplicationContext pattern
  • Add examples of proper context usage
  • Update the "Thread Safety" section to mention contextvars
  • Add migration guide for downstream projects

Example section to add:

### Container Context Management

The container uses `contextvars` for thread-safe isolation:

```python
from omnibase_core.context import ApplicationContext

# Async usage
async with ApplicationContext(container):
    # Container available in this context
    current = get_current_container()

# Sync usage
with ApplicationContext.sync(container):
    current = get_current_container()

---

## Code Quality Assessment

| Aspect | Rating | Notes |
|--------|--------|-------|
| **Architecture** | ⭐⭐⭐⭐⭐ | Excellent use of contextvars, clean design |
| **Code Quality** | ⭐⭐⭐⭐⭐ | Well-structured, typed, documented |
| **Testing** | ⭐⭐⭐⭐⭐ | Comprehensive test coverage |
| **Documentation** | ⭐⭐⭐⭐ | Good inline docs, could add migration guide |
| **Backward Compatibility** | ⭐⭐⭐⭐⭐ | Excellent migration strategy |
| **Thread Safety** | ⭐⭐⭐⭐⭐ | Properly isolated via contextvars |
| **Security** | ⭐⭐⭐⭐⭐ | No security concerns identified |

---

## Security Assessment

✅ **No security concerns identified**

- No injection vulnerabilities
- No unsafe imports or dynamic code execution
- Proper exception handling
- No credential or secret management issues
- Context isolation prevents cross-context data leakage

---

## Test Coverage Assessment

Based on the PR description and fixture implementation:

✅ **Excellent test isolation support**:
- Multiple fixtures for different isolation needs
- Proper cleanup in all scenarios
- Exception-safe context management
- Fresh event loop support for async tests

**Expected Impact on CI**:
- Should **improve** test reliability in parallel execution
- May slightly increase setup/teardown time (minimal)
- Should eliminate test interference issues
- Compatible with existing 20-split strategy

---

## Performance Considerations

| Aspect | Impact | Notes |
|--------|--------|-------|
| **Context Variable Access** | ✅ Minimal | O(1) lookup, thread-local |
| **Event Loop Creation** | 🟡 Low | Only on first sync container access per context |
| **Test Fixtures** | ✅ Minimal | Small overhead for cleanup |
| **Memory Usage** | ✅ Minimal | One container reference per context |
| **CI Runtime** | ✅ Neutral/Positive | Better isolation may prevent flaky test reruns |

---

## Migration Checklist

The PR addresses all critical migration aspects:

- ✅ New `ApplicationContext` module implemented
- ✅ Container integration completed
- ✅ All registries migrated to container-based access
- ✅ Test isolation fixtures implemented
- ✅ Legacy singleton holders deprecated with migration guide
- ✅ Backward compatibility maintained
- ✅ Comprehensive test coverage
- ⚠️ Documentation updates needed (CLAUDE.md, guides)
- ⚠️ Migration guide for downstream projects would be helpful

---

## Recommendations for Merge

### Before Merge:

1. ✅ **Verify CI passes** - Ensure all 20 parallel splits complete successfully
2. ✅ **Check test stability** - Run full test suite multiple times to ensure no flaky tests
3. 🟡 **Update CLAUDE.md** - Add ApplicationContext documentation and migration examples
4. 🟡 **Add migration guide** - Document for downstream projects using omnibase_core

### After Merge:

1. Monitor CI performance for any regressions
2. Watch for context-related issues in downstream projects
3. Consider adding debug utilities if context issues arise
4. Update other ONEX projects with migration guide

---

## Final Verdict

### ✅ **APPROVED - Excellent Work\!**

This PR represents a **significant architectural improvement** that:
1. Eliminates global mutable state
2. Provides proper thread and async safety
3. Enables reliable parallel test execution
4. Maintains backward compatibility
5. Follows Python best practices

The implementation is **production-ready** with only minor documentation improvements recommended.

### Quality Score: **95/100**

**Deductions**:
- -3 for missing CLAUDE.md updates
- -2 for potential event loop creation overhead (minor)

---

## Questions for Author

1. Have you run the full test suite multiple times to verify test stability?
2. Any performance benchmarks comparing before/after on CI?
3. Plans to update CLAUDE.md with ApplicationContext examples?
4. Should we add debug utilities for context inspection?

---

**Reviewed by**: Claude (AI Code Reviewer)  
**Review Date**: 2025-11-27  
**Correlation ID**: `context-migration-review-pr92`

---

### Additional Context

For reviewers examining this PR:
- **Key Files**: `src/omnibase_core/context/application_context.py`, `tests/fixtures/isolation.py`
- **Migration Guide**: `src/omnibase_core/utils/util_singleton_holders.py`
- **Test Coverage**: `tests/unit/context/test_application_context.py`
- **Integration Points**: All registry files, container module

**ONEX Alignment**: ✅ Fully aligned with ONEX architecture principles and Poetry-based development workflow.

@claude

claude Bot commented Nov 27, 2025

Copy link
Copy Markdown

Comprehensive Code Review - PR #92

🎯 Overall Assessment: APPROVE with Minor Recommendations

This is an excellent architectural improvement that eliminates a fundamental source of test flakiness in parallel execution. The migration from global singleton holders to contextvars-based container management is well-executed and aligns perfectly with ONEX framework principles.


✅ Strengths

1. Solid Architecture & Design

  • ✨ contextvars is the ideal solution for this problem - provides proper isolation between async tasks and threads
  • 🏗️ Clean migration path with comprehensive deprecation documentation
  • 🎯 Follows ONEX protocol-driven DI patterns consistently
  • 🧪 Excellent test coverage with 391 lines of comprehensive tests for the new ApplicationContext

2. Code Quality

  • 📝 Exceptional documentation throughout - docstrings explain the "why" not just the "what"
  • 🔒 Type-safe implementation with proper TYPE_CHECKING guards
  • 🎨 Clean API design with both sync and async context managers
  • ♻️ DRY principle well-applied - ApplicationContext implements both __enter__/__exit__ and __aenter__/__aexit__

3. Test Isolation Strategy

  • 🧩 SingletonResetContext properly saves/restores state with token-based reset
  • 🔄 Multiple fixtures for different isolation needs (reset_all_singletons, reset_container_singleton, etc.)
  • 🎭 fresh_asyncio_loop fixture handles event loop isolation elegantly
  • 📊 Test coverage demonstrates thread and async task isolation work correctly

4. Migration Excellence

  • 🗺️ Clear migration guide in util_singleton_holders.py docstring
  • 🧹 Massive cleanup: 28,611 deletions (mostly deprecated scripts)
  • 🔄 Backward compatibility maintained through thoughtful fixture design

🔍 Issues & Recommendations

Critical Issues: NONE ✅

High Priority

1. Update Stale Comment in pyproject.toml (line 323)

Issue: Comment references --dist=loadscope but configuration now uses --dist=loadgroup

Impact: Documentation inconsistency could confuse developers

Fix:

-# - Use --dist=loadscope to group tests by module (reduces import overhead)
+# - Use --dist=loadgroup to group tests by @pytest.mark.xdist_group (enables finer control)

Location: pyproject.toml:323


Medium Priority

2. Direct Access to Private _current_container in Test Fixtures

Issue: tests/fixtures/isolation.py imports and uses _current_container (private variable with underscore prefix)

Impact: Breaks encapsulation, creates maintenance burden if implementation changes

Recommendation: Expose a public API in application_context.py:

def clear_current_container() -> contextvars.Token[ModelONEXContainer | None]:
    """Clear the current container, returning a token for restore.
    
    Primarily for testing - resets container context to None.
    """
    return _current_container.set(None)

Then update isolation.py:73:

from omnibase_core.context.application_context import clear_current_container
return clear_current_container()

Locations:

  • src/omnibase_core/context/application_context.py (add function)
  • tests/fixtures/isolation.py:73 (use it)
  • tests/unit/models/core/test_model_cli_command_registry.py:664 (also uses _current_container)

3. Inconsistent Exception Handling Patterns

Issue: Some registry reset functions use silent except Exception: pass while others raise ModelOnexError

Locations:

  • src/omnibase_core/models/core/model_action_registry.py:284 (silent)
  • src/omnibase_core/models/core/model_event_type_registry.py:246 (silent)
  • src/omnibase_core/models/core/model_cli_command_registry.py:270 (raises)

Recommendation: Document the intentional difference or standardize:

except Exception:  # noqa: BLE001 - Intentional no-op for testing, no container = nothing to reset
    pass

Low Priority (Nice to Have)

4. __all__ Export Order in context/init.py

Issue: Exports not alphabetically sorted (minor style inconsistency)

Fix:

__all__ = [
    "ApplicationContext",
    "get_current_container",
    "reset_container",
    "run_with_container",
    "run_with_container_sync",
    "set_current_container",
]

Location: src/omnibase_core/context/__init__.py:50-57


5. Consider Logging in Registry Reset Functions

Current: Silent exception swallowing in reset functions

Suggestion: Add debug logging to aid troubleshooting:

except Exception as e:
    import logging
    logging.debug(f"reset_action_registry no-op (container not initialized): {e}")

Locations: Same as issue #3


🔒 Security Analysis

✅ No security concerns identified

  • No credential handling in changed code
  • No SQL injection vectors
  • No XSS vulnerabilities
  • No unsafe deserialization (beyond existing pickle usage in tests, which is acceptable for test isolation)
  • Thread-safe implementation using standard library primitives

⚡ Performance Considerations

Positive Impacts:

  • ✅ Reduced test flakiness → faster CI feedback loops
  • ✅ Better parallelization → 20 splits running efficiently
  • ✅ lru_cache patterns for logger/protocol services reduce repeated lookups

Neutral:

  • contextvars have minimal overhead (nanoseconds per access)
  • Token-based reset is O(1) operation

Monitoring:

  • CI split times currently 2m35s - 3m35s (within expected range per CLAUDE.md benchmarks)
  • No performance degradation expected from this change

📊 Test Coverage Assessment

Excellent Coverage:

  • 391 lines of dedicated tests for ApplicationContext
  • Thread isolation tested with barriers (test_application_context.py:313-344)
  • Async task inheritance tested (test_application_context.py:351-380)
  • Fixture behavior validated (test_isolation_fixtures.py)

Completeness:

  • ✅ Sync context manager
  • ✅ Async context manager
  • ✅ Nested contexts
  • ✅ Exception handling
  • ✅ Thread isolation
  • ✅ Async task isolation

🎓 Best Practices Alignment

ONEX Framework Compliance:

✅ Protocol-driven DI (get_service("ProtocolName"))
✅ Structured errors with ModelOnexError
✅ Type safety (100% mypy strict compliance maintained)
✅ Documentation excellence
✅ Thread safety considerations documented

Python Best Practices:

✅ contextvars for context management (PEP 567)
✅ Proper use of context managers
✅ Type hints with TYPE_CHECKING guards
✅ Comprehensive docstrings


🚀 CI/CD Impact

Before PR:

  • Test isolation issues with pytest-xdist
  • Potential for shared state contamination between parallel workers
  • Singleton holders causing race conditions

After PR:

  • ✅ Proper isolation between parallel test workers
  • ✅ Each thread/task has independent container context
  • ✅ --dist=loadgroup + --reruns=2 handles flaky tests gracefully
  • ✅ Maintained 20 parallel splits (2m58s average per CLAUDE.md)

📋 Checklist Review

From PR description:

  • ✅ Pre-commit hooks pass (mypy, ruff, black, isort, ONEX validations)
  • ⏳ Unit tests pass (pending CI - tests look well-structured)
  • ⏳ Integration tests pass (pending CI)
  • ⏳ CI pipeline passes (pending)

CodeRabbit Review: 6 actionable comments, mostly documentation improvements and minor nits - nothing blocking


🎯 Final Recommendation

APPROVE - Merge after addressing the documentation inconsistency (#1) and considering API encapsulation improvement (#2).

Must Fix Before Merge:

  1. Update pyproject.toml:323 comment to reference loadgroup not loadscope

Recommended for Follow-up PR:

  1. Add public clear_current_container() API to reduce private member access
  2. Add noqa comments to intentional exception swallowing
  3. Sort __all__ exports alphabetically

Excellent Work On:

  • 🏆 Solving a real architectural problem (test isolation)
  • 🏆 Clean, well-tested implementation
  • 🏆 Comprehensive documentation
  • 🏆 Thoughtful migration strategy

📚 References

  • PR Summary: Introduces contextvars-based container management
  • Files Changed: 100 (mostly deletions of deprecated scripts)
  • Key Addition: src/omnibase_core/context/application_context.py (263 lines)
  • Test Coverage: tests/unit/context/test_application_context.py (391 lines)
  • CI Strategy: 20 parallel splits with loadgroup distribution
  • Related Docs: CLAUDE.md sections on Testing and Thread Safety

Reviewed by: Claude Code (Sonnet 4.5)
Review Date: 2025-11-27

@claude

claude Bot commented Nov 27, 2025

Copy link
Copy Markdown

Pull Request Review: Context-Based Container Management

Overview

This PR introduces a significant architectural improvement by migrating from singleton holder patterns to contextvars-based container management. This is a well-designed solution to parallel test execution issues with pytest-xdist.


Strengths

1. Excellent Architecture Choice

  • contextvars is the correct solution for thread-safe and async-safe context propagation
  • Each thread and async task gets proper isolation automatically
  • Token-based reset mechanism is clean and predictable
  • Both sync and async context managers provided

2. Comprehensive Test Coverage

The new ApplicationContext has excellent test coverage in tests/unit/context/test_application_context.py (391 lines) thoroughly testing thread isolation, async task isolation, nested context managers, exception handling, and token-based reset.

3. Well-Documented

  • Clear docstrings explaining thread safety guarantees
  • Migration examples in deprecated util_singleton_holders.py
  • Proper type hints throughout

4. Test Configuration Improvements

  • --dist=loadgroup provides better control than loadscope
  • --reruns=2 with --reruns-delay=1 handles flaky tests automatically

Issues and Concerns

1. CRITICAL: Stale Documentation Comment

Location: pyproject.toml:323

The comment references --dist=loadscope but line 306 uses --dist=loadgroup. Update comment to match actual configuration.

2. Direct Access to Private ContextVar

Location: tests/fixtures/isolation.py:73

Test utilities directly access private _current_container variable. Consider exposing a public clear_current_container() API to maintain encapsulation.

3. Inconsistent Error Handling

Some registries use silent no-op on error while others raise structured errors. Document when silent failures are acceptable (reset functions in tests) vs when errors should propagate (getter functions).

4. PR Size Concern

Stats: 1,114 files changed. While massive deletions are positive (removing old migration scripts), large scope makes thorough review challenging.


Code Quality

Positive

  • Strict mypy compliance maintained
  • Proper type annotations throughout
  • Follows ONEX coding conventions
  • Good use of pytest fixtures for isolation
  • Excellent docstring coverage

Minor Issues

  • Some unused fixture parameters trigger Ruff warnings (acceptable for pytest)
  • all in context/init.py not alphabetically sorted
  • Unpacked but unused kwargs in test

Testing Recommendations

Before Merge

  1. Verify CI passes all 20 parallel splits
  2. Check splits complete within 2m30s-3m30s benchmark
  3. Run full test suite locally with parallelism

Post-Merge Monitoring

  • Watch for reduced flaky test reports
  • Monitor CI run times
  • Check for remaining test isolation issues

Final Recommendation

APPROVE with minor fixes required before merge

Must Fix Before Merge

  1. Update stale comment in pyproject.toml:323

Why Approve

  • Solves real architectural problem (test isolation in parallel execution)
  • Uses correct Python primitive (contextvars) per PEP 567
  • Comprehensive test coverage
  • Maintains backward compatibility
  • Removes significant technical debt (28k+ deletions)
  • Follows ONEX coding conventions

Risk Assessment

  • Low Risk: Migration is well-tested and gradual
  • High Value: Enables reliable parallel test execution
  • Good Documentation: Migration path is clear

Great work on this architectural improvement!

@jonahgabriel
jonahgabriel merged commit e2fe28b into main Nov 27, 2025
26 checks passed
@jonahgabriel
jonahgabriel deleted the feature/pytest-xdist-scope-optimization branch November 27, 2025 17:56
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