Repository navigation
feat(infra): infrastructure integration with handler contracts and E2E fixes [OMN-1317] - #143
Conversation
…E fixes [OMN-1317] - Add 6 handler contracts for plugin-based handler discovery (db, consul, http, vault, filesystem, mcp) - Add runtime fail-fast behavior when no handlers registered - Standardize environment variable naming (ONEX_CONTRACTS_DIR) - Fix Pydantic serialization in mixin_node_introspection (enum conversion) - Fix E2E test Kafka topic subscription (static topics with unique consumer groups) - Fix heartbeat timing issues in E2E tests - Rename migration 003a to 004 for proper ordering - Add Valkey service to E2E Docker stack
📝 WalkthroughWalkthroughAdds contract-driven handler discovery with security metadata and protocol_type propagation, renames CONTRACTS_DIR → ONEX_CONTRACTS_DIR with a deprecated fallback, enforces fail-fast startup when no handlers register, introduces routing models, and migrates tests to envelope-based events with readiness helpers. Changes
Sequence Diagram(s)sequenceDiagram
actor Kernel
participant Runtime as RuntimeHostProcess
participant Discovery as ContractHandlerDiscovery
participant Loader as HandlerPluginLoader
participant Registry as ProtocolBindingRegistry
Kernel->>Runtime: bootstrap(contract_paths=[...])
Runtime->>Discovery: scan(contract_paths)
Discovery->>Loader: load_from_contract(contract_path)
Loader->>Loader: validate YAML, security, derive protocol_type
Loader-->>Runtime: ModelLoadedHandler(protocol_type=...)
Runtime->>Registry: register(key=protocol_type, handler=ModelLoadedHandler)
Registry-->>Runtime: ack
Runtime->>Runtime: if registry empty -> raise ProtocolConfigurationError
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🧹 Recent nitpick comments
📜 Recent review detailsConfiguration used: defaults Review profile: CHILL Plan: Lite 📒 Files selected for processing (10)
🧰 Additional context used📓 Path-based instructions (2)**/*.py📄 CodeRabbit inference engine (CLAUDE.md)
Files:
**/model_*.py📄 CodeRabbit inference engine (CLAUDE.md)
Files:
🧠 Learnings (60)📓 Common learnings📚 Learning: 2025-11-30T21:55:10.298ZApplied to files:
📚 Learning: 2025-11-30T21:55:10.298ZApplied to files:
📚 Learning: 2025-11-24T17:23:49.777ZApplied to files:
📚 Learning: 2025-11-24T16:32:55.606ZApplied to files:
📚 Learning: 2025-11-24T17:23:49.777ZApplied to files:
📚 Learning: 2026-01-11T17:31:33.550ZApplied to files:
📚 Learning: 2025-12-03T16:55:49.755ZApplied to files:
📚 Learning: 2025-12-03T16:55:49.755ZApplied to files:
📚 Learning: 2026-01-11T17:31:33.550ZApplied to files:
📚 Learning: 2025-11-30T21:55:10.298ZApplied to files:
📚 Learning: 2026-01-11T17:31:33.550ZApplied to files:
📚 Learning: 2025-11-24T16:33:32.747ZApplied to files:
📚 Learning: 2026-01-11T17:31:33.550ZApplied to files:
📚 Learning: 2026-01-11T17:31:33.550ZApplied to files:
📚 Learning: 2026-01-11T17:31:33.550ZApplied to files:
📚 Learning: 2025-11-24T16:31:48.648ZApplied to files:
📚 Learning: 2026-01-11T17:31:33.550ZApplied to files:
📚 Learning: 2026-01-11T17:31:33.550ZApplied to files:
📚 Learning: 2025-11-24T17:22:32.195ZApplied to files:
📚 Learning: 2025-11-29T17:13:38.776ZApplied to files:
📚 Learning: 2025-11-24T16:33:09.011ZApplied to files:
📚 Learning: 2025-11-28T18:58:53.781ZApplied to files:
📚 Learning: 2025-11-29T17:13:38.776ZApplied to files:
📚 Learning: 2025-11-24T17:23:24.207ZApplied to files:
📚 Learning: 2025-11-24T16:32:37.719ZApplied to files:
📚 Learning: 2025-11-24T17:23:49.777ZApplied to files:
📚 Learning: 2025-11-24T17:22:32.195ZApplied to files:
📚 Learning: 2026-01-14T01:38:17.497ZApplied to files:
📚 Learning: 2025-11-24T16:32:55.606ZApplied to files:
📚 Learning: 2025-11-24T17:23:49.777ZApplied to files:
📚 Learning: 2026-01-14T01:38:17.497ZApplied to files:
📚 Learning: 2025-11-24T17:22:32.195ZApplied to files:
📚 Learning: 2025-11-28T18:58:53.781ZApplied to files:
📚 Learning: 2025-11-28T18:58:53.781ZApplied to files:
📚 Learning: 2026-01-06T17:57:00.689ZApplied to files:
📚 Learning: 2025-11-24T17:24:41.687ZApplied to files:
📚 Learning: 2025-11-24T16:33:32.747ZApplied to files:
📚 Learning: 2025-11-24T16:33:32.747ZApplied to files:
📚 Learning: 2025-11-24T16:33:32.747ZApplied to files:
📚 Learning: 2025-11-24T17:24:41.687ZApplied to files:
📚 Learning: 2025-11-24T17:24:41.687ZApplied to files:
📚 Learning: 2025-11-24T17:24:41.687ZApplied to files:
📚 Learning: 2025-11-24T16:33:32.747ZApplied to files:
📚 Learning: 2026-01-14T01:38:17.497ZApplied to files:
📚 Learning: 2025-11-24T17:24:41.687ZApplied to files:
📚 Learning: 2025-11-29T17:13:38.776ZApplied to files:
📚 Learning: 2025-11-29T17:13:38.776ZApplied to files:
📚 Learning: 2025-11-28T18:58:53.781ZApplied to files:
📚 Learning: 2026-01-14T01:38:17.497ZApplied to files:
📚 Learning: 2025-11-28T18:58:53.781ZApplied to files:
📚 Learning: 2025-11-24T17:24:41.687ZApplied to files:
📚 Learning: 2025-11-24T17:22:32.195ZApplied to files:
📚 Learning: 2025-11-24T16:33:32.747ZApplied to files:
📚 Learning: 2026-01-14T01:38:17.497ZApplied to files:
📚 Learning: 2025-11-24T17:24:41.687ZApplied to files:
📚 Learning: 2025-11-24T17:24:41.687ZApplied to files:
📚 Learning: 2025-11-24T17:24:41.687ZApplied to files:
📚 Learning: 2025-11-24T17:24:41.687ZApplied to files:
📚 Learning: 2025-11-24T17:24:54.193ZApplied to files:
🧬 Code graph analysis (1)src/omnibase_infra/models/runtime/model_handler_contract.py (3)
🔇 Additional comments (22)
✏️ Tip: You can disable this entire section by setting Comment |
PR Review: Infrastructure Integration with Handler Contracts and E2E FixesOverviewThis PR introduces plugin-based handler discovery through contracts, fail-fast validation, and several E2E test improvements. The changes align well with the repository's declarative, contract-driven architecture. ✅ Strengths1. Contract-Driven Handler DiscoveryThe 6 handler contracts (db, consul, http, vault, filesystem, mcp) follow the plugin pattern documented in
2. Fail-Fast Validation (runtime_host_process.py:718-738)The new validation that prevents runtime startup without handlers is excellent defensive programming: if not self._handlers:
raise ProtocolConfigurationError(
"No handlers registered. The runtime cannot start..."
)This catches misconfiguration early rather than silently starting a useless runtime. ✅ 3. Environment Variable StandardizationThe migration from
4. Pydantic Serialization Fix (mixin_node_introspection.py)Converting string reasons to 5. E2E Test ImprovementsThe shift from dynamic topic creation to static topics with unique consumer groups (test_full_orchestrator_flow.py:95-121) is pragmatic:
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In @docker/docker-compose.e2e.yml:
- Around line 191-209: The docker-compose service "valkey" is pinned to image
tag valkey/valkey:8 which is outdated; update the image reference in the valkey
service (image: ...) to valkey/valkey:9.0.1 (or valkey/valkey:latest) to run E2E
against the current stable release, leaving the rest of the valkey service
config (container_name omnibase-infra-valkey, ports, volumes, command,
healthcheck, labels) unchanged.
In @tests/integration/registration/e2e/test_full_orchestrator_flow.py:
- Around line 515-537: The async fixture ensure_test_topic_exists is annotated
as returning AsyncGenerator but it simply returns a string
(TEST_INTROSPECTION_TOPIC), causing a docs/type mismatch; change its signature
to return str (async def ensure_test_topic_exists(...) -> str) and update the
docstring accordingly, remove any now-unneeded imports of AsyncGenerator, and
keep the async function and its dependency on real_kafka_event_bus intact.
🧹 Nitpick comments (3)
src/omnibase_infra/mixins/mixin_node_introspection.py (1)
1369-1425: Reason coercion: prefer Enum-first + stricter type guard (clarity + safer runtime behavior).
EnumIntrospectionReasoninherits fromstr, soisinstance(reason, str)is true for bothstrandEnumIntrospectionReason. This currently works, but it’s easy to misread and harder to extend safely (e.g., if some otherstr-ish type slips in).Proposed refactor
- # Convert string reason to enum if needed - reason_enum: EnumIntrospectionReason - if isinstance(reason, str): - try: - reason_enum = EnumIntrospectionReason(reason) - except ValueError: - logger.warning( - f"Unknown introspection reason '{reason}', defaulting to HEARTBEAT", - extra={ - "node_id": self._introspection_node_id, - "provided_reason": reason, - }, - ) - reason_enum = EnumIntrospectionReason.HEARTBEAT - else: - reason_enum = reason + # Convert reason to enum (EnumIntrospectionReason is also a str, so check enum first) + reason_enum: EnumIntrospectionReason + if isinstance(reason, EnumIntrospectionReason): + reason_enum = reason + elif isinstance(reason, str): + try: + reason_enum = EnumIntrospectionReason(reason.strip().lower()) + except ValueError: + logger.warning( + f"Unknown introspection reason '{reason}', defaulting to HEARTBEAT", + extra={ + "node_id": self._introspection_node_id, + "provided_reason": reason, + }, + ) + reason_enum = EnumIntrospectionReason.HEARTBEAT + else: + raise TypeError( + f"reason must be str or EnumIntrospectionReason, got {type(reason).__name__}" + )tests/integration/registration/e2e/test_two_way_registration_e2e.py (1)
1251-1254: Consumer-readiness via fixed sleep can still flake; consider polling for readiness.
IfKafkaEventBus.subscribe()exposes a “ready/assigned” signal (or you can poll for first message), that’s usually more deterministic thansleep(1.0).tests/integration/registration/e2e/test_full_orchestrator_flow.py (1)
108-122: get_test_topic simplification is fine (static topic), but consider removing if unused.
Only if nothing imports it anymore; otherwise leaving it is fine for compatibility.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Lite
📒 Files selected for processing (17)
contracts/handlers/consul/handler_contract.yamlcontracts/handlers/db/handler_contract.yamlcontracts/handlers/filesystem/handler_contract.yamlcontracts/handlers/http/handler_contract.yamlcontracts/handlers/mcp/handler_contract.yamlcontracts/handlers/vault/handler_contract.yamldocker/Dockerfile.runtimedocker/README.mddocker/docker-compose.e2e.ymldocker/docker-compose.runtime.ymldocker/migrations/004_capability_fields_concurrent.sqlsrc/omnibase_infra/mixins/mixin_node_introspection.pysrc/omnibase_infra/runtime/kernel.pysrc/omnibase_infra/runtime/runtime_host_process.pytests/integration/mixins/test_mixin_node_introspection_contract_integration.pytests/integration/registration/e2e/test_full_orchestrator_flow.pytests/integration/registration/e2e/test_two_way_registration_e2e.py
🧰 Additional context used
📓 Path-based instructions (3)
**/handler_contract.yaml
📄 CodeRabbit inference engine (CLAUDE.md)
**/handler_contract.yaml: Handler contract files must declare handler routing withrouting_strategy, event models, handler classes, and handler modules
Handlers must be discovered and loaded dynamically via YAML contracts using plugin pattern, not hardcoded registries
Files:
contracts/handlers/filesystem/handler_contract.yamlcontracts/handlers/http/handler_contract.yamlcontracts/handlers/vault/handler_contract.yamlcontracts/handlers/consul/handler_contract.yamlcontracts/handlers/mcp/handler_contract.yamlcontracts/handlers/db/handler_contract.yaml
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Never useAnytype - useobjectfor generic payloads in function parameters and return types
UseX | None(PEP 604) instead ofOptional[X]for nullable types
All services must useModelONEXContainerfor dependency injection via__init__(self, container: ModelONEXContainer)
Use@allow_anydecorator with documented reason as exemption mechanism forAnytype violations
UseJsonTypefromomnibase_core.typesas the canonical type alias for JSON-compatible values
UseModelEventEnvelope[object]for generic dispatcher interfaces andobjectfor generic payloads
Infrastructure error handling must useOnexErrorbase class and never expose passwords, API keys, PII, or connection strings with credentials in error messages
UseInfraConnectionError,InfraTimeoutError,InfraAuthenticationError,InfraUnavailableErrorfor transport failures with properModelInfraErrorContext
Correlation IDs must be propagated from incoming requests, auto-generated withuuid4()if missing, and included in all error contexts
External service adapters must implementMixinAsyncCircuitBreakerwith appropriate threshold and reset_timeout configuration
Protocol resolution must use duck typing via protocols, never useisinstancechecks
Files:
tests/integration/mixins/test_mixin_node_introspection_contract_integration.pytests/integration/registration/e2e/test_two_way_registration_e2e.pysrc/omnibase_infra/runtime/kernel.pytests/integration/registration/e2e/test_full_orchestrator_flow.pysrc/omnibase_infra/mixins/mixin_node_introspection.pysrc/omnibase_infra/runtime/runtime_host_process.py
**/mixin_*.py
📄 CodeRabbit inference engine (CLAUDE.md)
File naming convention: Mixins must use
mixin_<name>.pywith class nameMixin<Name>
Files:
src/omnibase_infra/mixins/mixin_node_introspection.py
🧠 Learnings (53)
📓 Common learnings
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/handler_contract.yaml : Handlers must be discovered and loaded dynamically via YAML contracts using plugin pattern, not hardcoded registries
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contracts/contract_*.yaml : All ONEX node contract definitions must use the new subcontract architecture pattern, breaking down complex contracts into separate contract_actions.yaml, contract_models.yaml, contract_validation.yaml, and optional contract_cli.yaml and contract_capabilities.yaml files for separation of concerns, maintainability, reusability, modularity, and future tool-as-a-service readiness
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/handler_contract.yaml : Handler contract files must declare handler routing with `routing_strategy`, event models, handler classes, and handler modules
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contracts/contract_*.yaml : All ONEX node subcontracts must be organized in a `contracts/` subdirectory within the versioned implementation directory with separate files for contract_actions.yaml, contract_models.yaml, contract_validation.yaml, contract_cli.yaml (optional), and contract_capabilities.yaml (optional)
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/handler_contract.yaml : Handlers must be discovered and loaded dynamically via YAML contracts using plugin pattern, not hardcoded registries
Applied to files:
contracts/handlers/filesystem/handler_contract.yamlcontracts/handlers/http/handler_contract.yamlcontracts/handlers/vault/handler_contract.yamlcontracts/handlers/consul/handler_contract.yamlcontracts/handlers/mcp/handler_contract.yamlcontracts/handlers/db/handler_contract.yaml
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/handler_contract.yaml : Handler contract files must declare handler routing with `routing_strategy`, event models, handler classes, and handler modules
Applied to files:
contracts/handlers/filesystem/handler_contract.yamlcontracts/handlers/http/handler_contract.yamlcontracts/handlers/vault/handler_contract.yamlcontracts/handlers/consul/handler_contract.yamlcontracts/handlers/mcp/handler_contract.yamlcontracts/handlers/db/handler_contract.yaml
📚 Learning: 2025-11-24T17:22:32.195Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-24T17:22:32.195Z
Learning: Applies to **/v[0-9]_[0-9]_[0-9]/contracts/ : Organize contract subcomponents into separate files (contract_actions.yaml, contract_models.yaml, contract_validation.yaml, etc.) and reference them from main contract.yaml
Applied to files:
contracts/handlers/filesystem/handler_contract.yamlcontracts/handlers/vault/handler_contract.yamlcontracts/handlers/consul/handler_contract.yaml
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contracts/contract_*.yaml : All ONEX node contract definitions must use the new subcontract architecture pattern, breaking down complex contracts into separate contract_actions.yaml, contract_models.yaml, contract_validation.yaml, and optional contract_cli.yaml and contract_capabilities.yaml files for separation of concerns, maintainability, reusability, modularity, and future tool-as-a-service readiness
Applied to files:
contracts/handlers/filesystem/handler_contract.yamlcontracts/handlers/http/handler_contract.yamlcontracts/handlers/vault/handler_contract.yamlcontracts/handlers/consul/handler_contract.yamldocker/README.mdcontracts/handlers/mcp/handler_contract.yamldocker/Dockerfile.runtimedocker/docker-compose.runtime.yml
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/contract.yaml : Contract files must use semantic versioning with `contract_version` and `node_version` fields, specify node type (EFFECT/COMPUTE/REDUCER/ORCHESTRATOR), and strongly type all I/O with `input_model` and `output_model`
Applied to files:
contracts/handlers/filesystem/handler_contract.yamlcontracts/handlers/http/handler_contract.yamlcontracts/handlers/consul/handler_contract.yamlcontracts/handlers/mcp/handler_contract.yaml
📚 Learning: 2025-11-24T17:24:41.687Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T17:24:41.687Z
Learning: Applies to **/contracts/contract_*.yaml : Subcontract files must follow the naming pattern `contract_<domain>.yaml` and be located in `*/contracts/` directories
Applied to files:
contracts/handlers/filesystem/handler_contract.yamlcontracts/handlers/vault/handler_contract.yaml
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: When both `handler_contract.yaml` and `contract.yaml` exist in the same directory, the loader must raise an error (AMBIGUOUS_CONTRACT_CONFIGURATION)
Applied to files:
contracts/handlers/filesystem/handler_contract.yamlcontracts/handlers/vault/handler_contract.yamlcontracts/handlers/consul/handler_contract.yaml
📚 Learning: 2025-11-24T17:24:41.687Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T17:24:41.687Z
Learning: Applies to **/contracts/contract_{actions,models,validation,cli,capabilities}.yaml : Subcontract files must be organized with naming convention: `contract_actions.yaml`, `contract_models.yaml`, `contract_validation.yaml`, `contract_cli.yaml`, `contract_capabilities.yaml`
Applied to files:
contracts/handlers/filesystem/handler_contract.yamlcontracts/handlers/vault/handler_contract.yaml
📚 Learning: 2025-12-06T22:21:32.649Z
Learnt from: CR
Repo: OmniNode-ai/omniagent PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T22:21:32.649Z
Learning: Applies to nodes/**/*.py : Use `omnibase_infra` handlers for OmniIntelligence queries via HttpRestAdapter envelope pattern
Applied to files:
contracts/handlers/http/handler_contract.yaml
📚 Learning: 2025-11-24T17:24:41.687Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T17:24:41.687Z
Learning: Applies to **/v[0-9]_[0-9]_[0-9]/contract.yaml : Main contract files must be named `contract.yaml` and serve as the interface definition (source of truth) for the node
Applied to files:
contracts/handlers/vault/handler_contract.yaml
📚 Learning: 2025-11-24T17:24:41.687Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T17:24:41.687Z
Learning: Applies to **/v[0-9]_[0-9]_[0-9]/contract.yaml : The main contract.yaml file serves as the source of truth for node interfaces and should reference subcontracts using $ref patterns
Applied to files:
contracts/handlers/vault/handler_contract.yaml
📚 Learning: 2025-11-24T16:33:32.747Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T16:33:32.747Z
Learning: Main contract.yaml should contain only interface definitions; data structures should be in subcontracts located in contracts/ subdirectory
Applied to files:
contracts/handlers/consul/handler_contract.yaml
📚 Learning: 2026-01-13T11:03:28.097Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T11:03:28.097Z
Learning: Applies to src/omnibase_core/nodes/**/*.py : Use available mixins (MixinDiscoveryResponder, MixinEventHandler, etc.) to add reusable behavior to nodes
Applied to files:
tests/integration/mixins/test_mixin_node_introspection_contract_integration.py
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contract.yaml : All ONEX node contract definitions must follow the linked document architecture pattern with contract.yaml linking to node_config.yaml and deployment_config.yaml as associated documents
Applied to files:
docker/README.mddocker/docker-compose.runtime.yml
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contract.yaml : All ONEX node contract definitions must support optional documents pattern with optional flag and required_capability field for future extensibility
Applied to files:
docker/README.md
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contracts/contract_*.yaml : All ONEX node subcontracts must be organized in a `contracts/` subdirectory within the versioned implementation directory with separate files for contract_actions.yaml, contract_models.yaml, contract_validation.yaml, contract_cli.yaml (optional), and contract_capabilities.yaml (optional)
Applied to files:
docker/README.mddocker/Dockerfile.runtimedocker/docker-compose.runtime.ymlsrc/omnibase_infra/runtime/kernel.py
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: All ONEX nodes must conform to the canonical structure, code generation, and interface patterns established in the `node_cli` node, using it as the primary source of truth for directory structure, contract schema patterns, linked document architecture, base state patterns, shared schema references, extensibility patterns, CLI interface declarations, code generation, dependency injection, error handling, testing, and documentation
Applied to files:
docker/README.mddocker/Dockerfile.runtimedocker/docker-compose.runtime.yml
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contracts/contract_cli.yaml : All ONEX node CLI interface definitions, if applicable, must be included in contract_cli.yaml with entrypoint and commands specifications
Applied to files:
docker/README.mddocker/Dockerfile.runtimedocker/docker-compose.runtime.yml
📚 Learning: 2025-11-24T16:32:55.606Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T16:32:55.606Z
Learning: Applies to **/*contract*.yaml : All ONEX nodes must have validated YAML contracts following the contract-driven development pattern with input_state and output_state schema definitions
Applied to files:
docker/README.mddocker/Dockerfile.runtimedocker/docker-compose.runtime.yml
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contracts/contract_capabilities.yaml : All ONEX node execution capability definitions, if applicable, must be included in contract_capabilities.yaml with supported_node_types, supported_delivery_modes, and performance_constraints specifications
Applied to files:
docker/README.md
📚 Learning: 2025-11-29T22:07:25.230Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: migration_sources/omniarchon/CLAUDE.md:0-0
Timestamp: 2025-11-29T22:07:25.230Z
Learning: Applies to migration_sources/omniarchon/**/postgres* : For PostgreSQL connections from Docker services, use `POSTGRES_HOST=omninode-bridge-postgres` (internal Docker network). For host scripts, use `POSTGRES_HOST=192.168.86.200` with external port 5436. Always use environment variables, never hardcode connection details.
Applied to files:
docker/README.md
📚 Learning: 2026-01-06T17:57:00.689Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_spi PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:57:00.689Z
Learning: Applies to src/omnibase_spi/protocols/handlers/**/*.py : Protocol naming convention: Handler protocols must follow `Protocol{Type}Handler` pattern
Applied to files:
contracts/handlers/mcp/handler_contract.yaml
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/*.py : Use `ModelEventEnvelope[object]` for generic dispatcher interfaces and `object` for generic payloads
Applied to files:
tests/integration/registration/e2e/test_two_way_registration_e2e.pytests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-24T16:32:55.606Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T16:32:55.606Z
Learning: Node communication must use event-driven patterns through `ModelEventEnvelope` from `omnibase_core.models.events.model_event_envelope`
Applied to files:
tests/integration/registration/e2e/test_two_way_registration_e2e.pytests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to src/omninode_bridge/nodes/**/{models,node}.py : Bridge nodes MUST implement FSM states: PENDING, PROCESSING, COMPLETED, FAILED. Use Pydantic v2 models with proper state enum validation
Applied to files:
tests/integration/registration/e2e/test_two_way_registration_e2e.pytests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-24T16:33:32.747Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T16:33:32.747Z
Learning: Applies to **/*.py : Import enums from `omnibase.enums` package
Applied to files:
tests/integration/registration/e2e/test_two_way_registration_e2e.py
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/introspection.py : All ONEX nodes must include an `introspection.py` file implementing standards-compliant introspection logic
Applied to files:
tests/integration/registration/e2e/test_two_way_registration_e2e.pysrc/omnibase_infra/mixins/mixin_node_introspection.py
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to src/**/{config,settings}/**/*.py : Environment variables MUST include: POSTGRES_HOST, POSTGRES_PORT, POSTGRES_DATABASE, POSTGRES_USER, POSTGRES_PASSWORD, KAFKA_BOOTSTRAP_SERVERS, CONSUL_HOST, CONSUL_PORT, LOG_LEVEL. Use secrets manager for production passwords.
Applied to files:
docker/Dockerfile.runtime
📚 Learning: 2025-11-29T22:07:25.230Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: migration_sources/omniarchon/CLAUDE.md:0-0
Timestamp: 2025-11-29T22:07:25.230Z
Learning: Applies to migration_sources/omniarchon/**/*.py : All Docker services must receive environment variables via `docker-compose.yml`. Scripts reading configuration must support `.env` files via python-dotenv or similar. Never assume environment variables are set without defaults.
Applied to files:
docker/docker-compose.runtime.yml
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contract*.yaml : All ONEX node contract definitions must reference shared schemas using project root paths (e.g., 'schemas/...' or 'omnibase/schemas/...') rather than relative paths
Applied to files:
docker/docker-compose.runtime.yml
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/models/model_contract_*.py : All ONEX node auto-generated Pydantic models must be organized in a `models/` directory with files for state.py, model_contract_actions.py, model_contract_models.py, model_contract_validation.py, model_contract_cli.py (optional), model_contract_capabilities.py (optional), and error_codes.py, generated from the corresponding contract definitions
Applied to files:
docker/docker-compose.runtime.yml
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to deployment/docker-compose*.yml : Docker Compose files MUST use dual listener architecture for Kafka (9092 internal, 29092 external). Update /etc/hosts with: 192.168.86.200 omninode-bridge-redpanda omninode-bridge-consul omninode-bridge-postgres
Applied to files:
docker/docker-compose.e2e.yml
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Remote infrastructure runs on 192.168.86.200. All Docker containers use internal hostnames (omninode-bridge-redpanda, omninode-bridge-postgres, omninode-bridge-consul) for inter-container communication.
Applied to files:
docker/docker-compose.e2e.yml
📚 Learning: 2025-11-29T22:07:25.230Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: migration_sources/omniarchon/CLAUDE.md:0-0
Timestamp: 2025-11-29T22:07:25.230Z
Learning: Applies to migration_sources/omniarchon/**/*.py : For Redpanda/Kafka connection patterns: Docker services use `omninode-bridge-redpanda:9092` (DNS resolves via /etc/hosts to 192.168.86.200:9092), host scripts use `192.168.86.200:29092` (direct IP with external port), remote server access uses `localhost:29092`. Never mix these contexts.
Applied to files:
docker/docker-compose.e2e.yml
📚 Learning: 2025-12-06T22:21:32.649Z
Learnt from: CR
Repo: OmniNode-ai/omniagent PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T22:21:32.649Z
Learning: Use bootstrap server `omninode-bridge-redpanda:9092` for Docker service connections
Applied to files:
docker/docker-compose.e2e.yml
📚 Learning: 2025-11-29T22:07:25.230Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: migration_sources/omniarchon/CLAUDE.md:0-0
Timestamp: 2025-11-29T22:07:25.230Z
Learning: Applies to migration_sources/omniarchon/**/docker-compose.yml : For Docker services connecting to Kafka/Redpanda, use `KAFKA_BOOTSTRAP_SERVERS=omninode-bridge-redpanda:9092` (internal Docker network port 9092). For host scripts, use `192.168.86.200:29092` (external published port). Do not hardcode ports - use environment variables with proper defaults.
Applied to files:
docker/docker-compose.e2e.yml
📚 Learning: 2025-12-03T16:55:49.755Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-03T16:55:49.755Z
Learning: Applies to deployment/docker-compose.yml : Structure Docker Compose services with external network omninode-bridge-network for cross-repository service communication
Applied to files:
docker/docker-compose.e2e.yml
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to src/omninode_bridge/events/**/*.py : Kafka event publishing MUST use OnexEnvelopeV1 format with 13 topics for event streaming at all workflow lifecycle stages
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-12-06T22:21:32.649Z
Learnt from: CR
Repo: OmniNode-ai/omniagent PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T22:21:32.649Z
Learning: Applies to nodes/effect/**/*.py : Use handler envelopes from `omnibase_infra` for all I/O operations (HTTP, database, Kafka) instead of custom clients
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.pysrc/omnibase_infra/runtime/runtime_host_process.py
📚 Learning: 2025-12-07T17:50:13.678Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T17:50:13.678Z
Learning: Implement Kafka event-driven architecture with proper topic naming using prefix dev.archon-intelligence. and proper event flow pattern with Effect nodes consuming events, processing, and publishing results with Dead Letter Queue routing
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-12-06T22:21:32.649Z
Learnt from: CR
Repo: OmniNode-ai/omniagent PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T22:21:32.649Z
Learning: Applies to nodes/**/*.py : Use event bus mixins from `omnibase_core` for Kafka publishing instead of direct Kafka clients
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.pysrc/omnibase_infra/mixins/mixin_node_introspection.py
📚 Learning: 2025-11-28T18:58:53.781Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-28T18:58:53.781Z
Learning: Applies to **/*.py : Implement Node classes by inheriting from `NodeBase` with proper UUID and `ModelSemVer` fields
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-12-03T16:55:49.755Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-03T16:55:49.755Z
Learning: Applies to **/*.py : Publish intelligence requests to Kafka event bus using topics: dev.archon-intelligence.intelligence.code-analysis-{requested,completed,failed}.v1 for consistency and event-driven architecture
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to src/omninode_bridge/nodes/**/*.py : Import mixins from omnibase_core.mixins.* and use Mixin* naming pattern (e.g., MixinHealthCheck, MixinMetrics, MixinEventBus) - never use local custom mixins unless experimental and documented
Applied to files:
src/omnibase_infra/mixins/mixin_node_introspection.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Node Introspection Security - use Python reflection for service discovery, but prefix internal/sensitive methods with `_`, use generic parameter names, and configure Kafka topic ACLs for introspection topics
Applied to files:
src/omnibase_infra/mixins/mixin_node_introspection.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/*.py : Use `InfraConnectionError`, `InfraTimeoutError`, `InfraAuthenticationError`, `InfraUnavailableError` for transport failures with proper `ModelInfraErrorContext`
Applied to files:
src/omnibase_infra/runtime/runtime_host_process.py
📚 Learning: 2026-01-13T11:03:28.097Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T11:03:28.097Z
Learning: Applies to src/omnibase_core/**/*.py : Use structured error handling with ModelOnexError and EnumCoreErrorCode, never raise generic Exception
Applied to files:
src/omnibase_infra/runtime/runtime_host_process.py
📚 Learning: 2025-11-24T16:33:32.747Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T16:33:32.747Z
Learning: Applies to **/*.py : Import protocols from `omnibase.protocol.protocol_*` paths
Applied to files:
src/omnibase_infra/runtime/runtime_host_process.py
📚 Learning: 2026-01-06T17:57:00.689Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_spi PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:57:00.689Z
Learning: Applies to src/omnibase_spi/protocols/**/*.py : Every protocol must inherit from `typing.Protocol` and have the `runtime_checkable` decorator
Applied to files:
src/omnibase_infra/runtime/runtime_host_process.py
📚 Learning: 2025-11-28T18:58:53.781Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-28T18:58:53.781Z
Learning: Applies to **/*.py : Use `EnumCoreErrorCode` with `ModelOnexError` for proper error code usage
Applied to files:
src/omnibase_infra/runtime/runtime_host_process.py
📚 Learning: 2026-01-13T11:03:28.097Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T11:03:28.097Z
Learning: Applies to src/omnibase_core/**/*.py : Use centralized exception constants from omnibase_core.errors.exception_groups instead of inline exception tuples
Applied to files:
src/omnibase_infra/runtime/runtime_host_process.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/*.py : Infrastructure error handling must use `OnexError` base class and never expose passwords, API keys, PII, or connection strings with credentials in error messages
Applied to files:
src/omnibase_infra/runtime/runtime_host_process.py
🧬 Code graph analysis (3)
tests/integration/mixins/test_mixin_node_introspection_contract_integration.py (2)
src/omnibase_infra/enums/enum_introspection_reason.py (1)
EnumIntrospectionReason(18-151)src/omnibase_infra/mixins/mixin_node_introspection.py (1)
publish_introspection(1369-1497)
src/omnibase_infra/mixins/mixin_node_introspection.py (1)
src/omnibase_infra/enums/enum_introspection_reason.py (1)
EnumIntrospectionReason(18-151)
src/omnibase_infra/runtime/runtime_host_process.py (3)
src/omnibase_infra/errors/error_infra.py (1)
ProtocolConfigurationError(154-189)src/omnibase_infra/models/errors/model_infra_error_context.py (1)
ModelInfraErrorContext(17-96)src/omnibase_infra/enums/enum_infra_transport_type.py (1)
EnumInfraTransportType(32-60)
🔇 Additional comments (28)
src/omnibase_infra/runtime/runtime_host_process.py (3)
56-62: LGTM! Import addition is correct.The
ProtocolConfigurationErrorimport aligns with the relevant code snippets showing this is the appropriate error class for configuration validation failures, usingEnumCoreErrorCode.INVALID_CONFIGURATION.
718-738: Well-implemented fail-fast validation.This is an excellent defensive addition that catches misconfiguration early. The implementation properly:
- Uses
ModelInfraErrorContextwithEnumInfraTransportType.RUNTIMEper coding guidelines- Auto-generates correlation_id with
uuid4()for traceability- Provides actionable error message mentioning
ONEX_CONTRACTS_DIR- Includes debugging context (failed handler counts/names)
1614-1644: Health check correctly reflects handler registration state.The health calculation logic is consistent with the fail-fast behavior in
start():
no_handlers_registeredprovides explicit visibility into configuration issues- Adding
and not no_handlers_registeredto thehealthycondition ensures load balancers/orchestrators can distinguish misconfigured runtimes from other failure modes- The flag enables proper alerting on deployment configuration errors
docker/docker-compose.runtime.yml (1)
103-103: Environment variable rename aligns with PR objectives.The rename from
CONTRACTS_DIRtoONEX_CONTRACTS_DIRfollows the ONEX naming convention. The hardcoded/app/contractspath correctly corresponds to the read-only volume mount at line 157 (../contracts:/app/contracts:ro).contracts/handlers/http/handler_contract.yaml (1)
1-19: Same schema completeness concern as vault handler contract.This contract has the same structure and may be missing required fields (
routing_strategy, event models) per coding guidelines. See review comment oncontracts/handlers/vault/handler_contract.yamlfor verification scripts.contracts/handlers/db/handler_contract.yaml (2)
10-16: Good inline documentation of handler_type semantics.The comments explaining
effect,compute, andnondeterministic_computeclassification provide helpful context for future maintainers. Consider adding similar documentation to the other handler contracts for consistency.
1-23: Same schema completeness concern as other handler contracts.This contract follows the same minimal structure. If the discovery system requires additional fields (
routing_strategy, event models), this will need updates. See verification scripts in the vault handler contract review.contracts/handlers/vault/handler_contract.yaml (1)
1-19: No issues found. The vault handler contract is valid and complete.The contract properly declares all required fields (
name,handler_class,handler_type,tags) per theModelHandlerContractschema. Routing strategy and event models are node-level concerns, not handler contract requirements. The structure matches other deployed handler contracts like filesystem and http.docker/Dockerfile.runtime (1)
34-34: LGTM! Consistent environment variable rename.The rename from
CONTRACTS_DIRtoONEX_CONTRACTS_DIRis applied consistently across the documentation comment (line 34), the ENV declaration (line 191), and the CMD comment (line 264). The default path/app/contractsaligns with theCOPYinstruction at line 236.Also applies to: 191-191, 264-264
contracts/handlers/mcp/handler_contract.yaml (1)
1-20: LGTM! Well-documented MCP handler contract.The handler contract correctly classifies the MCP handler as an
effecttype since it exposes ONEX nodes as MCP tools for external AI agent integration. The tags (mcp,ai-agent,tool-interface) are well-chosen for discovery and filtering purposes.docker/README.md (1)
513-513: LGTM! Documentation accurately reflects the environment variable rename.The
ONEX_CONTRACTS_DIRdocumentation at line 513 correctly shows the default path/app/contracts, and the troubleshooting section at line 584 properly guides users to adjust this variable if the contracts directory is missing. The documentation is consistent with the Dockerfile changes.Also applies to: 584-584
contracts/handlers/filesystem/handler_contract.yaml (1)
1-19: Handler contract schema is correct as-is.Handler contracts (
handler_contract.yaml) are intentionally minimal discovery/registration metadata containingname,handler_class,handler_type, andtags. Thehandler_moduleis implicit in the fully qualifiedhandler_classpath.Fields like
routing_strategyand event models (input_model,output_model) belong in node contracts, not handler contracts. Node contracts define how operations are routed to handlers and specify node-level I/O types. Handler implementations self-define their operations and models internally.All handler contracts in this codebase (filesystem, db, vault, http, mcp, consul) consistently follow this minimal schema by design, as part of the OMN-1317 handler discovery pattern.
Likely an incorrect or invalid review comment.
src/omnibase_infra/runtime/kernel.py (4)
129-130: LGTM!The legacy constant is well-documented with a clear deprecation timeline (v2.0.0). Having a constant rather than inline strings improves maintainability and makes the deprecation path discoverable.
140-173: LGTM!The legacy fallback implementation is well-structured:
- Clear precedence documentation in the docstring
- Actionable deprecation warning with version target
- Structured logging with
extrafields for observability- Returns early when preferred env var is set, avoiding unnecessary legacy checks
1352-1358: LGTM!The legacy constant is properly exported, allowing external consumers to reference it for migration tooling or deprecation checks.
846-850: Thecontract_pathsparameter is correctly passed toRuntimeHostProcess.Verification confirms that
RuntimeHostProcess.__init__acceptscontract_paths: list[str] | None = None, and the code correctly passescontract_paths=[str(contracts_dir)]to enable contract-based handler discovery as intended.docker/docker-compose.e2e.yml (4)
5-6: LGTM!Header comments accurately document the addition of Valkey to the E2E infrastructure stack.
Also applies to: 31-31
253-256: LGTM!The runtime service correctly depends on Valkey with
service_healthycondition, ensuring the Redis-compatible store is available before the runtime starts.
273-282: LGTM!Environment variables are correctly configured:
REDIS_HOST: valkeyuses Docker's internal DNS for service discoveryONEX_CONTRACTS_DIRaligns with the kernel.py changes and standardizes the environment variable namingBased on learnings, using internal hostnames (
valkey) for inter-container communication is the correct pattern.
314-316: LGTM!Volume definition follows the established naming convention (
omnibase-infra-*-data).tests/integration/mixins/test_mixin_node_introspection_contract_integration.py (2)
33-34: Good: tests now import and exercise EnumIntrospectionReason.
647-651: Good: publish_introspection called with EnumIntrospectionReason (stronger typing, clearer intent).tests/integration/registration/e2e/test_two_way_registration_e2e.py (4)
149-152: Good: E2E tests now pass EnumIntrospectionReason (consistent with production typing).Also applies to: 261-264, 2287-2289
1461-1482: Nice: heartbeat timestamp is now explicit and reused across payload + envelope.
2077-2082: Good: SemVer assertion updated to use ModelSemVer.patch (avoids string parsing).
46-51: Envelope-based handler calls verified and working correctly.The
ModelEventEnvelopecontract andHandler.handle()signature are correctly implemented. Verified that:
ModelEventEnvelopeaccepts the expected fields (envelope_id,payload,envelope_timestamp,correlation_id,source)HandlerNodeIntrospected.handle()signature isasync def handle(self, envelope: ModelEventEnvelope[ModelNodeIntrospectionEvent]) -> ModelHandlerOutput[object]ModelHandlerOutputprovides the.eventsfield that tests access- Handler returns properly constructed
ModelHandlerOutputwithevents=()orevents=(tuple_of_events,)- Pattern is consistent across all test locations (lines 398, 800, 888, 1769)
No API contract mismatches or breaking changes detected.
tests/integration/registration/e2e/test_full_orchestrator_flow.py (2)
209-229: Good: pipeline wraps payload into ModelEventEnvelope and gates on handler_output.events.
Just make sureHandlerNodeIntrospected.handle()is definitively the envelope-based API everywhere this test runs.
95-106: The test isolation strategy is already correctly implemented. TheKafkaEventBusis configured withauto_offset_reset="latest"by default (inModelKafkaEventBusConfig), which is passed to each consumer at subscription time. Combined with unique consumer group IDs per test, this ensures each test starts consuming from the latest offset and avoids replaying old messages. No additional verification or changes are needed.Likely an incorrect or invalid review comment.
PR Review Fixes: - Add security metadata to all 6 handler contracts (trusted_namespace, audit_logging) - Vault handler has additional requires_authentication flag - Update Valkey image to 9.0.1 in docker-compose.e2e.yml - Fix fixture return type annotation (AsyncGenerator -> str) - Refactor reason coercion to enum-first pattern with stricter type guard - Replace fixed sleeps with wait_for_consumer_ready helper - Add comprehensive observability logging to E2E pipeline E2E Test Quality Fixes: - Fix ProtocolIntrospectableTestNode missing 5 protocol methods - Fix ModelNodeCapabilities invalid kwargs (handlers -> supported_types) - Fix E402 import order violations in conftest.py and test_runtime_e2e.py - Add type annotations to 21 test functions - Fix type mismatches (dict variance, json.loads, model attributes) - Document all 33 asyncio.sleep calls with explanatory comments - Fix G003 logging violations (use constants instead of concatenation) New Files: - Add routing models (ModelRoutingEntry, ModelRoutingSubcontract) to fix missing omnibase_core import
Code Review - PR #143: Infrastructure Integration with Handler ContractsOverall Assessment: Strong implementation with good adherence to ONEX patterns. A few critical issues to address before merge. ✅ Strengths
|
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/omnibase_infra/nodes/node_registration_orchestrator/node.py (1)
107-147: Correct transport_type and catch Pydantic validation errors in contract parsing.The current implementation uses
EnumInfraTransportType.DATABASEfor all file-related operations, which should beEnumInfraTransportType.FILESYSTEM. Additionally,ModelRoutingSubcontracthasrouting_strategy: Literal["payload_type_match"], so any invalid value will raise an unhandled PydanticValidationError. The constructor call must be wrapped in a try/except block to normalize validation failures intoProtocolConfigurationError.Proposed fix
-from omnibase_infra.errors import ModelInfraErrorContext, ProtocolConfigurationError +from omnibase_infra.errors import ModelInfraErrorContext, ProtocolConfigurationError +from pydantic import ValidationError def _create_handler_routing_subcontract() -> ModelRoutingSubcontract: try: with contract_path.open("r", encoding="utf-8") as f: contract = yaml.safe_load(f) except FileNotFoundError as e: ctx = ModelInfraErrorContext( - transport_type=EnumInfraTransportType.DATABASE, + transport_type=EnumInfraTransportType.FILESYSTEM, operation="load_handler_routing_contract", target_name=str(contract_path), ) except yaml.YAMLError as e: ctx = ModelInfraErrorContext( - transport_type=EnumInfraTransportType.DATABASE, + transport_type=EnumInfraTransportType.FILESYSTEM, operation="parse_handler_routing_contract", target_name=str(contract_path), ) if contract is None: ctx = ModelInfraErrorContext( - transport_type=EnumInfraTransportType.DATABASE, + transport_type=EnumInfraTransportType.FILESYSTEM, operation="validate_handler_routing_contract", target_name=str(contract_path), ) if handler_routing is None: ctx = ModelInfraErrorContext( - transport_type=EnumInfraTransportType.DATABASE, + transport_type=EnumInfraTransportType.FILESYSTEM, operation="validate_handler_routing_contract", target_name=str(contract_path), ) - return ModelRoutingSubcontract( - version=ModelSemVer(major=1, minor=0, patch=0), - routing_strategy=handler_routing.get("routing_strategy", "payload_type_match"), - handlers=entries, - default_handler=None, - ) + try: + return ModelRoutingSubcontract( + version=ModelSemVer(major=1, minor=0, patch=0), + routing_strategy=handler_routing.get("routing_strategy", "payload_type_match"), + handlers=entries, + default_handler=None, + ) + except ValidationError as e: + ctx = ModelInfraErrorContext( + transport_type=EnumInfraTransportType.FILESYSTEM, + operation="validate_handler_routing_contract", + target_name=str(contract_path), + ) + raise ProtocolConfigurationError( + "Invalid handler_routing configuration in contract.yaml", + context=ctx, + ) from e
🤖 Fix all issues with AI agents
In @tests/integration/registration/e2e/conftest.py:
- Around line 168-171: The sleep logic allows sleeping less than the intended
0.5s minimum; change the await asyncio.sleep(min(actual_wait, max_wait)) to
await asyncio.sleep(actual_wait) (or equivalently await
asyncio.sleep(max(default_wait, max_wait))) so the code honors the intended
minimum wait of default_wait while still allowing longer waits when max_wait >
default_wait; update the comment if you instead intend max_wait to be a strict
upper bound.
🧹 Nitpick comments (4)
contracts/handlers/http/handler_contract.yaml (1)
4-9: Minor naming inconsistency in comment.The comment on line 4 says "HandlerHttp" but the actual class name on line 9 is
HttpRestHandler. Consider updating the comment for consistency.-# Handler contract for HandlerHttp (HTTP REST client operations) +# Handler contract for HttpRestHandler (HTTP REST client operations)tests/integration/registration/e2e/test_runtime_e2e.py (1)
428-430: Consider usingwait_for_consumer_readyhelper for consistency.The 2-second delay for Kafka consumer group join duplicates the pattern that
wait_for_consumer_readywas designed to encapsulate. Using the helper would improve consistency and make future improvements easier.♻️ Suggested refactor
+from tests.integration.registration.e2e.conftest import ( + wait_for_consumer_ready, + wrap_event_in_envelope, +) # ... try: - # Allow Kafka consumer group join to complete before publishing. - # Without this delay, the consumer may miss the first message. - await asyncio.sleep(2.0) + # Wait for Kafka consumer to be ready before publishing + await wait_for_consumer_ready(real_kafka_event_bus, output_topic, max_wait=2.0)tests/integration/registration/e2e/test_two_way_registration_e2e.py (1)
785-787: Replace fixed sleeps afterpersist()with deterministic waits to reduce E2E flakiness.
Several tests doawait asyncio.sleep(...)to “allow PostgreSQL async write to complete”; preferwait_for_postgres_registration(...)/ reader polling keyed byentity_idbefore proceeding.Also applies to: 873-875, 1659-1661, 1751-1753, 1844-1846, 1875-1877
tests/integration/registration/e2e/test_full_orchestrator_flow.py (1)
985-987: Sleep-after-malformed-message is OK, but a deterministic “pipeline idle” signal would be better long-term.
Not blocking, but if you can expose an “events_processed” counter or an asyncio.Event from the pipeline, you can eliminate timing guesses.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Lite
📒 Files selected for processing (19)
contracts/handlers/consul/handler_contract.yamlcontracts/handlers/db/handler_contract.yamlcontracts/handlers/filesystem/handler_contract.yamlcontracts/handlers/http/handler_contract.yamlcontracts/handlers/mcp/handler_contract.yamlcontracts/handlers/vault/handler_contract.yamldocker/docker-compose.e2e.ymlsrc/omnibase_infra/mixins/mixin_node_introspection.pysrc/omnibase_infra/models/__init__.pysrc/omnibase_infra/models/routing/__init__.pysrc/omnibase_infra/models/routing/model_routing_entry.pysrc/omnibase_infra/models/routing/model_routing_subcontract.pysrc/omnibase_infra/nodes/node_registration_orchestrator/node.pytests/integration/registration/e2e/conftest.pytests/integration/registration/e2e/performance_utils.pytests/integration/registration/e2e/test_full_orchestrator_flow.pytests/integration/registration/e2e/test_runtime_e2e.pytests/integration/registration/e2e/test_two_way_registration_e2e.pytests/integration/registration/e2e/verification_helpers.py
✅ Files skipped from review due to trivial changes (2)
- contracts/handlers/filesystem/handler_contract.yaml
- tests/integration/registration/e2e/performance_utils.py
🚧 Files skipped from review as they are similar to previous changes (3)
- contracts/handlers/consul/handler_contract.yaml
- contracts/handlers/db/handler_contract.yaml
- contracts/handlers/mcp/handler_contract.yaml
🧰 Additional context used
📓 Path-based instructions (5)
**/handler_contract.yaml
📄 CodeRabbit inference engine (CLAUDE.md)
**/handler_contract.yaml: Handler contract files must declare handler routing withrouting_strategy, event models, handler classes, and handler modules
Handlers must be discovered and loaded dynamically via YAML contracts using plugin pattern, not hardcoded registries
Files:
contracts/handlers/vault/handler_contract.yamlcontracts/handlers/http/handler_contract.yaml
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Never useAnytype - useobjectfor generic payloads in function parameters and return types
UseX | None(PEP 604) instead ofOptional[X]for nullable types
All services must useModelONEXContainerfor dependency injection via__init__(self, container: ModelONEXContainer)
Use@allow_anydecorator with documented reason as exemption mechanism forAnytype violations
UseJsonTypefromomnibase_core.typesas the canonical type alias for JSON-compatible values
UseModelEventEnvelope[object]for generic dispatcher interfaces andobjectfor generic payloads
Infrastructure error handling must useOnexErrorbase class and never expose passwords, API keys, PII, or connection strings with credentials in error messages
UseInfraConnectionError,InfraTimeoutError,InfraAuthenticationError,InfraUnavailableErrorfor transport failures with properModelInfraErrorContext
Correlation IDs must be propagated from incoming requests, auto-generated withuuid4()if missing, and included in all error contexts
External service adapters must implementMixinAsyncCircuitBreakerwith appropriate threshold and reset_timeout configuration
Protocol resolution must use duck typing via protocols, never useisinstancechecks
Files:
src/omnibase_infra/models/routing/model_routing_entry.pysrc/omnibase_infra/nodes/node_registration_orchestrator/node.pysrc/omnibase_infra/models/routing/model_routing_subcontract.pysrc/omnibase_infra/models/__init__.pysrc/omnibase_infra/models/routing/__init__.pytests/integration/registration/e2e/test_two_way_registration_e2e.pytests/integration/registration/e2e/verification_helpers.pysrc/omnibase_infra/mixins/mixin_node_introspection.pytests/integration/registration/e2e/test_full_orchestrator_flow.pytests/integration/registration/e2e/test_runtime_e2e.pytests/integration/registration/e2e/conftest.py
**/model_*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/model_*.py: File naming convention: Models must usemodel_<name>.pywith class nameModel<Name>
Each model file must contain exactly oneModel*class
Pydantic workaround forAnytype must include# NOTE:comment documenting the reason when technically required
UseSerializeAsAnytype wrapper for Pydantic fields containing complex nested models to preserve subclass fields during serialization
Files:
src/omnibase_infra/models/routing/model_routing_entry.pysrc/omnibase_infra/models/routing/model_routing_subcontract.py
**/node.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/node.py: Node files must be namednode.pywith class nameNode<Name><Type>and must be declarative with no custom logic
All nodes must extend base classes fromomnibase_core.nodes(NodeOrchestrator, NodeEffect, NodeCompute, NodeReducer) with container injection and no custom logic in node.py
Files:
src/omnibase_infra/nodes/node_registration_orchestrator/node.py
**/mixin_*.py
📄 CodeRabbit inference engine (CLAUDE.md)
File naming convention: Mixins must use
mixin_<name>.pywith class nameMixin<Name>
Files:
src/omnibase_infra/mixins/mixin_node_introspection.py
🧠 Learnings (49)
📓 Common learnings
Learnt from: CR
Repo: OmniNode-ai/omniagent PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T22:21:32.649Z
Learning: Applies to nodes/**/*.py : Use `omnibase_infra` handlers for OmniIntelligence queries via HttpRestAdapter envelope pattern
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contracts/contract_*.yaml : All ONEX node contract definitions must use the new subcontract architecture pattern, breaking down complex contracts into separate contract_actions.yaml, contract_models.yaml, contract_validation.yaml, and optional contract_cli.yaml and contract_capabilities.yaml files for separation of concerns, maintainability, reusability, modularity, and future tool-as-a-service readiness
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/handler_contract.yaml : Handler contract files must declare handler routing with `routing_strategy`, event models, handler classes, and handler modules
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contracts/contract_*.yaml : All ONEX node subcontracts must be organized in a `contracts/` subdirectory within the versioned implementation directory with separate files for contract_actions.yaml, contract_models.yaml, contract_validation.yaml, contract_cli.yaml (optional), and contract_capabilities.yaml (optional)
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T16:32:55.606Z
Learning: Applies to **/*contract*.yaml : All ONEX nodes must have validated YAML contracts following the contract-driven development pattern with input_state and output_state schema definitions
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-24T17:22:32.195Z
Learning: Applies to **/v[0-9]_[0-9]_[0-9]/contracts/ : Organize contract subcomponents into separate files (contract_actions.yaml, contract_models.yaml, contract_validation.yaml, etc.) and reference them from main contract.yaml
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to src/omninode_bridge/nodes/**/contract.yaml : All contract YAML files for ONEX v2.0 nodes MUST define subcontract references, input/output models, and FSM configurations. Use YAML 1.2 syntax.
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contracts/contract_capabilities.yaml : All ONEX node execution capability definitions, if applicable, must be included in contract_capabilities.yaml with supported_node_types, supported_delivery_modes, and performance_constraints specifications
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contract.yaml : All ONEX node contract definitions must support optional documents pattern with optional flag and required_capability field for future extensibility
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/handler_contract.yaml : Handlers must be discovered and loaded dynamically via YAML contracts using plugin pattern, not hardcoded registries
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/contract.yaml : Contract files must use semantic versioning with `contract_version` and `node_version` fields, specify node type (EFFECT/COMPUTE/REDUCER/ORCHESTRATOR), and strongly type all I/O with `input_model` and `output_model`
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/handler_contract.yaml : Handlers must be discovered and loaded dynamically via YAML contracts using plugin pattern, not hardcoded registries
Applied to files:
contracts/handlers/vault/handler_contract.yamlcontracts/handlers/http/handler_contract.yaml
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/handler_contract.yaml : Handler contract files must declare handler routing with `routing_strategy`, event models, handler classes, and handler modules
Applied to files:
contracts/handlers/vault/handler_contract.yamlsrc/omnibase_infra/models/routing/model_routing_entry.pysrc/omnibase_infra/nodes/node_registration_orchestrator/node.pysrc/omnibase_infra/models/routing/model_routing_subcontract.pysrc/omnibase_infra/models/routing/__init__.pycontracts/handlers/http/handler_contract.yaml
📚 Learning: 2025-11-24T17:22:32.195Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-24T17:22:32.195Z
Learning: Applies to **/v[0-9]_[0-9]_[0-9]/contracts/ : Organize contract subcomponents into separate files (contract_actions.yaml, contract_models.yaml, contract_validation.yaml, etc.) and reference them from main contract.yaml
Applied to files:
contracts/handlers/vault/handler_contract.yaml
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contracts/contract_*.yaml : All ONEX node contract definitions must use the new subcontract architecture pattern, breaking down complex contracts into separate contract_actions.yaml, contract_models.yaml, contract_validation.yaml, and optional contract_cli.yaml and contract_capabilities.yaml files for separation of concerns, maintainability, reusability, modularity, and future tool-as-a-service readiness
Applied to files:
contracts/handlers/vault/handler_contract.yamlsrc/omnibase_infra/nodes/node_registration_orchestrator/node.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: When both `handler_contract.yaml` and `contract.yaml` exist in the same directory, the loader must raise an error (AMBIGUOUS_CONTRACT_CONFIGURATION)
Applied to files:
contracts/handlers/vault/handler_contract.yaml
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to src/omninode_bridge/nodes/**/*.py : All nodes in omninode_bridge MUST use omnibase_core standards (ModelServiceEffect, ModelServiceCompute for effect/compute nodes; NodeOrchestrator, NodeReducer with mixins for orchestrator/reducer nodes)
Applied to files:
src/omnibase_infra/nodes/node_registration_orchestrator/node.pysrc/omnibase_infra/models/__init__.py
📚 Learning: 2026-01-13T11:03:28.097Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T11:03:28.097Z
Learning: Applies to src/omnibase_core/nodes/**/*.py : Always use ModelONEXContainer for dependency injection in node constructors, never use generic ModelContainer
Applied to files:
src/omnibase_infra/nodes/node_registration_orchestrator/node.pytests/integration/registration/e2e/test_two_way_registration_e2e.py
📚 Learning: 2026-01-13T11:03:28.097Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T11:03:28.097Z
Learning: Applies to src/omnibase_core/nodes/**/*.py : Use node base classes (NodeCompute, NodeReducer, NodeOrchestrator, NodeEffect) from omnibase_core.nodes, eliminating 80+ lines of boilerplate
Applied to files:
src/omnibase_infra/nodes/node_registration_orchestrator/node.py
📚 Learning: 2025-12-06T22:21:32.649Z
Learnt from: CR
Repo: OmniNode-ai/omniagent PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T22:21:32.649Z
Learning: Applies to nodes/effect/**/*.py : Use handler envelopes from `omnibase_infra` for all I/O operations (HTTP, database, Kafka) instead of custom clients
Applied to files:
src/omnibase_infra/nodes/node_registration_orchestrator/node.py
📚 Learning: 2025-12-06T22:21:32.649Z
Learnt from: CR
Repo: OmniNode-ai/omniagent PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T22:21:32.649Z
Learning: Applies to nodes/**/*.py : Use `omnibase_infra` handlers for OmniIntelligence queries via HttpRestAdapter envelope pattern
Applied to files:
src/omnibase_infra/nodes/node_registration_orchestrator/node.pycontracts/handlers/http/handler_contract.yaml
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/models/model_contract_*.py : All ONEX node auto-generated Pydantic models must be organized in a `models/` directory with files for state.py, model_contract_actions.py, model_contract_models.py, model_contract_validation.py, model_contract_cli.py (optional), model_contract_capabilities.py (optional), and error_codes.py, generated from the corresponding contract definitions
Applied to files:
src/omnibase_infra/nodes/node_registration_orchestrator/node.pysrc/omnibase_infra/models/routing/model_routing_subcontract.pysrc/omnibase_infra/models/routing/__init__.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/node.py : All nodes must extend base classes from `omnibase_core.nodes` (NodeOrchestrator, NodeEffect, NodeCompute, NodeReducer) with container injection and no custom logic in node.py
Applied to files:
src/omnibase_infra/nodes/node_registration_orchestrator/node.py
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/models/error_codes.py : All ONEX node error handling must use auto-generated error codes defined in `models/error_codes.py` from contract definitions
Applied to files:
src/omnibase_infra/nodes/node_registration_orchestrator/node.py
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to src/omninode_bridge/nodes/**/contract.yaml : All contract YAML files for ONEX v2.0 nodes MUST define subcontract references, input/output models, and FSM configurations. Use YAML 1.2 syntax.
Applied to files:
src/omnibase_infra/nodes/node_registration_orchestrator/node.py
📚 Learning: 2025-11-24T16:32:55.606Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T16:32:55.606Z
Learning: Applies to **/*contract*.yaml : All ONEX nodes must have validated YAML contracts following the contract-driven development pattern with input_state and output_state schema definitions
Applied to files:
src/omnibase_infra/nodes/node_registration_orchestrator/node.py
📚 Learning: 2026-01-13T11:03:28.097Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T11:03:28.097Z
Learning: Applies to src/omnibase_core/runtime/**/*.py : Use FileRegistry for loading YAML contracts and configuration files from disk with proper error handling
Applied to files:
src/omnibase_infra/nodes/node_registration_orchestrator/node.py
📚 Learning: 2025-12-06T22:21:32.649Z
Learnt from: CR
Repo: OmniNode-ai/omniagent PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T22:21:32.649Z
Learning: Workflow coordination must be defined in YAML contracts loaded by `NodeAgentOrchestrator`, not as separate Python classes
Applied to files:
src/omnibase_infra/nodes/node_registration_orchestrator/node.py
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contracts/contract_*.yaml : All ONEX node subcontracts must be organized in a `contracts/` subdirectory within the versioned implementation directory with separate files for contract_actions.yaml, contract_models.yaml, contract_validation.yaml, contract_cli.yaml (optional), and contract_capabilities.yaml (optional)
Applied to files:
src/omnibase_infra/nodes/node_registration_orchestrator/node.py
📚 Learning: 2025-11-28T18:58:53.781Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-28T18:58:53.781Z
Learning: Applies to **/*.py : Use `ModelSemVer` instead of string versions in YAML contracts and version fields
Applied to files:
src/omnibase_infra/nodes/node_registration_orchestrator/node.pysrc/omnibase_infra/models/routing/model_routing_subcontract.py
📚 Learning: 2025-11-24T17:24:41.687Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T17:24:41.687Z
Learning: Applies to **/models/model_contract_*.py : Models must be auto-generated from contract.yaml files, never hand-written
Applied to files:
src/omnibase_infra/nodes/node_registration_orchestrator/node.py
📚 Learning: 2025-11-24T17:24:41.687Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T17:24:41.687Z
Learning: Applies to **/models/model_contract_{actions,models,validation,cli,capabilities}.py : Generated models from subcontracts must follow the naming pattern: `model_contract_actions.py`, `model_contract_models.py`, `model_contract_validation.py`, etc.
Applied to files:
src/omnibase_infra/models/routing/model_routing_subcontract.py
📚 Learning: 2025-11-24T16:33:32.747Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T16:33:32.747Z
Learning: Applies to **/*.py : Import models from shared core paths using `omnibase.model.core.model_*` pattern
Applied to files:
src/omnibase_infra/models/__init__.py
📚 Learning: 2025-11-28T18:58:53.781Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-28T18:58:53.781Z
Learning: Organize models under `src/omnibase_core/models/` by domain including: base, cli, common, config, core, contracts, discovery, health, infrastructure, logging, metadata, nodes, operations, results, security, service, tools, validation, and workflows
Applied to files:
src/omnibase_infra/models/routing/__init__.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/*.py : Use `ModelEventEnvelope[object]` for generic dispatcher interfaces and `object` for generic payloads
Applied to files:
tests/integration/registration/e2e/test_two_way_registration_e2e.pytests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-24T16:32:55.606Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T16:32:55.606Z
Learning: Node communication must use event-driven patterns through `ModelEventEnvelope` from `omnibase_core.models.events.model_event_envelope`
Applied to files:
tests/integration/registration/e2e/test_two_way_registration_e2e.pytests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-12-06T22:21:32.649Z
Learnt from: CR
Repo: OmniNode-ai/omniagent PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T22:21:32.649Z
Learning: Applies to nodes/**/*.py : Use event bus mixins from `omnibase_core` for Kafka publishing instead of direct Kafka clients
Applied to files:
tests/integration/registration/e2e/test_two_way_registration_e2e.pysrc/omnibase_infra/mixins/mixin_node_introspection.pytests/integration/registration/e2e/test_runtime_e2e.pytests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/introspection.py : All ONEX nodes must include an `introspection.py` file implementing standards-compliant introspection logic
Applied to files:
tests/integration/registration/e2e/test_two_way_registration_e2e.pysrc/omnibase_infra/mixins/mixin_node_introspection.pytests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to src/omninode_bridge/nodes/**/*.py : Import mixins from omnibase_core.mixins.* and use Mixin* naming pattern (e.g., MixinHealthCheck, MixinMetrics, MixinEventBus) - never use local custom mixins unless experimental and documented
Applied to files:
src/omnibase_infra/mixins/mixin_node_introspection.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Node Introspection Security - use Python reflection for service discovery, but prefix internal/sensitive methods with `_`, use generic parameter names, and configure Kafka topic ACLs for introspection topics
Applied to files:
src/omnibase_infra/mixins/mixin_node_introspection.pytests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to src/omninode_bridge/events/**/*.py : Kafka event publishing MUST use OnexEnvelopeV1 format with 13 topics for event streaming at all workflow lifecycle stages
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.pytests/integration/registration/e2e/test_runtime_e2e.py
📚 Learning: 2025-12-07T17:50:13.678Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T17:50:13.678Z
Learning: Implement Kafka event-driven architecture with proper topic naming using prefix dev.archon-intelligence. and proper event flow pattern with Effect nodes consuming events, processing, and publishing results with Dead Letter Queue routing
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-28T18:58:53.781Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-28T18:58:53.781Z
Learning: Applies to **/*.py : Implement Node classes by inheriting from `NodeBase` with proper UUID and `ModelSemVer` fields
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to src/omninode_bridge/nodes/**/{models,node}.py : Bridge nodes MUST implement FSM states: PENDING, PROCESSING, COMPLETED, FAILED. Use Pydantic v2 models with proper state enum validation
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2026-01-13T11:03:28.097Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T11:03:28.097Z
Learning: Applies to tests/**/*.py : Write unit tests with pytest.mark.unit, integration tests with pytest.mark.integration, and use other markers (slow, smoke, performance) appropriately
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-12-06T22:21:32.649Z
Learnt from: CR
Repo: OmniNode-ai/omniagent PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T22:21:32.649Z
Learning: Applies to tests/**/*.py : Use pytest markers `pytest.mark.unit`, `pytest.mark.integration`, `pytest.mark.slow`, and `pytest.mark.performance` for test categorization
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-12-03T16:55:49.755Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-03T16:55:49.755Z
Learning: Applies to **/*.py : Publish intelligence requests to Kafka event bus using topics: dev.archon-intelligence.intelligence.code-analysis-{requested,completed,failed}.v1 for consistency and event-driven architecture
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.pytests/integration/registration/e2e/conftest.py
📚 Learning: 2025-12-07T17:50:13.678Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T17:50:13.678Z
Learning: Organize tests following the structure: tests/conftest.py for shared fixtures, tests/unit/ for unit tests (no infrastructure), tests/integration/ for integration tests (requires Kafka/DBs), tests/nodes/ for node-specific tests
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-24T16:33:51.604Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T16:33:51.604Z
Learning: Applies to tests/**/conftest.py : Test fixtures must be defined in `conftest.py` and should provide reusable sample data, UUIDs, semantic versions, and model data
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-12-19T02:58:44.081Z
Learnt from: sudharsanv177
Repo: OmniNode-ai/omninode_infra PR: 4
File: docker/onex-api/main.py:0-0
Timestamp: 2025-12-19T02:58:44.081Z
Learning: In the omninode_infra repository, production configuration is managed via Kubernetes Secrets and ConfigMaps injected as environment variables, not committed .env files or Pydantic Settings. The deployment model uses os.getenv() with sensible defaults for local development, and explicit resolution patterns (e.g., checking POSTGRES_DSN first, then deriving from component variables) are preferred over mutating os.environ.
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-29T22:07:25.230Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: migration_sources/omniarchon/CLAUDE.md:0-0
Timestamp: 2025-11-29T22:07:25.230Z
Learning: Applies to migration_sources/omniarchon/**/tests/**/*.py : All integration tests must verify correct Kafka port usage for context (9092 for Docker, 29092 for host). Test both local (qdrant, memgraph) and remote (PostgreSQL, Redpanda) database connectivity. Never assume test environment configuration.
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-29T22:07:25.230Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: migration_sources/omniarchon/CLAUDE.md:0-0
Timestamp: 2025-11-29T22:07:25.230Z
Learning: Applies to migration_sources/omniarchon/**/*.py : Always use REMOTE Redpanda at 192.168.86.200 for event bus. NEVER start local Redpanda. Remote Redpanda enables OmniNode integration, data consistency, and production parity. Use correct ports: 9092 (Docker) or 29092 (host scripts).
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-24T16:32:55.606Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T16:32:55.606Z
Learning: Node implementations must use mixin-based composition from `omnibase_core.mixins` (e.g., `MixinHealthCheck`, `MixinNodeExecutor`) to add capabilities
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to deployment/docker-compose*.yml : Docker Compose files MUST use dual listener architecture for Kafka (9092 internal, 29092 external). Update /etc/hosts with: 192.168.86.200 omninode-bridge-redpanda omninode-bridge-consul omninode-bridge-postgres
Applied to files:
docker/docker-compose.e2e.yml
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Remote infrastructure runs on 192.168.86.200. All Docker containers use internal hostnames (omninode-bridge-redpanda, omninode-bridge-postgres, omninode-bridge-consul) for inter-container communication.
Applied to files:
docker/docker-compose.e2e.yml
📚 Learning: 2025-11-29T22:07:25.230Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: migration_sources/omniarchon/CLAUDE.md:0-0
Timestamp: 2025-11-29T22:07:25.230Z
Learning: Applies to migration_sources/omniarchon/**/*.py : For Redpanda/Kafka connection patterns: Docker services use `omninode-bridge-redpanda:9092` (DNS resolves via /etc/hosts to 192.168.86.200:9092), host scripts use `192.168.86.200:29092` (direct IP with external port), remote server access uses `localhost:29092`. Never mix these contexts.
Applied to files:
docker/docker-compose.e2e.yml
📚 Learning: 2025-12-06T22:21:32.649Z
Learnt from: CR
Repo: OmniNode-ai/omniagent PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T22:21:32.649Z
Learning: Use bootstrap server `omninode-bridge-redpanda:9092` for Docker service connections
Applied to files:
docker/docker-compose.e2e.yml
📚 Learning: 2025-11-29T22:07:25.230Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: migration_sources/omniarchon/CLAUDE.md:0-0
Timestamp: 2025-11-29T22:07:25.230Z
Learning: Applies to migration_sources/omniarchon/**/docker-compose.yml : For Docker services connecting to Kafka/Redpanda, use `KAFKA_BOOTSTRAP_SERVERS=omninode-bridge-redpanda:9092` (internal Docker network port 9092). For host scripts, use `192.168.86.200:29092` (external published port). Do not hardcode ports - use environment variables with proper defaults.
Applied to files:
docker/docker-compose.e2e.yml
📚 Learning: 2025-12-03T16:55:49.755Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-03T16:55:49.755Z
Learning: Applies to deployment/docker-compose.yml : Structure Docker Compose services with external network omninode-bridge-network for cross-repository service communication
Applied to files:
docker/docker-compose.e2e.yml
🧬 Code graph analysis (8)
src/omnibase_infra/nodes/node_registration_orchestrator/node.py (2)
src/omnibase_infra/models/routing/model_routing_entry.py (1)
ModelRoutingEntry(14-49)src/omnibase_infra/models/routing/model_routing_subcontract.py (1)
ModelRoutingSubcontract(21-67)
src/omnibase_infra/models/routing/model_routing_subcontract.py (1)
src/omnibase_infra/models/routing/model_routing_entry.py (1)
ModelRoutingEntry(14-49)
src/omnibase_infra/models/__init__.py (2)
src/omnibase_infra/models/routing/model_routing_entry.py (1)
ModelRoutingEntry(14-49)src/omnibase_infra/models/routing/model_routing_subcontract.py (1)
ModelRoutingSubcontract(21-67)
src/omnibase_infra/models/routing/__init__.py (2)
src/omnibase_infra/models/routing/model_routing_entry.py (1)
ModelRoutingEntry(14-49)src/omnibase_infra/models/routing/model_routing_subcontract.py (1)
ModelRoutingSubcontract(21-67)
tests/integration/registration/e2e/test_two_way_registration_e2e.py (3)
src/omnibase_infra/enums/enum_introspection_reason.py (1)
EnumIntrospectionReason(18-151)src/omnibase_infra/models/registration/model_node_introspection_event.py (1)
ModelNodeIntrospectionEvent(32-192)src/omnibase_infra/models/registration/model_node_capabilities.py (1)
ModelNodeCapabilities(19-173)
src/omnibase_infra/mixins/mixin_node_introspection.py (1)
src/omnibase_infra/enums/enum_introspection_reason.py (1)
EnumIntrospectionReason(18-151)
tests/integration/registration/e2e/test_runtime_e2e.py (1)
tests/integration/registration/e2e/conftest.py (1)
wrap_event_in_envelope(179-202)
tests/integration/registration/e2e/conftest.py (4)
src/omnibase_infra/enums/enum_introspection_reason.py (1)
EnumIntrospectionReason(18-151)src/omnibase_infra/models/registration/model_node_introspection_event.py (1)
ModelNodeIntrospectionEvent(32-192)src/omnibase_infra/utils/util_error_sanitization.py (1)
sanitize_error_message(144-203)tests/conftest.py (1)
check_service_registry_available(31-71)
🔇 Additional comments (40)
tests/integration/registration/e2e/verification_helpers.py (8)
131-132: LGTM!Good addition of inline documentation clarifying the polling interval purpose. The 0.2s retry interval is reasonable for Consul KV lookups.
200-201: LGTM!Clear documentation of the polling behavior, consistent with other helper functions.
314-315: LGTM!Consistent polling interval documentation.
535-537: LGTM!Good documentation clarifying that this is a fixed collection window. The comment explains why the full timeout is awaited rather than exiting early.
614-615: LGTM!Consistent polling interval documentation for the dual registration check.
681-682: LGTM!Consistent polling interval documentation.
800-801: LGTM!Good documentation explaining why the polling interval is longer (1.0s) compared to other helpers - it aligns with the 30s heartbeat cycle.
878-898: Field namecapabilitiesis correct.The assertion correctly uses
event.capabilities, which matches the field defined inModelNodeBecameActive(line 97 of the model definition). No changes needed.contracts/handlers/http/handler_contract.yaml (1)
1-25: Missing required handler contract fields per coding guidelines.Same issue as the vault handler contract: per coding guidelines, handler contracts must declare
routing_strategy, event models, and handler modules. This contract is missing those fields.See verification script in the vault handler review for checking whether these fields are required.
docker/docker-compose.e2e.yml (5)
191-209: LGTM! Valkey service configuration is well-structured.The Valkey service is properly configured with:
- Appropriate healthcheck using
valkey-cli ping- Persistence disabled for faster E2E testing (
--save "" --appendonly no)- Proper network and volume configuration
- Consistent labeling with other services
273-275: Environment variable naming uses Redis convention for compatibility.Using
REDIS_HOSTandREDIS_PORT(rather thanVALKEY_HOST/VALKEY_PORT) is appropriate since most Redis client libraries look for these standard environment variables. This ensures drop-in compatibility.
282-282: LGTM! Environment variable rename aligns with PR objectives.The rename from
CONTRACTS_DIRtoONEX_CONTRACTS_DIRfollows the standardization mentioned in the PR objectives. Ensure the legacy fallback is implemented in the runtime code that reads this variable.
253-256: LGTM! Proper service dependency with health check condition.The runtime correctly depends on Valkey being healthy before starting, consistent with other infrastructure service dependencies.
314-315: LGTM! Volume naming follows established pattern.The
valkey_datavolume uses the same naming convention as other infrastructure volumes.contracts/handlers/vault/handler_contract.yaml (1)
1-27: Handler contract structure is correct as-is.Handler contracts (handler_contract.yaml) declare handler metadata only: name, handler_class, handler_type, and tags. The fields
routing_strategyandevent_modelsare orchestrator-level configurations that map event types to handlers at runtime—they belong in orchestrator contracts withhandler_routingsections, not in individual handler contracts.The vault handler contract correctly follows the standard pattern established across all handler contracts in the codebase (vault, http, filesystem, mcp, db, consul).
src/omnibase_infra/models/routing/model_routing_entry.py (1)
1-52: LGTM! Well-structured routing entry model.The model follows the
model_<name>.pynaming convention and contains exactly oneModel*class as per coding guidelines. The frozen configuration ensures immutability, which is appropriate for routing configuration data. The docstring is comprehensive with clear attribute documentation and usage examples.src/omnibase_infra/mixins/mixin_node_introspection.py (2)
1369-1428: LGTM! Well-implemented enum coercion with backward compatibility.The type coercion correctly handles the inheritance hierarchy (checking
EnumIntrospectionReasonbeforestrsince the enum inherits fromstr). The fallback toHEARTBEATfor invalid strings is appropriately logged, and raisingTypeErrorfor unsupported types provides clear feedback. The docstring examples clearly demonstrate both enum (preferred) and string (backward-compatible) usage patterns.
1430-1501: Consistent enum usage throughout the method.The logging statements correctly use
reason_enum.valuefor string representation, while themodel_copyupdate correctly passes the enum directly to match theModelNodeIntrospectionEvent.reasonfield type.tests/integration/registration/e2e/conftest.py (3)
179-202: Clean envelope wrapping helper.The helper correctly wraps introspection events in
ModelEventEnvelopewith proper typing and documentation. Using the event'scorrelation_idensures tracing continuity.
858-887: Protocol correctly mirrors MixinNodeIntrospection interface.The protocol additions match the
MixinNodeIntrospectioninterface. Including_publish_heartbeatin the protocol is acceptable here since this is a test protocol designed to exactly match the mixin's interface for type checking fixture implementations.
1109-1139: Well-configured E2E logging fixture.The session-scoped autouse fixture appropriately configures logging for all E2E tests. The handler duplication check prevents log spam from multiple handler additions, and the format provides good observability with timestamps and structured output.
tests/integration/registration/e2e/test_runtime_e2e.py (2)
67-191: Well-structured runtime E2E test configuration.The configuration section is well-organized with:
- Clear env var overrides for CI flexibility
- Early validation of SLA thresholds via module-level assertion
- Explicit opt-in for processing tests (
RUNTIME_PROCESSING_ENABLED) to avoid long timeout waits- Informative skip reasons that guide users on what's missing
278-279: Consistent envelope wrapping across all tests.The tests correctly wrap introspection events in envelopes before publishing, aligning with the envelope pattern documented in the conftest helper.
src/omnibase_infra/models/__init__.py (1)
55-58: Properly structured routing model exports.The routing models are correctly imported and exported following the existing patterns in the file, with appropriate section comments for organization.
Also applies to: 92-94
src/omnibase_infra/models/routing/__init__.py (1)
1-25: Clean package initialization with appropriate documentation.The package initializer follows conventions with proper SPDX header, clear module docstring explaining the purpose, and a helpful note about potential future promotion to
omnibase_core. The exports are correctly structured.src/omnibase_infra/models/routing/model_routing_subcontract.py (2)
21-70: Well-designed routing subcontract model.The model follows conventions with:
- Frozen configuration for immutability
- Proper use of
default_factoryfor mutable defaultsLiteraltype for extensible strategy enumeration- Comprehensive docstring with example usage
Based on learnings, this aligns with the handler contract pattern requiring
routing_strategy, event models, and handler declarations.
58-61: No changes needed.ModelRoutingEntryis a simple configuration value object with only two string fields and no subclass hierarchy.SerializeAsAnyis intended for complex nested models with polymorphic subclasses, not for basic scalar-field models like this one.Likely an incorrect or invalid review comment.
src/omnibase_infra/nodes/node_registration_orchestrator/node.py (2)
64-69: Routing model rename looks consistent (ModelRoutingEntry/ModelRoutingSubcontract).
No issues with the import/update itself.
302-310: Doc updates match the new routing field names.
The mappingevent_model.name -> routing_key/handler.name -> handler_keyis much clearer.tests/integration/registration/e2e/test_two_way_registration_e2e.py (7)
129-156: EnumIntrospectionReason usage is a solid improvement over raw strings.
This should prevent drift/typos and aligns with the updated introspection contract.Also applies to: 264-268, 2295-2297
2083-2088: Nice: version assertions now useModelSemVer.patchinstead of string parsing.
This is less brittle and matches the model type.
2919-2925: Consul KV value decoding/JSON parsing is safer with explicit bytes→str handling.
Good defensive handling for differing client return types.
2827-2856: Usingsupported_typesfor handler capabilities aligns withModelNodeCapabilitiesshape.
The assertions make the intended schema usage explicit.
1254-1259: Consider parameterizing the wait time or documenting CI timeout expectations.The
wait_for_consumer_readyfunction uses a 0.5s minimum delay with your specifiedmax_wait=1.0(2x the minimum). The implementation notes explicitly state that tests requiring heartbeat capture "may need longer waits," which justifies this value. However, on significantly slower CI runners, even 1.0s could be insufficient to capture the "immediate" heartbeat reliably. If flakiness appears in CI, increasingmax_waitto 2.0 or higher would be a straightforward fix.
391-402: The suggested helper cannot be reused as-is for this code.While
wrap_event_in_envelopeexists in conftest.py, it only acceptsModelNodeIntrospectionEventand doesn't setenvelope_idorsource—both explicitly provided in the code being reviewed. The existing helper derivescorrelation_idfrom the event itself, whereas the test code passes it separately.Creating a generic envelope wrapper that accepts arbitrary payloads and supports explicit
envelope_id,source, and externalcorrelation_idwould reduce duplication across lines 391-402, 794-804, 882-892, 1467-1488, and 1765-1776, but the current helper is not compatible.Likely an incorrect or invalid review comment.
41-56: No action needed. The import pathfrom omnibase_core.container import ModelONEXContainerat line 85-86 is correct and follows the standard convention across the codebase. This is the canonical import path used in production services (service_health.py,service_capability_query.py,service_node_selector.py) and the vast majority of test files in this repository.Likely an incorrect or invalid review comment.
tests/integration/registration/e2e/test_full_orchestrator_flow.py (4)
49-69: Envelope import + consumer readiness helper are the right direction for true E2E stability.
No concerns with these imports/usage.
676-727: Good: wait_for_consumer_ready before publishing.
This is the right place to put it for reducing “publish before subscribe is live” flakes.
1219-1309: Double-unsubscribe is safe and no action needed.Both KafkaEventBus and InMemoryEventBus implementations handle multiple unsubscribe calls gracefully. The KafkaEventBus unsubscribe searches for the subscription by ID and silently skips if not found, while InMemoryEventBus explicitly catches and ignores the ValueError from calling
remove()on an already-removed item. The test's double-unsubscribe pattern is safe.
185-404: Pipeline envelope API verified; offset defaults to "latest" rather than "earliest", mitigating old-message reads.The KafkaEventBus uses
auto_offset_reset="latest"by default withenable_auto_commit=True, so new subscribers start from the latest offset and don't re-read old traffic on shared topics. Offset commits occur automatically, preventing lag accumulation.
- Fix 48 failing idempotency guard tests by mocking handlers for fail-fast validation - Add _setup_mock_handlers() helper to architecture validation and shutdown tests - Add coerce_to_node_kind() helper for safer enum coercion in E2E tests - Remove unused _TEST_SESSION_ID and get_test_topic() from E2E tests - Add TODO for deterministic wait improvements in malformed message handling Tests now pass fail-fast handler validation introduced in runtime_host_process.py:718-738
Pull Request Review: Handler Contracts and Infrastructure IntegrationOverall AssessmentThis PR delivers a significant infrastructure enhancement for plugin-based handler discovery via contract files. The implementation is well-structured, follows ONEX patterns, and includes important fail-fast validations. Strong work on the architecture and safety mechanisms. Code Quality ✅Strengths:
Handler Contract Structure: # contracts/handlers/db/handler_contract.yaml
name: handler-db
handler_class: omnibase_infra.handlers.handler_db.HandlerDb
handler_type: effect
security:
trusted_namespace: omnibase_infra.handlers
audit_logging: trueClean, minimal, and follows the documented pattern. Security Considerations ✅Positive Security Patterns:
Recommendation:
Potential Issues 🔍1. File Size Limits Not Enforced in Contract DiscoveryLocation: The contract discovery flow doesn't explicitly validate file sizes before loading. While # Suggested addition to _discover_handlers_from_contracts
for contract_path in self._contract_paths:
if contract_path.is_file() and contract_path.stat().st_size > 10 * 1024 * 1024:
logger.warning("Contract file exceeds 10MB limit",
extra={"path": str(contract_path)})
continueSeverity: Low (HandlerPluginLoader already checks, but early validation improves error messages) 2. Migration File Renaming Without Rollback PathFile: The migration was renamed without a corresponding rollback script. Ensure:
Severity: Medium (could break deployments if 003a exists in production) 3. E2E Test Topic Naming May ConflictLocation: ONEX_INPUT_TOPIC: dev.onex.evt.node-introspection.v1
ONEX_OUTPUT_TOPIC: dev.onex.evt.registration-completed.v1Static topic names in E2E tests could cause conflicts if multiple test runs execute concurrently. Consider:
Severity: Low (mainly affects local development with parallel test runs) Performance Considerations ⚡Efficient Patterns:
No blocking operations detected in the critical path. Testing Coverage 📊Covered:
Recommendations:
Documentation Quality 📚Excellent docstrings throughout:
Suggestions:
Adherence to CLAUDE.md ✅Compliant:
Breaking Changes Noted:
Per CLAUDE.md policy: Breaking changes are acceptable. Ensure downstream consumers are notified. Final Recommendations
VerdictLGTM with minor suggestions 🚀 This PR significantly improves the runtime architecture with plugin-based handler discovery. The fail-fast validation for zero handlers is a critical safety improvement. The few concerns raised are minor and can be addressed in follow-up work. Estimated Risk: Low AcknowledgmentsSolid engineering on:
Well done! 🎯 |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Fix all issues with AI agents
In @tests/integration/registration/e2e/conftest.py:
- Around line 1109-1141: The docstring for configure_e2e_logging says DEBUG for
omnibase_infra but infra_logger.setLevel is set to INFO; update
infra_logger.setLevel(logging.DEBUG) to match the docstring (or edit the
docstring to reflect INFO), and while here consider disabling propagation to
avoid duplicate logs by setting e2e_logger.propagate = False when configuring
the e2e_logger; ensure you adjust the configure_e2e_logging fixture accordingly.
In @tests/integration/registration/e2e/test_full_orchestrator_flow.py:
- Around line 674-750: The fixture ensure_test_topic_exists incorrectly assumes
AIOKafkaAdminClient.describe_topics raises for missing topics and includes an
exception branch that attempts to treat missing-topic errors; remove that
misleading comment and the exception handler that checks for "unknown
topic"/"not found" and instead rely on the existing if not topic_descriptions:
detection to call pytest.fail for TEST_INTROSPECTION_TOPIC, while keeping the
try/finally to start/close admin_client so real exceptions
(connection/auth/timeouts) propagate from describe_topics and admin client
startup.
In @tests/unit/runtime/test_runtime_host_architecture_validation.py:
- Around line 130-132: Tests currently seed a mock handler via
_setup_mock_handlers (populating _handlers={"mock": ...}) but several test
comments say “no handlers” while intending “no registry-discovered handlers”;
update the test code to clarify this by renaming the helper or comments: either
rename _setup_mock_handlers to _seed_mock_handler_for_startup_validation (or add
a one-line comment above calls to _setup_mock_handlers) and change the “Should
not raise - no validation occurs” comments to “Should not raise - no
registry-discovered handlers (mock seeded for startup validation)” in the tests
that call _setup_mock_handlers (references: _setup_mock_handlers and
_handlers={"mock": ...} in the test_runtime_host_architecture_validation.py
locations noted).
In @tests/unit/runtime/test_runtime_idempotency_guard.py:
- Around line 36-42: The mock_handler fixture can yield non-awaitable
shutdown/health_check methods which breaks await process.stop(); update the
fixture so the mock handler exposes async-compatible methods: keep
handler.execute as AsyncMock and add handler.shutdown =
AsyncMock(return_value=None) and handler.health_check =
AsyncMock(return_value=True) (or appropriate return values used by
RuntimeHostProcess), or alternatively create the mock with an explicit spec that
includes async shutdown/health_check to ensure those attributes are awaitable
when process.stop() is called.
🧹 Nitpick comments (7)
tests/integration/runtime/test_shutdown_health_integration.py (1)
152-159: Consider extracting port discovery into a helper.The pattern of getting the actual port from the health server's internal socket is repeated in multiple tests (lines 152-159, 213-220, 274-281, 453-460, 499-506). This could be extracted into a small helper method to reduce duplication and improve maintainability.
♻️ Suggested helper extraction
def _get_health_server_port(health_server: ServiceHealth) -> int: """Extract the actual bound port from the health server.""" site = health_server._site assert site is not None internal_server = site._server assert internal_server is not None sockets = getattr(internal_server, "sockets", None) assert sockets is not None and len(sockets) > 0 return sockets[0].getsockname()[1]tests/unit/runtime/test_runtime_host_process.py (1)
1223-1229: Reduce duplication: centralize “seed handlers to bypass fail-fast” setup.
This pattern is repeated across many tests; a small helper/fixture (and usingpatch.object(process, "_handlers", ...)instead of direct assignment) would make it harder to forget details likeinitialized=Truein tests that asserthealthy=True.Proposed refactor sketch
+def _seed_mock_handlers(process: RuntimeHostProcess, *, healthy: bool = True) -> None: + handler = MockHandler() + handler.initialized = healthy + process._handlers = {"mock": handler}Then replace repeated blocks with
_seed_mock_handlers(process, healthy=True/False).Also applies to: 1262-1265, 1290-1296, 1323-1326, 2180-2183, 2223-2226, 2256-2259, 2463-2468, 2498-2503, 2535-2540
tests/unit/runtime/test_runtime_idempotency_guard.py (1)
70-90: Consider a shared “start with seeded handlers” helper to reduce boilerplate.
You repeatedly (1) patch_populate_handlers_from_registryand (2) seedprocess._handlers. A small helper/fixture would tighten consistency across idempotency scenarios. Based on learnings, prefer reusable fixtures for test contexts.Also applies to: 102-121, 129-154, 180-183, 220-223, 262-265, 323-326, 359-370, 440-451, 473-484, 506-526, 574-585, 619-630, 669-697, 710-734
tests/unit/runtime/test_runtime_host_architecture_validation.py (1)
40-50: Good: helper uses AsyncMock for async lifecycle methods (avoids await pitfalls).Small naming/comment tweak: consider calling out that this is “fail-fast bypass” rather than “handlers exist for validation”.
tests/integration/registration/e2e/conftest.py (1)
124-172:wait_for_consumer_ready:max_waitnaming/behavior mismatch (always sleeps 2s by default).
Right nowmax_waitacts like “sleep at least this long”, and the default makes every subscription wait 2 seconds. Consider either (a) rename towait_seconds, or (b) implement an actual poll-with-timeout loop and treatmax_waitas a true upper bound.Option A: minimal rename + semantics clarity
-async def wait_for_consumer_ready( +async def wait_for_consumer_ready( event_bus: KafkaEventBus, topic: str, - max_wait: float = 2.0, + wait_seconds: float = 0.5, poll_interval: float = 0.1, ) -> bool: @@ - await asyncio.sleep(max(default_wait, max_wait)) + await asyncio.sleep(max(default_wait, wait_seconds)) return Truetests/integration/registration/e2e/test_full_orchestrator_flow.py (2)
840-868: Consider publishingModelEventEnvelopeto Kafka here (tests currently publish raw event bytes).
OrchestratorPipeline._deserialize_introspection_event()already supports envelope format, and the E2E conftest states events should be envelope-wrapped “on the wire”; switching these publishes would make the E2E flow closer to production expectations. Based on learnings, node communication should useModelEventEnvelope.Sketch: publish envelope instead of raw event dict
- event_bytes = json.dumps(event.model_dump(mode="json")).encode("utf-8") + envelope = ModelEventEnvelope( + envelope_id=uuid4(), + payload=event, + envelope_timestamp=datetime.now(UTC), + correlation_id=unique_correlation_id, + source="e2e-test", + ) + event_bytes = json.dumps(envelope.model_dump(mode="json")).encode("utf-8")Also applies to: 909-940, 976-1009
116-149:coerce_to_node_kindis fine; consider reusing a shared helper if it spreads.
Exporting it via__all__suggests reuse—worth moving to a test utils module if more files start depending on it.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Lite
📒 Files selected for processing (6)
tests/integration/registration/e2e/conftest.pytests/integration/registration/e2e/test_full_orchestrator_flow.pytests/integration/runtime/test_shutdown_health_integration.pytests/unit/runtime/test_runtime_host_architecture_validation.pytests/unit/runtime/test_runtime_host_process.pytests/unit/runtime/test_runtime_idempotency_guard.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Never useAnytype - useobjectfor generic payloads in function parameters and return types
UseX | None(PEP 604) instead ofOptional[X]for nullable types
All services must useModelONEXContainerfor dependency injection via__init__(self, container: ModelONEXContainer)
Use@allow_anydecorator with documented reason as exemption mechanism forAnytype violations
UseJsonTypefromomnibase_core.typesas the canonical type alias for JSON-compatible values
UseModelEventEnvelope[object]for generic dispatcher interfaces andobjectfor generic payloads
Infrastructure error handling must useOnexErrorbase class and never expose passwords, API keys, PII, or connection strings with credentials in error messages
UseInfraConnectionError,InfraTimeoutError,InfraAuthenticationError,InfraUnavailableErrorfor transport failures with properModelInfraErrorContext
Correlation IDs must be propagated from incoming requests, auto-generated withuuid4()if missing, and included in all error contexts
External service adapters must implementMixinAsyncCircuitBreakerwith appropriate threshold and reset_timeout configuration
Protocol resolution must use duck typing via protocols, never useisinstancechecks
Files:
tests/unit/runtime/test_runtime_host_process.pytests/unit/runtime/test_runtime_host_architecture_validation.pytests/unit/runtime/test_runtime_idempotency_guard.pytests/integration/runtime/test_shutdown_health_integration.pytests/integration/registration/e2e/test_full_orchestrator_flow.pytests/integration/registration/e2e/conftest.py
🧠 Learnings (26)
📓 Common learnings
Learnt from: CR
Repo: OmniNode-ai/omniagent PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T22:21:32.649Z
Learning: Applies to nodes/**/*.py : Use `omnibase_infra` handlers for OmniIntelligence queries via HttpRestAdapter envelope pattern
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/handler_contract.yaml : Handler contract files must declare handler routing with `routing_strategy`, event models, handler classes, and handler modules
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contracts/contract_*.yaml : All ONEX node contract definitions must use the new subcontract architecture pattern, breaking down complex contracts into separate contract_actions.yaml, contract_models.yaml, contract_validation.yaml, and optional contract_cli.yaml and contract_capabilities.yaml files for separation of concerns, maintainability, reusability, modularity, and future tool-as-a-service readiness
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contracts/contract_*.yaml : All ONEX node subcontracts must be organized in a `contracts/` subdirectory within the versioned implementation directory with separate files for contract_actions.yaml, contract_models.yaml, contract_validation.yaml, contract_cli.yaml (optional), and contract_capabilities.yaml (optional)
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T16:32:55.606Z
Learning: Applies to **/*contract*.yaml : All ONEX nodes must have validated YAML contracts following the contract-driven development pattern with input_state and output_state schema definitions
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-24T17:22:32.195Z
Learning: Applies to **/v[0-9]_[0-9]_[0-9]/contracts/ : Organize contract subcomponents into separate files (contract_actions.yaml, contract_models.yaml, contract_validation.yaml, etc.) and reference them from main contract.yaml
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/handler_contract.yaml : Handlers must be discovered and loaded dynamically via YAML contracts using plugin pattern, not hardcoded registries
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to src/omninode_bridge/nodes/**/contract.yaml : All contract YAML files for ONEX v2.0 nodes MUST define subcontract references, input/output models, and FSM configurations. Use YAML 1.2 syntax.
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contract.yaml : All ONEX node contract definitions must support optional documents pattern with optional flag and required_capability field for future extensibility
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contracts/contract_capabilities.yaml : All ONEX node execution capability definitions, if applicable, must be included in contract_capabilities.yaml with supported_node_types, supported_delivery_modes, and performance_constraints specifications
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/contract.yaml : Contract files must use semantic versioning with `contract_version` and `node_version` fields, specify node type (EFFECT/COMPUTE/REDUCER/ORCHESTRATOR), and strongly type all I/O with `input_model` and `output_model`
📚 Learning: 2025-11-24T17:24:54.193Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T17:24:54.193Z
Learning: Applies to **/*test*.py : Use context-based fixtures with pytest.param and conditional dependency injection (e.g., UNIT_CONTEXT vs INTEGRATION_CONTEXT) for mock and integration tests
Applied to files:
tests/unit/runtime/test_runtime_idempotency_guard.py
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to src/omninode_bridge/events/**/*.py : Kafka event publishing MUST use OnexEnvelopeV1 format with 13 topics for event streaming at all workflow lifecycle stages
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-12-07T17:50:13.678Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T17:50:13.678Z
Learning: Implement Kafka event-driven architecture with proper topic naming using prefix dev.archon-intelligence. and proper event flow pattern with Effect nodes consuming events, processing, and publishing results with Dead Letter Queue routing
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-12-06T22:21:32.649Z
Learnt from: CR
Repo: OmniNode-ai/omniagent PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T22:21:32.649Z
Learning: Applies to nodes/effect/**/*.py : Use handler envelopes from `omnibase_infra` for all I/O operations (HTTP, database, Kafka) instead of custom clients
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Node Introspection Security - use Python reflection for service discovery, but prefix internal/sensitive methods with `_`, use generic parameter names, and configure Kafka topic ACLs for introspection topics
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.pytests/integration/registration/e2e/conftest.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/*.py : Use `ModelEventEnvelope[object]` for generic dispatcher interfaces and `object` for generic payloads
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-12-06T22:21:32.649Z
Learnt from: CR
Repo: OmniNode-ai/omniagent PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T22:21:32.649Z
Learning: Applies to nodes/**/*.py : Use event bus mixins from `omnibase_core` for Kafka publishing instead of direct Kafka clients
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.pytests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-29T22:07:25.230Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: migration_sources/omniarchon/CLAUDE.md:0-0
Timestamp: 2025-11-29T22:07:25.230Z
Learning: Applies to migration_sources/omniarchon/**/tests/**/*.py : All integration tests must verify correct Kafka port usage for context (9092 for Docker, 29092 for host). Test both local (qdrant, memgraph) and remote (PostgreSQL, Redpanda) database connectivity. Never assume test environment configuration.
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.pytests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-29T17:13:38.776Z
Learnt from: CR
Repo: OmniNode-ai/omniarchon PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T17:13:38.776Z
Learning: Applies to **/*.py : All Kafka topics must use the prefix `dev.archon-intelligence` for development/staging environments.
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-12-03T16:55:49.755Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-03T16:55:49.755Z
Learning: Applies to **/*.py : Publish intelligence requests to Kafka event bus using topics: dev.archon-intelligence.intelligence.code-analysis-{requested,completed,failed}.v1 for consistency and event-driven architecture
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-12-03T16:55:49.755Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-03T16:55:49.755Z
Learning: Applies to scripts/tests/**/*.sh : Implement comprehensive test suites in scripts/tests/ with separate test files for Kafka, PostgreSQL, Intelligence, and Routing functionality
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-24T16:32:55.606Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T16:32:55.606Z
Learning: Node communication must use event-driven patterns through `ModelEventEnvelope` from `omnibase_core.models.events.model_event_envelope`
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-28T18:58:53.781Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-28T18:58:53.781Z
Learning: Applies to **/*.py : Implement Node classes by inheriting from `NodeBase` with proper UUID and `ModelSemVer` fields
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to src/omninode_bridge/nodes/**/{models,node}.py : Bridge nodes MUST implement FSM states: PENDING, PROCESSING, COMPLETED, FAILED. Use Pydantic v2 models with proper state enum validation
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2026-01-13T11:03:28.097Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T11:03:28.097Z
Learning: Applies to tests/**/*.py : Write unit tests with pytest.mark.unit, integration tests with pytest.mark.integration, and use other markers (slow, smoke, performance) appropriately
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-12-06T22:21:32.649Z
Learnt from: CR
Repo: OmniNode-ai/omniagent PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T22:21:32.649Z
Learning: Applies to tests/**/*.py : Use pytest markers `pytest.mark.unit`, `pytest.mark.integration`, `pytest.mark.slow`, and `pytest.mark.performance` for test categorization
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/node_tests/**/*.py : All ONEX node tests must be organized in a `node_tests/` directory using scenario-driven testing patterns with fixture-injected tests
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-24T16:32:55.606Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T16:32:55.606Z
Learning: Applies to tests/unit/infrastructure/**/test_*.py : All node implementations must have comprehensive unit tests following the testing pattern in `tests/unit/infrastructure/` with tests for node initialization and node execution
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-12-07T17:50:13.678Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T17:50:13.678Z
Learning: Organize tests following the structure: tests/conftest.py for shared fixtures, tests/unit/ for unit tests (no infrastructure), tests/integration/ for integration tests (requires Kafka/DBs), tests/nodes/ for node-specific tests
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.pytests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-24T16:33:51.604Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T16:33:51.604Z
Learning: Applies to tests/**/*.py : Test files must follow the naming convention `test_[module_name].py` (examples: `test_enum_acknowledgment_type.py`, `test_model_node_status.py`, `test_mixin_hash_computation.py`)
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-24T16:33:51.604Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T16:33:51.604Z
Learning: Applies to tests/**/conftest.py : Test fixtures must be defined in `conftest.py` and should provide reusable sample data, UUIDs, semantic versions, and model data
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-12-19T02:58:44.081Z
Learnt from: sudharsanv177
Repo: OmniNode-ai/omninode_infra PR: 4
File: docker/onex-api/main.py:0-0
Timestamp: 2025-12-19T02:58:44.081Z
Learning: In the omninode_infra repository, production configuration is managed via Kubernetes Secrets and ConfigMaps injected as environment variables, not committed .env files or Pydantic Settings. The deployment model uses os.getenv() with sensible defaults for local development, and explicit resolution patterns (e.g., checking POSTGRES_DSN first, then deriving from component variables) are preferred over mutating os.environ.
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-29T22:07:25.230Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: migration_sources/omniarchon/CLAUDE.md:0-0
Timestamp: 2025-11-29T22:07:25.230Z
Learning: Applies to migration_sources/omniarchon/**/*.py : Always use REMOTE Redpanda at 192.168.86.200 for event bus. NEVER start local Redpanda. Remote Redpanda enables OmniNode integration, data consistency, and production parity. Use correct ports: 9092 (Docker) or 29092 (host scripts).
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-24T16:32:55.606Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T16:32:55.606Z
Learning: Node implementations must use mixin-based composition from `omnibase_core.mixins` (e.g., `MixinHealthCheck`, `MixinNodeExecutor`) to add capabilities
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/introspection.py : All ONEX nodes must include an `introspection.py` file implementing standards-compliant introspection logic
Applied to files:
tests/integration/registration/e2e/conftest.py
🧬 Code graph analysis (3)
tests/unit/runtime/test_runtime_host_process.py (1)
tests/unit/runtime/test_protocol_lifecycle_executor.py (1)
MockHandler(55-78)
tests/unit/runtime/test_runtime_idempotency_guard.py (1)
tests/unit/runtime/test_runtime_host_process.py (5)
mock_handler(253-255)execute(95-118)execute(145-148)execute(839-841)execute(1506-1507)
tests/integration/registration/e2e/conftest.py (5)
src/omnibase_infra/enums/enum_introspection_reason.py (1)
EnumIntrospectionReason(18-151)src/omnibase_infra/models/registration/model_node_introspection_event.py (1)
ModelNodeIntrospectionEvent(32-192)tests/conftest.py (1)
check_service_registry_available(31-71)tests/integration/envelope_routing/test_envelope_routing_integration.py (2)
event_bus(54-64)correlation_id(126-132)src/omnibase_infra/mixins/mixin_node_introspection.py (2)
publish_introspection(1369-1501)get_introspection_data(1162-1367)
🔇 Additional comments (9)
tests/integration/runtime/test_shutdown_health_integration.py (5)
19-19: LGTM!The import additions for
AsyncMockandMagicMockare appropriate for setting up the mock handler with async methods.
29-38: Well-structured test helper for satisfying fail-fast validation.The helper correctly sets up a minimal mock handler with the required async methods (
shutdown,health_check). The direct access toruntime._handlersis acceptable in integration tests where internal state manipulation is necessary to isolate specific behaviors.One consideration: if the handler interface evolves to require additional methods, this helper will need updates. Consider adding a brief comment noting the minimal interface requirements.
62-65: LGTM!The pattern of calling
_setup_mock_handlers(runtime)within the patch context and beforeruntime.start()is correctly applied throughout the test class.
440-477: LGTM!This test correctly omits the
_setup_mock_handlerscall since the runtime is intentionally never started. This validates the health endpoint behavior when the runtime remains in an unstarted state.
386-394: Good coverage for degraded state edge case.The test correctly validates that the degraded flag accurately reflects the runtime state:
Truewhile running with failed handlers, andFalseafter shutdown (since degraded only applies to running processes with reduced functionality).tests/unit/runtime/test_runtime_host_process.py (1)
36-36: Import change looks fine.
[safe_to_skip]tests/integration/registration/e2e/conftest.py (1)
858-887: Protocol signature expansion looks consistent with MixinNodeIntrospection usage.
This makes the fixture contract clearer for type-checking.tests/integration/registration/e2e/test_full_orchestrator_flow.py (1)
213-424: Pipeline stage logging + envelope-based handler call is a solid debugging upgrade.
The staged separators + correlation_id threading should make E2E failures much easier to triage.tests/unit/runtime/test_runtime_idempotency_guard.py (1)
586-590: The production code correctly handles the exception injected in this test. At line 2062 ofruntime_host_process.py, the code catchesException(matching the test'sException("Store unavailable")injection) and implements proper fail-open behavior with comprehensive error logging. The exception handling is neither overfitted to the test nor mismatched—it appropriately uses a broadExceptioncatch to ensure any store-related errors trigger fail-open behavior, as intended.
## CI Fixes - Fix Docker health check failures by using `protocol_type` for handler registry keys instead of `handler_name` - Add `protocol_type` field to ModelHandlerContract and ModelLoadedHandler - Update contract_handler_discovery to register handlers by protocol_type ## Test Improvements - Add 21 new unit tests for handler discovery in test_handler_discovery.py - Enhance ensure_test_topic_exists with 4-point fail-fast validation - Replace 15+ fixed sleeps with deterministic polling for E2E reliability - Add wait_for_postgres_write() helper for deterministic write verification - Fix conftest.py wait calculation naming (default_wait -> minimum_wait) ## Documentation - Create MIGRATION_UPGRADE_003a_to_004.md with 4 upgrade scenarios - Update migrations README with renumbering documentation - Fix SQL file references from 003a to 004 ## Code Quality - Split ModelContractSecurityConfig into separate file (one-model-per-file) - Rename to avoid 'Handler' anti-pattern in model name - All ONEX validators now pass (7/7) [OMN-1317]
PR Review: Infrastructure Integration with Handler Contracts and E2E FixesThis is an excellent and comprehensive PR that implements critical infrastructure improvements. The code quality is very high, with thorough documentation, testing, and adherence to ONEX patterns. ✅ Strengths1. Handler Contract Architecture (Outstanding)
Contracts: # Example: contracts/handlers/db/handler_contract.yaml
name: handler-db
handler_class: omnibase_infra.handlers.handler_db.HandlerDb
handler_type: effect
security:
trusted_namespace: omnibase_infra.handlers
audit_logging: true2. Runtime Fail-Fast Behavior (Critical Improvement)# runtime_host_process.py:718-738
if not self._handlers:
raise ProtocolConfigurationError(
"No handlers registered. The runtime cannot start without at least one handler."
)
3. E2E Test Reliability Improvements (Significant)
4. Migration Renumbering (Well-Documented)
5. Type Safety & Model Changes
6. Test Coverage (Exceptional)
🔍 Issues & RecommendationsCRITICALNone - no blocking issues found. HIGH PRIORITY1. Environment Variable Naming Inconsistency (Minor)
2. Handler Registry Key Change Risk
MEDIUM PRIORITY3. Valkey Service Unused (Clarification Needed)
4. Pydantic Serialization Warning Suppression
5. Handler Contract YAML Size Limit
LOW PRIORITY (Code Quality)6. Docstring Consistency
7. Test Organization
8. E2E Test Duplication
📋 Code Quality Checklist
🎯 Final RecommendationAPPROVE with minor suggestions for follow-up. This PR demonstrates exceptional engineering quality:
The breaking changes are acceptable per ONEX policy (no backwards compatibility maintained), and the migration guide provides clear upgrade paths. Suggested Follow-Up Tickets
📊 Impact Summary
Great work on this infrastructure milestone! 🚀 |
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 Fix all issues with AI agents
In @src/omnibase_infra/models/runtime/model_handler_contract.py:
- Around line 122-132: The protocol_type Field currently falls back to a
stripped handler_name which can become empty (e.g., handler_name == "handler-");
update the model validation in the ModelHandlerContract class to compute
protocol_type when None by stripping the "handler-" prefix from handler_name but
then guard against an empty result—if the derived suffix is empty either raise a
pydantic ValidationError (ValueError) or set protocol_type to the full
handler_name as a safe fallback; implement this via a pydantic @validator or
root_validator for protocol_type/handler_name so the model never ends up with an
empty protocol key (also apply the same change to the other validator block
referenced around lines 208-243).
In @tests/integration/registration/e2e/test_full_orchestrator_flow.py:
- Around line 674-790: The fixture ensure_test_topic_exists incorrectly treats
topic_descriptions as a list; update handling so topic_descriptions is accessed
as a mapping (use topic_descriptions.get(TEST_INTROSPECTION_TOPIC) into
topic_metadata), then validate that topic_metadata is a list of
PartitionMetadata objects (remove .get("topic") and .get("error_code") usage and
instead check that topic_metadata is truthy and has at least one partition), and
replace admin_client.close() with the documented admin_client.stop() for
graceful shutdown; ensure error messages and topic_creation_hint are preserved
and the function still returns TEST_INTROSPECTION_TOPIC.
In @tests/integration/registration/e2e/test_runtime_e2e.py:
- Around line 529-551: The health polling loop currently calls
client.get(RUNTIME_HEALTH_URL) without catching httpx exceptions, so any
network/error will raise instead of marking the runtime unhealthy; wrap the call
to client.get(...) in a try/except catching httpx.HTTPError, set health_ok =
False and break in the except block, and keep the existing status_code check
behavior; apply the same try/except change to the second polling block later in
the file (the similar loop around lines referenced in the review).
- Around line 67-70: The two tests test_runtime_publishes_completion_event and
test_runtime_dual_registration_creates_consul_entry currently swallow failures
on timeout/absence; update them to be gated by the RUNTIME_PROCESSING_ENABLED
env flag (like other processing tests) and replace any early returns/warnings on
timeout with assertions that fail the test (e.g., raise AssertionError or use
assert) so missing completion events or Consul entries cause test failure; use
the existing wait_for_consumer_ready/wrap_event_in_envelope flow but ensure wait
timeouts/assert missing events and that the Consul lookup in
test_runtime_dual_registration_creates_consul_entry asserts the presence of the
expected entry instead of returning quietly.
In @tests/unit/runtime/test_handler_discovery.py:
- Around line 51-59: The test fixture VALID_HANDLER_CONTRACT_YAML uses incorrect
field names and omits required security metadata; update that YAML template (and
the other handler test fixture referenced later) to use "name" instead of
"handler_name" and "tags" instead of "capability_tags", and add a "security"
block containing "trusted_namespace" and "audit_logging" fields (use sensible
defaults for tests); ensure the templates still include "handler_class" and
"handler_type" and optionally add other real-schema fields (e.g., handler_id,
version, descriptor, input_model, output_model, capability_outputs,
supports_lifecycle, supports_health_check, supports_provisioning, metadata) only
if needed by the tests that reference VALID_HANDLER_CONTRACT_YAML so they
conform to the actual contracts in ./contracts/handlers/.
- Around line 489-685: Tests that expect RuntimeHostProcess.start() to raise
must still call RuntimeHostProcess.stop() to avoid leaked tasks/subscriptions;
wrap the start call (the with pytest.raises(...) block) in a try/finally and in
the finally await process.stop() (or ensure an outer try/finally around the with
pytest.raises) so that process.stop() is always invoked even when
RuntimeHostProcess.start() raises; apply this pattern to the failing tests that
use the process variable and RuntimeHostProcess.start/stop.
🧹 Nitpick comments (8)
docker/migrations/README.md (1)
12-16: Consider clarifying "optional variants" terminology.The term "optional variants" (Line 16) might be ambiguous. Rollback scripts, while using letter suffixes, aren't truly "optional" when you need to roll back a migration. Consider using more specific terminology like "alternative implementations" or "environment-specific variants" to avoid confusion.
💡 Suggested rewording
-> **Note on Sub-sequences**: Letter suffixes are suitable for optional variants (e.g., rollback scripts). For production-recommended variants like concurrent indexes, prefer main sequence numbers (see migration 004). +> **Note on Sub-sequences**: Letter suffixes are suitable for alternative or rollback variants. For production-recommended variants like concurrent indexes, prefer main sequence numbers (see migration 004).src/omnibase_infra/models/runtime/model_contract_security_config.py (1)
29-38: Consider addingfrozen=Truefor immutability.Other runtime models like
ModelLoadedHandlerusefrozen=Truein theirmodel_config. IfModelContractSecurityConfiginstances don't need to be modified after creation, consider addingfrozen=Truefor consistency and immutability guarantees.♻️ Suggested refactor
- model_config = ConfigDict(extra="forbid") + model_config = ConfigDict(extra="forbid", frozen=True)tests/integration/registration/e2e/test_runtime_e2e.py (1)
659-661: Tight SLA polling is fine; keep an eye on CI load.0.1s polling improves measurement resolution; just be aware it can increase load on Postgres/CI runners if many jobs run in parallel.
-->tests/integration/registration/e2e/test_two_way_registration_e2e.py (1)
460-468: Consider usingJsonTypefor handler envelopes in tests (consistency with infra typing).There are still several
dict[str, object]“envelopes” passed to infra handlers (e.g., Consul). If the repo standard isJsonTypefor JSON-compatible payloads, it may be worth switching for consistency. As per coding guidelines,JsonTypeis the canonical alias.
-->Also applies to: 593-602, 681-690, 2429-2437
tests/integration/registration/e2e/test_full_orchestrator_flow.py (2)
116-150:coerce_to_node_kind()helper is a good safety addition; keep node_version typing consistent.The coercion helper improves runtime safety around
node_type. Fornode_version, you sometimes passstr(event.node_version)intoModelRegistrationProjection(Line 539-545, 1218-1224). If the projection model expectsModelSemVer, prefer passing the object and letting serialization happen at the edges (unless the model explicitly wants string).
-->Also applies to: 475-486, 535-545, 1214-1224
330-372: Pipeline “intents generated” aren’t actually used for effect execution.Stage 3 computes
reducer_output.intents, but Stage 4 executes registration by rebuilding aModelRegistryRequest(ignoring the intents). If the goal is to validate “handler -> reducer -> effect” wiring, consider either:
- executing based on
reducer_output.intents, or- asserting the intents match what the effect is about to do (so the test still validates reducer correctness).
-->Also applies to: 456-504
tests/integration/registration/e2e/conftest.py (2)
124-171: Unused parameters create a misleading API.The
event_bus,topic, andpoll_intervalparameters are accepted but never used, making this function behave as a simpleasyncio.sleep()wrapper. While the docstring documents this as forward-compatible design, callers might expect actual readiness verification.Consider either:
- Removing unused parameters until actual polling is implemented
- Adding a deprecation-style comment or raising a warning if callers rely on these semantics
The always-
Truereturn value also means callers cannot distinguish between "ready" and "timed out waiting" — this may be acceptable for current usage but limits future error handling.
884-886: Private method exposed in Protocol interface.
_publish_heartbeatuses the underscore prefix convention indicating an internal/private method, but exposing it in theProtocolmakes it part of the public interface contract. This contradicts the naming convention.If tests need to call this method directly, consider either:
- Removing the underscore prefix (make it public):
publish_heartbeat- Removing it from the Protocol if tests should use
publish_introspection(reason=EnumIntrospectionReason.HEARTBEAT)insteadBased on learnings, internal methods should be prefixed with
_for security, but Protocol members define the public contract.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Lite
📒 Files selected for processing (18)
docker/migrations/003_capability_fields.sqldocker/migrations/004_capability_fields_concurrent.sqldocker/migrations/MIGRATION_UPGRADE_003a_to_004.mddocker/migrations/README.mdsrc/omnibase_infra/models/runtime/__init__.pysrc/omnibase_infra/models/runtime/model_contract_security_config.pysrc/omnibase_infra/models/runtime/model_handler_contract.pysrc/omnibase_infra/models/runtime/model_loaded_handler.pysrc/omnibase_infra/runtime/contract_handler_discovery.pysrc/omnibase_infra/runtime/handler_plugin_loader.pytests/integration/registration/e2e/conftest.pytests/integration/registration/e2e/test_full_orchestrator_flow.pytests/integration/registration/e2e/test_runtime_e2e.pytests/integration/registration/e2e/test_two_way_registration_e2e.pytests/integration/registration/e2e/verification_helpers.pytests/unit/runtime/conftest.pytests/unit/runtime/test_handler_discovery.pytests/unit/runtime/test_kernel.py
✅ Files skipped from review due to trivial changes (3)
- tests/unit/runtime/test_kernel.py
- docker/migrations/004_capability_fields_concurrent.sql
- docker/migrations/MIGRATION_UPGRADE_003a_to_004.md
🧰 Additional context used
📓 Path-based instructions (3)
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Never useAnytype - useobjectfor generic payloads in function parameters and return types
UseX | None(PEP 604) instead ofOptional[X]for nullable types
All services must useModelONEXContainerfor dependency injection via__init__(self, container: ModelONEXContainer)
Use@allow_anydecorator with documented reason as exemption mechanism forAnytype violations
UseJsonTypefromomnibase_core.typesas the canonical type alias for JSON-compatible values
UseModelEventEnvelope[object]for generic dispatcher interfaces andobjectfor generic payloads
Infrastructure error handling must useOnexErrorbase class and never expose passwords, API keys, PII, or connection strings with credentials in error messages
UseInfraConnectionError,InfraTimeoutError,InfraAuthenticationError,InfraUnavailableErrorfor transport failures with properModelInfraErrorContext
Correlation IDs must be propagated from incoming requests, auto-generated withuuid4()if missing, and included in all error contexts
External service adapters must implementMixinAsyncCircuitBreakerwith appropriate threshold and reset_timeout configuration
Protocol resolution must use duck typing via protocols, never useisinstancechecks
Files:
tests/unit/runtime/conftest.pysrc/omnibase_infra/models/runtime/__init__.pysrc/omnibase_infra/models/runtime/model_loaded_handler.pysrc/omnibase_infra/models/runtime/model_contract_security_config.pysrc/omnibase_infra/runtime/handler_plugin_loader.pysrc/omnibase_infra/runtime/contract_handler_discovery.pysrc/omnibase_infra/models/runtime/model_handler_contract.pytests/integration/registration/e2e/test_two_way_registration_e2e.pytests/integration/registration/e2e/test_runtime_e2e.pytests/integration/registration/e2e/test_full_orchestrator_flow.pytests/integration/registration/e2e/conftest.pytests/unit/runtime/test_handler_discovery.pytests/integration/registration/e2e/verification_helpers.py
**/model_*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/model_*.py: File naming convention: Models must usemodel_<name>.pywith class nameModel<Name>
Each model file must contain exactly oneModel*class
Pydantic workaround forAnytype must include# NOTE:comment documenting the reason when technically required
UseSerializeAsAnytype wrapper for Pydantic fields containing complex nested models to preserve subclass fields during serialization
Files:
src/omnibase_infra/models/runtime/model_loaded_handler.pysrc/omnibase_infra/models/runtime/model_contract_security_config.pysrc/omnibase_infra/models/runtime/model_handler_contract.py
**/handler_*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Handlers must NOT have direct event bus access - only orchestrators may have bus parameters and publish events
Files:
src/omnibase_infra/runtime/handler_plugin_loader.py
🧠 Learnings (50)
📓 Common learnings
Learnt from: CR
Repo: OmniNode-ai/omniagent PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T22:21:32.649Z
Learning: Applies to nodes/**/*.py : Use `omnibase_infra` handlers for OmniIntelligence queries via HttpRestAdapter envelope pattern
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/handler_contract.yaml : Handler contract files must declare handler routing with `routing_strategy`, event models, handler classes, and handler modules
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/handler_contract.yaml : Handlers must be discovered and loaded dynamically via YAML contracts using plugin pattern, not hardcoded registries
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contracts/contract_*.yaml : All ONEX node contract definitions must use the new subcontract architecture pattern, breaking down complex contracts into separate contract_actions.yaml, contract_models.yaml, contract_validation.yaml, and optional contract_cli.yaml and contract_capabilities.yaml files for separation of concerns, maintainability, reusability, modularity, and future tool-as-a-service readiness
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contracts/contract_*.yaml : All ONEX node subcontracts must be organized in a `contracts/` subdirectory within the versioned implementation directory with separate files for contract_actions.yaml, contract_models.yaml, contract_validation.yaml, contract_cli.yaml (optional), and contract_capabilities.yaml (optional)
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T16:32:55.606Z
Learning: Applies to **/*contract*.yaml : All ONEX nodes must have validated YAML contracts following the contract-driven development pattern with input_state and output_state schema definitions
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-24T17:22:32.195Z
Learning: Applies to **/v[0-9]_[0-9]_[0-9]/contracts/ : Organize contract subcomponents into separate files (contract_actions.yaml, contract_models.yaml, contract_validation.yaml, etc.) and reference them from main contract.yaml
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to src/omninode_bridge/nodes/**/contract.yaml : All contract YAML files for ONEX v2.0 nodes MUST define subcontract references, input/output models, and FSM configurations. Use YAML 1.2 syntax.
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: When both `handler_contract.yaml` and `contract.yaml` exist in the same directory, the loader must raise an error (AMBIGUOUS_CONTRACT_CONFIGURATION)
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/contract.yaml : Contract files must use semantic versioning with `contract_version` and `node_version` fields, specify node type (EFFECT/COMPUTE/REDUCER/ORCHESTRATOR), and strongly type all I/O with `input_model` and `output_model`
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/models/model_contract_*.py : All ONEX node auto-generated Pydantic models must be organized in a `models/` directory with files for state.py, model_contract_actions.py, model_contract_models.py, model_contract_validation.py, model_contract_cli.py (optional), model_contract_capabilities.py (optional), and error_codes.py, generated from the corresponding contract definitions
📚 Learning: 2025-11-24T17:22:32.195Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-24T17:22:32.195Z
Learning: Applies to **/testing/testing_scenario_harness.py : Registry resolver should use dynamic fixture detection based on constructor signatures using inspect.signature to determine which parameters to inject
Applied to files:
tests/unit/runtime/conftest.py
📚 Learning: 2025-11-24T17:24:54.193Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T17:24:54.193Z
Learning: Applies to **/*test*.py : Use registry=None in test harness to force registry resolver usage instead of manually creating registry instances
Applied to files:
tests/unit/runtime/conftest.py
📚 Learning: 2025-11-24T16:33:51.604Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T16:33:51.604Z
Learning: Applies to tests/**/conftest.py : Test fixtures must be defined in `conftest.py` and should provide reusable sample data, UUIDs, semantic versions, and model data
Applied to files:
tests/unit/runtime/conftest.pytests/integration/registration/e2e/conftest.py
📚 Learning: 2026-01-06T17:57:00.689Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_spi PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:57:00.689Z
Learning: Applies to src/omnibase_spi/protocols/**/*.py : Every protocol must inherit from `typing.Protocol` and have the `runtime_checkable` decorator
Applied to files:
tests/unit/runtime/conftest.pysrc/omnibase_infra/models/runtime/model_loaded_handler.pysrc/omnibase_infra/runtime/contract_handler_discovery.py
📚 Learning: 2025-11-24T17:22:32.195Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-24T17:22:32.195Z
Learning: Applies to **/protocols/protocol_*.py : Use Protocol from typing module for all interface definitions; never use ABC (Abstract Base Classes) for service interfaces
Applied to files:
tests/unit/runtime/conftest.pysrc/omnibase_infra/runtime/contract_handler_discovery.py
📚 Learning: 2025-11-24T17:24:41.687Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T17:24:41.687Z
Learning: Applies to **/protocols/protocol_*.py : Use Protocol for tool interfaces and plugin APIs based on method shape (structural typing), not Pydantic models with inheritance
Applied to files:
tests/unit/runtime/conftest.pysrc/omnibase_infra/models/runtime/model_loaded_handler.pysrc/omnibase_infra/runtime/handler_plugin_loader.py
📚 Learning: 2026-01-13T15:05:43.781Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T15:05:43.781Z
Learning: Applies to src/omnibase_core/**/__init__.py : Use barrel exports in `__init__.py` files to define public API boundaries; use underscore prefixes for internal/selective re-exports
Applied to files:
src/omnibase_infra/models/runtime/__init__.py
📚 Learning: 2026-01-06T17:57:00.689Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_spi PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:57:00.689Z
Learning: Applies to src/omnibase_spi/protocols/handlers/**/*.py : Protocol naming convention: Handler protocols must follow `Protocol{Type}Handler` pattern
Applied to files:
src/omnibase_infra/models/runtime/model_loaded_handler.pysrc/omnibase_infra/runtime/handler_plugin_loader.pysrc/omnibase_infra/runtime/contract_handler_discovery.pysrc/omnibase_infra/models/runtime/model_handler_contract.py
📚 Learning: 2025-11-24T17:22:32.195Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-24T17:22:32.195Z
Learning: Applies to **/protocols/protocol_*.py : All Protocol definitions must use model-only signatures: methods accept only validated Pydantic models, never dict, primitives, or argument models
Applied to files:
src/omnibase_infra/models/runtime/model_loaded_handler.pysrc/omnibase_infra/models/runtime/model_handler_contract.py
📚 Learning: 2025-11-24T16:33:32.747Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T16:33:32.747Z
Learning: Applies to **/protocols/protocol_*.py : All protocol method signatures must use Pydantic models exclusively, never primitives or dicts
Applied to files:
src/omnibase_infra/models/runtime/model_loaded_handler.py
📚 Learning: 2025-11-24T17:24:41.687Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T17:24:41.687Z
Learning: Applies to **/protocols/protocol_*.py : Protocol method signatures must use Pydantic models only, never primitives or dicts as parameters or return types
Applied to files:
src/omnibase_infra/models/runtime/model_loaded_handler.py
📚 Learning: 2026-01-13T15:05:43.781Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T15:05:43.781Z
Learning: Applies to src/omnibase_core/models/**/*.py : Every Pydantic model MUST have an explicit `model_config` with `ConfigDict()` that declares field behavior (frozen, extra, from_attributes)
Applied to files:
src/omnibase_infra/models/runtime/model_contract_security_config.pysrc/omnibase_infra/models/runtime/model_handler_contract.py
📚 Learning: 2025-11-24T17:24:41.687Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T17:24:41.687Z
Learning: Applies to **/models/model_contract_*.py : Models must be auto-generated from contract.yaml files, never hand-written
Applied to files:
src/omnibase_infra/models/runtime/model_contract_security_config.py
📚 Learning: 2025-11-24T17:24:41.687Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T17:24:41.687Z
Learning: Applies to **/models/model_contract_*.py : Contract-backed model files must follow the naming pattern `model_contract_<domain>.py` and be located in `*/models/` directories
Applied to files:
src/omnibase_infra/models/runtime/model_contract_security_config.py
📚 Learning: 2025-11-24T16:33:32.747Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T16:33:32.747Z
Learning: Applies to **/models/model_contract_*.py : Contract model files must follow the naming pattern `model_contract_<domain>.py` and be located in `*/models/` directories
Applied to files:
src/omnibase_infra/models/runtime/model_contract_security_config.py
📚 Learning: 2025-11-28T18:58:53.781Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-28T18:58:53.781Z
Learning: Applies to **/*.py : Use `ModelSemVer` instead of string versions in YAML contracts and version fields
Applied to files:
src/omnibase_infra/models/runtime/model_contract_security_config.py
📚 Learning: 2025-11-24T17:22:32.195Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-24T17:22:32.195Z
Learning: Applies to **/v[0-9]_[0-9]_[0-9]/models/*.py : All Pydantic models in models/ directory must be auto-generated from contract.yaml; never hand-write models
Applied to files:
src/omnibase_infra/models/runtime/model_contract_security_config.py
📚 Learning: 2025-11-24T17:24:41.687Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T17:24:41.687Z
Learning: Applies to **/models/model_contract_{actions,models,validation,cli,capabilities}.py : Generated models from subcontracts must follow the naming pattern: `model_contract_actions.py`, `model_contract_models.py`, `model_contract_validation.py`, etc.
Applied to files:
src/omnibase_infra/models/runtime/model_contract_security_config.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/handler_contract.yaml : Handlers must be discovered and loaded dynamically via YAML contracts using plugin pattern, not hardcoded registries
Applied to files:
src/omnibase_infra/runtime/handler_plugin_loader.pysrc/omnibase_infra/runtime/contract_handler_discovery.pytests/unit/runtime/test_handler_discovery.py
📚 Learning: 2026-01-06T17:57:00.689Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_spi PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:57:00.689Z
Learning: Applies to src/omnibase_spi/protocols/contracts/**/*.py : Protocol naming convention: Compiler protocols must follow `Protocol{Type}ContractCompiler` pattern
Applied to files:
src/omnibase_infra/runtime/handler_plugin_loader.pysrc/omnibase_infra/runtime/contract_handler_discovery.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/handler_contract.yaml : Handler contract files must declare handler routing with `routing_strategy`, event models, handler classes, and handler modules
Applied to files:
src/omnibase_infra/runtime/handler_plugin_loader.py
📚 Learning: 2026-01-13T15:05:43.780Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T15:05:43.780Z
Learning: Applies to src/omnibase_core/**/*.py : Use protocol names for dependency injection (e.g., `container.get_service('ProtocolEventBus')`, never concrete class names)
Applied to files:
src/omnibase_infra/runtime/contract_handler_discovery.py
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: All PostgreSQL migrations MUST be applied before starting services. Migration 005 (node_registrations table) is CRITICAL - verify it exists before deployment
Applied to files:
docker/migrations/003_capability_fields.sqldocker/migrations/README.md
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to migrations/*.sql : Database migrations in migrations/*.sql MUST be applied in order. Critical migration: 005-node_registrations.sql. Always backup before migrations in production.
Applied to files:
docker/migrations/003_capability_fields.sqldocker/migrations/README.md
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: PostgreSQL extension 'uuid-ossp' MUST be created before running migrations (requires superuser privileges). Use automated setup script: bash deployment/scripts/setup_postgres_extensions.sh
Applied to files:
docker/migrations/003_capability_fields.sql
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/*.py : Use `ModelEventEnvelope[object]` for generic dispatcher interfaces and `object` for generic payloads
Applied to files:
tests/integration/registration/e2e/test_two_way_registration_e2e.pytests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-24T16:32:55.606Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T16:32:55.606Z
Learning: Node communication must use event-driven patterns through `ModelEventEnvelope` from `omnibase_core.models.events.model_event_envelope`
Applied to files:
tests/integration/registration/e2e/test_two_way_registration_e2e.pytests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/introspection.py : All ONEX nodes must include an `introspection.py` file implementing standards-compliant introspection logic
Applied to files:
tests/integration/registration/e2e/test_two_way_registration_e2e.pytests/integration/registration/e2e/conftest.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Node Introspection Security - use Python reflection for service discovery, but prefix internal/sensitive methods with `_`, use generic parameter names, and configure Kafka topic ACLs for introspection topics
Applied to files:
tests/integration/registration/e2e/test_two_way_registration_e2e.pytests/integration/registration/e2e/test_full_orchestrator_flow.pytests/integration/registration/e2e/conftest.py
📚 Learning: 2026-01-13T15:05:43.780Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T15:05:43.780Z
Learning: Applies to src/omnibase_core/nodes/**/*.py : Use `ModelONEXContainer` (not `ModelContainer`) for dependency injection in node constructors
Applied to files:
tests/integration/registration/e2e/test_two_way_registration_e2e.py
📚 Learning: 2025-12-03T16:55:49.755Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-03T16:55:49.755Z
Learning: Applies to **/*.py : Publish intelligence requests to Kafka event bus using topics: dev.archon-intelligence.intelligence.code-analysis-{requested,completed,failed}.v1 for consistency and event-driven architecture
Applied to files:
tests/integration/registration/e2e/test_runtime_e2e.pytests/integration/registration/e2e/test_full_orchestrator_flow.pytests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to src/omninode_bridge/events/**/*.py : Kafka event publishing MUST use OnexEnvelopeV1 format with 13 topics for event streaming at all workflow lifecycle stages
Applied to files:
tests/integration/registration/e2e/test_runtime_e2e.pytests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-12-06T22:21:32.649Z
Learnt from: CR
Repo: OmniNode-ai/omniagent PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T22:21:32.649Z
Learning: Applies to nodes/**/*.py : Use event bus mixins from `omnibase_core` for Kafka publishing instead of direct Kafka clients
Applied to files:
tests/integration/registration/e2e/test_runtime_e2e.pytests/integration/registration/e2e/conftest.py
📚 Learning: 2025-12-06T22:21:32.649Z
Learnt from: CR
Repo: OmniNode-ai/omniagent PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T22:21:32.649Z
Learning: Applies to nodes/effect/**/*.py : Use handler envelopes from `omnibase_infra` for all I/O operations (HTTP, database, Kafka) instead of custom clients
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-12-07T17:50:13.678Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T17:50:13.678Z
Learning: Implement Kafka event-driven architecture with proper topic naming using prefix dev.archon-intelligence. and proper event flow pattern with Effect nodes consuming events, processing, and publishing results with Dead Letter Queue routing
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-29T22:07:25.230Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: migration_sources/omniarchon/CLAUDE.md:0-0
Timestamp: 2025-11-29T22:07:25.230Z
Learning: Applies to migration_sources/omniarchon/**/tests/**/*.py : All integration tests must verify correct Kafka port usage for context (9092 for Docker, 29092 for host). Test both local (qdrant, memgraph) and remote (PostgreSQL, Redpanda) database connectivity. Never assume test environment configuration.
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.pytests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-29T17:13:38.776Z
Learnt from: CR
Repo: OmniNode-ai/omniarchon PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T17:13:38.776Z
Learning: Applies to **/*.py : All Kafka topics must use the prefix `dev.archon-intelligence` for development/staging environments.
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-12-03T16:55:49.755Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-03T16:55:49.755Z
Learning: Applies to scripts/tests/**/*.sh : Implement comprehensive test suites in scripts/tests/ with separate test files for Kafka, PostgreSQL, Intelligence, and Routing functionality
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-29T17:13:38.776Z
Learnt from: CR
Repo: OmniNode-ai/omniarchon PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T17:13:38.776Z
Learning: Applies to {services/**/*.py,scripts/bulk_ingest_repository.py} : Implement fail-closed configuration for security hardening. All external requests must validate URLs, implement DLQ routing, and handle failures gracefully.
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-28T18:58:53.781Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-28T18:58:53.781Z
Learning: Applies to **/*.py : Implement Node classes by inheriting from `NodeBase` with proper UUID and `ModelSemVer` fields
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to src/omninode_bridge/nodes/**/{models,node}.py : Bridge nodes MUST implement FSM states: PENDING, PROCESSING, COMPLETED, FAILED. Use Pydantic v2 models with proper state enum validation
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-12-06T22:21:32.649Z
Learnt from: CR
Repo: OmniNode-ai/omniagent PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T22:21:32.649Z
Learning: Applies to tests/**/*.py : Use pytest markers `pytest.mark.unit`, `pytest.mark.integration`, `pytest.mark.slow`, and `pytest.mark.performance` for test categorization
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/node_tests/**/*.py : All ONEX node tests must be organized in a `node_tests/` directory using scenario-driven testing patterns with fixture-injected tests
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-24T16:32:55.606Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T16:32:55.606Z
Learning: Applies to tests/unit/infrastructure/**/test_*.py : All node implementations must have comprehensive unit tests following the testing pattern in `tests/unit/infrastructure/` with tests for node initialization and node execution
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-12-07T17:50:13.678Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T17:50:13.678Z
Learning: Organize tests following the structure: tests/conftest.py for shared fixtures, tests/unit/ for unit tests (no infrastructure), tests/integration/ for integration tests (requires Kafka/DBs), tests/nodes/ for node-specific tests
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.pytests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-24T16:33:51.604Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T16:33:51.604Z
Learning: Applies to tests/**/*.py : Test files must follow the naming convention `test_[module_name].py` (examples: `test_enum_acknowledgment_type.py`, `test_model_node_status.py`, `test_mixin_hash_computation.py`)
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-12-19T02:58:44.081Z
Learnt from: sudharsanv177
Repo: OmniNode-ai/omninode_infra PR: 4
File: docker/onex-api/main.py:0-0
Timestamp: 2025-12-19T02:58:44.081Z
Learning: In the omninode_infra repository, production configuration is managed via Kubernetes Secrets and ConfigMaps injected as environment variables, not committed .env files or Pydantic Settings. The deployment model uses os.getenv() with sensible defaults for local development, and explicit resolution patterns (e.g., checking POSTGRES_DSN first, then deriving from component variables) are preferred over mutating os.environ.
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-29T22:07:25.230Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: migration_sources/omniarchon/CLAUDE.md:0-0
Timestamp: 2025-11-29T22:07:25.230Z
Learning: Applies to migration_sources/omniarchon/**/*.py : Always use REMOTE Redpanda at 192.168.86.200 for event bus. NEVER start local Redpanda. Remote Redpanda enables OmniNode integration, data consistency, and production parity. Use correct ports: 9092 (Docker) or 29092 (host scripts).
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-24T16:32:55.606Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T16:32:55.606Z
Learning: Node implementations must use mixin-based composition from `omnibase_core.mixins` (e.g., `MixinHealthCheck`, `MixinNodeExecutor`) to add capabilities
Applied to files:
tests/integration/registration/e2e/conftest.py
🧬 Code graph analysis (6)
tests/unit/runtime/conftest.py (1)
src/omnibase_infra/runtime/registry/registry_protocol_binding.py (1)
ProtocolBindingRegistry(131-439)
src/omnibase_infra/models/runtime/__init__.py (1)
src/omnibase_infra/models/runtime/model_contract_security_config.py (1)
ModelContractSecurityConfig(17-38)
src/omnibase_infra/runtime/handler_plugin_loader.py (1)
src/omnibase_infra/runtime/projector_plugin_loader.py (1)
contract(114-116)
src/omnibase_infra/models/runtime/model_handler_contract.py (2)
src/omnibase_infra/enums/enum_handler_type_category.py (1)
EnumHandlerTypeCategory(35-58)src/omnibase_infra/models/runtime/model_contract_security_config.py (1)
ModelContractSecurityConfig(17-38)
tests/integration/registration/e2e/test_two_way_registration_e2e.py (2)
src/omnibase_infra/enums/enum_introspection_reason.py (1)
EnumIntrospectionReason(18-151)tests/integration/registration/e2e/conftest.py (1)
wait_for_consumer_ready(124-171)
tests/unit/runtime/test_handler_discovery.py (3)
src/omnibase_infra/runtime/registry/registry_protocol_binding.py (1)
ProtocolBindingRegistry(131-439)src/omnibase_infra/runtime/runtime_host_process.py (1)
_discover_handlers_from_contracts(944-1024)src/omnibase_infra/errors/error_infra.py (1)
ProtocolConfigurationError(154-189)
🔇 Additional comments (21)
docker/migrations/README.md (2)
174-179: Decision tree is clear and well-structured.The decision tree provides a logical flow for determining the next migration number, prioritizing production-optimized variants, then rollback scripts, with a sensible default.
1-188: Well-documented migration convention update.The documentation comprehensively updates all references from the old
003anaming to the new004convention. The historical note, updated examples, and upgrade notes section provide clear guidance for both new deployments and existing systems.docker/migrations/003_capability_fields.sql (3)
104-159: DDL statements are well-structured and idempotent.The column additions and index creation follow PostgreSQL best practices:
IF NOT EXISTSclauses ensure safe re-runs.- GIN indexes are appropriate for array containment queries (
@>).- Default empty arrays on array columns simplify query logic by avoiding NULL handling.
- Composite B-tree index on
(contract_type, current_state)supports efficient filtering.
215-228: Idempotent constraint creation is correctly implemented.The DO block properly checks
pg_constraintbefore adding, preventing duplicate constraint errors on re-runs. The constraint values align with documented ONEX node archetypes, and the thorough documentation (lines 162-212) clearly explains the distinction between NULL (unprocessed) and 'unknown' (legacy backfill marker).
47-67: Migration file correctly updated; stale references remain in supporting documentation.The
003_capability_fields.sqlmigration file properly references004_capability_fields_concurrent.sqlthroughout its comments and deployment guidance. However, stale references to the old003a_capability_fields_concurrent.sqlnaming persist indocker/migrations/README.md, which should be updated to reflect the current naming convention for consistency with the renamed migration sequence.⛔ Skipped due to learnings
Learnt from: CR Repo: OmniNode-ai/omninode_bridge PR: 0 File: CLAUDE.md:0-0 Timestamp: 2025-11-30T21:55:10.298Z Learning: Applies to migrations/*.sql : Database migrations in migrations/*.sql MUST be applied in order. Critical migration: 005-node_registrations.sql. Always backup before migrations in production.Learnt from: CR Repo: OmniNode-ai/omninode_bridge PR: 0 File: CLAUDE.md:0-0 Timestamp: 2025-11-30T21:55:10.298Z Learning: All PostgreSQL migrations MUST be applied before starting services. Migration 005 (node_registrations table) is CRITICAL - verify it exists before deploymenttests/unit/runtime/conftest.py (1)
36-53: LGTM! Good pattern for handler registration tests.Providing a real
ProtocolBindingRegistryinstance while mocking other services is a sound approach for testing handler discovery and registration flows. The shared registry ensures consistent state across the test scope.tests/integration/registration/e2e/verification_helpers.py (2)
217-284: Well-designed deterministic polling helper.This implementation correctly replaces fixed sleeps with targeted polling, which improves test reliability and execution speed. The default 50ms poll interval is appropriately aggressive for fast write verification.
968-968: The assertion correctly referencescapabilitiesas defined in theModelNodeBecameActivemodel (line 97-100). No changes needed.src/omnibase_infra/models/runtime/__init__.py (1)
12-14: LGTM! Clean barrel export addition.The new
ModelContractSecurityConfigexport follows the established pattern and maintains alphabetical ordering in__all__.Also applies to: 31-31
src/omnibase_infra/models/runtime/model_loaded_handler.py (1)
88-95: LGTM! Requiredprotocol_typefield with proper validation.The
min_length=1constraint ensures non-empty values, and the required nature of the field guarantees it's always present. This supports the registration-by-protocol-type pattern inContractHandlerDiscovery.src/omnibase_infra/runtime/handler_plugin_loader.py (2)
567-574: LGTM! Protocol type extraction with defensive assertion.The assertion correctly guards against the unlikely case where
protocol_typeisNoneafter model validation. The comment appropriately documents why this should never happen (model_validator handles defaulting).Note: If assertions are disabled in production (via
-Oflag), this check would be bypassed. Consider using an explicitifcheck with a raise if this needs guaranteed runtime validation.
637-645: LGTM! ModelLoadedHandler construction includes protocol_type.The
protocol_typefield is correctly passed to the constructor, satisfying the new required field constraint.src/omnibase_infra/runtime/contract_handler_discovery.py (1)
343-365: LGTM! Protocol-type based registration enables cleaner routing.The change to use
protocol_typeas the registry key aligns with message routing semantics where handlers are selected by protocol (e.g., "db", "http") rather than handler name. The debug logging includes both identifiers for good traceability. Theprotocol_typefield is guaranteed non-None and non-empty via Pydantic validation (min_length=1), confirming this registration approach is safe.tests/unit/runtime/test_handler_discovery.py (1)
319-472: Good coverage of discovery lifecycle + mixed valid/invalid contracts.The tests around “logs errors but still registers valid handlers” and “fail-fast when nothing registers” are the right shape for this feature.
-->src/omnibase_infra/models/runtime/model_handler_contract.py (2)
96-101: Model config + aliasing approach looks good.
extra="forbid"+populate_by_name=Trueis a good combo for strict contracts while still supportingname/tagsaliases.
-->Also applies to: 102-121
26-33: Confirm contract schema alignment with actualhandler_contract.yamlfiles.The local
ModelHandlerContractallows onlyhandler_name,handler_class,handler_type,capability_tags,protocol_type, andsecuritywithextra="forbid". Simple contracts in./contracts/handlers/{db,consul,http,vault,filesystem}/are compatible. However, extended contracts in./src/omnibase_infra/contracts/handlers/{filesystem,mcp}/contain additional fields (handler_id,version,descriptor,capability_outputs,input_model,output_model,supports_lifecycle,supports_health_check,supports_provisioning,metadata) that would be rejected by the current model.Note:
handler_contract_source.pyimportsModelHandlerContractfromomnibase_core.models.contracts(external package), whilehandler_plugin_loader.pyimports from the local model. Verify which code path validates the extended contracts and whether the omnibase_core version accommodates these fields, or extend the local model to support them.tests/integration/registration/e2e/test_two_way_registration_e2e.py (1)
41-52: Envelope-based test flows + typed introspection reasons are solid.The shift to
ModelEventEnvelopeandEnumIntrospectionReasonreduces stringly-typed drift and keeps the tests aligned with the on-the-wire format. Thewait_for_postgres_write()polling also looks like a meaningful flake reduction.
-->Also applies to: 144-156, 392-403, 786-793, 879-886, 1500-1511
tests/integration/registration/e2e/test_full_orchestrator_flow.py (1)
827-830: Polling + consumer readiness additions look good for E2E stability.The explicit readiness wait and polling loops are the right direction to avoid fixed sleeps and race conditions around Kafka consumer group joins.
-->Also applies to: 915-921, 987-993, 1055-1064
tests/integration/registration/e2e/conftest.py (3)
1109-1140: LGTM with minor note on logging setup.The fixture correctly:
- Uses session scope to configure once per test run
- Checks for existing handlers before adding
- Provides clear formatting for observability
Note:
infra_loggerhas its level set to INFO (line 1128) but no handler is added, so its output depends on the root logger configuration. This is likely intentional to avoid duplicate handlers, but worth verifying that infrastructure logs appear as expected during E2E runs.
1146-1188: LGTM!The
__all__exports are correctly updated to include the newwait_for_consumer_readyhelper andconfigure_e2e_loggingfixture, with appropriate categorization comments.
820-833: LGTM!The Protocol docstring update accurately reflects the new introspection lifecycle methods. Good documentation of the fixture-internal implementation pattern.
| @pytest.fixture | ||
| async def ensure_test_topic_exists( | ||
| real_kafka_event_bus: KafkaEventBus, | ||
| ) -> str: | ||
| """Validate and return the pre-existing test topic name. | ||
|
|
||
| This fixture validates that the test topic (e2e-test.node.introspection.v1) | ||
| exists in the Kafka cluster before tests run. The topic should be pre-created | ||
| during initial infrastructure setup. | ||
|
|
||
| Fail-fast behavior: If the topic doesn't exist or validation fails, this | ||
| fixture fails immediately with a clear error message, preventing cryptic | ||
| failures later in the test. | ||
|
|
||
| Test isolation is achieved via unique consumer group IDs rather than | ||
| unique topic names. | ||
|
|
||
| Args: | ||
| real_kafka_event_bus: Real Kafka event bus (unused but kept for | ||
| fixture dependency ordering). | ||
|
|
||
| Returns: | ||
| The test topic name. | ||
|
|
||
| Raises: | ||
| pytest.fail: If the topic does not exist in Kafka or validation fails. | ||
| """ | ||
| import os | ||
|
|
||
| from aiokafka.admin import AIOKafkaAdminClient | ||
|
|
||
| bootstrap_servers = os.getenv("KAFKA_BOOTSTRAP_SERVERS") | ||
| if not bootstrap_servers: | ||
| pytest.fail("KAFKA_BOOTSTRAP_SERVERS environment variable not set") | ||
|
|
||
| admin_client: AIOKafkaAdminClient | None = None | ||
| topic_creation_hint = ( | ||
| f"Create it before running E2E tests: " | ||
| f"rpk topic create {TEST_INTROSPECTION_TOPIC} --partitions 1" | ||
| ) | ||
|
|
||
| try: | ||
| admin_client = AIOKafkaAdminClient(bootstrap_servers=bootstrap_servers) | ||
| await admin_client.start() | ||
|
|
||
| # Validate topic exists by describing it | ||
| # describe_topics returns list of topic metadata or raises exception | ||
| topic_descriptions = await admin_client.describe_topics( | ||
| [TEST_INTROSPECTION_TOPIC] | ||
| ) | ||
|
|
||
| # Fail-fast validation 1: Empty response means topic doesn't exist | ||
| if not topic_descriptions: | ||
| pytest.fail( | ||
| f"Test topic '{TEST_INTROSPECTION_TOPIC}' does not exist " | ||
| f"(describe_topics returned empty response). {topic_creation_hint}" | ||
| ) | ||
|
|
||
| # Fail-fast validation 2: Check if topic is actually in the response | ||
| # The response is a list of dicts with topic metadata | ||
| topic_metadata = topic_descriptions[0] | ||
|
|
||
| # Validate topic name matches (handles potential mismatch) | ||
| topic_name = topic_metadata.get("topic", topic_metadata.get("name")) | ||
| if topic_name and topic_name != TEST_INTROSPECTION_TOPIC: | ||
| pytest.fail( | ||
| f"Topic name mismatch: expected '{TEST_INTROSPECTION_TOPIC}', " | ||
| f"got '{topic_name}'. {topic_creation_hint}" | ||
| ) | ||
|
|
||
| # Fail-fast validation 3: Check for error codes in response | ||
| # aiokafka may return error_code field for non-existent topics | ||
| error_code = topic_metadata.get("error_code", 0) | ||
| if error_code != 0: | ||
| pytest.fail( | ||
| f"Test topic '{TEST_INTROSPECTION_TOPIC}' has error code {error_code}. " | ||
| f"Topic may not exist or has invalid configuration. {topic_creation_hint}" | ||
| ) | ||
|
|
||
| # Fail-fast validation 4: Ensure topic has at least one partition | ||
| partitions = topic_metadata.get("partitions", []) | ||
| if not partitions: | ||
| pytest.fail( | ||
| f"Test topic '{TEST_INTROSPECTION_TOPIC}' has no partitions. " | ||
| f"Topic may be misconfigured. {topic_creation_hint}" | ||
| ) | ||
|
|
||
| logger.info( | ||
| "Test topic validated successfully", | ||
| extra={ | ||
| "topic": TEST_INTROSPECTION_TOPIC, | ||
| "partitions": len(partitions), | ||
| }, | ||
| ) | ||
|
|
||
| except Exception as e: | ||
| # Check if it's a "topic not found" type error | ||
| error_msg = str(e).lower() | ||
| if "unknown topic" in error_msg or "not found" in error_msg: | ||
| pytest.fail( | ||
| f"Test topic '{TEST_INTROSPECTION_TOPIC}' does not exist. " | ||
| f"{topic_creation_hint}" | ||
| ) | ||
| # Check for other common Kafka errors | ||
| if "timeout" in error_msg: | ||
| pytest.fail( | ||
| f"Timeout validating topic '{TEST_INTROSPECTION_TOPIC}'. " | ||
| f"Kafka cluster may be unreachable at {bootstrap_servers}." | ||
| ) | ||
| # Re-raise other errors (connection issues, etc.) | ||
| raise | ||
| finally: | ||
| if admin_client is not None: | ||
| await admin_client.close() | ||
|
|
||
| return TEST_INTROSPECTION_TOPIC | ||
|
|
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
aiokafka 0.11.0 AIOKafkaAdminClient describe_topics documentation return format
💡 Result:
AIOKafkaAdminClient.describe_topics (aiokafka v0.11.0) returns topic metadata as a mapping of topic name → topic/partition metadata. Concretely you get each topic mapped to a list/structure of PartitionMetadata entries (aiokafka.structs.PartitionMetadata / TopicPartition-like objects) containing the partition id plus broker info: leader, replicas and ISR (in-sync replicas) — essentially the same partition metadata shape used across Kafka admin APIs (TopicDescription / PartitionMetadata). See aiokafka structs and the release that includes AIOKafkaAdminClient. [1][2]
References
- aiokafka structs (Partition/Topic metadata types). [1]
- aiokafka v0.11.0 release (AIOKafkaAdminClient present). [2]
If you want an exact example Python shape (example):
{
"my-topic": [
PartitionMetadata(partition=0, leader=1, replicas=[1,2], isr=[1,2]),
PartitionMetadata(partition=1, leader=2, replicas=[2,3], isr=[2,3]),
...
],
...
}
(Ask if you want a live example from a running broker.)
🌐 Web query:
aiokafka 0.11.0 AIOKafkaAdminClient close method vs stop method shutdown
💡 Result:
Short answer: use stop() for the high‑level, graceful async shutdown of aiokafka clients; close() is the lower‑level close of the underlying network/client object that stop() calls as part of shutdown.
Details / evidence:
- aiokafka’s high‑level clients expose start() / stop() as the public lifecycle API and the docs show stop() performs finalization (flush/leave group/etc.) then awaits the underlying client.close(). [1][2]
- Producers and consumers’ stop() implementations explicitly call await self.client.close() after doing client‑specific finalizers (flush/commit/leave group). That pattern is the same for admin: stop() performs any admin finalization and then closes the underlying client; close() is the lower‑level client shutdown. [2][3]
References:
- aiokafka README / docs (start/stop usage). [1]
- aiokafka consumer/producer implementation showing stop() calling await self.client.close(). [2][3]
If you want, I can fetch the exact AIOKafkaAdminClient 0.11.0 source lines and show which method calls which.
🏁 Script executed:
# Find dependency specifications to confirm aiokafka version
find . -type f \( -name "requirements*.txt" -o -name "setup.py" -o -name "pyproject.toml" -o -name "Pipfile" \) | head -20Repository: OmniNode-ai/omnibase_infra
Length of output: 196
🏁 Script executed:
# Check what aiokafka version is referenced in the test file or nearby
rg "aiokafka" --type py -A 2 -B 2 | head -50Repository: OmniNode-ai/omnibase_infra
Length of output: 3610
🏁 Script executed:
# Check other admin client usages for describe_topics pattern
rg "describe_topics" --type py -B 3 -A 5Repository: OmniNode-ai/omnibase_infra
Length of output: 2804
🏁 Script executed:
# Check how admin_client shutdown is done elsewhere
rg "admin_client\.(close|stop)" --type py -B 2 -A 2Repository: OmniNode-ai/omnibase_infra
Length of output: 703
Fix describe_topics response handling: it returns a dict, not a list.
aiokafka 0.11.0's describe_topics() returns a dict mapping topic names to partition metadata (e.g., {"topic-name": [PartitionMetadata(...), ...]}). The fixture currently indexes it as a list at line 723 (topic_metadata = topic_descriptions[0]), which will fail at runtime.
Correct the access pattern to: topic_metadata = topic_descriptions.get(TEST_INTROSPECTION_TOPIC). Then, since topic_metadata is a list of PartitionMetadata objects (not a dict), the subsequent .get("error_code") and .get("topic") calls on lines 743 and 739 will not work and should be removed or refactored to validate the partition list structure directly.
Additionally, consider using stop() instead of close() for graceful shutdown of the admin client, which is the documented public lifecycle API.
🤖 Prompt for AI Agents
In @tests/integration/registration/e2e/test_full_orchestrator_flow.py around
lines 674 - 790, The fixture ensure_test_topic_exists incorrectly treats
topic_descriptions as a list; update handling so topic_descriptions is accessed
as a mapping (use topic_descriptions.get(TEST_INTROSPECTION_TOPIC) into
topic_metadata), then validate that topic_metadata is a list of
PartitionMetadata objects (remove .get("topic") and .get("error_code") usage and
instead check that topic_metadata is truthy and has at least one partition), and
replace admin_client.close() with the documented admin_client.stop() for
graceful shutdown; ensure error messages and topic_creation_hint are preserved
and the function still returns TEST_INTROSPECTION_TOPIC.
…ts, and nitpicks PR Review Fixes: - Add comprehensive security documentation for handler contracts and plugin loader - Add ADR for handler contract schema evolution strategy - Document migration path from 003a → 004 with validation SQL - Create wire_default_handlers() migration guide Test Improvements: - Add 17 unit tests for _discover_handlers_from_contracts() - Add 48 negative tests for invalid contract YAML handling - Add tests for no_handlers_registered health check field - Centralize handler seeding setup to reduce test duplication - Fix mock_handler async shutdown/health_check methods Code Quality: - Fix logging level consistency in E2E conftest - Improve wait calculation logic in E2E tests - Clarify "no handlers" semantics in architecture validation tests - Remove unused imports across 100 files Documentation: - Update handler plugin loader patterns with security model - Add migration section to patterns README - Update HANDLER_PROTOCOL_DRIVEN_ARCHITECTURE.md All 1896 unit tests pass.
PR Review: Infrastructure Integration with Handler Contracts and E2E Fixes [OMN-1317]Overall AssessmentStatus: ✅ Approve with recommendations This is a substantial and well-executed PR (6544 additions, 131 files) that successfully implements contract-based handler discovery and addresses critical E2E test infrastructure issues. The implementation follows ONEX conventions and demonstrates strong attention to detail. Key Strengths1. Contract-Based Handler Discovery ✅
2. E2E Test Infrastructure Fixes ✅
3. Code Quality & Documentation ✅
Critical Issues1.
|
There was a problem hiding this comment.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (5)
tests/unit/mixins/test_circuit_breaker_transitions.py (1)
690-708: Test does not verify its stated behavior.The test claims to verify that "failures during OPEN state don't extend timeout," but the bare
get_open_until()call on line 701 discards its return value. The test only asserts that the state remains OPEN, not that the timeout wasn't extended.Either remove the dead call entirely, or implement the actual verification:
Proposed fix to verify the timeout behavior
# Open the circuit for _ in range(fast_service.circuit_breaker_threshold): await fast_service.record_failure() - fast_service.get_open_until() + original_open_until = fast_service.get_open_until() # Record more failures (simulating if somehow failures were recorded) await fast_service.record_failure() await fast_service.record_failure() - # The open_until timestamp might update, but circuit stays open + # Verify timeout wasn't extended and circuit stays open + assert fast_service.get_open_until() == original_open_until assert fast_service.get_state() == EnumCircuitState.OPENtests/unit/nodes/test_orchestrator_purity.py (1)
150-160: Dead code: bare set comprehension has no effect.Line 154 creates a set from
consumed_eventsbut discards the result immediately since it's not assigned to a variable. This also makes line 152 dead code sinceconsumed_eventsis now unused. The comment on lines 150-151 mentions checking consumed events "for completeness," but no actual assertion uses them.Either remove both lines 152 and 154 entirely, or restore the variable assignment if consumed topics were intended to be used.
🧹 Proposed fix: remove dead code
- # Also check consumed_events for completeness (consumed can have any type) - # But published should NEVER have commands - consumed_events = contract_data.get("consumed_events", []) - published_topics = {e.get("topic") for e in published_events} - {e.get("topic") for e in consumed_events} - - # Published and consumed should not share command topics + # Published should NEVER have commands + published_topics = {e.get("topic") for e in published_events} for topic in published_topics:src/omnibase_infra/runtime/handler_plugin_loader.py (1)
562-574: Avoidassertforprotocol_typevalidation; raise a structured error instead.
assertcan be stripped with-O, and ifprotocol_typeever regresses toNoneyou’ll get worse/less structured failures downstream. Prefer an explicit check that raisesProtocolConfigurationErrorwith a loader error code.Proposed fix
handler_type = contract.handler_type capability_tags = contract.capability_tags # protocol_type is the registry key (e.g., "db", "http") # The model_validator in ModelHandlerContract sets this from handler_name # if not explicitly provided (strips "handler-" prefix) protocol_type = contract.protocol_type - # Should never be None after model_validator, but assert for type safety - assert protocol_type is not None, ( - "protocol_type should be set by model_validator" - ) + # Should never be None after model_validator, but fail with structured error + if protocol_type is None: + context = ModelInfraErrorContext( + transport_type=EnumInfraTransportType.RUNTIME, + operation="load_from_contract", + correlation_id=correlation_id, + ) + raise ProtocolConfigurationError( + "Contract validation failed: protocol_type is missing", + context=context, + loader_error=EnumHandlerLoaderError.SCHEMA_VALIDATION_FAILED.value, + contract_path=str(contract_path), + )tests/integration/event_bus/conftest.py (1)
16-126: Makeconsumer_countcomparison type-safe (avoidNone/strcomparison surprises).Since
health_check()isdict[str, object], a defensive cast keeps this helper robust ifconsumer_countis ever missing/None/string-typed.Proposed fix
initial_health = await event_bus.health_check() - initial_consumer_count = initial_health.get("consumer_count", 0) + initial_consumer_count_raw = initial_health.get("consumer_count", 0) + initial_consumer_count = int(initial_consumer_count_raw or 0) # Poll until consumer count increases or timeout while (asyncio.get_running_loop().time() - start_time) < max_wait: health = await event_bus.health_check() - consumer_count = health.get("consumer_count", 0) + consumer_count_raw = health.get("consumer_count", 0) + consumer_count = int(consumer_count_raw or 0)If the “always return True” behavior is still required, consider adding an opt-in
strict: bool = Falsethat returnsFalseon timeout for new call sites (while keeping current callers unchanged).docs/patterns/handler_plugin_loader.md (1)
82-103: Doc “Required Fields” appears incomplete vs this repo’s handler_contract requirements.
The doc currently implies onlyhandler_name,handler_class,handler_typeare required, but in this repo handler contracts must also declare routing info and models. Please either (a) expand “Required Fields” to match the handler contract schema or (b) label this section explicitly as “minimum fields the loader reads” (not a valid contract for this repo).Based on learnings, handler contracts must include
routing_strategy, event models, handler classes, and handler modules.
🤖 Fix all issues with AI agents
In @docker/migrations/README.md:
- Around line 12-17: The README currently indicates "Next sub-migration for 004:
`004b_*.sql`" which conflicts with the documented letter-suffix scheme (where
`004a` should be the next sub-sequence) and will confuse authors; update the
text so it either lists `004a_*.sql` as the next sub-migration or add an
explicit note in the "Note on Sub-sequences" clarifying that `004a` is
intentionally reserved/skipped (and why), and make the same correction wherever
the incorrect `004b_*.sql` reference appears (e.g., the blocks corresponding to
the earlier and later repeats).
In @tests/performance/registration/effect/test_idempotency_store_performance.py:
- Around line 495-496: Remove the orphaned expression `burst_size * num_bursts`
which produces a discarded value (likely leftover from a removed `total_ops`
assignment); delete that standalone line so the test contains no
side-effect-free expressions and, if `total_ops` is still needed, reintroduce it
as an assignment (e.g., `total_ops = burst_size * num_bursts`) where referenced.
In @tests/unit/nodes/test_orchestrator_time_injection.py:
- Line 264: Remove the dead expression that computes the intersection without
using its result: delete the standalone `imports & time_related_imports`
statement in the test (it references the variables `imports` and
`time_related_imports` in tests/unit/nodes/test_orchestrator_time_injection.py)
so the test relies only on the existing assertion (`"time" not in imports`) and
avoids the no-op computation.
In @tests/unit/projectors/test_snapshot_cache_operations.py:
- Line 611: Remove the orphaned MagicMock() call in the test — it's creating a
discarded mock and is unnecessary because mock_consumer.getmany is set to return
an empty dict; simply delete the standalone MagicMock() line (the one not
assigned to a variable) so only the relevant mocks (e.g., mock_consumer.getmany
and mock_tp usages in other tests) remain.
In @tests/unit/runtime/test_handler_discovery.py:
- Around line 1879-1888: The test currently builds a list comprehension over
caplog.records to find records containing a correlation_id but never asserts its
result; replace that dead code with an explicit assertion such as assert
any(hasattr(r, "correlation_id") or "correlation_id" in r.__dict__ for r in
caplog.records), and keep the existing info_logs = [r for r in caplog.records if
r.levelno == logging.INFO] / assert len(info_logs) > 0 to ensure INFO-level logs
are present; update the test around the caplog.records check so the presence of
a correlation_id is actually asserted.
🧹 Nitpick comments (23)
tests/unit/validation/test_validator_defaults.py (1)
429-431: Remove unusedCliRunnerinstantiation.The
CliRunner()call creates an instance that's never used. This test only inspects Click command parameter metadata viavalidate_architecture_cmd.params, which doesn't require a runner. The previous change removed the variable assignment but kept the unnecessary instantiation.🧹 Suggested cleanup
def test_architecture_cli_defaults(self) -> None: """Verify architecture CLI command has correct defaults.""" - from click.testing import CliRunner - - CliRunner() - # Check default max_violations in option from omnibase_infra.cli.commands import validate_architecture_cmdtests/unit/runtime/handler_plugin_loader/test_edge_cases_advanced.py (1)
26-27: UnusedTYPE_CHECKINGimport after cleanup.The
TYPE_CHECKINGimport on line 26 is no longer used since theif TYPE_CHECKING:block was removed. This should be cleaned up along with the other import simplifications.Proposed fix
-from typing import TYPE_CHECKING from unittest.mock import patchtests/unit/event_bus/test_inmemory_event_bus_race_conditions.py (1)
164-180: Dead code:asyncio.Lock()creates an unused object.Line 166 creates a
Lockthat is immediately discarded since it's not assigned to a variable. This appears to be leftover from a refactor where the lock was originally used to protect concurrent writes tooffsets, but since offsets are now collected post-hoc from history (line 180), the lock became unnecessary.The test logic is correct—remove the dead statement.
🧹 Proposed cleanup
num_concurrent = 100 offsets: list[str] = [] - asyncio.Lock() async def publish_and_record() -> None:tests/unit/runtime/test_lru_cache_eviction_stress.py (2)
1004-1006: Remove dead code: standalone expression has no effect.The list index access on line 1005 computes the p50 value but discards it. Since
_get_semver_cache_info()is a pure getter and list indexing has no side effects, this line does nothing. Either remove it entirely or restore the variable assignment if the value is useful for debugging.🧹 Suggested fix
# Calculate statistics latencies.sort() - latencies[len(latencies) // 2] p99 = latencies[int(len(latencies) * 0.99)]Or if p50 is useful for debugging/logging:
# Calculate statistics latencies.sort() - latencies[len(latencies) // 2] + p50 = latencies[len(latencies) // 2] # noqa: F841 - useful for debugging p99 = latencies[int(len(latencies) * 0.99)]
1047-1048: Remove dead code and misleading comment.The comment says "Record initial state" but the result of
_get_semver_cache_info()is discarded. Since this method is a pure getter with no side effects, the call does nothing. Remove both the comment and the line.🧹 Suggested fix
cache_size = 32 PolicyRegistry.SEMVER_CACHE_SIZE = cache_size - # Record initial state - PolicyRegistry._get_semver_cache_info() - # Perform many operations for i in range(50_000):src/omnibase_infra/handlers/registration_storage/handler_mock_registration_storage.py (1)
344-346: No-op statement:len(self._records)result is unused.The bare
len()call computes a value but discards it, making it effectively dead code. If the intent is simply to hold the lock momentarily to verify acquisition, usepassfor clarity. Otherwise, remove the statement.♻️ Suggested fix
async with self._lock: - len(self._records) + pass # Acquire lock to verify handler responsivenessOr remove the lock acquisition entirely if no actual verification is needed:
- async with self._lock: - len(self._records) - - latency_ms = (time.monotonic() - start_time) * 1000 + latency_ms = (time.monotonic() - start_time) * 1000tests/unit/errors/test_registry_errors_correlation_id.py (1)
298-301: Consider consolidating related imports for consistency.The
datetimeclass is imported locally here, butUTC(used together on line 301) is imported at module level (line 16). Since both are only used in this test method, consider consolidating them:-from datetime import datetime +from datetime import UTC, datetimeAnd remove
UTCfrom line 16. Alternatively, move both to module level if preferred.tests/integration/nodes/test_node_registry_effect_integration.py (2)
119-128: Consider removing unusedsimple_mock_containerparameter during migration.The
simple_mock_containerfixture is injected into several test methods (e.g.,test_register_node_parallel_execution,test_register_node_partial_failure_consul_fails, etc.) but is never referenced within those test bodies. Since these tests are already pending migration for OMN-1103, the unused parameter can be cleaned up at that time.Also applies to: 234-238
418-421: InconsistentModelBackendResultinstantiation — missingbackend_id.This instantiation omits
backend_idwhile otherModelBackendResultinstances throughout the file include it. The same pattern appears at line 706. For consistency and to avoid potential issues ifbackend_idbecomes required, consider adding it during migration:mock_postgres.upsert = AsyncMock( - return_value=ModelBackendResult(success=True, duration_ms=10.0) + return_value=ModelBackendResult(success=True, duration_ms=10.0, backend_id="postgres") )tests/unit/nodes/architecture_validator/test_node_architecture_validator.py (1)
1298-1340: Consider either removing unused instance creation or enhancing immutability tests.The model instances created on lines 1300, 1310, 1320, and 1334 are discarded without being used—the assertions only check the class-level
model_config. While checkingmodel_config.get("frozen")is valid for verifying Pydantic configuration, the instance creation is effectively dead code.Two options:
- Remove instance creation if only checking class config
- Enhance tests to verify runtime immutability by attempting mutation
♻️ Option 2: Enhanced immutability test example
def test_validation_result_is_frozen(self) -> None: """Verify ModelArchitectureValidationResult is frozen.""" - ModelArchitectureValidationResult.passed( + result = ModelArchitectureValidationResult.passed( rules_checked=("RULE_1",), nodes_checked=5, ) config = ModelArchitectureValidationResult.model_config assert config.get("frozen") is True + + # Verify runtime immutability + with pytest.raises(ValidationError): + result.nodes_checked = 10 # type: ignore[misc]Apply similar pattern to the other three tests.
tests/unit/runtime/handler_plugin_loader/test_error_codes.py (1)
113-122: Implementation-coupled mock, but acceptable for unit tests.The
call_counttracking assumes the loader callsstat()exactly twice before the size check. If the loader's internal implementation changes, this test will break. Consider adding a brief comment documenting this assumption for future maintainers.📝 Optional: Add clarifying comment
# Get the original stat result to return for initial calls original_stat_result = contract_file.stat() call_count = [0] def mock_stat(self, *args, **kwargs): call_count[0] += 1 - # First two calls are for exists() and is_file(), third is for size check + # Implementation detail: loader calls stat() for exists() and is_file() + # before the size check. If loader changes, this count may need adjustment. if call_count[0] <= 2: return original_stat_result raise OSError("Permission denied")docs/migration/MIGRATION_WIRE_DEFAULT_HANDLERS.md (1)
67-84: Consider expanding the contract example with optional fields.Based on learnings, handler contract files should declare
routing_strategy, event models, handler classes, and handler modules. The minimal example is good for getting started, but consider noting that production contracts may include additional fields.📝 Enhanced example with additional fields
# src/handlers/http/handler_contract.yaml handler_name: "http" handler_class: "omnibase_infra.handlers.handler_http.HttpRestHandler" +handler_module: "omnibase_infra.handlers.handler_http" handler_type: "effect" capability_tags: - http - rest +routing_strategy: "direct" # Optional: direct, fanout, etc.src/omnibase_infra/runtime/handler_plugin_loader.py (1)
623-644: Includeprotocol_typein the success log context (helps debug routing/registry issues).Right now you log
handler_name,handler_class,handler_type, etc. Addingprotocol_typetoextramakes it much easier to troubleshoot protocol-bound registration.src/omnibase_infra/mixins/mixin_node_introspection.py (1)
1369-1505: Enum coercion forreasonlooks correct; consider truncatingprovided_reasonin logs.Nice: you normalize
reasontoEnumIntrospectionReasonearly (handling theEnum-is-strinheritance correctly) and pass the enum through the event update so JSON serialization is consistent.Minor: the warning includes the full raw
reasonstring; if this is user-supplied anywhere, cap it (e.g.,reason[:100]) to avoid log bloat.docker/migrations/validate_migration_state.sql (1)
159-176: Consider handling the case whereregistration_projectionstable doesn't exist.The query on lines 159-164 will fail with an error if the table doesn't exist, while the DO block on lines 167-176 will also fail. This could confuse operators running validation before migration 001.
♻️ Proposed defensive guard
+-- Guard against missing table +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM information_schema.tables + WHERE table_name = 'registration_projections' + AND table_schema = 'public' + ) THEN + RAISE NOTICE 'Table registration_projections does not exist - run migration 001 first'; + RETURN; + END IF; +END$$; + SELECT indexrelid::regclass AS index_name, 'INVALID - needs recreation' AS status FROM pg_index WHERE NOT indisvalid AND indrelid = 'registration_projections'::regclass;docker/migrations/MIGRATION_UPGRADE_003a_to_004.md (1)
374-380: Changelog has inconsistent year in dates.The changelog shows dates from both 2025 and 2026:
2026-01-13- Added Migration Gap Detection section2025-01-13- Renamed 003a to 0042025-01-XX- Initial 003a createdGiven the current date is January 2026, the 2025 dates may be intentional (historical), but the
2025-01-XXplaceholder should be filled in with the actual date for completeness.📝 Suggested fix for changelog consistency
| Date | Change | |------|--------| | 2026-01-13 | Added Migration Gap Detection section with validation SQL script | -| 2025-01-13 | Renamed `003a` to `004` per PR #143 review feedback | -| 2025-01-XX | Initial `003a_capability_fields_concurrent.sql` created | +| 2026-01-13 | Renamed `003a` to `004` per PR #143 review feedback | +| 2026-01-XX | Initial `003a_capability_fields_concurrent.sql` created |tests/integration/event_bus/test_kafka_event_bus_integration.py (1)
294-295: Consider separate readiness waits for multiple subscribers.With two subscribers on different consumer groups, a single
wait_for_consumer_readycall may return once the first consumer is ready, potentially before the second is fully initialized. For improved robustness, consider waiting for each subscriber separately or adding a brief additional delay.However, the current approach may work due to the subscription being synchronous before the wait, and the existing
MESSAGE_DELIVERY_WAIT_SECONDS * 3timeout provides margin. This is a minor observation.src/omnibase_infra/runtime/runtime_host_process.py (1)
718-739: Tighten fail-fast error context + messaging (preferwith_correlation(), clarifycontract_pathsvs env var, include registry count).
Current message implies env var is the primary control path, but this runtime also supportscontract_paths. Also consider adding the registry’s protocol count to make diagnostics less guessy.Proposed adjustment
if not self._handlers: - context = ModelInfraErrorContext( - transport_type=EnumInfraTransportType.RUNTIME, - operation="validate_handlers", - target_name="runtime_host_process", - correlation_id=uuid4(), - ) + context = ModelInfraErrorContext.with_correlation( + transport_type=EnumInfraTransportType.RUNTIME, + operation="validate_handlers", + target_name="runtime_host_process", + ) + handler_registry = await self._get_handler_registry() + registered_protocol_count = len(handler_registry.list_protocols()) raise ProtocolConfigurationError( "No handlers registered. The runtime cannot start without at least one handler. " "Configure handlers via contract_paths parameter or ensure wire_handlers() " "registers handlers in the handler registry. " - "Check ONEX_CONTRACTS_DIR environment variable points to valid contracts directory.", + "If using env-based discovery, check ONEX_CONTRACTS_DIR points to a valid contracts directory.", context=context, - registered_handler_count=0, + registered_handler_count=0, # instantiated handler count + registered_protocol_count=registered_protocol_count, # registry entries failed_handler_count=len(self._failed_handlers), failed_handlers=list(self._failed_handlers.keys()), )docs/decisions/adr-handler-plugin-loader-security.md (1)
51-85: Align doc examples with ONEX error conventions (avoidSecurityError(Exception)in infra docs).
Since this repo standardizes onOnexError-derived errors, consider updating the wrapper-pattern example to raiseProtocolConfigurationError(or another appropriate Onex error) instead of a genericException.Based on coding guidelines, use
OnexError-family errors.Also applies to: 344-388
docs/patterns/handler_plugin_loader.md (1)
470-546: Nice security additions; consider updating wrapper example to use OnexError-family exceptions.
Same as the ADR: swapping the genericSecurityError(Exception)example forProtocolConfigurationError(or similar) will keep the docs aligned with the project’s error-handling patterns.Based on coding guidelines, use
OnexError-family errors.Also applies to: 625-690
tests/integration/registration/e2e/test_full_orchestrator_flow.py (1)
116-150: Hardencoerce_to_node_kind()against non-string inputs (avoid unexpectedTypeError).
Right now an unhashable input (e.g., list) will raiseTypeErrorduringnode_type not in valid_values.Proposed tweak
def coerce_to_node_kind(node_type: str | EnumNodeKind) -> EnumNodeKind: @@ if isinstance(node_type, EnumNodeKind): return node_type + + if not isinstance(node_type, str): + raise ValueError( + f"Invalid node_type {node_type!r}. Expected str or EnumNodeKind." + ) @@ valid_values = {e.value for e in EnumNodeKind} if node_type not in valid_values: raise ValueError( f"Invalid node_type '{node_type}'. Expected one of: {sorted(valid_values)}" )tests/integration/registration/e2e/test_two_way_registration_e2e.py (1)
1406-1416: Consider exposing heartbeat publish for testability.The test directly accesses the protected method
_publish_heartbeat()to measure overhead. While this works, it couples the test to implementation details that could change. Consider whether the mixin should expose a publicpublish_heartbeat()method for testing scenarios, or document that_publish_heartbeatis part of the testing contract.tests/integration/registration/e2e/conftest.py (1)
124-198: Consumer readiness helper has reliability concerns.Several observations about this implementation:
Always returns True on timeout (lines 191-198): While documented as "backwards compatibility," this masks actual readiness failures. Tests may proceed before consumers are ready, causing flakiness. Consider returning
Falseon timeout and having callers decide how to handle it.
poll_intervalparameter unused (line 150): The docstring notes it's "kept for API compat," but since this is new code, consider removing the unused parameter or using it instead ofinitial_backoff.Global consumer count check (lines 176-180): Checking if
consumer_countincreased doesn't guarantee the specific topic's consumer is ready. In parallel test execution, another test's consumer registration could satisfy this check prematurely.♻️ Consider returning False on timeout for better failure visibility
- # Return True for backwards compatibility even on timeout - # Log at debug level for diagnostics - logger.debug( + # Log warning for visibility when timeout occurs + logger.warning( "wait_for_consumer_ready timed out after %.2fs for topic %s", max_wait, topic, ) - return True + return FalseThen update callers to handle the False return appropriately, or assert on it if consumer readiness is required.
- Fix CI failure: test_error_propagation_preserves_correlation_id_in_logs - Specify logger name explicitly in caplog.at_level() for reliable capture - Critical fixes: - Update doc examples to use OnexError-family exceptions - Fix describe_topics to handle both dict and list return types - Major fixes: - Add missing backend_id to ModelBackendResult instantiations - Add protocol_type to success log context for debugging - Fix inconsistent changelog dates (2025→2026) - Tighten fail-fast error context with with_correlation() - Harden coerce_to_node_kind() against non-string inputs - Guard against empty derived protocol_type in model_handler_contract - Convert soft warnings to hard assertions with skipif markers - Add try/finally for RuntimeHostProcess.stop() cleanup - Fix migration README numbering (004b→004a) - Minor fixes: - Fix logging docstring/code mismatch in conftest - Narrow exception handling to specific exceptions - Fix Pydantic enum serialization with .value - Add deprecation timeline for CONTRACTS_DIR - Enhance no-handlers error message with troubleshooting - Add timing logs for handler discovery performance - Add warning when allowed_namespaces is empty - Dead code cleanup: - Remove orphaned expressions and unused imports - Remove unused CliRunner, asyncio.Lock() statements - Fix incomplete correlation ID test assertion
Comprehensive PR Review: Infrastructure Integration with Handler Contracts and E2E FixesExecutive SummaryPR #143 introduces contract-based handler discovery (OMN-1317), runtime fail-fast behavior, environment variable standardization, and significant E2E test improvements. The implementation is well-structured with strong error handling, but requires attention to security metadata usage. Overall Assessment: ✅ Approve with Recommendations (address critical security concerns before merge) 1. Code Quality & Best Practices✅ StrengthsHandler Plugin Loader: Excellent error sanitization with path disclosure prevention, comprehensive error codes and validation, proper correlation ID tracking throughout. Runtime Host Process: Fail-fast startup validation prevents misconfigured deployments, graceful degradation with partial handler failures, clean shutdown with drain period implementation. 🔴 CRITICAL: Security Metadata Not UsedHandler contracts include security metadata but the loader does not validate or enforce it. The audit_logging flag has no runtime effect, and namespace validation is not cross-checked. Recommendations:
2. Potential BugsFail-Fast Error Message: The no-handlers error at runtime_host_process.py:731-746 is 15 lines and may be truncated by log aggregation. Split into concise error plus structured troubleshooting_steps list. Migration Documentation: MIGRATION_UPGRADE_003a_to_004.md is 380 lines for a file rename. Add a TL;DR section at top. 3. Performance Considerations✅ Well Optimized: Concurrent indexes with timing estimates and monitoring queries. E2E Kafka strategy uses deterministic polling, consumer isolation, and static topics. Enhancements: Add autovacuum impact warning to migration 004 and test timeout assertions. 4. Security Concerns🔴 Critical: Namespace Allowlisting is Optionalallowed_namespaces defaults to None (allow all). Production may forget restrictions, allowing arbitrary code execution. Recommendations:
5. Test Coverage✅ Excellent Improvements
📋 Future Tests Needed
6. Architecture & Design✅ Excellent CLAUDE.md Adherence
Summary of Action Items🔴 Critical (Block Merge)
|
There was a problem hiding this comment.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (6)
tests/unit/runtime/handler_plugin_loader/test_edge_cases_advanced.py (1)
1059-1111: Docstring claims error code verification that isn't implemented.The docstring states the error "should be caught and reported with HANDLER_LOADER_012" but the test only verifies that an exception is raised without checking the error code. Contrast with
test_syntax_error_in_handler_module_raises_import_errorwhich properly verifiesEnumHandlerLoaderError.IMPORT_ERROR.value.Either update the docstring to reflect the actual test behavior, or add error code verification for consistency:
🔧 Option 1: Update docstring to match behavior
def test_circular_import_in_handler_module_raises_import_error( self, tmp_path: Path ) -> None: """Test that circular imports in handler modules raise IMPORT_ERROR. If a handler module has circular imports that cause ImportError, - this should be caught and reported with HANDLER_LOADER_012. + this should be caught and raise an appropriate exception. + Note: Circular imports may manifest as ImportError or AttributeError + depending on timing, so we accept multiple exception types. """🔧 Option 2: Add error code verification (if feasible)
# Circular imports may cause ImportError or AttributeError - with pytest.raises((InfraConnectionError, ImportError)): + with pytest.raises(InfraConnectionError) as exc_info: loader.load_from_contract(contract_file) + + error = exc_info.value + assert ( + error.model.context.get("loader_error") + == EnumHandlerLoaderError.IMPORT_ERROR.value + )docs/decisions/adr-handler-plugin-loader-security.md (1)
365-395: Code example doesn't follow ONEX error handling patterns.The
SecurityValidationErrorexample has several issues:
- Unused imports (lines 365-367):
ModelInfraErrorContextandEnumInfraTransportTypeare imported but never used in the example.- Missing error code: The exception is raised on line 388 with only a string message, not following the ONEX pattern of using specific error codes with proper error context.
Since this is documentation that developers will reference, the example should follow best practices.
Based on learnings, all error handling must use OnexError with specific error codes from error enums.
♻️ Suggested fix for proper ONEX error handling
-from omnibase_infra.errors import ProtocolConfigurationError, ModelInfraErrorContext -from omnibase_infra.enums import EnumInfraTransportType +from omnibase_infra.errors import ProtocolConfigurationError +from omnibase_infra.enums import EnumInfraErrorCode class SecurityValidationError(ProtocolConfigurationError): """Raised when security validation fails. Extends ProtocolConfigurationError to integrate with ONEX error handling. """ pass def secure_load_from_contract( loader: HandlerPluginLoader, path: Path, correlation_id: str | None = None, ) -> ModelLoadedHandler: """Load handler with additional custom validation.""" with open(path) as f: contract_data = yaml.safe_load(f) handler_class = contract_data.get("handler_class", "") if not any(handler_class.startswith(prefix) for prefix in ALLOWED_MODULE_PREFIXES): raise SecurityValidationError( + error_code=EnumInfraErrorCode.HANDLER_LOADER_013, # NAMESPACE_NOT_ALLOWED f"Handler module path '{handler_class}' not in allowlist. " - f"Allowed prefixes: {ALLOWED_MODULE_PREFIXES}" + f"Allowed prefixes: {ALLOWED_MODULE_PREFIXES}", + correlation_id=correlation_id, ) # Additional custom validation can go here return loader.load_from_contract(path, correlation_id)Note: Line 334 already mentions error code
HANDLER_LOADER_013(NAMESPACE_NOT_ALLOWED), so the example should use it consistently.Based on learnings.
tests/integration/registration/e2e/test_full_orchestrator_flow.py (1)
442-470: Deserialization should fail closed on non-dict JSON payloads (avoid AttributeError crash).
Right now, JSON that parses but isn’t a dict (e.g.,[]) will throw on.get(...)and bubble as an exception (notNone), which is avoidable.Proposed fix
def _deserialize_introspection_event( self, message: ModelEventMessage ) -> ModelNodeIntrospectionEvent | None: @@ - try: + try: if not message.value: return None data = json.loads(message.value.decode("utf-8")) - # Handle both envelope format and direct event format - payload = data.get("payload", data) + # Handle both envelope format and direct event format + if not isinstance(data, dict): + return None + payload = data.get("payload", data) + if not isinstance(payload, dict): + return None return ModelNodeIntrospectionEvent.model_validate(payload) - except (json.JSONDecodeError, ValueError) as e: + except (json.JSONDecodeError, ValueError, TypeError) as e: logger.warning( "Failed to deserialize message", extra={"error": str(e)}, ) return Nonesrc/omnibase_infra/runtime/runtime_host_process.py (1)
705-748: Startup failure now leaks a partially-started event bus (needs cleanup on exception).
Youawait self._event_bus.start()and then may raiseProtocolConfigurationError(or other errors) without closing the bus/subscription tasks. That makes “fail-fast” potentially leave background tasks running.Proposed fix (ensure bus is closed on start() failure)
async def start(self) -> None: @@ - # Step 2: Start event bus - await self._event_bus.start() - - # Step 3: Discover/wire handlers (OMN-1133) - await self._discover_or_wire_handlers() - - # Step 4: Populate self._handlers from singleton registry - await self._populate_handlers_from_registry() + # Step 2: Start event bus + await self._event_bus.start() + + try: + # Step 3: Discover/wire handlers (OMN-1133) + await self._discover_or_wire_handlers() + + # Step 4: Populate self._handlers from singleton registry + await self._populate_handlers_from_registry() # Step 4.1: FAIL-FAST validation - runtime MUST have at least one handler @@ raise ProtocolConfigurationError( @@ failed_handlers=list(self._failed_handlers.keys()), ) + except Exception: + # Prevent partially-started runtime from leaking background tasks + await self._event_bus.close() + raisetests/integration/registration/e2e/test_runtime_e2e.py (1)
418-494:on_completion()should not be able to throw (it can currently AttributeError on non-dict JSON).
An exception in the consumer callback can turn into a silent “no completion received” timeout. Alsolist[dict]is effectivelyAny.Proposed fix
- received_completions: list[dict] = [] + received_completions: list[dict[str, object]] = [] @@ - async def on_completion(message: object) -> None: + async def on_completion(message: object) -> None: if hasattr(message, "value") and message.value: try: data = json.loads(message.value.decode("utf-8")) - - # Events are wrapped in ModelEventEnvelope, so extract payload - # The envelope structure is: {envelope_id, payload: {...}, ...} - payload = data.get( - "payload", data - ) # Fall back to data if no envelope + if not isinstance(data, dict): + return + # Events may be envelope-wrapped; extract payload if present. + payload = data.get("payload", data) + if not isinstance(payload, dict): + return @@ - except (json.JSONDecodeError, UnicodeDecodeError): + except (json.JSONDecodeError, UnicodeDecodeError, AttributeError, TypeError): pass.env.example (1)
6-16: Remove backwards-compatible fallback and deprecation narrative—repo policy mandates breaking changes only.The codebase currently maintains CONTRACTS_DIR fallback support in
src/omnibase_infra/runtime/kernel.pywith a deprecation timeline (v2.0.0 removal), but repo learnings explicitly state "no backwards compatibility, remove old patterns immediately, no deprecation periods." Either the fallback logic and .env.example deprecation narrative (lines 6-16, 243-266) must be removed immediately, or the repo policy needs clarification. This conflict must be resolved before merge.
🤖 Fix all issues with AI agents
In @.env.example:
- Around line 249-252: The DEPRECATION TIMELINE entry currently pins a specific
removal quarter ("v2.0.0 (Q2 2026)"), which can become inaccurate; update the
comment in the DEPRECATION TIMELINE block so it omits the quarter/date and
instead states the removal more generally (e.g., "in v2.0.0") and keep the
reference to CONTRACTS_DIR and its deprecation warning intact.
In @docker/migrations/MIGRATION_UPGRADE_003a_to_004.md:
- Around line 52-55: The Scenario 1 steps are ambiguous because
003_capability_fields.sql contains both column and index creation; update the
instructions to explicitly state whether the user must edit
003_capability_fields.sql to comment out or remove index statements before
running it, or alternatively provide an explicit command sequence (e.g., run a
provided “003_columns_only” variant or use psql to apply only column-related
statements) and/or reference Scenario 3’s safe approach; mention the exact files
003_capability_fields.sql and 004_capability_fields_concurrent.sql and specify
“comment out or remove index creation in 003” if that is the intended action.
In @tests/integration/registration/e2e/test_full_orchestrator_flow.py:
- Around line 101-109: Update the test comment and/or consumer config to
acknowledge and mitigate auto-commit behavior: explicitly document that
consumers using enable_auto_commit=True can commit offsets even if a test fails
mid-run (which can leak state between parallel workers despite
auto_offset_reset="latest" and unique group IDs), and preferably change the test
consumer configuration to enable_auto_commit=False to avoid committing offsets
on partial runs (or add a note explaining the tradeoff if leaving it True).
Reference the TEST_INTROSPECTION_TOPIC constant and any consumer
creation/fixture that sets enable_auto_commit to locate where to update the
comment and/or set enable_auto_commit=False.
In @tests/unit/runtime/test_handler_discovery.py:
- Around line 1646-1767: The three symlink tests
(test_discovery_with_symlink_to_valid_directory,
test_discovery_with_symlink_to_file, test_discovery_with_broken_symlink) fail on
Windows; add a pytest.skipif marker to each test using
pytest.mark.skipif(os.name == "nt", reason="Symlinks require admin privileges on
Windows") immediately above the pytest.mark.asyncio decorator so the tests are
skipped on Windows, matching the pattern used elsewhere (e.g.,
tests/unit/runtime/handler_plugin_loader/test_edge_cases_advanced.py).
In @tests/unit/runtime/test_runtime_host_architecture_validation.py:
- Around line 194-208: The docstring in
test_empty_registry_skips_architecture_validation incorrectly references
_setup_mock_handlers(); update the wording to reference the actual helper
function seed_mock_handlers() (and adjust any surrounding phrasing to match that
function’s behavior) so the docstring accurately describes that
seed_mock_handlers() is called to populate process._handlers while
registry.list_protocols() returns [] for architecture validation.
🧹 Nitpick comments (19)
src/omnibase_infra/handlers/registration_storage/handler_mock_registration_storage.py (1)
344-346: The lock acquisition happens atasync with, making thelen()call redundant for latency measurement.The comment states the purpose is to "force lock acquisition," but the lock is already acquired when entering the
async with self._lockblock on line 344. Thelen()call doesn't contribute to the latency measurement—it only adds minimal overhead for the dictionary length operation.The code is functionally correct, but if you prefer, you could simplify to just
passor remove the comment since the lock acquisition is already guaranteed by the context manager.Suggested simplification (optional)
async with self._lock: - _ = len(self._records) # Force lock acquisition to measure latency + pass # Lock acquired; measuring acquisition latencytests/unit/runtime/handler_plugin_loader/test_edge_cases_advanced.py (1)
650-653: Consider verifying thread completion after join with timeout.When using
join(timeout=...), the thread may still be running if it hangs. Adding a check ensures tests fail explicitly rather than passing with incomplete results.♻️ Suggested improvement
for t in threads: t.join(timeout=5.0) + # Verify all threads completed (not stuck) + for t in threads: + assert not t.is_alive(), f"Thread {t.name} did not complete within timeout"Apply the same pattern to other test methods:
test_concurrent_directory_loading_is_thread_safe(line 745),test_discover_and_load_concurrent_is_thread_safe(line 892), andtest_repeated_loads_are_idempotent_under_concurrency(line 936).tests/unit/runtime/test_runtime_host_architecture_validation.py (1)
53-77: Consider consolidating duplicate documentation.The Handler Semantics Note at lines 55-77 duplicates the content already in the module docstring (lines 15-34). While placing it near the imports improves visibility for developers reading the code, it creates a maintenance burden if the semantics change.
Consider keeping only the module-level docstring and adding a brief reference comment here instead:
from tests.conftest import seed_mock_handlers # See module docstring "Handler Semantics Note" for explanation of the # two distinct handler concepts (process._handlers vs registry.list_protocols()).tests/unit/nodes/architecture_validator/test_node_architecture_validator.py (1)
1297-1339: Consider enhancing immutability tests to verify behavior, not just configuration.The tests correctly verify that
model_confighasfrozen=True, but they don't actually test the frozen behavior. A more robust approach would attempt mutation and verify it raises an exception.Additionally, the class name
TestImmutabilityAndThreadSafetyis misleading since no thread safety is tested here—only configuration is checked.💡 Optional enhancement to test actual frozen behavior
def test_validation_result_is_frozen(self) -> None: """Verify ModelArchitectureValidationResult is frozen.""" - ModelArchitectureValidationResult.passed( + result = ModelArchitectureValidationResult.passed( rules_checked=("RULE_1",), nodes_checked=5, ) config = ModelArchitectureValidationResult.model_config assert config.get("frozen") is True + + # Verify actual immutability behavior + with pytest.raises(ValidationError): + result.nodes_checked = 10 # type: ignore[misc]Apply similar patterns to other tests in this class.
docs/patterns/handler_plugin_loader.md (1)
647-649: Remove unused imports from example code.The imports
ModelInfraErrorContextandEnumInfraTransportTypeare not used in the code example below. This could confuse readers copying the example.🧹 Proposed cleanup
-from omnibase_infra.errors import ProtocolConfigurationError, ModelInfraErrorContext -from omnibase_infra.enums import EnumInfraTransportType +from omnibase_infra.errors import ProtocolConfigurationErrorIf these imports are needed for other examples or context not shown, consider adding a comment explaining their purpose.
tests/unit/runtime/test_handler_discovery.py (3)
659-690: Consider removing duplicate test.The test
test_empty_contract_directory_raises_configuration_errorat line 660 is nearly identical totest_empty_directory_raises_configuration_errorinTestNoHandlersRegisteredHealthCheckat line 746. Both test the same scenario (empty directory with isolated registry raisesProtocolConfigurationError). Consider removing one to reduce test maintenance overhead.
904-936: Minor: Missing try/finally cleanup in test.Unlike other tests in this file,
test_health_check_after_stop_shows_handlers_still_registereddoesn't use a try/finally block. While the test explicitly callsstop()before the final assertions, if an assertion fails afterstart()but before the explicitstop(), the process won't be cleaned up. Consider wrapping in try/finally for consistency.♻️ Suggested improvement
async def test_health_check_after_stop_shows_handlers_still_registered( self, valid_handler_contract_dir: Path, ) -> None: ... - await process.start() - assert process.is_running - - await process.stop() - assert not process.is_running - - # After stop, handlers should still be registered - health = await process.health_check() - assert health["is_running"] is False - # Handlers remain registered after stop - assert health["no_handlers_registered"] is False + try: + await process.start() + assert process.is_running + + await process.stop() + assert not process.is_running + + # After stop, handlers should still be registered + health = await process.health_check() + assert health["is_running"] is False + # Handlers remain registered after stop + assert health["no_handlers_registered"] is False + finally: + await process.stop()
1137-1146: Consider moving__all__to the end of the file.The
__all__export list is placed in the middle of the file (line 1137), before the classesTestDiscoverHandlersFromContractsUnit,TestDiscoverHandlersFromContractsErrorHandling,TestDiscoverHandlersFromContractsFileSystemEdgeCases, andTestDiscoverHandlersFromContractsCorrelationTrackingthat it references. While this works correctly in Python, it's unconventional and can be confusing during code navigation. Consider moving__all__to the end of the file for better readability.docker/migrations/README.md (3)
26-28: Consider clarifying the "companion" terminology.Line 27 describes 004 as a "companion to 003", which might be confusing since the renumbering was done to make 004 a standalone main migration rather than a sub-migration. Consider rephrasing to clarify the relationship:
📝 Suggested clarification
-- `003_capability_fields.sql` - Capability discovery columns and standard indexes -- `004_capability_fields_concurrent.sql` - Production concurrent indexes (companion to 003) +- `003_capability_fields.sql` - Capability discovery columns and standard indexes +- `004_capability_fields_concurrent.sql` - Concurrent indexes for production (requires 003 columns)This makes it clearer that 004 is independent but has a prerequisite, rather than being a sub-variant.
100-102: Reconsider the 004a example in "Next available".Line 102 suggests
004a_*.sqlas a possible next sub-migration for 004. Given that 004 is specifically the concurrent index variant, it's unclear what a sub-migration of 004 would be (a rollback? an alternative concurrent strategy?). Consider whether this example adds clarity or confusion.💡 Possible alternatives
Option 1: Remove the 004a example if there's no realistic use case:
**Next available:** - Next main migration: `005_*.sql` - Next sub-migration for 003: `003b_*.sql` -- Next sub-migration for 004: `004a_*.sql`Option 2: Keep it but add a note about realistic use cases:
**Next available:** - Next main migration: `005_*.sql` - Next sub-migration for 003: `003b_*.sql` -- Next sub-migration for 004: `004a_*.sql` +- Next sub-migration for 004: `004a_*.sql` (e.g., rollback or environment-specific variant)
174-179: Decision tree step 1 may need refinement.Line 176 states: "Is this a production-optimized variant? -> Use next main number with
_concurrentsuffix"This guidance works for the 003 → 004 case but could be ambiguous for future migrations. Should it be:
- "Production variant of the MOST RECENT migration" → next main number
- "Production variant of ANY migration" → could be either main number or letter suffix depending on context
Consider clarifying whether this guidance applies only to production variants of the immediately preceding migration, or more broadly:
📝 Suggested clarification
**Decision tree for next migration:** -1. Is this a production-optimized variant? -> Use next main number with `_concurrent` suffix +1. Is this a production-optimized variant of the previous migration? -> Use next main number with `_concurrent` suffix 2. Is this a rollback/cleanup for an existing migration? -> Use letter suffix (`003b`) 3. Otherwise -> Use next main number (`005`)Or add an example:
**Decision tree for next migration:** -1. Is this a production-optimized variant? -> Use next main number with `_concurrent` suffix +1. Is this a production-optimized variant (e.g., concurrent indexes for 003)? -> Use next main number with `_concurrent` suffix (004) 2. Is this a rollback/cleanup for an existing migration? -> Use letter suffix (`003b`) 3. Otherwise -> Use next main number (`005`)docker/migrations/MIGRATION_UPGRADE_003a_to_004.md (2)
21-21: Clarify the "standalone" terminology.Line 21 states that renumbering "makes it explicit that this is a standalone migration," but this could be misleading since 004 depends on 003's columns (as correctly noted in the relationship diagram at lines 28-35).
Consider rephrasing to avoid confusion:
📝 Suggested clarification
-The renumbering to `004` makes it explicit that this is a standalone migration that can be applied instead of (or in addition to) `003`. +The renumbering to `004` makes it explicit that this is a first-class production migration (with a prerequisite on 003's columns) rather than an optional sub-variant.Or:
-The renumbering to `004` makes it explicit that this is a standalone migration that can be applied instead of (or in addition to) `003`. +The renumbering to `004` makes it a first-class migration in the sequence, though it requires 003's column additions as a prerequisite.
290-324: Consider adding invalid index detection to the automated script.The validation script correctly checks for the presence of 4 GIN indexes (lines 307-310), but doesn't verify that those indexes are valid (not in a failed INVALID state from interrupted concurrent creation).
🔧 Suggested enhancement
Add a check for invalid indexes:
SELECT 1 WHERE (SELECT COUNT(*) FROM pg_indexes WHERE tablename = 'registration_projections' AND indexname IN ('idx_registration_capability_tags', 'idx_registration_intent_types', 'idx_registration_protocols', 'idx_registration_contract_type_state')) < 4 + UNION ALL + SELECT 1 WHERE EXISTS ( + SELECT 1 FROM pg_index idx + JOIN pg_class c ON c.oid = idx.indexrelid + WHERE idx.indrelid = 'registration_projections'::regclass + AND c.relname IN ('idx_registration_capability_tags', 'idx_registration_intent_types', + 'idx_registration_protocols', 'idx_registration_contract_type_state') + AND NOT idx.indisvalid + ) ) missing;This ensures the script catches indexes in INVALID state and flags them for remediation.
tests/integration/registration/e2e/test_full_orchestrator_flow.py (2)
116-165:coerce_to_node_kind()looks solid; consider centralizing if it’s now shared behavior.
It’s doing the right enum-first/type-guard validation and removes repeatedEnumNodeKind(...)casts. If other tests/runtime paths need it too, moving to a shared test util would avoid drift.Also applies to: 494-501, 553-560, 1370-1377, 1586-1593
1254-1262: Flaky fixed sleep in malformed-message test—good TODO, but it still risks CI variance.
If you can’t add a “processed/rejected” signal soon, consider at least waiting until the consumer loop has had a chance to poll (e.g., a short bounded loop checkingpipeline.processing_errorsdidn’t grow unexpectedly).src/omnibase_infra/runtime/runtime_host_process.py (2)
718-747: Error message “troubleshooting steps” is helpful; consider usingModelInfraErrorContext.with_correlation()for consistency.
Not required, but it matches the existing pattern and avoids repeatinguuid4()call sites. Based on coding guidelines.
1506-1653: Health semantics update is good (no-handlers is not healthy), butno_handlers_registeredmay be misleading before start().
Right nowno_handlers_registered=Trueeven whenis_running=False(i.e., “not started yet”). If this endpoint can be called pre-start, consider gating it behindis_running.tests/integration/registration/e2e/conftest.py (2)
214-238:wrap_event_in_envelope()is a good shared utility; consider standardizing optional fields across tests.
Right now some tests addenvelope_id/sourcewhile this helper doesn’t—either is fine, but mixing increases chance of “works in one test, not another” if the model tightens.
1144-1176: Logging fixture may duplicate output if log propagation/root handlers are already configured by pytest.
Consider settinge2e_logger.propagate = False(or documenting expected pytest logging flags) to avoid doubled lines.
…nor/nitpick) Address all remaining PR #143 review feedback for release readiness: Documentation & Security: - Fix SecurityError(Exception) → InfraAuthenticationError in error_sanitization_patterns.md - Add namespace allowlist warning in handler_plugin_loader.py E2E Tests: - Narrow exception handling in health polling (catch specific httpx errors) Unit Tests: - Add execute/initialize AsyncMock to seed_mock_handlers() - Fix incomplete correlation ID assertion (validate UUID format) - Fix "no handlers" docstring reference Model/Handler Fixes: - Add missing backend_id to 50+ ModelBackendResult instantiations - Enhance no-handlers error with troubleshooting steps and context Dead Code Cleanup: - Rename 12 unused loop variables to _ convention (ruff compliance) Configuration: - Fix migrations README (003a availability clarification)
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In @tests/unit/runtime/test_lru_cache_eviction_stress.py:
- Line 1005: The line computing latencies[len(latencies) // 2] is dead code:
either remove it or store the result; update the test to assign the median to a
variable (e.g., p50 = latencies[len(latencies) // 2]) if you intend to assert or
log it, or simply delete that expression if the p50 value is not needed; refer
to the latencies list and add any subsequent assertion/logging that uses p50 if
you keep the assignment.
🧹 Nitpick comments (11)
tests/unit/nodes/reducers/test_registration_reducer.py (1)
3779-3797: Minor consistency nit:_attemptis fine, but consider_unless you plan to use the index.
If you don’t need the attempt number,for _ in range(3):is the most idiomatic (and matches the earlier loop).docs/patterns/error_sanitization_patterns.md (1)
84-93: Clarify the IP address example to avoid confusion.The NOTE states to "avoid in user-facing errors," but the example immediately includes
user_ipin the error message. While the inline comment mentions "May be acceptable for security logs," this creates ambiguity about when IPs should or shouldn't be included.Consider one of these approaches:
- Show both a BAD example (user-facing error with IP) and a GOOD example (security audit log with IP)
- Remove the IP from the error message entirely and demonstrate including it only in structured logging context
- More explicitly differentiate between error messages (avoid IPs) vs. log entries (may include IPs)
Additionally,
correlation_idis referenced but not defined in this example scope.📝 Suggested clarification
-# IP addresses of users (in some contexts) -user_ip = "192.168.1.100" -# NOTE: Including IPs is context-dependent - avoid in user-facing errors -raise InfraAuthenticationError( - f"Blocked request from {user_ip}", # May be acceptable for security logs - context=ModelInfraErrorContext( - transport_type=EnumInfraTransportType.HTTP, - operation="authenticate", - target_name="api-gateway", - correlation_id=correlation_id, - ), -) +# IP addresses of users (context-dependent) +user_ip = "192.168.1.100" +correlation_id = uuid4() + +# BAD: Including user IP in error message exposes PII +# raise InfraAuthenticationError(f"Blocked request from {user_ip}") + +# GOOD: Sanitized error message, IP only in audit logs +raise InfraAuthenticationError( + "Authentication blocked - suspicious activity detected", + context=ModelInfraErrorContext( + transport_type=EnumInfraTransportType.HTTP, + operation="authenticate", + target_name="api-gateway", + correlation_id=correlation_id, + ), +) +# Log IP separately for security audit (not in error message) +logger.warning("Blocked authentication", extra={"user_ip": user_ip, "correlation_id": correlation_id})tests/unit/nodes/node_registry_effect/handlers/test_handler_consul_deregister.py (1)
152-156: Consider addingbackend_idto failure mocks for consistency.The mock at line 152-156 omits
backend_id, while similar mocks elsewhere include it. Although tests pass because the handler enriches the result withbackend_id="consul", adding it to all mocks improves consistency and makes the test's intent clearer.Same applies to mocks at lines 179-183, 295-299, and 388-389.
♻️ Suggested consistency fix
mock_client.deregister_service.return_value = ModelBackendResult( success=False, error="Service not found in Consul catalog", duration_ms=5.0, + backend_id="consul", )tests/unit/nodes/node_registry_effect/handlers/test_handler_postgres_upsert.py (1)
167-171: Consider addingbackend_idto failure mocks for consistency.Similar to the Consul handler tests, the failure mocks here omit
backend_idwhile the assertions expectbackend_id="postgres". Adding it to all mocks improves consistency.Same applies to mocks at lines 194-198, 329-333, and 422-424.
♻️ Suggested consistency fix
mock_adapter.upsert.return_value = ModelBackendResult( success=False, error="Duplicate key violation", duration_ms=5.0, + backend_id="postgres", )tests/unit/runtime/test_lru_cache_eviction_stress.py (1)
1048-1048: Discarded return value may indicate dead code.The call to
_get_semver_cache_info()returns cache statistics but the result isn't captured or used. This method is read-only and doesn't initialize the cache (that happens via_parse_semvercalls). Consider removing this line if the initial state comparison was intentionally dropped, or restore the assignment if initial/final comparison was intended.🧹 Suggested fix
# Record initial state - PolicyRegistry._get_semver_cache_info() + # Note: Cache not yet initialized; first _parse_semver call will initialize it # Perform many operationstests/integration/registration/e2e/test_runtime_e2e.py (1)
574-604: LGTM! Consider extracting duplicate polling logic.The polling-based health check approach is better than fixed sleeps for catching transient failures. The RATIONALE comment clearly explains why this negative test can't use deterministic polling.
The exception handling logic correctly differentiates between crash indicators (
ConnectError) and transient issues (TimeoutException).Note: This polling pattern is duplicated in
test_runtime_handles_missing_fields(lines 631-651). Consider extracting to a helper function if more negative tests are added.♻️ Optional: Extract polling helper
async def poll_runtime_health_stable( health_url: str, duration: float = 2.0, poll_interval: float = 0.2, ) -> bool: """Poll runtime health for duration, return False if unhealthy at any point.""" start_time = asyncio.get_running_loop().time() async with httpx.AsyncClient(timeout=10.0) as client: while asyncio.get_running_loop().time() - start_time < duration: try: response = await client.get(health_url) if response.status_code != 200: return False except httpx.ConnectError: return False except httpx.TimeoutException: pass # Continue polling await asyncio.sleep(poll_interval) return Truetests/integration/registration/e2e/test_two_way_registration_e2e.py (1)
1409-1411: Consider exposing a test-friendly method for heartbeat performance testing.Accessing the private
_publish_heartbeat()method directly works for this test, but tightly couples the test to implementation details. If the mixin's internal structure changes, this test will break.Consider adding a public method like
publish_heartbeat_once()or using dependency injection to make the heartbeat publisher testable without accessing private internals.docker/migrations/README.md (3)
42-42: Update example to use003ainstead of003bfor consistency.The example uses
003b_rollback.sql, but according to lines 89, 101, and 104,003ais the next available sub-migration number (since the original003a_capability_fields_concurrent.sqlwas renamed to004). For consistency and accuracy, this example should use003a.📝 Proposed fix
-- Rollback or cleanup scripts for a main migration (e.g., `003b_rollback.sql`) +- Rollback or cleanup scripts for a main migration (e.g., `003a_rollback.sql`)
173-173: Update example to use003afor consistency.The example uses
003b_rollback.sql, but003ais the next available sub-migration number as documented elsewhere in the file (lines 89, 101, 104).📝 Proposed fix
-| `NNNa_desc.sql` | `003b_rollback.sql` | Companion/rollback to NNN | +| `NNNa_desc.sql` | `003a_rollback.sql` | Companion/rollback to NNN |
179-179: Update example to use003afor consistency.The decision tree uses
003bas an example, but003ais the next available sub-migration number as documented in lines 89, 101, and 104.📝 Proposed fix
-2. Is this a rollback/cleanup for an existing migration? -> Use letter suffix (`003b`) +2. Is this a rollback/cleanup for an existing migration? -> Use letter suffix (`003a`)src/omnibase_infra/runtime/handler_plugin_loader.py (1)
586-593: Consider replacingassertwith explicit validation for production safety.The
assertstatement at line 591 will be removed when Python runs with optimization (python -O). Sinceprotocol_typebeingNonewould be a contract model error, consider using an explicit check that survives optimization:🔧 Proposed fix
# protocol_type is the registry key (e.g., "db", "http") # The model_validator in ModelHandlerContract sets this from handler_name # if not explicitly provided (strips "handler-" prefix) protocol_type = contract.protocol_type - # Should never be None after model_validator, but assert for type safety - assert protocol_type is not None, ( - "protocol_type should be set by model_validator" - ) + # Should never be None after model_validator, but validate for production safety + if protocol_type is None: + context = ModelInfraErrorContext( + transport_type=EnumInfraTransportType.RUNTIME, + operation="load_from_contract", + correlation_id=correlation_id, + ) + raise ProtocolConfigurationError( + f"Contract missing protocol_type for handler: {handler_name}", + context=context, + loader_error=EnumHandlerLoaderError.MISSING_REQUIRED_FIELDS.value, + contract_path=str(contract_path), + )
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Lite
📒 Files selected for processing (28)
docker/migrations/README.mddocs/patterns/error_sanitization_patterns.mdsrc/omnibase_infra/event_bus/kafka_event_bus.pysrc/omnibase_infra/projectors/snapshot_publisher_registration.pysrc/omnibase_infra/runtime/handler_plugin_loader.pysrc/omnibase_infra/runtime/runtime_host_process.pytests/chaos/test_recovery_circuit_breaker.pytests/conftest.pytests/integration/nodes/test_node_registry_effect_integration.pytests/integration/nodes/test_registration_orchestrator_runtime_execution.pytests/integration/registration/e2e/test_runtime_e2e.pytests/integration/registration/e2e/test_two_way_registration_e2e.pytests/integration/registration/effect/test_doubles.pytests/replay/test_no_hidden_state.pytests/replay/test_replay_performance.pytests/unit/nodes/node_registry_effect/handlers/test_handler_consul_deregister.pytests/unit/nodes/node_registry_effect/handlers/test_handler_consul_register.pytests/unit/nodes/node_registry_effect/handlers/test_handler_partial_retry.pytests/unit/nodes/node_registry_effect/handlers/test_handler_postgres_deactivate.pytests/unit/nodes/node_registry_effect/handlers/test_handler_postgres_upsert.pytests/unit/nodes/reducers/test_registration_reducer.pytests/unit/registration/effect/test_effect_partial_failure.pytests/unit/registration/effect/test_effect_retry_backoff.pytests/unit/runtime/test_handler_discovery.pytests/unit/runtime/test_lru_cache_eviction_stress.pytests/unit/runtime/test_policy_registry_performance.pytests/unit/runtime/test_registry_compute.pytests/unit/runtime/test_runtime_host_architecture_validation.py
✅ Files skipped from review due to trivial changes (3)
- src/omnibase_infra/projectors/snapshot_publisher_registration.py
- tests/replay/test_no_hidden_state.py
- tests/unit/runtime/test_policy_registry_performance.py
🚧 Files skipped from review as they are similar to previous changes (1)
- tests/conftest.py
🧰 Additional context used
📓 Path-based instructions (2)
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Never useAnytype - useobjectfor generic payloads in function parameters and return types
UseX | None(PEP 604) instead ofOptional[X]for nullable types
All services must useModelONEXContainerfor dependency injection via__init__(self, container: ModelONEXContainer)
Use@allow_anydecorator with documented reason as exemption mechanism forAnytype violations
UseJsonTypefromomnibase_core.typesas the canonical type alias for JSON-compatible values
UseModelEventEnvelope[object]for generic dispatcher interfaces andobjectfor generic payloads
Infrastructure error handling must useOnexErrorbase class and never expose passwords, API keys, PII, or connection strings with credentials in error messages
UseInfraConnectionError,InfraTimeoutError,InfraAuthenticationError,InfraUnavailableErrorfor transport failures with properModelInfraErrorContext
Correlation IDs must be propagated from incoming requests, auto-generated withuuid4()if missing, and included in all error contexts
External service adapters must implementMixinAsyncCircuitBreakerwith appropriate threshold and reset_timeout configuration
Protocol resolution must use duck typing via protocols, never useisinstancechecks
Files:
tests/integration/nodes/test_registration_orchestrator_runtime_execution.pytests/replay/test_replay_performance.pytests/unit/nodes/reducers/test_registration_reducer.pytests/unit/nodes/node_registry_effect/handlers/test_handler_postgres_deactivate.pytests/unit/runtime/test_handler_discovery.pytests/unit/registration/effect/test_effect_partial_failure.pytests/integration/registration/e2e/test_two_way_registration_e2e.pysrc/omnibase_infra/runtime/handler_plugin_loader.pytests/unit/registration/effect/test_effect_retry_backoff.pytests/unit/nodes/node_registry_effect/handlers/test_handler_consul_deregister.pytests/integration/nodes/test_node_registry_effect_integration.pysrc/omnibase_infra/event_bus/kafka_event_bus.pytests/unit/nodes/node_registry_effect/handlers/test_handler_consul_register.pytests/integration/registration/effect/test_doubles.pytests/integration/registration/e2e/test_runtime_e2e.pytests/unit/runtime/test_lru_cache_eviction_stress.pytests/unit/runtime/test_runtime_host_architecture_validation.pytests/chaos/test_recovery_circuit_breaker.pytests/unit/runtime/test_registry_compute.pytests/unit/nodes/node_registry_effect/handlers/test_handler_postgres_upsert.pytests/unit/nodes/node_registry_effect/handlers/test_handler_partial_retry.pysrc/omnibase_infra/runtime/runtime_host_process.py
**/handler_*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Handlers must NOT have direct event bus access - only orchestrators may have bus parameters and publish events
Files:
src/omnibase_infra/runtime/handler_plugin_loader.py
🧠 Learnings (44)
📓 Common learnings
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/handler_contract.yaml : Handler contract files must declare handler routing with `routing_strategy`, event models, handler classes, and handler modules
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/handler_contract.yaml : Handlers must be discovered and loaded dynamically via YAML contracts using plugin pattern, not hardcoded registries
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contracts/contract_*.yaml : All ONEX node contract definitions must use the new subcontract architecture pattern, breaking down complex contracts into separate contract_actions.yaml, contract_models.yaml, contract_validation.yaml, and optional contract_cli.yaml and contract_capabilities.yaml files for separation of concerns, maintainability, reusability, modularity, and future tool-as-a-service readiness
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contracts/contract_*.yaml : All ONEX node subcontracts must be organized in a `contracts/` subdirectory within the versioned implementation directory with separate files for contract_actions.yaml, contract_models.yaml, contract_validation.yaml, contract_cli.yaml (optional), and contract_capabilities.yaml (optional)
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T16:32:55.606Z
Learning: Applies to **/*contract*.yaml : All ONEX nodes must have validated YAML contracts following the contract-driven development pattern with input_state and output_state schema definitions
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-24T17:22:32.195Z
Learning: Applies to **/v[0-9]_[0-9]_[0-9]/contracts/ : Organize contract subcomponents into separate files (contract_actions.yaml, contract_models.yaml, contract_validation.yaml, etc.) and reference them from main contract.yaml
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: When both `handler_contract.yaml` and `contract.yaml` exist in the same directory, the loader must raise an error (AMBIGUOUS_CONTRACT_CONFIGURATION)
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to src/omninode_bridge/nodes/**/contract.yaml : All contract YAML files for ONEX v2.0 nodes MUST define subcontract references, input/output models, and FSM configurations. Use YAML 1.2 syntax.
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/models/model_contract_*.py : All ONEX node auto-generated Pydantic models must be organized in a `models/` directory with files for state.py, model_contract_actions.py, model_contract_models.py, model_contract_validation.py, model_contract_cli.py (optional), model_contract_capabilities.py (optional), and error_codes.py, generated from the corresponding contract definitions
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/*.py : Use `InfraConnectionError`, `InfraTimeoutError`, `InfraAuthenticationError`, `InfraUnavailableError` for transport failures with proper `ModelInfraErrorContext`
Applied to files:
docs/patterns/error_sanitization_patterns.mdsrc/omnibase_infra/runtime/runtime_host_process.py
📚 Learning: 2026-01-13T16:21:16.950Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T16:21:16.950Z
Learning: Applies to src/omnibase_core/nodes/node_orchestrator.py : ORCHESTRATOR nodes cannot return typed results. They can only emit events and intents with result=None.
Applied to files:
tests/integration/nodes/test_registration_orchestrator_runtime_execution.py
📚 Learning: 2025-12-06T22:21:32.649Z
Learnt from: CR
Repo: OmniNode-ai/omniagent PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T22:21:32.649Z
Learning: Applies to nodes/effect/**/*.py : Use `DbAdapter` envelope pattern for database operations instead of custom PostgreSQL clients
Applied to files:
tests/unit/nodes/node_registry_effect/handlers/test_handler_postgres_deactivate.pytests/unit/nodes/node_registry_effect/handlers/test_handler_postgres_upsert.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/handler_contract.yaml : Handlers must be discovered and loaded dynamically via YAML contracts using plugin pattern, not hardcoded registries
Applied to files:
tests/unit/runtime/test_handler_discovery.pysrc/omnibase_infra/runtime/handler_plugin_loader.pysrc/omnibase_infra/runtime/runtime_host_process.py
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contracts/contract_*.yaml : All ONEX node contract definitions must use the new subcontract architecture pattern, breaking down complex contracts into separate contract_actions.yaml, contract_models.yaml, contract_validation.yaml, and optional contract_cli.yaml and contract_capabilities.yaml files for separation of concerns, maintainability, reusability, modularity, and future tool-as-a-service readiness
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/contract.yaml : Contract files must use semantic versioning with `contract_version` and `node_version` fields, specify node type (EFFECT/COMPUTE/REDUCER/ORCHESTRATOR), and strongly type all I/O with `input_model` and `output_model`
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/handler_contract.yaml : Handler contract files must declare handler routing with `routing_strategy`, event models, handler classes, and handler modules
Applied to files:
tests/unit/runtime/test_handler_discovery.pysrc/omnibase_infra/runtime/handler_plugin_loader.py
📚 Learning: 2025-11-24T16:32:55.606Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T16:32:55.606Z
Learning: Applies to **/*contract*.yaml : All ONEX nodes must have validated YAML contracts following the contract-driven development pattern with input_state and output_state schema definitions
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2025-12-07T17:50:13.678Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T17:50:13.678Z
Learning: Applies to **/contracts/*.yaml : Validate contracts using the contract linter tool: python -m omniintelligence.tools.contract_linter for YAML contract definitions
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2025-11-24T17:24:41.687Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T17:24:41.687Z
Learning: Applies to **/contracts/contract_*.yaml : Subcontract files must follow the naming pattern `contract_<domain>.yaml` and be located in `*/contracts/` directories
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2025-11-24T17:24:41.687Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T17:24:41.687Z
Learning: Applies to **/contracts/contract_{actions,models,validation,cli,capabilities}.yaml : Subcontract files must be organized with naming convention: `contract_actions.yaml`, `contract_models.yaml`, `contract_validation.yaml`, `contract_cli.yaml`, `contract_capabilities.yaml`
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to src/omninode_bridge/nodes/**/contract.yaml : All contract YAML files for ONEX v2.0 nodes MUST define subcontract references, input/output models, and FSM configurations. Use YAML 1.2 syntax.
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2025-12-03T16:55:49.755Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-03T16:55:49.755Z
Learning: Applies to agents/**/*.py : Use correlation_id UUID for end-to-end traceability across all agent routing, manifest injection, and execution events
Applied to files:
tests/unit/runtime/test_handler_discovery.pysrc/omnibase_infra/runtime/handler_plugin_loader.py
📚 Learning: 2025-12-03T16:55:49.755Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-03T16:55:49.755Z
Learning: Applies to agents/**/*.py : Implement agent observability using three-layer traceability with correlation_id tracking through agent_routing_decisions, agent_manifest_injections, and agent_execution_logs tables
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2025-11-29T17:13:38.776Z
Learnt from: CR
Repo: OmniNode-ai/omniarchon PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T17:13:38.776Z
Learning: Applies to {services/**/*.py,scripts/**/*.py} : Use correlation IDs for distributed logging across services. Implement log tracing with `python3 scripts/view_pipeline_logs.py --correlation-id X`.
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/*.py : Correlation IDs must be propagated from incoming requests, auto-generated with `uuid4()` if missing, and included in all error contexts
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/*.py : Use `ModelEventEnvelope[object]` for generic dispatcher interfaces and `object` for generic payloads
Applied to files:
tests/integration/registration/e2e/test_two_way_registration_e2e.py
📚 Learning: 2025-11-24T16:32:55.606Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T16:32:55.606Z
Learning: Node communication must use event-driven patterns through `ModelEventEnvelope` from `omnibase_core.models.events.model_event_envelope`
Applied to files:
tests/integration/registration/e2e/test_two_way_registration_e2e.py
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/introspection.py : All ONEX nodes must include an `introspection.py` file implementing standards-compliant introspection logic
Applied to files:
tests/integration/registration/e2e/test_two_way_registration_e2e.py
📚 Learning: 2026-01-13T16:21:16.950Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T16:21:16.950Z
Learning: Applies to **/nodes/node_*.py : Use ModelONEXContainer in node constructors, never ModelContainer. ModelONEXContainer provides dependency injection with service resolution via get_service().
Applied to files:
tests/integration/registration/e2e/test_two_way_registration_e2e.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Node Introspection Security - use Python reflection for service discovery, but prefix internal/sensitive methods with `_`, use generic parameter names, and configure Kafka topic ACLs for introspection topics
Applied to files:
tests/integration/registration/e2e/test_two_way_registration_e2e.py
📚 Learning: 2026-01-06T17:57:00.689Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_spi PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:57:00.689Z
Learning: Applies to src/omnibase_spi/protocols/handlers/**/*.py : Protocol naming convention: Handler protocols must follow `Protocol{Type}Handler` pattern
Applied to files:
src/omnibase_infra/runtime/handler_plugin_loader.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: When both `handler_contract.yaml` and `contract.yaml` exist in the same directory, the loader must raise an error (AMBIGUOUS_CONTRACT_CONFIGURATION)
Applied to files:
src/omnibase_infra/runtime/handler_plugin_loader.py
📚 Learning: 2025-11-24T17:24:41.687Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T17:24:41.687Z
Learning: Applies to **/models/model_contract_*.py : Contract-backed model files must follow the naming pattern `model_contract_<domain>.py` and be located in `*/models/` directories
Applied to files:
src/omnibase_infra/runtime/handler_plugin_loader.py
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/models/model_contract_*.py : All ONEX node auto-generated Pydantic models must be organized in a `models/` directory with files for state.py, model_contract_actions.py, model_contract_models.py, model_contract_validation.py, model_contract_cli.py (optional), model_contract_capabilities.py (optional), and error_codes.py, generated from the corresponding contract definitions
Applied to files:
src/omnibase_infra/runtime/handler_plugin_loader.py
📚 Learning: 2025-11-24T16:33:32.747Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T16:33:32.747Z
Learning: Applies to **/models/model_contract_*.py : Contract model files must follow the naming pattern `model_contract_<domain>.py` and be located in `*/models/` directories
Applied to files:
src/omnibase_infra/runtime/handler_plugin_loader.py
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contracts/contract_*.yaml : All ONEX node subcontracts must be organized in a `contracts/` subdirectory within the versioned implementation directory with separate files for contract_actions.yaml, contract_models.yaml, contract_validation.yaml, contract_cli.yaml (optional), and contract_capabilities.yaml (optional)
Applied to files:
src/omnibase_infra/runtime/handler_plugin_loader.py
📚 Learning: 2025-11-24T17:24:54.193Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T17:24:54.193Z
Learning: Applies to **/*test*.py : Use registry=None in test harness to force registry resolver usage instead of manually creating registry instances
Applied to files:
tests/integration/nodes/test_node_registry_effect_integration.pytests/unit/runtime/test_registry_compute.py
📚 Learning: 2025-12-06T22:21:32.649Z
Learnt from: CR
Repo: OmniNode-ai/omniagent PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T22:21:32.649Z
Learning: Applies to nodes/**/*.py : Use event bus mixins from `omnibase_core` for Kafka publishing instead of direct Kafka clients
Applied to files:
src/omnibase_infra/event_bus/kafka_event_bus.pytests/integration/registration/e2e/test_runtime_e2e.py
📚 Learning: 2025-12-03T16:55:49.755Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-03T16:55:49.755Z
Learning: Applies to **/*.py : Publish intelligence requests to Kafka event bus using topics: dev.archon-intelligence.intelligence.code-analysis-{requested,completed,failed}.v1 for consistency and event-driven architecture
Applied to files:
src/omnibase_infra/event_bus/kafka_event_bus.py
📚 Learning: 2025-12-03T16:55:49.755Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-03T16:55:49.755Z
Learning: Applies to agents/**/*.py : Implement quality gates with <200ms execution target and performance metrics logging to PostgreSQL agent_execution_logs table
Applied to files:
tests/integration/registration/e2e/test_runtime_e2e.py
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to src/omninode_bridge/events/**/*.py : Kafka event publishing MUST use OnexEnvelopeV1 format with 13 topics for event streaming at all workflow lifecycle stages
Applied to files:
tests/integration/registration/e2e/test_runtime_e2e.py
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to migrations/*.sql : Database migrations in migrations/*.sql MUST be applied in order. Critical migration: 005-node_registrations.sql. Always backup before migrations in production.
Applied to files:
docker/migrations/README.md
📚 Learning: 2025-11-24T16:31:48.648Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/checklist_rule.md:0-0
Timestamp: 2025-11-24T16:31:48.648Z
Learning: Document migration requirements when upgrading from Checklist Rule v3 to v4: add dependencies, blockers, relationships, and work_context sections to existing tickets
Applied to files:
docker/migrations/README.md
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: All PostgreSQL migrations MUST be applied before starting services. Migration 005 (node_registrations table) is CRITICAL - verify it exists before deployment
Applied to files:
docker/migrations/README.md
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/*.py : External service adapters must implement `MixinAsyncCircuitBreaker` with appropriate threshold and reset_timeout configuration
Applied to files:
tests/chaos/test_recovery_circuit_breaker.py
📚 Learning: 2025-11-24T17:22:32.195Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-24T17:22:32.195Z
Learning: Applies to **/testing/testing_scenario_harness.py : Registry resolver should use dynamic fixture detection based on constructor signatures using inspect.signature to determine which parameters to inject
Applied to files:
tests/unit/runtime/test_registry_compute.py
📚 Learning: 2026-01-06T17:57:00.689Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_spi PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:57:00.689Z
Learning: Applies to src/omnibase_spi/protocols/**/*.py : Every protocol must inherit from `typing.Protocol` and have the `runtime_checkable` decorator
Applied to files:
src/omnibase_infra/runtime/runtime_host_process.py
📚 Learning: 2026-01-13T16:21:16.950Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T16:21:16.950Z
Learning: Applies to src/omnibase_core/**/*.py : Always use ModelOnexError with error codes instead of generic Exception.
Applied to files:
src/omnibase_infra/runtime/runtime_host_process.py
📚 Learning: 2025-11-24T16:33:32.747Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T16:33:32.747Z
Learning: Applies to **/*.py : Import protocols from `omnibase.protocol.protocol_*` paths
Applied to files:
src/omnibase_infra/runtime/runtime_host_process.py
📚 Learning: 2025-12-06T22:21:32.649Z
Learnt from: CR
Repo: OmniNode-ai/omniagent PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T22:21:32.649Z
Learning: Applies to nodes/effect/**/*.py : Use handler envelopes from `omnibase_infra` for all I/O operations (HTTP, database, Kafka) instead of custom clients
Applied to files:
src/omnibase_infra/runtime/runtime_host_process.py
📚 Learning: 2025-11-28T18:58:53.781Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-28T18:58:53.781Z
Learning: Applies to **/*.py : Use `EnumCoreErrorCode` with `ModelOnexError` for proper error code usage
Applied to files:
src/omnibase_infra/runtime/runtime_host_process.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/*.py : Infrastructure error handling must use `OnexError` base class and never expose passwords, API keys, PII, or connection strings with credentials in error messages
Applied to files:
src/omnibase_infra/runtime/runtime_host_process.py
🧬 Code graph analysis (17)
tests/unit/nodes/node_registry_effect/handlers/test_handler_postgres_deactivate.py (1)
src/omnibase_infra/nodes/effects/models/model_backend_result.py (1)
ModelBackendResult(50-185)
tests/unit/runtime/test_handler_discovery.py (4)
src/omnibase_infra/event_bus/inmemory_event_bus.py (1)
InMemoryEventBus(64-709)src/omnibase_infra/runtime/registry/registry_protocol_binding.py (1)
ProtocolBindingRegistry(130-438)src/omnibase_infra/errors/error_infra.py (1)
ProtocolConfigurationError(154-189)src/omnibase_infra/runtime/contract_handler_discovery.py (1)
last_discovery_result(140-163)
tests/unit/registration/effect/test_effect_partial_failure.py (3)
src/omnibase_infra/nodes/effects/protocol_consul_client.py (1)
register_service(49-68)src/omnibase_infra/nodes/effects/models/model_backend_result.py (1)
ModelBackendResult(50-185)src/omnibase_infra/nodes/effects/protocol_postgres_adapter.py (1)
upsert(54-75)
tests/integration/registration/e2e/test_two_way_registration_e2e.py (4)
src/omnibase_infra/enums/enum_introspection_reason.py (1)
EnumIntrospectionReason(18-151)tests/integration/registration/e2e/conftest.py (6)
wait_for_consumer_ready(124-206)projection_reader(446-461)node_id(830-831)node_id(871-873)node_type(834-835)node_type(876-878)tests/integration/registration/e2e/verification_helpers.py (1)
wait_for_postgres_write(217-284)src/omnibase_infra/models/registration/model_node_introspection_event.py (1)
ModelNodeIntrospectionEvent(32-192)
src/omnibase_infra/runtime/handler_plugin_loader.py (3)
src/omnibase_infra/models/runtime/model_loaded_handler.py (1)
ModelLoadedHandler(30-117)src/omnibase_infra/models/errors/model_infra_error_context.py (2)
ModelInfraErrorContext(17-96)with_correlation(71-96)src/omnibase_infra/enums/enum_infra_transport_type.py (1)
EnumInfraTransportType(32-60)
tests/unit/nodes/node_registry_effect/handlers/test_handler_consul_deregister.py (1)
src/omnibase_infra/nodes/effects/models/model_backend_result.py (1)
ModelBackendResult(50-185)
tests/integration/nodes/test_node_registry_effect_integration.py (1)
src/omnibase_infra/nodes/effects/models/model_backend_result.py (1)
ModelBackendResult(50-185)
tests/unit/nodes/node_registry_effect/handlers/test_handler_consul_register.py (1)
src/omnibase_infra/nodes/effects/models/model_backend_result.py (1)
ModelBackendResult(50-185)
tests/integration/registration/effect/test_doubles.py (1)
src/omnibase_infra/nodes/effects/models/model_backend_result.py (1)
ModelBackendResult(50-185)
tests/integration/registration/e2e/test_runtime_e2e.py (1)
tests/integration/registration/e2e/conftest.py (2)
wait_for_consumer_ready(124-206)wrap_event_in_envelope(214-237)
tests/unit/runtime/test_lru_cache_eviction_stress.py (1)
src/omnibase_infra/runtime/policy_registry.py (2)
PolicyRegistry(107-1559)_get_semver_cache_info(1258-1285)
tests/unit/runtime/test_runtime_host_architecture_validation.py (2)
tests/conftest.py (1)
seed_mock_handlers(979-1039)src/omnibase_infra/runtime/registry/registry_protocol_binding.py (1)
list_protocols(316-330)
tests/chaos/test_recovery_circuit_breaker.py (1)
src/omnibase_infra/enums/enum_infra_transport_type.py (1)
EnumInfraTransportType(32-60)
tests/unit/runtime/test_registry_compute.py (1)
tests/unit/runtime/test_protocol_binding_registry_race_fix.py (1)
registry(36-38)
tests/unit/nodes/node_registry_effect/handlers/test_handler_postgres_upsert.py (1)
src/omnibase_infra/nodes/effects/models/model_backend_result.py (1)
ModelBackendResult(50-185)
tests/unit/nodes/node_registry_effect/handlers/test_handler_partial_retry.py (1)
src/omnibase_infra/nodes/effects/models/model_backend_result.py (1)
ModelBackendResult(50-185)
src/omnibase_infra/runtime/runtime_host_process.py (3)
src/omnibase_infra/errors/error_infra.py (1)
ProtocolConfigurationError(154-189)src/omnibase_infra/models/errors/model_infra_error_context.py (1)
ModelInfraErrorContext(17-96)src/omnibase_infra/runtime/registry/registry_protocol_binding.py (1)
list_protocols(316-330)
PR Review: Infrastructure Integration with Handler Contracts and E2E Fixes [OMN-1317]Overall AssessmentThis is a substantial and well-executed PR (6,997 additions across 104 files) that introduces plugin-based handler discovery and significantly improves E2E test reliability. The implementation demonstrates excellent engineering practices with comprehensive documentation, fail-fast validation, and systematic test improvements. Recommendation: ✅ Approve with minor fixes required Critical Issues (Must Fix Before Merge)1. ❌ Vault Handler Contract Will Fail to LoadLocation: Issue: The contract defines Impact: Vault handler will fail to load at runtime Fix Options:
2.
|
| Priority | Issue | Action |
|---|---|---|
| P0 (Blocking) | Vault contract invalid field | Remove requires_authentication or add to security model |
| P0 (Blocking) | Security metadata not enforced | Add _validate_security_metadata() method |
| P1 | Missing security fail-fast | Add validation step in RuntimeHostProcess.start() |
| P1 | Valkey no test coverage | Add integration tests or document intended use |
| P2 | Network partition test gaps | Add failover scenario tests in follow-up |
| P2 | Poll interval magic numbers | Extract to constants for tunability |
| P3 | Empty namespace allowlist | Consider ERROR instead of WARNING |
Conclusion
This PR represents high-quality engineering work with:
- ✅ Comprehensive plugin-based handler architecture
- ✅ Excellent test reliability improvements (40+ deterministic polling locations)
- ✅ Production-grade migration safety
- ✅ Strong CLAUDE.md compliance
The two critical issues (vault contract field + security enforcement) must be addressed before merge, but they are straightforward fixes. Once resolved, this PR will significantly improve the infrastructure's maintainability and reliability.
Great work on the systematic approach to test reliability and comprehensive documentation! 🎉
Documentation: - Fix error conventions in retry_backoff_compensation_strategy.md (use OnexError hierarchy) - Clarify migration upgrade path 003a → 004 in README.md - Improve Scenario 1 guidance in MIGRATION_UPGRADE_003a_to_004.md - Fix ADR-004 date inconsistencies (2024 → 2025) Source Code: - Enhance no-handlers error message with detailed troubleshooting steps - Add backend_id to ModelBackendResult/ModelRegistryResponse docstring examples Tests: - Add Windows skipif markers for symlink tests in test_handler_discovery.py - Add try/finally for proper cleanup when start() raises - Complete correlation ID assertion - Remove dead code in test_lru_cache_eviction_stress.py - Clarify "no handlers" test semantics in architecture validation tests - Enhance wait_for_consumer_ready documentation in conftest.py Configuration: - Remove specific deprecation timeline from .env.example (use generic notice)
PR Review - Infrastructure Integration with Handler Contracts [OMN-1317]OverviewThis is an excellent pull request that implements a robust, production-ready handler discovery system. The implementation demonstrates strong adherence to ONEX architectural principles and shows significant attention to security, error handling, and operational concerns. ✅ Strengths1. Security Implementation (Outstanding)
Security Recommendation: Consider enabling 2. Error Handling (Excellent)
3. Documentation (Outstanding)
4. Testing Coverage
5. Code Quality
🔍 Code Quality ObservationsHandler Plugin Loader (
|
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In @docker/migrations/README.md:
- Line 89: There’s an inconsistency in the migration README where rollback
naming is called out as `003a` in multiple spots but line 180 references `003b`;
update the README to consistently reference `003a` for the rollback script
(e.g., change the `003b` mention at line 180 to `003a`) and, if desired, add a
short clarifying note near the examples (the
`003a_capability_fields_rollback.sql` example) stating that alternate letter
suffixes are only allowed if the earlier suffix has already been used.
In @docs/patterns/retry_backoff_compensation_strategy.md:
- Around line 510-519: The example incorrectly hardcodes
transport_type=EnumInfraTransportType.HTTP when building ModelInfraErrorContext
for saga compensation; instead either use a generic transport (e.g.,
EnumInfraTransportType.GENERIC) or aggregate/preserve per-step contexts from
compensation_errors so real transport info isn’t lost. Update the
CompensationFailedError construction (the raise of CompensationFailedError) to
collect existing ModelInfraErrorContext instances from each err in
compensation_errors (or fallback to a generic context when missing), and pass
that aggregated or step-specific context into the CompensationFailedError rather
than always using EnumInfraTransportType.HTTP.
In @tests/unit/runtime/test_lru_cache_eviction_stress.py:
- Around line 1046-1047: The inline comment "Record initial state" is stale
because the call to PolicyRegistry._get_semver_cache_info() no longer
records/uses a value; remove that dead call and its stale comment, or
alternatively replace the comment with a clearer one like "Ensure cache is
initialized" if you want to keep the call; locate the invocation of
PolicyRegistry._get_semver_cache_info() near the loop that calls
PolicyRegistry._parse_semver and either delete both the comment and the call
(preferred) or update the comment to reflect the initialization purpose.
🧹 Nitpick comments (4)
docker/migrations/README.md (1)
103-106: Simplify the messaging about 003a slot availability.This note is quite dense and attempts to explain multiple concepts: availability of 003a, recommendation against using it, and upgrade path. Consider splitting this into clearer guidance:
- Clarify that while 003a is technically available, it should only be used for rollback scripts closely related to migration 003
- Move the upgrade path information to the "Upgrade Notes" section (which already exists at lines 201-210)
- Simplify the recommendation to: "For new features, use the next main number (005). For rollbacks of migration 003, you may use 003a."
This would reduce confusion about whether users should or shouldn't use the 003a slot.
tests/integration/registration/e2e/conftest.py (1)
124-219: Consider extracting sharedwait_for_consumer_readyto common test utilities.The implementation here is identical to
tests/integration/event_bus/conftest.py:53–123, including the exponential backoff logic, health check polling, and timeout behavior. The only difference is the deprecatedpoll_intervalparameter in this version.Consolidate into a single shared utility (e.g.,
tests/helpers/or a dedicated test utilities module) to prevent drift and reduce maintenance burden.tests/unit/runtime/test_handler_discovery.py (2)
926-941: Doublestop()call is redundant.The test explicitly calls
await process.stop()at line 930, then thefinallyblock calls it again at line 940. While this should be harmless ifstop()is idempotent, it's redundant. Consider restructuring:♻️ Suggested cleanup
try: await process.start() assert process.is_running await process.stop() assert not process.is_running # After stop, handlers should still be registered health = await process.health_check() assert health["is_running"] is False # Handlers remain registered after stop assert health["no_handlers_registered"] is False finally: - # Ensure stop() is called even if assertions fail - await process.stop() + # Ensure stop() is called if start succeeded but assertions failed + if process.is_running: + await process.stop()
1142-1151: Consider moving__all__to the end of the file.The
__all__export list references classes likeTestDiscoverHandlersFromContractsUnit,TestDiscoverHandlersFromContractsErrorHandling, etc., that are defined after this declaration (lines 1159+). While this is valid Python, it's unconventional and can confuse readers. Typically,__all__either appears at the top (with all exports defined above) or at the end of the file.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Lite
📒 Files selected for processing (12)
.env.exampledocker/migrations/MIGRATION_UPGRADE_003a_to_004.mddocker/migrations/README.mddocs/adr/ADR-004-performance-baseline-thresholds.mddocs/patterns/retry_backoff_compensation_strategy.mdsrc/omnibase_infra/nodes/effects/models/model_backend_result.pysrc/omnibase_infra/nodes/effects/models/model_registry_response.pysrc/omnibase_infra/runtime/runtime_host_process.pytests/integration/registration/e2e/conftest.pytests/unit/runtime/test_handler_discovery.pytests/unit/runtime/test_lru_cache_eviction_stress.pytests/unit/runtime/test_runtime_host_architecture_validation.py
✅ Files skipped from review due to trivial changes (2)
- docs/adr/ADR-004-performance-baseline-thresholds.md
- src/omnibase_infra/nodes/effects/models/model_registry_response.py
🚧 Files skipped from review as they are similar to previous changes (2)
- docker/migrations/MIGRATION_UPGRADE_003a_to_004.md
- .env.example
🧰 Additional context used
📓 Path-based instructions (3)
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Never useAnytype - useobjectfor generic payloads in function parameters and return types
UseX | None(PEP 604) instead ofOptional[X]for nullable types
All services must useModelONEXContainerfor dependency injection via__init__(self, container: ModelONEXContainer)
Use@allow_anydecorator with documented reason as exemption mechanism forAnytype violations
UseJsonTypefromomnibase_core.typesas the canonical type alias for JSON-compatible values
UseModelEventEnvelope[object]for generic dispatcher interfaces andobjectfor generic payloads
Infrastructure error handling must useOnexErrorbase class and never expose passwords, API keys, PII, or connection strings with credentials in error messages
UseInfraConnectionError,InfraTimeoutError,InfraAuthenticationError,InfraUnavailableErrorfor transport failures with properModelInfraErrorContext
Correlation IDs must be propagated from incoming requests, auto-generated withuuid4()if missing, and included in all error contexts
External service adapters must implementMixinAsyncCircuitBreakerwith appropriate threshold and reset_timeout configuration
Protocol resolution must use duck typing via protocols, never useisinstancechecks
Files:
src/omnibase_infra/nodes/effects/models/model_backend_result.pytests/unit/runtime/test_runtime_host_architecture_validation.pysrc/omnibase_infra/runtime/runtime_host_process.pytests/unit/runtime/test_handler_discovery.pytests/unit/runtime/test_lru_cache_eviction_stress.pytests/integration/registration/e2e/conftest.py
**/model_*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/model_*.py: File naming convention: Models must usemodel_<name>.pywith class nameModel<Name>
Each model file must contain exactly oneModel*class
Pydantic workaround forAnytype must include# NOTE:comment documenting the reason when technically required
UseSerializeAsAnytype wrapper for Pydantic fields containing complex nested models to preserve subclass fields during serialization
Files:
src/omnibase_infra/nodes/effects/models/model_backend_result.py
**/model_*result*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Result models may override
__bool__to enable idiomatic conditional checks, with requiredWarningsection in docstring explaining non-standard behavior
Files:
src/omnibase_infra/nodes/effects/models/model_backend_result.py
🧠 Learnings (33)
📓 Common learnings
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/handler_contract.yaml : Handler contract files must declare handler routing with `routing_strategy`, event models, handler classes, and handler modules
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/handler_contract.yaml : Handlers must be discovered and loaded dynamically via YAML contracts using plugin pattern, not hardcoded registries
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contracts/contract_*.yaml : All ONEX node contract definitions must use the new subcontract architecture pattern, breaking down complex contracts into separate contract_actions.yaml, contract_models.yaml, contract_validation.yaml, and optional contract_cli.yaml and contract_capabilities.yaml files for separation of concerns, maintainability, reusability, modularity, and future tool-as-a-service readiness
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contracts/contract_*.yaml : All ONEX node subcontracts must be organized in a `contracts/` subdirectory within the versioned implementation directory with separate files for contract_actions.yaml, contract_models.yaml, contract_validation.yaml, contract_cli.yaml (optional), and contract_capabilities.yaml (optional)
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T16:32:55.606Z
Learning: Applies to **/*contract*.yaml : All ONEX nodes must have validated YAML contracts following the contract-driven development pattern with input_state and output_state schema definitions
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-24T17:22:32.195Z
Learning: Applies to **/v[0-9]_[0-9]_[0-9]/contracts/ : Organize contract subcomponents into separate files (contract_actions.yaml, contract_models.yaml, contract_validation.yaml, etc.) and reference them from main contract.yaml
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: When both `handler_contract.yaml` and `contract.yaml` exist in the same directory, the loader must raise an error (AMBIGUOUS_CONTRACT_CONFIGURATION)
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/models/model_contract_*.py : All ONEX node auto-generated Pydantic models must be organized in a `models/` directory with files for state.py, model_contract_actions.py, model_contract_models.py, model_contract_validation.py, model_contract_cli.py (optional), model_contract_capabilities.py (optional), and error_codes.py, generated from the corresponding contract definitions
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to src/omninode_bridge/nodes/**/contract.yaml : All contract YAML files for ONEX v2.0 nodes MUST define subcontract references, input/output models, and FSM configurations. Use YAML 1.2 syntax.
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T16:21:16.950Z
Learning: Applies to src/omnibase_core/runtime/runtime_*.py : Use FileRegistry to load runtime contracts from YAML configuration files.
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to migrations/*.sql : Database migrations in migrations/*.sql MUST be applied in order. Critical migration: 005-node_registrations.sql. Always backup before migrations in production.
Applied to files:
docker/migrations/README.md
📚 Learning: 2025-11-24T16:31:48.648Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/checklist_rule.md:0-0
Timestamp: 2025-11-24T16:31:48.648Z
Learning: Document migration requirements when upgrading from Checklist Rule v3 to v4: add dependencies, blockers, relationships, and work_context sections to existing tickets
Applied to files:
docker/migrations/README.md
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: All PostgreSQL migrations MUST be applied before starting services. Migration 005 (node_registrations table) is CRITICAL - verify it exists before deployment
Applied to files:
docker/migrations/README.md
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/*.py : Use `InfraConnectionError`, `InfraTimeoutError`, `InfraAuthenticationError`, `InfraUnavailableError` for transport failures with proper `ModelInfraErrorContext`
Applied to files:
docs/patterns/retry_backoff_compensation_strategy.mdsrc/omnibase_infra/runtime/runtime_host_process.py
📚 Learning: 2026-01-13T16:21:16.950Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T16:21:16.950Z
Learning: Applies to src/omnibase_core/**/*.py : Always use ModelOnexError with error codes instead of generic Exception.
Applied to files:
src/omnibase_infra/runtime/runtime_host_process.py
📚 Learning: 2025-11-24T16:33:32.747Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T16:33:32.747Z
Learning: Applies to **/*.py : Import protocols from `omnibase.protocol.protocol_*` paths
Applied to files:
src/omnibase_infra/runtime/runtime_host_process.py
📚 Learning: 2026-01-06T17:57:00.689Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_spi PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-06T17:57:00.689Z
Learning: Applies to src/omnibase_spi/protocols/**/*.py : Every protocol must inherit from `typing.Protocol` and have the `runtime_checkable` decorator
Applied to files:
src/omnibase_infra/runtime/runtime_host_process.py
📚 Learning: 2025-12-06T22:21:32.649Z
Learnt from: CR
Repo: OmniNode-ai/omniagent PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T22:21:32.649Z
Learning: Applies to nodes/effect/**/*.py : Use handler envelopes from `omnibase_infra` for all I/O operations (HTTP, database, Kafka) instead of custom clients
Applied to files:
src/omnibase_infra/runtime/runtime_host_process.py
📚 Learning: 2025-11-28T18:58:53.781Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-28T18:58:53.781Z
Learning: Applies to **/*.py : Use `EnumCoreErrorCode` with `ModelOnexError` for proper error code usage
Applied to files:
src/omnibase_infra/runtime/runtime_host_process.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/*.py : Infrastructure error handling must use `OnexError` base class and never expose passwords, API keys, PII, or connection strings with credentials in error messages
Applied to files:
src/omnibase_infra/runtime/runtime_host_process.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/handler_contract.yaml : Handlers must be discovered and loaded dynamically via YAML contracts using plugin pattern, not hardcoded registries
Applied to files:
src/omnibase_infra/runtime/runtime_host_process.pytests/unit/runtime/test_handler_discovery.py
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contracts/contract_*.yaml : All ONEX node contract definitions must use the new subcontract architecture pattern, breaking down complex contracts into separate contract_actions.yaml, contract_models.yaml, contract_validation.yaml, and optional contract_cli.yaml and contract_capabilities.yaml files for separation of concerns, maintainability, reusability, modularity, and future tool-as-a-service readiness
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/contract.yaml : Contract files must use semantic versioning with `contract_version` and `node_version` fields, specify node type (EFFECT/COMPUTE/REDUCER/ORCHESTRATOR), and strongly type all I/O with `input_model` and `output_model`
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/handler_contract.yaml : Handler contract files must declare handler routing with `routing_strategy`, event models, handler classes, and handler modules
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2025-11-24T16:32:55.606Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T16:32:55.606Z
Learning: Applies to **/*contract*.yaml : All ONEX nodes must have validated YAML contracts following the contract-driven development pattern with input_state and output_state schema definitions
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2025-12-07T17:50:13.678Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T17:50:13.678Z
Learning: Applies to **/contracts/*.yaml : Validate contracts using the contract linter tool: python -m omniintelligence.tools.contract_linter for YAML contract definitions
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2025-11-24T17:24:41.687Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T17:24:41.687Z
Learning: Applies to **/contracts/contract_*.yaml : Subcontract files must follow the naming pattern `contract_<domain>.yaml` and be located in `*/contracts/` directories
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2025-11-24T17:24:41.687Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T17:24:41.687Z
Learning: Applies to **/contracts/contract_{actions,models,validation,cli,capabilities}.yaml : Subcontract files must be organized with naming convention: `contract_actions.yaml`, `contract_models.yaml`, `contract_validation.yaml`, `contract_cli.yaml`, `contract_capabilities.yaml`
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to src/omninode_bridge/nodes/**/contract.yaml : All contract YAML files for ONEX v2.0 nodes MUST define subcontract references, input/output models, and FSM configurations. Use YAML 1.2 syntax.
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2025-12-03T16:55:49.755Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-03T16:55:49.755Z
Learning: Applies to agents/**/*.py : Use correlation_id UUID for end-to-end traceability across all agent routing, manifest injection, and execution events
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2025-12-03T16:55:49.755Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-03T16:55:49.755Z
Learning: Applies to agents/**/*.py : Implement agent observability using three-layer traceability with correlation_id tracking through agent_routing_decisions, agent_manifest_injections, and agent_execution_logs tables
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2025-11-29T17:13:38.776Z
Learnt from: CR
Repo: OmniNode-ai/omniarchon PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T17:13:38.776Z
Learning: Applies to {services/**/*.py,scripts/**/*.py} : Use correlation IDs for distributed logging across services. Implement log tracing with `python3 scripts/view_pipeline_logs.py --correlation-id X`.
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/*.py : Correlation IDs must be propagated from incoming requests, auto-generated with `uuid4()` if missing, and included in all error contexts
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2025-12-07T17:50:13.678Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T17:50:13.678Z
Learning: Organize tests following the structure: tests/conftest.py for shared fixtures, tests/unit/ for unit tests (no infrastructure), tests/integration/ for integration tests (requires Kafka/DBs), tests/nodes/ for node-specific tests
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-24T16:33:51.604Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T16:33:51.604Z
Learning: Applies to tests/**/conftest.py : Test fixtures must be defined in `conftest.py` and should provide reusable sample data, UUIDs, semantic versions, and model data
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-12-19T02:58:44.081Z
Learnt from: sudharsanv177
Repo: OmniNode-ai/omninode_infra PR: 4
File: docker/onex-api/main.py:0-0
Timestamp: 2025-12-19T02:58:44.081Z
Learning: In the omninode_infra repository, production configuration is managed via Kubernetes Secrets and ConfigMaps injected as environment variables, not committed .env files or Pydantic Settings. The deployment model uses os.getenv() with sensible defaults for local development, and explicit resolution patterns (e.g., checking POSTGRES_DSN first, then deriving from component variables) are preferred over mutating os.environ.
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-29T22:07:25.230Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: migration_sources/omniarchon/CLAUDE.md:0-0
Timestamp: 2025-11-29T22:07:25.230Z
Learning: Applies to migration_sources/omniarchon/**/tests/**/*.py : All integration tests must verify correct Kafka port usage for context (9092 for Docker, 29092 for host). Test both local (qdrant, memgraph) and remote (PostgreSQL, Redpanda) database connectivity. Never assume test environment configuration.
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-29T22:07:25.230Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: migration_sources/omniarchon/CLAUDE.md:0-0
Timestamp: 2025-11-29T22:07:25.230Z
Learning: Applies to migration_sources/omniarchon/**/*.py : Always use REMOTE Redpanda at 192.168.86.200 for event bus. NEVER start local Redpanda. Remote Redpanda enables OmniNode integration, data consistency, and production parity. Use correct ports: 9092 (Docker) or 29092 (host scripts).
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to src/**/{config,settings,kafka,events}/**/*.py : Kafka Bootstrap Servers configuration depends on context: Docker services use 'omninode-bridge-redpanda:9092' (internal), host scripts use '192.168.86.200:29092' (external). Verify correct bootstrap server for your context.
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-24T16:32:55.606Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T16:32:55.606Z
Learning: Node implementations must use mixin-based composition from `omnibase_core.mixins` (e.g., `MixinHealthCheck`, `MixinNodeExecutor`) to add capabilities
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Node Introspection Security - use Python reflection for service discovery, but prefix internal/sensitive methods with `_`, use generic parameter names, and configure Kafka topic ACLs for introspection topics
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/introspection.py : All ONEX nodes must include an `introspection.py` file implementing standards-compliant introspection logic
Applied to files:
tests/integration/registration/e2e/conftest.py
🧬 Code graph analysis (4)
tests/unit/runtime/test_runtime_host_architecture_validation.py (2)
tests/conftest.py (1)
seed_mock_handlers(979-1039)src/omnibase_infra/runtime/registry/registry_protocol_binding.py (1)
list_protocols(316-330)
src/omnibase_infra/runtime/runtime_host_process.py (2)
src/omnibase_infra/errors/error_infra.py (1)
ProtocolConfigurationError(154-189)src/omnibase_infra/models/errors/model_infra_error_context.py (1)
ModelInfraErrorContext(17-96)
tests/unit/runtime/test_handler_discovery.py (2)
src/omnibase_infra/errors/error_infra.py (1)
ProtocolConfigurationError(154-189)src/omnibase_infra/runtime/contract_handler_discovery.py (1)
last_discovery_result(140-163)
tests/integration/registration/e2e/conftest.py (5)
src/omnibase_infra/enums/enum_introspection_reason.py (1)
EnumIntrospectionReason(18-151)src/omnibase_infra/models/registration/model_node_introspection_event.py (1)
ModelNodeIntrospectionEvent(32-192)src/omnibase_infra/utils/util_error_sanitization.py (1)
sanitize_error_message(144-203)tests/conftest.py (1)
check_service_registry_available(31-71)tests/integration/event_bus/conftest.py (1)
wait_for_consumer_ready(53-125)
🔇 Additional comments (37)
src/omnibase_infra/nodes/effects/models/model_backend_result.py (4)
1-48: LGTM!Module setup is well-structured with comprehensive documentation covering architecture, security considerations, and related components. The compiled regex at module level is a good performance optimization.
90-111: LGTM!Good documentation improvement. The updated examples now accurately demonstrate the
backend_idfield usage with appropriate backend identifiers ("consul", "postgres") that align with the dual-registration workflow described in the module docstring.
113-140: LGTM!Model fields are well-defined with proper types (
str | None,UUID | Noneper PEP 604), appropriate constraints, and clear descriptions. Thefrozen=Trueconfiguration ensures immutability for safe concurrent access. As per coding guidelines, noAnytype is used.
141-188: LGTM!The
_warn_on_potential_secretsvalidator is a well-designed defense-in-depth measure. The approach of logging warnings without blocking is appropriate—it provides observability for detecting missed sanitization without causing runtime failures. The docstring clearly explains the rationale and lists the detected patterns.src/omnibase_infra/runtime/runtime_host_process.py (5)
56-62: LGTM!The
ProtocolConfigurationErrorimport is correctly added and aligns with the new fail-fast validation logic. The error class is appropriate for configuration validation failures per the relevant code snippets showing it usesEnumCoreErrorCode.INVALID_CONFIGURATION.
718-793: Well-implemented fail-fast validation with comprehensive diagnostics.The implementation correctly:
- Validates after handler population but before subscribing to topics (clean failure)
- Uses
ModelInfraErrorContextwith proper fields per coding guidelines- Auto-generates correlation ID with
uuid4()for traceability- Provides actionable troubleshooting steps without exposing sensitive data
- Includes additional context (
registry_protocol_count,failed_handlers) for debuggingThe detailed error message will significantly improve operational debugging when handlers fail to load.
1559-1590: LGTM!The docstring updates accurately document the new
no_handlers_registeredfield and the updated health state matrix. The documentation is consistent with the implementation changes.
1668-1685: LGTM!The logic correctly treats a runtime with no handlers as unhealthy (not merely degraded), which aligns with the fail-fast validation in
start(). The distinction is appropriate:
degraded=True: Running with reduced functionality (some handlers failed)healthy=Falsewithno_handlers_registered=True: Critical configuration error (cannot process any events)
1687-1699: LGTM!The
no_handlers_registeredfield is correctly included in the health check response, enabling monitoring systems and load balancers to detect and alert on this critical configuration issue.tests/unit/runtime/test_runtime_host_architecture_validation.py (10)
15-52: Excellent documentation clarifying the dual handler semantics.The extended docstring clearly explains the distinction between:
- Fail-fast startup check (handler INSTANCES)
- Architecture validation (handler CLASSES)
The table format and explanation of why "empty registry" tests still need
seed_mock_handlers()will prevent future confusion when reading or modifying these tests.
74-85: LGTM!The quick reference table at the top of the test code provides an at-a-glance summary for developers who may skip the module docstring.
166-170: LGTM!The inline comment clearly explains that
seed_mock_handlerssatisfies the fail-fast check, allowing the test to focus on verifying that startup succeeds when no architecture rules are configured.
203-217: Well-documented test case demonstrating the dual handler semantics.The docstring clearly explains:
- Why the test uses a failing rule (would fail if handlers existed)
- Why
seed_mock_handlers()is still needed (separate fail-fast check)- The independence of the two checks
This serves as a reference implementation for understanding the pattern.
261-301: LGTM!Correctly omits
seed_mock_handlers()because the test expectsArchitectureViolationErrorto be raised during architecture validation, which occurs before the fail-fast check. The test properly verifies that all violations from multiple failing rules are collected.
381-385: LGTM!Correctly seeds handler instances because WARNING violations don't block startup, allowing execution to continue to the fail-fast check. The pattern is consistent with the documented semantics.
445-499: LGTM!Good test design for verifying execution order. Correctly omits
seed_mock_handlers()because the test expects validation to fail before reaching other startup steps, including the fail-fast check.
554-561: LGTM!Correctly seeds handler instances to satisfy the fail-fast check after architecture validation passes (empty registry). The test properly verifies that the injected container is passed to the validator.
657-660: LGTM!Correctly seeds handler instances for the passing validation scenario. The test verifies that passing rules allow normal startup to complete.
706-782: LGTM!Clean unit tests for the
ArchitectureViolationErrorclass, verifying violation storage, formatting, and context inclusion without involving the runtime process.tests/unit/runtime/test_lru_cache_eviction_stress.py (1)
534-535: LGTM!Good use of underscore-prefixed variables to indicate intentionally unused loop variables. This suppresses linter warnings while clearly communicating that only
sizeis needed for the assertion.docker/migrations/README.md (3)
12-17: LGTM! Clear guidance on sub-sequence usage.The note effectively steers users toward main sequence numbers for production-recommended variants, which aligns well with the 003a → 004 promotion.
201-210: Excellent addition of upgrade notes.This section provides clear guidance for users who may have applied the old 003a migration. The bullet points are concise and appropriately reference external documentation for full details.
26-28: LGTM! Consistent updates throughout the document.All examples, tables, and references have been consistently updated from 003a to 004 to reflect the promotion of the concurrent variant to main sequence numbering. This improves clarity and aligns with the new versioning guidance.
Also applies to: 33-33, 62-64, 80-82, 146-146, 173-176
docs/patterns/retry_backoff_compensation_strategy.md (2)
429-431: LGTM! Proper imports for ONEX error handling.The imports correctly bring in the infrastructure error types and context model needed for richer error propagation.
442-461: LGTM! Correct integration with ONEX error hierarchy.The CompensationFailedError now properly extends RuntimeHostError and accepts ModelInfraErrorContext for richer error propagation. This aligns with the infrastructure error handling patterns.
tests/integration/registration/e2e/conftest.py (5)
48-71: LGTM on imports and logger setup.The new imports (
asyncio,ModelEventEnvelope,EnumIntrospectionReason, infrastructure config defaults) are all used by the new helper functions and protocol definitions. Module-level logger with__name__follows standard Python logging patterns.Also applies to: 115-117
520-537: Well-documented configuration for test isolation.The
enable_auto_commit=Falsesetting with its detailed rationale comment effectively addresses:
- Message loss prevention on test failures
- Rebalance timing flakiness reduction
- Cross-test offset pollution prevention
This aligns well with the PR's goal of addressing E2E test determinism issues.
916-944: Protocol correctly exposes MixinNodeIntrospection interface.The lifecycle methods (
publish_introspection,get_introspection_data,start_introspection_tasks,stop_introspection_tasks) properly mirror the mixin interface.The inclusion of
_publish_heartbeat(underscore-prefixed) in the public Protocol is intentional for E2E test access, though unconventional. Consider documenting this explicitly in the Protocol docstring if tests rely on directly invoking this internal method.
1167-1198: LGTM on logging configuration fixture.The session-scoped, autouse fixture appropriately:
- Configures DEBUG level for E2E test loggers for visibility
- Keeps INFO level for infrastructure to reduce verbosity
- Guards against duplicate handlers (line 1190)
- Uses a clear timestamp-based format for observability
The pattern of checking
isinstance(h, logging.StreamHandler)before adding a new handler prevents accumulation during test reruns.
1205-1247: LGTM on updated exports.The
__all__list properly exports the newwait_for_consumer_readyhelper andconfigure_e2e_loggingfixture, making them available to dependent E2E test modules.tests/unit/runtime/test_handler_discovery.py (7)
1-136: LGTM!The module header, imports, and YAML templates are well-organized with clear documentation. The test templates cover a comprehensive range of scenarios including valid contracts, invalid syntax, missing fields, and non-existent handlers.
143-326: LGTM!Fixtures are well-structured, using
tmp_pathfor test isolation and covering a comprehensive set of scenarios. Themixed_valid_invalid_contract_dirfixture is particularly useful for testing partial success scenarios.
340-379: LGTM!The test correctly verifies that
_discover_handlers_from_contractsis called duringstart(). The monkeypatching approach with proper cleanup in thefinallyblock is appropriate for this verification test.
1159-1468: LGTM!This test class provides excellent direct unit test coverage of
_discover_handlers_from_contracts()without going throughstart(). The tests cover multiple paths, nested directories, idempotency, and edge cases like empty path lists. The assertions onlast_discovery_resultalign with the interface shown in the relevant code snippets.
1645-1869: LGTM!The filesystem edge case tests are comprehensive and include proper platform-specific handling with
pytest.mark.skipiffor symlink tests on Windows. The coverage of special characters, deep nesting, and broken symlinks ensures robust discovery behavior.
1954-1958: Fix assertion logic for correlation ID validation.The assertion
len(correlation_ids_found) > 0 or len(logs_with_correlation) == 0is logically inverted from what the message claims. The current logic passes even when correlation logs exist but no correlation IDs were extracted (because the second condition would still make the OR true).The message says "When correlation logs are present, they should contain valid correlation IDs", which should be:
🐛 Proposed fix
- assert len(correlation_ids_found) > 0 or len(logs_with_correlation) == 0, ( + assert len(logs_with_correlation) == 0 or len(correlation_ids_found) > 0, ( "When correlation logs are present, they should contain valid correlation IDs" )This ensures: if there are logs with correlation info, then we must have extracted valid correlation IDs from them.
⛔ Skipped due to learnings
Learnt from: CR Repo: OmniNode-ai/omniarchon PR: 0 File: CLAUDE.md:0-0 Timestamp: 2025-11-29T17:13:38.776Z Learning: Applies to {services/**/*.py,scripts/**/*.py} : Use correlation IDs for distributed logging across services. Implement log tracing with `python3 scripts/view_pipeline_logs.py --correlation-id X`.
534-554: No action required —stop()is already idempotent and safe to call after failedstart().The
RuntimeHostProcess.stop()method explicitly documents that it is idempotent and safe to call on an already-stopped process. The implementation checksif not self._is_running:at line 862 and returns early with no effect. Sincestart()raisesProtocolConfigurationErrorbefore setting_is_running = True(which occurs at line 805), callingstop()in thefinallyblock is safe and will simply no-op. The existing code pattern is correct as-is.Likely an incorrect or invalid review comment.
Documentation: - Fix misleading namespace matching comment in handler_plugin_loader.md - Make SagaExecutor transport_type configurable in retry_backoff_compensation_strategy.md - Add PolicyRegistryError definition in policy_registry_trust_model.md - Update migration decision tree example (003b → 003a) - Simplify MIGRATION_UPGRADE_003a_to_004.md Scenario 1 guidance - Add explicit v2.0.0 deprecation timeline for CONTRACTS_DIR in .env.example - Add Valkey version tracking comment in docker-compose.e2e.yml Source code: - Add backend_id to handler docstring examples (5 handlers) - Remove unused ModelRegistrationState import - Improve MCP availability check using importlib.util.find_spec Tests: - Improve correlation ID assertions with UUID validation - Fix docstring function name reference - Remove dead code and stale comments - Remove deprecated poll_interval parameter from wait_for_consumer_ready - Add UUID-suffixed topic fixtures for parallel test isolation
PR Review: Infrastructure Integration with Handler Contracts and E2E FixesSummaryThis is a comprehensive infrastructure upgrade introducing contract-based handler discovery, runtime fail-fast validation, Pydantic serialization fixes, and E2E test improvements. The PR adds 7,303 lines and removes 673 lines across 103 files, indicating significant foundational work. Code Quality Assessment: ⭐⭐⭐⭐ (4/5)Strengths ✅
Issues to Address 🔴Critical
High Priority
Medium Priority
Performance Considerations ⚡
Security Concerns 🔒
Testing 🧪E2E Test Improvements: The PR fixes heartbeat timing and Kafka subscription issues. Good defensive programming. Missing Test Coverage:
Architecture & Design 🏗️Excellent Adherence to ONEX Patterns:
Migration Path: The 003a → 004 migration guide is comprehensive and production-ready. RecommendationsMust Fix Before Merge
Should Fix Before Merge
Nice to Have
ConclusionThis is high-quality infrastructure work that significantly improves the ONEX runtime. The contract-based handler discovery is well-designed and production-ready. The main concerns are:
Recommendation: Approve with required changes listed above. The architectural direction is sound and the implementation is solid, but policy compliance needs adjustment. Review Style: Following repository conventions per CLAUDE.md - direct, objective feedback prioritizing technical accuracy over validation. Great work on this foundational upgrade! 🚀 |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (14)
docs/patterns/retry_backoff_compensation_strategy.md (1)
467-481: LGTM! Clean design for transport-aware error context.The new constructor properly enables transport-type configuration for error context propagation. The default of
HTTPis reasonable, and the docstring clearly guides users to override for database-centric or event-driven sagas.📝 Optional: Consider clarifying the transport_type guidance in the usage example
The docstring mentions overriding for "database-centric sagas," but the usage example at line 548 shows a funds transfer saga (primarily database operations) that relies on the HTTP default. Consider adding a comment or updating the example to demonstrate the override:
# For database-centric sagas, specify transport type explicitly saga = SagaExecutor(transport_type=EnumInfraTransportType.DATABASE)This would reinforce the guidance in the docstring and provide a concrete example of when to override the default.
tests/integration/registration/e2e/conftest.py (3)
126-222: Code duplication:wait_for_consumer_readyis duplicated across conftest files.This function is identical to the one in
tests/integration/event_bus/conftest.py(lines 52-124). Consider extracting it to a shared utility module (e.g.,tests/helpers/kafka_utils.py) to avoid drift when one copy is updated but not the other.♻️ Suggested refactor
Create a shared module and import from both conftest files:
# tests/helpers/kafka_utils.py async def wait_for_consumer_ready( event_bus: KafkaEventBus, topic: str, max_wait: float = 10.0, initial_backoff: float = 0.1, max_backoff: float = 1.0, backoff_multiplier: float = 1.5, ) -> bool: """Wait for Kafka consumer to be ready to receive messages using polling. ... """ # Implementation hereThen in both conftest files:
from tests.helpers.kafka_utils import wait_for_consumer_ready
1079-1081: Private method exposed in Protocol.
_publish_heartbeatuses underscore prefix convention indicating a private/internal method, yet it's exposed in the publicProtocolIntrospectableTestNode. If this is intentional for testing internal behavior, consider documenting that explicitly. Otherwise, consider whether tests should use the publicpublish_introspectionAPI instead.
621-640: Catch specific exception for topic creation instead of broad Exception.The broad
except Exceptionat line 635 can mask real errors like authentication failures, network issues, or broker misconfigurations. CatchTopicAlreadyExistsErrorspecifically, which is raised when the topic already exists:♻️ Suggested improvement
+from aiokafka.errors import TopicAlreadyExistsError + try: await admin.create_topics( [ NewTopic( name=unique_topic_name, num_partitions=partitions, replication_factor=1, ) ] ) created_topics.append(unique_topic_name) # Wait for topic metadata to propagate await _wait_for_topic_metadata(admin, unique_topic_name) - except Exception: - # Topic may already exist - still wait for metadata + except TopicAlreadyExistsError: + # Topic already exists - still wait for metadata to ensure it's ready if admin is not None: await _wait_for_topic_metadata(admin, unique_topic_name, timeout=5.0)tests/unit/runtime/test_handler_discovery.py (3)
746-779: Consider consolidating duplicate test.This test (
test_empty_directory_raises_configuration_error) is functionally identical to the one inTestInvalidContractYamlHandlingat lines 661-691. Both test that an empty contract directory raisesProtocolConfigurationErrorwith the same assertions.Consider removing one of them or parametrizing them to reduce duplication and maintenance overhead.
1142-1151: Consider relocating__all__to the end of the file or removing it entirely.The
__all__export list is defined mid-file but references classes (TestDiscoverHandlersFromContractsUnit,TestDiscoverHandlersFromContractsErrorHandling,TestDiscoverHandlersFromContractsFileSystemEdgeCases,TestDiscoverHandlersFromContractsCorrelationTracking) that are defined after it. This unconventional placement can cause confusion for readers.For test modules,
__all__is typically unnecessary since pytest discovers test classes automatically via naming conventions.💡 Suggested approach
Either move
__all__to the end of the file (after all class definitions), or remove it entirely since it serves no functional purpose in a pytest test module.
1923-1957: Consider usinguuid.UUID()for validation instead of manual string checks.The manual UUID format validation (checking length and hyphen positions) could miss malformed UUIDs that happen to match the pattern. Using
uuid.UUID(corr_id_str)would provide stricter validation.Additionally, the assertion at line 1946 that correlation IDs MUST be present in logs could become brittle if the logging implementation changes. Consider making this a softer check or documenting the expectation clearly.
♻️ Proposed validation improvement
+from uuid import UUID + # Inside the test method: for log_record in caplog.records: record_dict = log_record.__dict__ if "correlation_id" in record_dict: corr_id = record_dict["correlation_id"] assert corr_id is not None, "Correlation ID in log should not be None" corr_id_str = str(corr_id) - # UUID strings with hyphens are exactly 36 chars (8-4-4-4-12) - assert len(corr_id_str) == 36, ( - f"Correlation ID '{corr_id_str}' should be UUID format (36 chars)" - ) - # Verify UUID format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - parts = corr_id_str.split("-") - assert len(parts) == 5, ( - f"Correlation ID '{corr_id_str}' should have 5 hyphen-separated parts" - ) + # Validate UUID format by parsing + try: + UUID(corr_id_str) + except ValueError: + pytest.fail(f"Correlation ID '{corr_id_str}' is not a valid UUID") correlation_ids_found.append(corr_id_str)Based on coding guidelines requiring correlation IDs to be auto-generated with
uuid4()if missing.docker/migrations/MIGRATION_UPGRADE_003a_to_004.md (2)
169-177: Optional cleanup: Remove unused CTE.The
expected_stateCTE is defined but never referenced in the final query. This doesn't affect functionality but adds unnecessary code.♻️ Proposed cleanup
-WITH expected_state AS ( - SELECT * FROM (VALUES - -- (migration_id, description, validation_type, validation_target) - ('001', 'registration_projections table', 'table', 'registration_projections'), - ('002', 'updated_at audit index', 'index', 'idx_registration_projections_updated_at'), - ('003', 'capability columns', 'columns', 'contract_type,intent_types,protocols,capability_tags,contract_version'), - ('004', 'concurrent GIN indexes', 'indexes', 'idx_registration_capability_tags,idx_registration_intent_types,idx_registration_protocols,idx_registration_contract_type_state') - ) AS t(migration_id, description, validation_type, validation_target) -), -table_check AS ( +WITH table_check AS (
294-325: Document required environment variables.The validation script relies on environment variables (
POSTGRES_HOST,POSTGRES_PORT,POSTGRES_USER,POSTGRES_DATABASE) but doesn't document them. Users may not know these need to be set before running the script.📝 Proposed documentation addition
Add before line 294:
**Prerequisites:** Before running this script, ensure the following environment variables are set: ```bash export POSTGRES_HOST="your-db-host" export POSTGRES_PORT="5432" export POSTGRES_USER="your-db-user" export POSTGRES_DATABASE="your-db-name"Alternatively, set these in your CI/CD pipeline configuration.
</details> </blockquote></details> <details> <summary>docs/patterns/policy_registry_trust_model.md (1)</summary><blockquote> `135-158`: **Consider adding error code guidance to PolicyRegistryError documentation.** The documentation describes the error class constructor but doesn't mention how error codes should be passed or which error code enum values are appropriate for policy registry errors. Based on ONEX error handling patterns, the `**kwargs` parameter should support passing error codes. <details> <summary>📝 Suggested documentation enhancement</summary> Add a usage example showing error code usage: ```python from omnibase_infra.errors import ProtocolConfigurationError from omnibase_infra.enums import EnumInfraErrorCode # Or appropriate error code enum class PolicyRegistryError(ProtocolConfigurationError): """Raised when policy registration or execution fails. Extends ProtocolConfigurationError to integrate with ONEX error handling. Provides policy-specific context for debugging and monitoring. Args: message: Human-readable error description policy_id: Optional policy identifier for context **kwargs: Additional context (error_code, correlation_id, etc.) Example: raise PolicyRegistryError( "Policy 'rate_limiter' has not been reviewed", policy_id="rate_limiter", error_code=EnumInfraErrorCode.VALIDATION_FAILED, ) """ def __init__( self, message: str, policy_id: str | None = None, **kwargs: object, ) -> None: super().__init__(message, **kwargs) self.policy_id = policy_idBased on learnings, ONEX error handling must use error codes from error enums with OnexError base classes.
docs/patterns/handler_plugin_loader.md (4)
533-539: Consider improving the CI validation example.The grep pattern
grep -rE "(password|secret|key|token|credential).*:" contracts/will match YAML field names (likepassword:) rather than actual secret values, leading to false positives. While the specialized tools (gitleaks, trufflehog, detect-secrets) mentioned below are the recommended approach, the grep example could be improved or de-emphasized.🔍 Alternative approaches
Option 1: Improve the grep pattern to reduce false positives
# Look for suspicious patterns in values, not keys grep -rE ':\s*"[^"]{20,}"' contracts/ | grep -E "(password|secret|key|token)" && echo "FAIL: Potential secrets" && exit 1Option 2: De-emphasize grep, emphasize tools (preferred)
# Recommended: Use specialized secret detection tools # - gitleaks: Scan for hardcoded secrets # - trufflehog: Detect high-entropy strings # - detect-secrets: Pre-commit hook # Example with detect-secrets: detect-secrets scan contracts/ --baseline .secrets.baselineOption 3: Remove the grep example entirely
Simply reference the specialized tools without showing a potentially misleading grep command.
The specialized tools mentioned (gitleaks, trufflehog, detect-secrets) are more reliable for secret detection.
648-650: Remove unused imports from documentation example.The imports
ModelInfraErrorContextandEnumInfraTransportTypeare declared but never used in thesecure_load_from_contractexample. While this is documentation rather than production code, removing dead imports improves clarity.🧹 Proposed cleanup
-from omnibase_infra.errors import ProtocolConfigurationError, ModelInfraErrorContext -from omnibase_infra.enums import EnumInfraTransportType +from omnibase_infra.errors import ProtocolConfigurationError class SecurityValidationError(ProtocolConfigurationError):
652-657: Consider adding error code support to SecurityValidationError documentation.Similar to
PolicyRegistryError, theSecurityValidationErrorclass should document how to use error codes following ONEX error handling patterns. The current implementation shows only a pass-through class without demonstrating error code usage.📝 Suggested documentation enhancement
from omnibase_infra.errors import ProtocolConfigurationError from omnibase_infra.enums import EnumInfraErrorCode # Or appropriate error code enum class SecurityValidationError(ProtocolConfigurationError): """Raised when security validation fails. Extends ProtocolConfigurationError to integrate with ONEX error handling. Args: message: Human-readable error description **kwargs: Additional context (error_code, correlation_id, etc.) Example: raise SecurityValidationError( "Handler module path not in allowlist", error_code=EnumInfraErrorCode.NAMESPACE_NOT_ALLOWED, correlation_id=correlation_id, ) """ passThen update line 689 to include an error code when raising the exception.
Based on learnings, all error handling must use error codes from error enums with OnexError base classes.
688-692: Add error code when raising SecurityValidationError.The exception is raised without an error code, which doesn't follow ONEX error handling patterns. According to the error codes table (line 845),
NAMESPACE_NOT_ALLOWED(HANDLER_LOADER_013) is the appropriate error code for this scenario.🔧 Proposed fix
+from omnibase_infra.enums import EnumHandlerLoaderErrorCode # Or appropriate error code enum + # Check against allowlist if not any(handler_class.startswith(prefix) for prefix in ALLOWED_MODULE_PREFIXES): raise SecurityValidationError( f"Handler module path '{handler_class}' not in allowlist. " f"Allowed prefixes: {ALLOWED_MODULE_PREFIXES}", + error_code=EnumHandlerLoaderErrorCode.NAMESPACE_NOT_ALLOWED, + correlation_id=correlation_id, )Based on learnings, use error codes with ModelOnexError and never raise exceptions without specific error codes.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Lite
📒 Files selected for processing (17)
.env.exampledocker/docker-compose.e2e.ymldocker/migrations/MIGRATION_UPGRADE_003a_to_004.mddocker/migrations/README.mddocs/patterns/handler_plugin_loader.mddocs/patterns/policy_registry_trust_model.mddocs/patterns/retry_backoff_compensation_strategy.mdsrc/omnibase_infra/nodes/node_registry_effect/handlers/handler_consul_deregister.pysrc/omnibase_infra/nodes/node_registry_effect/handlers/handler_consul_register.pysrc/omnibase_infra/nodes/node_registry_effect/handlers/handler_partial_retry.pysrc/omnibase_infra/nodes/node_registry_effect/handlers/handler_postgres_deactivate.pysrc/omnibase_infra/nodes/node_registry_effect/handlers/handler_postgres_upsert.pytests/integration/handlers/test_mcp_handler_integration.pytests/integration/registration/e2e/conftest.pytests/unit/runtime/test_handler_discovery.pytests/unit/runtime/test_lru_cache_eviction_stress.pytests/unit/runtime/test_runtime_host_architecture_validation.py
✅ Files skipped from review due to trivial changes (3)
- src/omnibase_infra/nodes/node_registry_effect/handlers/handler_consul_deregister.py
- src/omnibase_infra/nodes/node_registry_effect/handlers/handler_partial_retry.py
- src/omnibase_infra/nodes/node_registry_effect/handlers/handler_consul_register.py
🚧 Files skipped from review as they are similar to previous changes (3)
- docker/docker-compose.e2e.yml
- tests/unit/runtime/test_runtime_host_architecture_validation.py
- .env.example
🧰 Additional context used
📓 Path-based instructions (2)
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Never useAnytype - useobjectfor generic payloads in function parameters and return types
UseX | None(PEP 604) instead ofOptional[X]for nullable types
All services must useModelONEXContainerfor dependency injection via__init__(self, container: ModelONEXContainer)
Use@allow_anydecorator with documented reason as exemption mechanism forAnytype violations
UseJsonTypefromomnibase_core.typesas the canonical type alias for JSON-compatible values
UseModelEventEnvelope[object]for generic dispatcher interfaces andobjectfor generic payloads
Infrastructure error handling must useOnexErrorbase class and never expose passwords, API keys, PII, or connection strings with credentials in error messages
UseInfraConnectionError,InfraTimeoutError,InfraAuthenticationError,InfraUnavailableErrorfor transport failures with properModelInfraErrorContext
Correlation IDs must be propagated from incoming requests, auto-generated withuuid4()if missing, and included in all error contexts
External service adapters must implementMixinAsyncCircuitBreakerwith appropriate threshold and reset_timeout configuration
Protocol resolution must use duck typing via protocols, never useisinstancechecks
Files:
src/omnibase_infra/nodes/node_registry_effect/handlers/handler_postgres_deactivate.pysrc/omnibase_infra/nodes/node_registry_effect/handlers/handler_postgres_upsert.pytests/unit/runtime/test_lru_cache_eviction_stress.pytests/unit/runtime/test_handler_discovery.pytests/integration/handlers/test_mcp_handler_integration.pytests/integration/registration/e2e/conftest.py
**/handler_*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Handlers must NOT have direct event bus access - only orchestrators may have bus parameters and publish events
Files:
src/omnibase_infra/nodes/node_registry_effect/handlers/handler_postgres_deactivate.pysrc/omnibase_infra/nodes/node_registry_effect/handlers/handler_postgres_upsert.py
🧠 Learnings (46)
📓 Common learnings
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/handler_contract.yaml : Handler contract files must declare handler routing with `routing_strategy`, event models, handler classes, and handler modules
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/handler_contract.yaml : Handlers must be discovered and loaded dynamically via YAML contracts using plugin pattern, not hardcoded registries
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contracts/contract_*.yaml : All ONEX node contract definitions must use the new subcontract architecture pattern, breaking down complex contracts into separate contract_actions.yaml, contract_models.yaml, contract_validation.yaml, and optional contract_cli.yaml and contract_capabilities.yaml files for separation of concerns, maintainability, reusability, modularity, and future tool-as-a-service readiness
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: When both `handler_contract.yaml` and `contract.yaml` exist in the same directory, the loader must raise an error (AMBIGUOUS_CONTRACT_CONFIGURATION)
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contracts/contract_*.yaml : All ONEX node subcontracts must be organized in a `contracts/` subdirectory within the versioned implementation directory with separate files for contract_actions.yaml, contract_models.yaml, contract_validation.yaml, contract_cli.yaml (optional), and contract_capabilities.yaml (optional)
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-24T17:22:32.195Z
Learning: Applies to **/v[0-9]_[0-9]_[0-9]/contracts/ : Organize contract subcomponents into separate files (contract_actions.yaml, contract_models.yaml, contract_validation.yaml, etc.) and reference them from main contract.yaml
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T16:32:55.606Z
Learning: Applies to **/*contract*.yaml : All ONEX nodes must have validated YAML contracts following the contract-driven development pattern with input_state and output_state schema definitions
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/models/model_contract_*.py : All ONEX node auto-generated Pydantic models must be organized in a `models/` directory with files for state.py, model_contract_actions.py, model_contract_models.py, model_contract_validation.py, model_contract_cli.py (optional), model_contract_capabilities.py (optional), and error_codes.py, generated from the corresponding contract definitions
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to src/omninode_bridge/nodes/**/contract.yaml : All contract YAML files for ONEX v2.0 nodes MUST define subcontract references, input/output models, and FSM configurations. Use YAML 1.2 syntax.
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T16:21:16.950Z
Learning: Applies to src/omnibase_core/runtime/runtime_*.py : Use FileRegistry to load runtime contracts from YAML configuration files.
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/*.py : Infrastructure error handling must use `OnexError` base class and never expose passwords, API keys, PII, or connection strings with credentials in error messages
Applied to files:
docs/patterns/policy_registry_trust_model.mddocs/patterns/handler_plugin_loader.md
📚 Learning: 2025-11-24T17:22:32.195Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-24T17:22:32.195Z
Learning: Applies to **/*.py : All error handling must use OnexError exception class with specific error codes from error enum, never raise generic Exception or ValueError
Applied to files:
docs/patterns/policy_registry_trust_model.mddocs/patterns/handler_plugin_loader.md
📚 Learning: 2025-11-24T17:22:32.195Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-24T17:22:32.195Z
Learning: Applies to **/v[0-9]_[0-9]_[0-9]/registry/registry_*.py : Registry classes must inherit from BaseOnexRegistry and define CANONICAL_TOOLS dictionary with default tool implementations
Applied to files:
docs/patterns/policy_registry_trust_model.md
📚 Learning: 2025-11-24T17:22:32.195Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-24T17:22:32.195Z
Learning: Applies to **/v[0-9]_[0-9]_[0-9]/{tools,registry}/**.py : Constructor-based dependency injection must be used for all tool and node classes; validate that required dependencies are not None, raising OnexError with specific error code if missing
Applied to files:
docs/patterns/policy_registry_trust_model.md
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/models/error_codes.py : All ONEX node error handling must use auto-generated error codes defined in `models/error_codes.py` from contract definitions
Applied to files:
docs/patterns/policy_registry_trust_model.md
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/*.py : All ONEX node implementations must follow dependency injection and protocol-first design patterns as established in the node_cli canonical reference
Applied to files:
docs/patterns/policy_registry_trust_model.md
📚 Learning: 2025-11-24T16:33:51.604Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T16:33:51.604Z
Learning: All Python code must have comprehensive test coverage following ONEX Core testing patterns with tests organized by domain, using proper fixtures, and achieving high coverage while maintaining code quality
Applied to files:
docs/patterns/policy_registry_trust_model.md
📚 Learning: 2025-12-06T22:21:32.649Z
Learnt from: CR
Repo: OmniNode-ai/omniagent PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T22:21:32.649Z
Learning: Applies to nodes/effect/**/*.py : Use `DbAdapter` envelope pattern for database operations instead of custom PostgreSQL clients
Applied to files:
src/omnibase_infra/nodes/node_registry_effect/handlers/handler_postgres_deactivate.py
📚 Learning: 2025-11-24T16:31:48.648Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/checklist_rule.md:0-0
Timestamp: 2025-11-24T16:31:48.648Z
Learning: Document migration requirements when upgrading from Checklist Rule v3 to v4: add dependencies, blockers, relationships, and work_context sections to existing tickets
Applied to files:
docker/migrations/MIGRATION_UPGRADE_003a_to_004.mddocker/migrations/README.md
📚 Learning: 2025-11-24T17:24:54.193Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T17:24:54.193Z
Learning: Applies to **/scenario_*.yaml : Modify only necessary fields in cloned scenarios: scenario_name, description, node, input test data, and expect messages - preserve version and registry_tools
Applied to files:
docker/migrations/MIGRATION_UPGRADE_003a_to_004.md
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to migrations/*.sql : Database migrations in migrations/*.sql MUST be applied in order. Critical migration: 005-node_registrations.sql. Always backup before migrations in production.
Applied to files:
docker/migrations/MIGRATION_UPGRADE_003a_to_004.mddocker/migrations/README.md
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: All PostgreSQL migrations MUST be applied before starting services. Migration 005 (node_registrations table) is CRITICAL - verify it exists before deployment
Applied to files:
docker/migrations/MIGRATION_UPGRADE_003a_to_004.mddocker/migrations/README.md
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/handler_contract.yaml : Handlers must be discovered and loaded dynamically via YAML contracts using plugin pattern, not hardcoded registries
Applied to files:
docs/patterns/handler_plugin_loader.mdtests/unit/runtime/test_handler_discovery.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: When both `handler_contract.yaml` and `contract.yaml` exist in the same directory, the loader must raise an error (AMBIGUOUS_CONTRACT_CONFIGURATION)
Applied to files:
docs/patterns/handler_plugin_loader.md
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/handler_contract.yaml : Handler contract files must declare handler routing with `routing_strategy`, event models, handler classes, and handler modules
Applied to files:
docs/patterns/handler_plugin_loader.mdtests/unit/runtime/test_handler_discovery.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/*.py : Use `InfraConnectionError`, `InfraTimeoutError`, `InfraAuthenticationError`, `InfraUnavailableError` for transport failures with proper `ModelInfraErrorContext`
Applied to files:
docs/patterns/handler_plugin_loader.mddocs/patterns/retry_backoff_compensation_strategy.md
📚 Learning: 2026-01-13T16:21:16.950Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T16:21:16.950Z
Learning: Applies to src/omnibase_core/**/*.py : Always use ModelOnexError with error codes instead of generic Exception.
Applied to files:
docs/patterns/handler_plugin_loader.md
📚 Learning: 2025-11-28T18:58:53.781Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-28T18:58:53.781Z
Learning: Applies to **/*.py : Use `EnumCoreErrorCode` with `ModelOnexError` for proper error code usage
Applied to files:
docs/patterns/handler_plugin_loader.md
📚 Learning: 2025-11-24T17:24:41.687Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T17:24:41.687Z
Learning: Applies to **/models/model_contract_*.py : Contract-backed model files must follow the naming pattern `model_contract_<domain>.py` and be located in `*/models/` directories
Applied to files:
docs/patterns/handler_plugin_loader.md
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contracts/contract_*.yaml : All ONEX node contract definitions must use the new subcontract architecture pattern, breaking down complex contracts into separate contract_actions.yaml, contract_models.yaml, contract_validation.yaml, and optional contract_cli.yaml and contract_capabilities.yaml files for separation of concerns, maintainability, reusability, modularity, and future tool-as-a-service readiness
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/contract.yaml : Contract files must use semantic versioning with `contract_version` and `node_version` fields, specify node type (EFFECT/COMPUTE/REDUCER/ORCHESTRATOR), and strongly type all I/O with `input_model` and `output_model`
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2025-11-24T16:32:55.606Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T16:32:55.606Z
Learning: Applies to **/*contract*.yaml : All ONEX nodes must have validated YAML contracts following the contract-driven development pattern with input_state and output_state schema definitions
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2025-12-07T17:50:13.678Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T17:50:13.678Z
Learning: Applies to **/contracts/*.yaml : Validate contracts using the contract linter tool: python -m omniintelligence.tools.contract_linter for YAML contract definitions
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2025-11-24T17:24:41.687Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T17:24:41.687Z
Learning: Applies to **/contracts/contract_*.yaml : Subcontract files must follow the naming pattern `contract_<domain>.yaml` and be located in `*/contracts/` directories
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2025-11-24T17:24:41.687Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T17:24:41.687Z
Learning: Applies to **/contracts/contract_{actions,models,validation,cli,capabilities}.yaml : Subcontract files must be organized with naming convention: `contract_actions.yaml`, `contract_models.yaml`, `contract_validation.yaml`, `contract_cli.yaml`, `contract_capabilities.yaml`
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to src/omninode_bridge/nodes/**/contract.yaml : All contract YAML files for ONEX v2.0 nodes MUST define subcontract references, input/output models, and FSM configurations. Use YAML 1.2 syntax.
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2025-12-03T16:55:49.755Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-03T16:55:49.755Z
Learning: Applies to agents/**/*.py : Use correlation_id UUID for end-to-end traceability across all agent routing, manifest injection, and execution events
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2025-12-03T16:55:49.755Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-03T16:55:49.755Z
Learning: Applies to agents/**/*.py : Implement agent observability using three-layer traceability with correlation_id tracking through agent_routing_decisions, agent_manifest_injections, and agent_execution_logs tables
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2025-11-29T17:13:38.776Z
Learnt from: CR
Repo: OmniNode-ai/omniarchon PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T17:13:38.776Z
Learning: Applies to {services/**/*.py,scripts/**/*.py} : Use correlation IDs for distributed logging across services. Implement log tracing with `python3 scripts/view_pipeline_logs.py --correlation-id X`.
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/*.py : Correlation IDs must be propagated from incoming requests, auto-generated with `uuid4()` if missing, and included in all error contexts
Applied to files:
tests/unit/runtime/test_handler_discovery.py
📚 Learning: 2025-12-07T17:50:13.678Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T17:50:13.678Z
Learning: Organize tests following the structure: tests/conftest.py for shared fixtures, tests/unit/ for unit tests (no infrastructure), tests/integration/ for integration tests (requires Kafka/DBs), tests/nodes/ for node-specific tests
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-12-03T16:55:49.755Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-03T16:55:49.755Z
Learning: Applies to **/*.py : Publish intelligence requests to Kafka event bus using topics: dev.archon-intelligence.intelligence.code-analysis-{requested,completed,failed}.v1 for consistency and event-driven architecture
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-12-06T22:21:32.649Z
Learnt from: CR
Repo: OmniNode-ai/omniagent PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T22:21:32.649Z
Learning: Applies to nodes/**/*.py : Use event bus mixins from `omnibase_core` for Kafka publishing instead of direct Kafka clients
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-12-07T17:50:13.678Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T17:50:13.678Z
Learning: Implement Kafka event-driven architecture with proper topic naming using prefix dev.archon-intelligence. and proper event flow pattern with Effect nodes consuming events, processing, and publishing results with Dead Letter Queue routing
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Node Introspection Security - use Python reflection for service discovery, but prefix internal/sensitive methods with `_`, use generic parameter names, and configure Kafka topic ACLs for introspection topics
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to src/omninode_bridge/events/**/*.py : Kafka event publishing MUST use OnexEnvelopeV1 format with 13 topics for event streaming at all workflow lifecycle stages
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-24T17:22:32.195Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-24T17:22:32.195Z
Learning: Follow canonical patterns from reference implementations: use node_cli/v1_0_0/ as primary reference and node_kafka_event_bus/v1_0_0/ for complex backend patterns
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: All ONEX nodes must use the node_kafka_event_bus as a secondary reference only for complex backend and event bus logic and advanced configuration patterns
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-12-19T02:58:44.081Z
Learnt from: sudharsanv177
Repo: OmniNode-ai/omninode_infra PR: 4
File: docker/onex-api/main.py:0-0
Timestamp: 2025-12-19T02:58:44.081Z
Learning: In the omninode_infra repository, production configuration is managed via Kubernetes Secrets and ConfigMaps injected as environment variables, not committed .env files or Pydantic Settings. The deployment model uses os.getenv() with sensible defaults for local development, and explicit resolution patterns (e.g., checking POSTGRES_DSN first, then deriving from component variables) are preferred over mutating os.environ.
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-29T22:07:25.230Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: migration_sources/omniarchon/CLAUDE.md:0-0
Timestamp: 2025-11-29T22:07:25.230Z
Learning: Applies to migration_sources/omniarchon/**/tests/**/*.py : All integration tests must verify correct Kafka port usage for context (9092 for Docker, 29092 for host). Test both local (qdrant, memgraph) and remote (PostgreSQL, Redpanda) database connectivity. Never assume test environment configuration.
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-29T22:07:25.230Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: migration_sources/omniarchon/CLAUDE.md:0-0
Timestamp: 2025-11-29T22:07:25.230Z
Learning: Applies to migration_sources/omniarchon/**/*.py : Always use REMOTE Redpanda at 192.168.86.200 for event bus. NEVER start local Redpanda. Remote Redpanda enables OmniNode integration, data consistency, and production parity. Use correct ports: 9092 (Docker) or 29092 (host scripts).
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to src/**/{config,settings,kafka,events}/**/*.py : Kafka Bootstrap Servers configuration depends on context: Docker services use 'omninode-bridge-redpanda:9092' (internal), host scripts use '192.168.86.200:29092' (external). Verify correct bootstrap server for your context.
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-24T16:32:55.606Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T16:32:55.606Z
Learning: Node implementations must use mixin-based composition from `omnibase_core.mixins` (e.g., `MixinHealthCheck`, `MixinNodeExecutor`) to add capabilities
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/introspection.py : All ONEX nodes must include an `introspection.py` file implementing standards-compliant introspection logic
Applied to files:
tests/integration/registration/e2e/conftest.py
📚 Learning: 2025-11-24T16:33:51.604Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T16:33:51.604Z
Learning: Applies to tests/**/conftest.py : Test fixtures must be defined in `conftest.py` and should provide reusable sample data, UUIDs, semantic versions, and model data
Applied to files:
tests/integration/registration/e2e/conftest.py
🧬 Code graph analysis (1)
tests/integration/registration/e2e/conftest.py (2)
tests/integration/event_bus/conftest.py (1)
wait_for_consumer_ready(53-125)src/omnibase_infra/projectors/snapshot_publisher_registration.py (1)
topic(270-272)
🔇 Additional comments (26)
tests/integration/handlers/test_mcp_handler_integration.py (1)
54-57: LGTM! Clean approach for checking module availability.Using
importlib.util.find_spec()is the idiomatic way to check if a module is installed without triggering its import side effects. This is preferable to try/except ImportError for availability checks in test collection.tests/unit/runtime/test_lru_cache_eviction_stress.py (1)
534-535: LGTM!Good cleanup using underscore prefix for intentionally unused loop variables (
_hits,_misses). This follows Python convention and silences linter warnings while clearly communicating intent to readers.src/omnibase_infra/nodes/node_registry_effect/handlers/handler_postgres_deactivate.py (1)
75-75: LGTM!The docstring example correctly reflects the updated
ModelBackendResultAPI withbackend_id="postgres". This aligns with the broader PR changes introducingbackend_idon result models.src/omnibase_infra/nodes/node_registry_effect/handlers/handler_postgres_upsert.py (1)
67-67: LGTM!The docstring example correctly reflects the updated
ModelBackendResultAPI withbackend_id="postgres", consistent with the deactivate handler and the broader PR changes.docs/patterns/retry_backoff_compensation_strategy.md (3)
429-432: LGTM! Correct imports for ONEX error handling integration.The new imports properly integrate with the ONEX error handling patterns, enabling transport-aware error context propagation in saga compensation flows.
442-461: LGTM! Proper integration with ONEX error handling patterns.The base class change from
ExceptiontoRuntimeHostErrorand the addition of the optionalcontextparameter correctly alignCompensationFailedErrorwith the infrastructure error handling patterns. The context propagation enables better observability and error tracking for saga compensation failures.
525-535: LGTM! Proper error context construction and propagation.The error context is correctly built with the configured transport type, operation name, and correlation ID, then properly passed to
CompensationFailedError. This enables full observability into saga compensation failures.tests/integration/registration/e2e/conftest.py (5)
230-253: LGTM!Clean helper that correctly wraps introspection events in envelopes with proper correlation ID propagation and UTC timestamps.
523-541: LGTM! Well-reasoned configuration change.Disabling auto-commit for test isolation is the right approach. The detailed comment explaining the three failure modes (lost messages, rebalance timing, cross-test pollution) is excellent documentation for future maintainers.
1304-1338: LGTM!Session-scoped logging configuration with proper handler deduplication check. The INFO level for
omnibase_infrais a good choice to reduce noise while keeping DEBUG available for test diagnostics.
665-682: LGTM!Clean composition pattern that provides a ready-to-use topic with UUID suffix for test isolation.
1345-1390: LGTM!Exports are well-organized by category and include all new public API surfaces.
tests/unit/runtime/test_handler_discovery.py (9)
1-44: LGTM!Well-structured module header with comprehensive docstring explaining test coverage scope and related modules. Imports are clean and organized.
45-136: LGTM!Good set of contract templates covering valid cases and various failure modes (invalid YAML syntax, missing required fields, non-existent modules/classes, empty files). This aligns with the learning that handler contracts must declare handler routing with handler classes.
138-176: LGTM!Well-designed fixtures with proper isolation using
tmp_path. Theisolated_handler_registryfixture ensures test independence by returning a freshProtocolBindingRegistryinstance rather than the singleton.
340-379: LGTM!Good use of method patching to verify
_discover_handlers_from_contractsis called duringstart(). Thetype: ignore[method-assign]comment appropriately suppresses the type checker warning for the monkey-patch.
510-554: LGTM!Thorough negative test that verifies both the exception type and log messages. The broad log assertion checking for "invalid", "yaml", or "error" is appropriate since different parsing failures may produce different messages.
1025-1136: LGTM!Good approach to testing logging behavior using keyword matching with
lower()for case-insensitivity. This makes the tests resilient to minor log message changes while still verifying the observability requirements.
1159-1204: LGTM!Good direct unit testing of
_discover_handlers_from_contracts()method, verifying the internalContractHandlerDiscoveryservice creation and result caching. The tests appropriately access private attributes since this is testing internal implementation.
1553-1601: LGTM!Excellent test verifying resilience - when one path fails (non-existent), subsequent paths are still processed. This ensures partial failures don't cause complete discovery failure.
1651-1700: LGTM!Good use of
pytest.mark.skipiffor symlink tests that require elevated privileges on Windows. The tests properly verify that discovery follows symlinks to both directories and files.docker/migrations/README.md (2)
12-17: Excellent documentation clarity on migration numbering conventions.The updated guidance clearly distinguishes between when to use sub-sequences (rollback/optional) versus main sequences (production-recommended variants). The historical note about 003a→004 provides helpful context, and the recommendation to use main sequence numbers for production variants aligns with best practices.
Also applies to: 37-49, 86-106
183-210: Well-structured validation and upgrade guidance.The new sections provide clear instructions for operators to validate migration state and understand the 003a→004 renaming. The cross-reference to detailed upgrade scenarios is helpful.
docker/migrations/MIGRATION_UPGRADE_003a_to_004.md (1)
368-374: No action needed. The filevalidate_migration_state.sqlalready exists in the repository atdocker/migrations/validate_migration_state.sql. The cross-reference at line 370 is valid and the file is correctly included. The inline SQL at lines 163-241 serves as documentation within the migration guide and does not need to be extracted.Likely an incorrect or invalid review comment.
docs/patterns/handler_plugin_loader.md (2)
271-290: LGTM! Excellent security reference design.The threat table provides clear categorization of security controls with actionable deployment guidance. The distinction between "MITIGATED" (built-in) and "OPTIONALLY MITIGATED" (requires configuration) is well-documented and helps users make informed security decisions.
427-469: Documentation snippet is accurate — no changes needed.The implementation snippet shown in the documentation (lines 427-469) matches the actual
_validate_namespace()method insrc/omnibase_infra/runtime/handler_plugin_loader.py. The core logic for package boundary validation is correctly documented, and the explanation of how namespace allowlisting prevents path traversal attacks is sound.
Documentation fixes: - Update error conventions in security_patterns.md, handler_plugin_loader.md - Add error codes to PolicyRegistryError and SecurityValidationError docs - Fix transport type in retry_backoff_compensation_strategy.md - Clarify migration README examples and UPGRADE_003a_to_004.md scenarios - Fix ADR-005 date inconsistency (2025→2026) Test improvements: - Fix describe_topics dict response handling in conftest.py - Update contract template field names in test_handler_discovery.py - Strengthen correlation ID test assertion - Add backend_id to ModelBackendResult instantiations - Narrow exception handling (Exception→TopicAlreadyExistsError) - Create shared tests/helpers/kafka_utils.py to eliminate duplication Code cleanup: - Fix no-op len() statement in handler_mock_registration_storage.py - Import shared wait_for_consumer_ready from tests.helpers
PR #143 Review: Infrastructure Integration with Handler ContractsExecutive SummaryThis is a substantial and well-executed PR that introduces plugin-based handler discovery, critical runtime fail-fast validation, and comprehensive E2E test improvements. The implementation demonstrates strong architectural discipline with extensive documentation, security considerations, and test coverage. Recommendation: APPROVE with minor observations 🎯 Strengths1. Excellent Security Documentation
2. Robust Fail-Fast BehaviorThe runtime now fails immediately when no handlers are registered (runtime_host_process.py:718-738): if not self._handlers:
raise ProtocolConfigurationError(
"No handlers registered. The runtime cannot start..."
)This prevents silent failures and provides detailed troubleshooting steps in the error message. 3. Strong Type Safety
4. Comprehensive Test Coverage
5. Migration Documentation Excellence
6. Backward Compatibility HandlingEnvironment variable migration with deprecation warning: # ONEX_CONTRACTS_DIR (preferred) with fallback to CONTRACTS_DIR (deprecated)
# Logs warning when legacy variable usedDeprecation timeline: v2.0.0 (documented in .env.example) 🔍 Code Quality Observations1. Protocol Type Registry Key (Fixed in commit 35efb37)Good catch switching from
2. Pydantic Serialization Fix (mixin_node_introspection.py)Proper enum serialization using # Before: reason_enum (would serialize as enum object)
# After: reason_enum.value (serializes as string)This prevents Pydantic serialization issues with nested enum fields. 3. E2E Test Reliability ImprovementsMajor improvements to test determinism:
4. Error Context EnhancementAll infrastructure errors include correlation IDs and structured context: context = ModelInfraErrorContext(
transport_type=EnumInfraTransportType.RUNTIME,
operation="validate_handlers",
target_name="runtime_host_process",
correlation_id=correlation_id,
)🐛 Potential Issues (None Critical)1. Handler Contract Ambiguity Detection (Fixed)The loader raises Status: ✅ Implemented correctly with clear error message 2. Windows Symlink Test Compatibility (Fixed)Added @pytest.mark.skipif(sys.platform == "win32", reason="Symlinks require admin on Windows")Status: ✅ Resolved in commit b581bf2 3. Empty Derived Protocol Type Guard (Fixed)Edge case where if not derived:
raise ValueError(
f"Cannot derive protocol_type from handler_name..."
)Status: ✅ Guard added in model_handler_contract.py:246-252 📊 Performance ConsiderationsPositive Impacts:
No Concerns:
🔒 Security AssessmentBuilt-in Mitigations (All Present):
Optional Hardening (Documented):
Security Documentation Quality:The ADR explicitly states: "YAML contracts are treated as executable code, not mere configuration" - this is excellent transparency for operators. 📝 Documentation QualityExceptional:
Examples from Code:# Step 4.1: FAIL-FAST validation - runtime MUST have at least one handler
# A runtime with no handlers cannot process any events and is misconfigured.
# This catches configuration issues early rather than silently starting a
# runtime that cannot do anything useful.Clear, actionable comments that explain why, not just what. 🧪 Test Coverage AssessmentUnit Tests:
Integration Tests:
E2E Improvements:
🎨 Adherence to CLAUDE.md✅ Excellent Compliance:
📁 File Naming Conventions:
|
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
tests/integration/registration/e2e/test_full_orchestrator_flow.py (1)
1417-1419: Fix node_type assertion to compare against enum value, not string literal.Line 1419 compares
projection.node_type(anEnumNodeKindenum) against the string"effect". Sincecoerce_to_node_kindreturnsEnumNodeKindandModelRegistrationProjection.node_typeis typed asEnumNodeKind, the assertion will fail. Change toassert projection.node_type == EnumNodeKind.EFFECT.docs/patterns/policy_registry_trust_model.md (1)
188-485: Critical issue: PolicyRegistryError does not accept error_code parameter.The code examples in this section pass
error_code="POLICY_REG_006"through"POLICY_REG_010"toPolicyRegistryError, but the class signature only acceptsmessage,policy_id,policy_type,context, and**extra_context. Theerror_codeparameter does not exist and will causeTypeErrorat runtime. Remove allerror_codearguments fromPolicyRegistryErrorcalls.Additionally, for the
execute_policy_safelyfunction (lines 462-478), useInfraTimeoutErrorinstead ofPolicyRegistryErrorwhen handlingasyncio.TimeoutError, as timeout scenarios are transport/infrastructure failures that should use the specialized error type per error handling guidelines.docs/patterns/handler_plugin_loader.md (1)
681-738: Wrapper function demonstrates custom validation pattern, but has error code inconsistency.The updated docstring (lines 688-699) clearly explains when to use this wrapper pattern versus the built-in
allowed_namespacesparameter. The error context construction is proper.However:
Hardcoded error code (line 731): Using
error_code="SECURITY_001"instead of referencing the enum value fromEnumHandlerLoaderError.NAMESPACE_NOT_ALLOWEDcreates inconsistency and bypasses type safety.Import placement (lines 712-713): Importing
uuid4inside the function is unconventional. While acceptable for documentation examples, consider moving to module-level imports for consistency with Python conventions.Suggested fix for error code usage
+from omnibase_infra.enums import EnumHandlerLoaderError + def secure_load_from_contract( loader: HandlerPluginLoader, path: Path, correlation_id: UUID | None = None, ) -> ModelLoadedHandler: + from uuid import uuid4 + # Pre-validate module path before loader processes it with open(path) as f: contract_data = yaml.safe_load(f) handler_class = contract_data.get("handler_class", "") # Check against allowlist if not any(handler_class.startswith(prefix) for prefix in ALLOWED_MODULE_PREFIXES): - from uuid import uuid4 - context = ModelInfraErrorContext( transport_type=EnumInfraTransportType.RUNTIME, operation="validate_handler_namespace", correlation_id=correlation_id or uuid4(), ) raise SecurityValidationError( f"Handler module path not in allowlist. " f"Allowed prefixes: {ALLOWED_MODULE_PREFIXES}", - error_code="SECURITY_001", + error_code=EnumHandlerLoaderError.NAMESPACE_NOT_ALLOWED.value, context=context, handler_class=handler_class, )
🤖 Fix all issues with AI agents
In @docs/patterns/handler_plugin_loader.md:
- Around line 648-678: The example SecurityValidationError uses non-existent
hardcoded error codes; update usages to reference the EnumHandlerLoaderError
enum (e.g., replace the hardcoded "SECURITY_001" with
EnumHandlerLoaderError.NAMESPACE_NOT_ALLOWED.value) in the
SecurityValidationError construction/annotations and anywhere else that mentions
those strings, and for the policy-rejection case replace with the appropriate
EnumHandlerLoaderError value if one exists or document it as future
functionality if no matching enum member is present.
In @docs/patterns/policy_registry_trust_model.md:
- Around line 150-156: Docstring currently lists POLICY_REG_001–POLICY_REG_005
but omits POLICY_REG_006–POLICY_REG_010 that are referenced later; update the
docstring block listing "Error Codes" to include entries for POLICY_REG_006
(Code review not approved), POLICY_REG_007 (Static analysis failed),
POLICY_REG_008 (Not in allowlist), POLICY_REG_009 (Timeout exceeded), and
POLICY_REG_010 (Memory exceeded) so the examples referencing those codes match
the documented set.
In @docs/patterns/security_patterns.md:
- Around line 589-601: AuthorizationContext is missing the correlation_id field
so getattr(ctx, 'correlation_id', None) in the authorization decorator always
yields None; add a correlation_id attribute to the AuthorizationContext model
(with appropriate type, optional/default) and update any model
constructor/validation (e.g., AuthorizationContext __init__ or
Pydantic/BaseModel fields) so instances carry correlation_id, then you can
remove the runtime fallback or keep getattr(ctx, 'correlation_id', None) knowing
it will be populated; reference AuthorizationContext, correlation_id, and the
decorator code that reads getattr(ctx, 'correlation_id', None).
In @tests/integration/registration/e2e/test_full_orchestrator_flow.py:
- Around line 1277-1285: Update the malformed TODO comment in the test around
the await asyncio.sleep(1.0) call: replace the placeholder TODO(OMN-XXX) with
TODO(OMN-TBD) and add a leading “[NEEDS TICKET]” marker on the first line of
that multi-line comment so the comment reads as a searchable TODO with the
temporary ticket format; leave the rest of the explanatory text intact.
🧹 Nitpick comments (10)
tests/unit/validation/test_exemption_patterns.py (1)
29-35: Identity check for type annotations is acceptable but fragile.Using
is stris more idiomatic than== strfor type identity since built-in types are singletons. However, this relies on annotations being evaluated types rather than string forward references (PEP 563).If
from __future__ import annotationsis added to the module definingExemptionPattern, these assertions would fail becauseannotations["file_pattern"]would be the string"str"instead of the typestr.For a more robust approach, consider using
typing.get_type_hints():import typing hints = typing.get_type_hints(ExemptionPattern) assert hints["file_pattern"] is strThat said, if the tests currently pass and the codebase doesn't use deferred annotation evaluation for this TypedDict, the current approach is fine.
tests/unit/nodes/node_registration_orchestrator/models/test_registry_intent.py (1)
305-331: Inconsistent assertion style for type annotations.Lines 309 and 315 use identity comparison (
is) forstrannotations, while lines 323 and 331 use equality comparison (==) forUUIDannotations. Both work correctly for type objects, but the inconsistency reduces readability.Consider using the same comparison style throughout:
♻️ Suggested consistency fix
def test_has_required_node_id_field(self) -> None: """Base model defines required node_id field.""" from uuid import UUID fields = ModelRegistryIntent.model_fields assert "node_id" in fields - assert fields["node_id"].annotation == UUID + assert fields["node_id"].annotation is UUID def test_has_required_correlation_id_field(self) -> None: """Base model defines required correlation_id field.""" from uuid import UUID fields = ModelRegistryIntent.model_fields assert "correlation_id" in fields - assert fields["correlation_id"].annotation == UUID + assert fields["correlation_id"].annotation is UUIDtests/unit/runtime/test_handler_discovery.py (2)
524-524: Consider moving import to module level.The
ProtocolConfigurationErroris imported inside each test method. While this works, moving it to the module-level imports would be more idiomatic and reduce duplication. The import appears 7 times across different test methods.♻️ Suggested refactor
Add to the imports section at the top of the file:
from omnibase_infra.errors import ProtocolConfigurationErrorThen remove the local imports from lines 524, 569, 606, 643, 673, 706, 760, 828, and 1105.
749-781: Minor test overlap noted.This test (
test_empty_directory_raises_configuration_error) is nearly identical totest_empty_contract_directory_raises_configuration_errorin theTestInvalidContractYamlHandlingclass (lines 663-693). While having tests in different logical groupings can be acceptable, consider if consolidating would reduce maintenance burden.docker/migrations/MIGRATION_UPGRADE_003a_to_004.md (2)
40-58: Clarify whether migration 004 is valid for fresh production deployments.Scenario 1 states that migration 003 is "sufficient for ALL fresh deployments (dev, staging, and production)," but doesn't explicitly address whether using 004 directly on a fresh production database is supported or discouraged.
Consider adding guidance such as:
- "For fresh production deployments, use 003 (sufficient and faster)"
- "Migration 004 is only needed when upgrading existing databases with data"
This would prevent operators from unnecessarily using the slower concurrent variant on empty tables.
294-325: Add error handling for database connection failures.The validation script doesn't check if the
psqlcommand succeeds before processing results. If the database connection fails,resultwill be empty, causingmissing_countto be treated as 0, and the script will incorrectly report "All migrations applied successfully."Recommended fix
#!/bin/bash # validate_migrations.sh - Exit 0 if all migrations applied, non-zero otherwise +set -e # Exit on any error +set -u # Exit on undefined variables +set -o pipefail # Catch errors in pipes + result=$(psql -h "$POSTGRES_HOST" -p "$POSTGRES_PORT" -U "$POSTGRES_USER" -d "$POSTGRES_DATABASE" -t -c " SELECT COUNT(*) FROM ( SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'registration_projections') ... ) missing; -") +") || { + echo "ERROR: Failed to connect to database" + exit 2 +} missing_count=$(echo "$result" | tr -d '[:space:]') +if [ -z "$missing_count" ]; then + echo "ERROR: No result from validation query" + exit 2 +fi + if [ "$missing_count" -eq 0 ]; then
docs/patterns/retry_backoff_compensation_strategy.md (1)
465-487: Consider condensing thetransport_typeguidance.The docstring provides comprehensive guidance on transport_type selection, which is valuable for strategy documentation. However, you might consider:
- Moving detailed examples to a separate "Transport Type Selection Guide" section
- Keeping the docstring focused on the parameter's purpose and default behavior
- Referencing the detailed guide for nuanced selection criteria
That said, given this is strategy documentation (not inline code), the current level of detail may be intentional and appropriate.
💡 Example of condensed docstring
- """Execute saga with automatic compensation on failure. - - Transport Type Selection: - The transport_type parameter is used in CompensationFailedError context - for observability and categorization. Choose based on your use case: - - **Recommended for Compensation Errors**: - - RUNTIME: For saga orchestration errors (compensation is a runtime concern) - - **Alternative: Entry Point Transport**: - - HTTP: REST API-triggered sagas (when correlation with trigger matters) - - KAFKA: Event-driven sagas (async message processing) - - DATABASE: Database-centric workflows (batch operations) - - **Guidance**: For saga compensation failures, `RUNTIME` is often more - accurate since compensation is an internal orchestration concern. Use - the trigger transport (HTTP, KAFKA) when you need to correlate - compensation failures with the original request source. - - Note: Individual saga steps may interact with multiple transports. - The executor's transport_type represents the error categorization, - not individual step operations. - """ + """Execute saga with automatic compensation on failure. + + Transport Type Selection: + Defaults to RUNTIME for saga orchestration errors. Override with the + trigger transport (HTTP, KAFKA, DATABASE) when correlating compensation + failures with the original request source. See "Transport Type Selection + Guide" in this document for detailed criteria. + """
tests/integration/event_bus/conftest.py (1)
295-296: Consider adding metadata wait for consistency withensure_test_topic.The
topic_factoryfixture doesn't wait for metadata when the topic already exists, whileensure_test_topic(line 157-158) does. This could cause subtle test flakiness if the topic was just created by another process.♻️ Optional: Add metadata wait for consistency
except TopicAlreadyExistsError: - pass # Topic already exists - acceptable in test environments + # Topic already exists - still wait for metadata in case just created + if admin is not None: + start_time = asyncio.get_running_loop().time() + while (asyncio.get_running_loop().time() - start_time) < 5.0: + try: + description = await admin.describe_topics([topic_name]) + if description: + break + except Exception: + pass + await asyncio.sleep(0.5)Alternatively, extract
_wait_for_topic_metadataas a module-level function to share between both fixtures.
tests/integration/registration/e2e/test_full_orchestrator_flow.py (1)
129-177: Well-implemented type coercion with comprehensive error handling.The
coerce_to_node_kindfunction follows a defensive pattern with clear error messages. The enum-first check avoids unnecessary string operations when already an enum.Minor optimization (optional): The
valid_valuesset is recreated on each call. For a test file this is fine, but if reused elsewhere, consider caching:♻️ Optional: Cache valid values
+# Module-level cache for valid EnumNodeKind values +_VALID_NODE_KIND_VALUES: frozenset[str] = frozenset(e.value for e in EnumNodeKind) + def coerce_to_node_kind(node_type: str | EnumNodeKind | None) -> EnumNodeKind: ... # Validate string is a valid enum value - valid_values = {e.value for e in EnumNodeKind} - if node_type not in valid_values: + if node_type not in _VALID_NODE_KIND_VALUES: raise ValueError( - f"Invalid node_type '{node_type}'. Expected one of: {sorted(valid_values)}" + f"Invalid node_type '{node_type}'. Expected one of: {sorted(_VALID_NODE_KIND_VALUES)}" )
docs/patterns/handler_plugin_loader.md (1)
427-469: Clear path traversal protection documentation.The section effectively explains package boundary validation and provides realistic attack examples. The implementation detail snippet and trailing dot recommendation are helpful.
The "less explicit" example (lines 463-468) correctly notes that boundary validation prevents "omnibase" from matching "omnibase_malicious", but consider simplifying by removing this example entirely to avoid potential confusion and strongly encourage the recommended trailing dot pattern.
| # Allow time for pipeline to process and reject the malformed message. | ||
| # This ensures the pipeline is ready for the next valid message. | ||
| # | ||
| # TODO(OMN-XXX): Replace with deterministic wait once pipeline exposes | ||
| # a "message processed" signal or callback. Options: | ||
| # 1. Pipeline.wait_until_idle() method that tracks in-flight messages | ||
| # 2. Counter-based approach: wait until processed_count increments | ||
| # 3. Expose processing completion via asyncio.Event per message | ||
| await asyncio.sleep(1.0) |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Check the actual TODO format in the codebase and find similar patterns
rg "TODO\(OMN-" tests/integration/registration/e2e/test_full_orchestrator_flow.py -A2 -B2Repository: OmniNode-ai/omnibase_infra
Length of output: 370
🏁 Script executed:
# Search for TODO patterns in the codebase to understand valid formats
rg "TODO\(OMN-(XXX|TBD|\d)" --type=py | head -20Repository: OmniNode-ai/omnibase_infra
Length of output: 2910
🏁 Script executed:
# Check if OMN-XXX pattern exists elsewhere or if it's clearly a placeholder
rg "OMN-XXX" --type=pyRepository: OmniNode-ai/omnibase_infra
Length of output: 214
TODO comment must use proper ticket format.
The TODO at line 1280 uses TODO(OMN-XXX) which is a placeholder and violates the coding guidelines. Per the Python file guidelines, all TODO comments must reference a Linear ticket number in the format TODO(OMN-XXXX), or use TODO(OMN-TBD) temporarily if the ticket hasn't been created yet.
Since the ticket for this work hasn't been created, update the comment to use TODO(OMN-TBD) and add a [NEEDS TICKET] marker on the first line of this multi-line comment for grep-ability.
🤖 Prompt for AI Agents
In @tests/integration/registration/e2e/test_full_orchestrator_flow.py around
lines 1277 - 1285, Update the malformed TODO comment in the test around the
await asyncio.sleep(1.0) call: replace the placeholder TODO(OMN-XXX) with
TODO(OMN-TBD) and add a leading “[NEEDS TICKET]” marker on the first line of
that multi-line comment so the comment reads as a searchable TODO with the
temporary ticket format; leave the rest of the explanatory text intact.
- Remove all backwards compatibility mentions per CLAUDE.md policy - Update docs/design/* to reflect no-BC policy - Rename TestBackwardsCompatibility to TestDispatchersWithoutNodeKind - Add correlation_id to AuthorizationContext in security_patterns.md - Add error_code parameter to PolicyRegistryError documentation - Fix handler_plugin_loader.md example (PolicyServiceValidationError) - Improve transport type guidance in retry_backoff_compensation_strategy.md - Fix TODO ticket format (OMN-1327) in E2E tests - Narrow exception handling in health polling (httpx specific types) - Update CHANGELOG to remove BC language - Restore ruff noqa comments for intentional security patterns
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (5)
docs/patterns/utility_directory_structure.md (3)
28-30: Remove theshared/utils/directory from the tree structure.The directory tree still shows
shared/utils/with a comment about "Legacy/transitional utilities (deprecated)", but the documentation states this directory has been removed. This creates confusion.If the directory is truly removed, it should not appear in the directory tree.
📝 Proposed fix
└── shared/ - └── utils/ # Legacy/transitional utilities (deprecated) - └── __init__.py # Re-exports from utils/ for compatibility
123-141: Remove or update the Removal Timeline section to reflect current status.This section describes a future removal in v2.0.0 with deprecation warnings, but the rest of the document states that
shared/utils/has already been removed. This creates a significant inconsistency.If the directory is already removed (as stated in lines 10, 16, 70, 72-73), this entire timeline section should be either:
- Removed entirely, or
- Updated to reflect that removal has already occurred
📝 Suggested approach
Either remove the entire "Removal Timeline" section (lines 123-141), or replace it with a brief note like:
### Removal Status The `shared/utils/` directory has been removed as of this version. All code must use the canonical `omnibase_infra.utils` import path.
164-164: Update "deprecated" to "removed" for consistency.The decision matrix describes
shared/utils/as "Legacy (deprecated)", but the rest of the document states it has been removed. Update this for consistency.📝 Proposed fix
-| Legacy (deprecated) | `shared/utils/` | Do not add new code | +| Removed | ~~`shared/utils/`~~ | N/A - directory removed |docs/patterns/policy_registry_trust_model.md (1)
411-435: Fix resource limit restoration bug.The context manager sets both
RLIMIT_AS(line 418-422) andRLIMIT_CPU(line 425-428) but only restoresRLIMIT_ASin the finally block (line 434). The original CPU limit should also be saved and restored to prevent the limit from persisting after the context manager exits.🔧 Proposed fix to restore both resource limits
`@contextmanager` def resource_limits( max_memory_mb: int = 100, max_cpu_seconds: float = 1.0, ): """Context manager to enforce resource limits on policy execution.""" # Set memory limit soft, hard = resource.getrlimit(resource.RLIMIT_AS) resource.setrlimit( resource.RLIMIT_AS, (max_memory_mb * 1024 * 1024, hard), ) # Set CPU time limit + cpu_soft, cpu_hard = resource.getrlimit(resource.RLIMIT_CPU) resource.setrlimit( resource.RLIMIT_CPU, (int(max_cpu_seconds), int(max_cpu_seconds) + 1), ) try: yield finally: # Restore original limits resource.setrlimit(resource.RLIMIT_AS, (soft, hard)) + resource.setrlimit(resource.RLIMIT_CPU, (cpu_soft, cpu_hard))docs/design/POLICY_REGISTRY_DI_EXAMPLES.md (1)
500-536: Inconsistent example code - deprecated fallback usage shown after removal.The
HybridRetryServiceclass correctly raisesValueErrorwhen neither container nor registry is provided (lines 512-516), but line 535 shows:# Old way (deprecated, backwards compatible) service3 = HybridRetryService() # Falls back to singletonThis would actually raise a
ValueErrorwith the updated code, not fall back to a singleton. The comment and example are inconsistent with the implementation.Suggested fix - remove or update the inconsistent example
# Migration way (for testing) test_registry = PolicyRegistry() service2 = HybridRetryService(registry=test_registry) - -# Old way (deprecated, backwards compatible) -service3 = HybridRetryService() # Falls back to singleton + +# NOTE: Calling HybridRetryService() without arguments now raises ValueError +# per the no-backwards-compatibility policy. Always provide container or registry.
🤖 Fix all issues with AI agents
In `@docs/design/POLICY_REGISTRY_DI_CHECKLIST.md`:
- Around line 122-125: The document has a contradiction between the Phase-based
migration (Phase 1 keeping existing code, Phases 4–5 deprecating/removing
singletons) and the checklist item "Verify container-based DI" which demands
immediate removal of singletons and no backwards compatibility; pick one
approach and make consistent edits: for Option A (no backwards compatibility)
remove or merge out Phase 4 and Phase 5 and change Phase 1 section 2 and the
"Verify container-based DI" checklist to require immediate removal of singleton
patterns and container-only usage, or for Option B (gradual migration) revert
the edited lines in the checklist and the "No backwards compatibility
maintained" wording so Phase 1 keeps code unchanged, Phase 4 adds deprecation
notices, and Phase 5 removes singletons; update all occurrences (the checklist
near "Verify container-based DI", Phase 1 section 2, Phase 4, Phase 5, and the
single sentence currently stating "No backwards compatibility maintained") so
the chosen approach is reflected everywhere.
In `@docs/design/POLICY_REGISTRY_DI_INTEGRATION.md`:
- Around line 693-700: The checklist has a duplicated "3." item; update the
numbering so the list reads 1, 2, 3, 4, 5 by changing the final "3. Update
`ProtocolBindingRegistry` and `EventBusBindingRegistry` to use container" to
"5." (referencing the items mentioning ModelOnexContainer, container-based DI,
and the symbol names ProtocolBindingRegistry and EventBusBindingRegistry to
locate the line).
In `@docs/patterns/handler_plugin_loader.md`:
- Around line 676-680: The docs show PolicyServiceValidationError using
hardcoded strings for error codes; introduce an enum (e.g.,
EnumPolicyServiceError) with members HANDLER_REJECTED, SERVICE_UNAVAILABLE,
HASH_NOT_APPROVED mapping to POLCIY_SERVICE_001/002/003 and update the
PolicyServiceValidationError examples to reference
EnumPolicyServiceError.<MEMBER> values (or explicitly note these are
domain-specific codes outside EnumHandlerLoaderError) so documentation
demonstrates the recommended enum-based pattern consistent with ONEX error
handling.
🧹 Nitpick comments (7)
tests/integration/handlers/conftest.py (1)
3-5: Clarify the S106 comment or add the suppression.Line 4 states "S106 disabled" but only S310 is actually disabled via the
# ruff: noqa: S310directive. This could mislead developers into thinking S106 violations will be suppressed when they won't.Consider either:
- Removing the "disabled" wording if S106 isn't actually suppressed here, or
- Adding S106 to the noqa directive if suppression is intended
Option 1: Clarify comment wording
# ruff: noqa: S310 -# S106 disabled: Test credential fixtures are intentional for integration testing +# S106 note: Test credential fixtures use env vars, not hardcoded values # S310 disabled: URL scheme validation happens at fixture level; Vault health check is internalOption 2: Add S106 to suppression if needed
-# ruff: noqa: S310 +# ruff: noqa: S106, S310 # S106 disabled: Test credential fixtures are intentional for integration testing # S310 disabled: URL scheme validation happens at fixture level; Vault health check is internaltests/unit/runtime/test_service_health.py (1)
566-582: Consider using more specific exception type.This test catches the raw
Exceptionwhile the test at line 662 (test_create_from_container_wraps_resolution_exception) properly tests forProtocolConfigurationError. Since the factory method wraps exceptions inProtocolConfigurationError, this test could also use that specific type for consistency.💡 Optional: Use specific exception type
- with pytest.raises(Exception) as exc_info: + with pytest.raises(ProtocolConfigurationError) as exc_info: await ServiceHealth.create_from_container(container=mock_container) assert "Service resolution failed" in str(exc_info.value)docs/patterns/policy_registry_trust_model.md (2)
220-238: Consider whether code hash should be included in error messages.The error message at line 234 includes the code hash. While this aids debugging, consider whether this constitutes sensitive information that could reveal implementation details. Since this error is raised within trusted infrastructure code (not exposed to external users), the current approach is likely acceptable.
309-325: Consider sanitizing security scanner output in error messages.The error message at line 321 includes the full output from security scanners, which might contain code snippets or vulnerability details. Consider whether this level of detail should be logged separately rather than included in the exception message, or ensure proper access controls on error logs.
docs/patterns/retry_backoff_compensation_strategy.md (1)
548-557: Consider aggregating individual compensation error contexts.The configurable
transport_typeis a significant improvement over the previous hardcoded approach. However, individual compensation errors (lines 530-536) may containModelInfraErrorContextwith valuable debugging information (specific transport types, target names, etc.) that is currently discarded.Consider extracting and aggregating contexts from
compensation_errorsto preserve step-specific transport information:♻️ Optional enhancement to preserve step contexts
# If any compensations failed, raise aggregate error if compensation_errors: + # Attempt to extract context from first compensation error if available + first_error_context = None + for _, comp_error in compensation_errors: + if hasattr(comp_error, 'context') and isinstance( + getattr(comp_error, 'context', None), ModelInfraErrorContext + ): + first_error_context = comp_error.context + break + context = ModelInfraErrorContext( - transport_type=self._transport_type, + # Prefer actual failed transport, fallback to executor's transport + transport_type=( + first_error_context.transport_type + if first_error_context + else self._transport_type + ), operation="saga_compensation", + target_name=( + first_error_context.target_name + if first_error_context + else None + ), correlation_id=correlation_id, )This preserves diagnostic context from the actual failed step while maintaining the current behavior when no context is available.
docs/patterns/security_patterns.md (1)
569-602:correlation_idfield added;getattrfallback now redundant.The
correlation_idfield was added toAuthorizationContext(line 569), which addresses the previous review feedback. However, line 597 still usesgetattr(ctx, 'correlation_id', None)as a fallback. Sincecorrelation_idis now a defined field with a default ofNone, you can simplify toctx.correlation_iddirectly.♻️ Simplify correlation_id access
context = ModelInfraErrorContext( transport_type=EnumInfraTransportType.HTTP, operation="authorization_check", target_name="permission_guard", - correlation_id=getattr(ctx, 'correlation_id', None), + correlation_id=ctx.correlation_id, )src/omnibase_infra/handlers/models/mcp/model_mcp_handler_config.py (1)
37-37: Consider addingfrom_attributes=Truetomodel_config.Based on learnings, frozen Pydantic models should include
from_attributes=Truein ConfigDict for pytest-xdist worker compatibility.Suggested change
- model_config = {"frozen": True} + model_config = {"frozen": True, "from_attributes": True}
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Lite
📒 Files selected for processing (39)
CHANGELOG.mddocs/design/ADR_DISPATCHER_TYPE_SAFETY.mddocs/design/POLICY_REGISTRY_DI_CHECKLIST.mddocs/design/POLICY_REGISTRY_DI_EXAMPLES.mddocs/design/POLICY_REGISTRY_DI_INTEGRATION.mddocs/patterns/handler_plugin_loader.mddocs/patterns/policy_registry_trust_model.mddocs/patterns/retry_backoff_compensation_strategy.mddocs/patterns/security_patterns.mddocs/patterns/utility_directory_structure.mdsrc/omnibase_infra/handlers/models/mcp/model_mcp_handler_config.pysrc/omnibase_infra/mixins/mixin_dict_like_accessors.pysrc/omnibase_infra/mixins/mixin_node_introspection.pysrc/omnibase_infra/models/dispatch/model_dispatch_error.pysrc/omnibase_infra/models/dispatch/model_dispatch_metadata.pysrc/omnibase_infra/models/dispatch/model_tracing_context.pysrc/omnibase_infra/models/logging/model_log_context.pysrc/omnibase_infra/runtime/dispatchers/dispatcher_node_introspected.pysrc/omnibase_infra/runtime/dispatchers/dispatcher_node_registration_acked.pysrc/omnibase_infra/runtime/dispatchers/dispatcher_runtime_tick.pysrc/omnibase_infra/runtime/handler_registry.pysrc/omnibase_infra/runtime/message_dispatch_engine.pysrc/omnibase_infra/services/service_health.pysrc/omnibase_infra/validation/validation_exemptions.yamltests/helpers/kafka_utils.pytests/integration/event_bus/conftest.pytests/integration/handlers/conftest.pytests/integration/projectors/conftest.pytests/integration/registration/e2e/test_full_orchestrator_flow.pytests/integration/registration/e2e/test_runtime_e2e.pytests/unit/errors/test_infra_errors.pytests/unit/handlers/test_handler_filesystem.pytests/unit/handlers/test_handler_mcp.pytests/unit/plugins/test_onex_architecture_compliance.pytests/unit/runtime/test_dispatch_context_integration.pytests/unit/runtime/test_message_dispatch_engine.pytests/unit/runtime/test_registry_compute.pytests/unit/runtime/test_service_health.pytests/unit/utils/test_util_dsn_validation.py
✅ Files skipped from review due to trivial changes (5)
- src/omnibase_infra/models/logging/model_log_context.py
- src/omnibase_infra/models/dispatch/model_tracing_context.py
- src/omnibase_infra/runtime/dispatchers/dispatcher_node_introspected.py
- tests/unit/utils/test_util_dsn_validation.py
- tests/unit/errors/test_infra_errors.py
🚧 Files skipped from review as they are similar to previous changes (2)
- tests/unit/runtime/test_registry_compute.py
- tests/unit/handlers/test_handler_filesystem.py
🧰 Additional context used
📓 Path-based instructions (5)
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py: Never useAnytype - useobjectfor generic payloads in function parameters and return types
UseX | None(PEP 604) instead ofOptional[X]for nullable types
All services must useModelONEXContainerfor dependency injection via__init__(self, container: ModelONEXContainer)
Use@allow_anydecorator with documented reason as exemption mechanism forAnytype violations
UseJsonTypefromomnibase_core.typesas the canonical type alias for JSON-compatible values
UseModelEventEnvelope[object]for generic dispatcher interfaces andobjectfor generic payloads
Infrastructure error handling must useOnexErrorbase class and never expose passwords, API keys, PII, or connection strings with credentials in error messages
UseInfraConnectionError,InfraTimeoutError,InfraAuthenticationError,InfraUnavailableErrorfor transport failures with properModelInfraErrorContext
Correlation IDs must be propagated from incoming requests, auto-generated withuuid4()if missing, and included in all error contexts
External service adapters must implementMixinAsyncCircuitBreakerwith appropriate threshold and reset_timeout configuration
Protocol resolution must use duck typing via protocols, never useisinstancechecks
Files:
src/omnibase_infra/models/dispatch/model_dispatch_error.pytests/integration/projectors/conftest.pysrc/omnibase_infra/runtime/dispatchers/dispatcher_node_registration_acked.pytests/unit/runtime/test_dispatch_context_integration.pytests/unit/runtime/test_service_health.pysrc/omnibase_infra/models/dispatch/model_dispatch_metadata.pysrc/omnibase_infra/mixins/mixin_node_introspection.pysrc/omnibase_infra/services/service_health.pytests/integration/registration/e2e/test_full_orchestrator_flow.pysrc/omnibase_infra/mixins/mixin_dict_like_accessors.pytests/unit/handlers/test_handler_mcp.pytests/integration/event_bus/conftest.pytests/unit/runtime/test_message_dispatch_engine.pysrc/omnibase_infra/runtime/message_dispatch_engine.pysrc/omnibase_infra/handlers/models/mcp/model_mcp_handler_config.pysrc/omnibase_infra/runtime/handler_registry.pytests/unit/plugins/test_onex_architecture_compliance.pytests/integration/handlers/conftest.pytests/integration/registration/e2e/test_runtime_e2e.pysrc/omnibase_infra/runtime/dispatchers/dispatcher_runtime_tick.pytests/helpers/kafka_utils.py
**/model_*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/model_*.py: File naming convention: Models must usemodel_<name>.pywith class nameModel<Name>
Each model file must contain exactly oneModel*class
Pydantic workaround forAnytype must include# NOTE:comment documenting the reason when technically required
UseSerializeAsAnytype wrapper for Pydantic fields containing complex nested models to preserve subclass fields during serialization
Files:
src/omnibase_infra/models/dispatch/model_dispatch_error.pysrc/omnibase_infra/models/dispatch/model_dispatch_metadata.pysrc/omnibase_infra/handlers/models/mcp/model_mcp_handler_config.py
**/mixin_*.py
📄 CodeRabbit inference engine (CLAUDE.md)
File naming convention: Mixins must use
mixin_<name>.pywith class nameMixin<Name>
Files:
src/omnibase_infra/mixins/mixin_node_introspection.pysrc/omnibase_infra/mixins/mixin_dict_like_accessors.py
**/service_*.py
📄 CodeRabbit inference engine (CLAUDE.md)
File naming convention: Services must use
service_<name>.pywith class nameService<Name>
Files:
src/omnibase_infra/services/service_health.py
**/handler_*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Handlers must NOT have direct event bus access - only orchestrators may have bus parameters and publish events
Files:
src/omnibase_infra/runtime/handler_registry.py
🧠 Learnings (76)
📓 Common learnings
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/handler_contract.yaml : Handlers must be discovered and loaded dynamically via YAML contracts using plugin pattern, not hardcoded registries
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/handler_contract.yaml : Handler contract files must declare handler routing with `routing_strategy`, event models, handler classes, and handler modules
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contracts/contract_*.yaml : All ONEX node contract definitions must use the new subcontract architecture pattern, breaking down complex contracts into separate contract_actions.yaml, contract_models.yaml, contract_validation.yaml, and optional contract_cli.yaml and contract_capabilities.yaml files for separation of concerns, maintainability, reusability, modularity, and future tool-as-a-service readiness
📚 Learning: 2025-11-24T16:33:51.604Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T16:33:51.604Z
Learning: Applies to tests/**/conftest.py : Test fixtures must be defined in `conftest.py` and should provide reusable sample data, UUIDs, semantic versions, and model data
Applied to files:
tests/integration/projectors/conftest.pytests/integration/handlers/conftest.py
📚 Learning: 2025-11-24T17:24:54.193Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T17:24:54.193Z
Learning: Applies to **/*test*.py : Use context-based fixtures with pytest.param and conditional dependency injection (e.g., UNIT_CONTEXT vs INTEGRATION_CONTEXT) for mock and integration tests
Applied to files:
tests/integration/projectors/conftest.pytests/integration/handlers/conftest.py
📚 Learning: 2025-12-07T17:50:13.678Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T17:50:13.678Z
Learning: Organize tests following the structure: tests/conftest.py for shared fixtures, tests/unit/ for unit tests (no infrastructure), tests/integration/ for integration tests (requires Kafka/DBs), tests/nodes/ for node-specific tests
Applied to files:
tests/integration/projectors/conftest.pytests/integration/registration/e2e/test_full_orchestrator_flow.pytests/integration/handlers/conftest.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/*.py : Use `ModelEventEnvelope[object]` for generic dispatcher interfaces and `object` for generic payloads
Applied to files:
tests/unit/runtime/test_dispatch_context_integration.pytests/integration/registration/e2e/test_full_orchestrator_flow.pytests/unit/runtime/test_message_dispatch_engine.pydocs/design/ADR_DISPATCHER_TYPE_SAFETY.md
📚 Learning: 2025-11-24T16:31:48.648Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/checklist_rule.md:0-0
Timestamp: 2025-11-24T16:31:48.648Z
Learning: Document migration requirements when upgrading from Checklist Rule v3 to v4: add dependencies, blockers, relationships, and work_context sections to existing tickets
Applied to files:
docs/design/POLICY_REGISTRY_DI_CHECKLIST.md
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/*.py : All services must use `ModelONEXContainer` for dependency injection via `__init__(self, container: ModelONEXContainer)`
Applied to files:
docs/design/POLICY_REGISTRY_DI_CHECKLIST.mddocs/design/POLICY_REGISTRY_DI_INTEGRATION.mddocs/design/POLICY_REGISTRY_DI_EXAMPLES.md
📚 Learning: 2025-11-24T17:22:32.195Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-24T17:22:32.195Z
Learning: Applies to **/testing/testing_scenario_harness.py : Registry resolver should use dynamic fixture detection based on constructor signatures using inspect.signature to determine which parameters to inject
Applied to files:
docs/design/POLICY_REGISTRY_DI_CHECKLIST.md
📚 Learning: 2026-01-14T01:38:17.497Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-14T01:38:17.497Z
Learning: Applies to src/omnibase_core/nodes/**/*.py : Use ModelONEXContainer for dependency injection in node constructors, never use generic ModelContainer.
Applied to files:
docs/design/POLICY_REGISTRY_DI_CHECKLIST.mddocs/design/POLICY_REGISTRY_DI_INTEGRATION.mddocs/design/POLICY_REGISTRY_DI_EXAMPLES.md
📚 Learning: 2025-11-28T18:58:53.781Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-28T18:58:53.781Z
Learning: Remove all backward compatibility patterns and legacy support code; use proper ONEX patterns from day one
Applied to files:
docs/design/POLICY_REGISTRY_DI_CHECKLIST.mddocs/design/POLICY_REGISTRY_DI_EXAMPLES.md
📚 Learning: 2025-11-29T17:13:38.776Z
Learnt from: CR
Repo: OmniNode-ai/omniarchon PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T17:13:38.776Z
Learning: Applies to services/intelligence/src/services/pattern_learning/**/*.py : Pattern Learning has 4 phases: Foundation (base models, ONEX compliance), Matching (hybrid scoring, semantic analysis), Validation (quality gates, compliance), Traceability (pattern lineage, analytics). Implement in `/services/intelligence/src/services/pattern_learning/`.
Applied to files:
docs/design/POLICY_REGISTRY_DI_CHECKLIST.md
📚 Learning: 2025-11-24T17:23:24.207Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/modes.mdc:0-0
Timestamp: 2025-11-24T17:23:24.207Z
Learning: PLAN mode: Draft a detailed technical plan using numbered checklists with file paths, function names, and sequential actions. Declare node types, template usage, and output structure. Forbidden: Writing code or implementation logic.
Applied to files:
docs/design/POLICY_REGISTRY_DI_CHECKLIST.md
📚 Learning: 2025-11-24T16:32:37.719Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/modes.mdc:0-0
Timestamp: 2025-11-24T16:32:37.719Z
Learning: PLAN mode: Draft detailed technical plans using numbered checklists with file paths, function names, and sequential actions. Declare node types, template usage, and output structure. Forbidden: writing code or implementation logic.
Applied to files:
docs/design/POLICY_REGISTRY_DI_CHECKLIST.md
📚 Learning: 2025-11-29T22:07:25.230Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: migration_sources/omniarchon/CLAUDE.md:0-0
Timestamp: 2025-11-29T22:07:25.230Z
Learning: Applies to migration_sources/omniarchon/**/tests/**/*.py : All integration tests must verify correct Kafka port usage for context (9092 for Docker, 29092 for host). Test both local (qdrant, memgraph) and remote (PostgreSQL, Redpanda) database connectivity. Never assume test environment configuration.
Applied to files:
tests/unit/runtime/test_service_health.pytests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2026-01-14T01:38:17.497Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-14T01:38:17.497Z
Learning: Applies to src/omnibase_core/**/*.py : Use absolute imports across packages and relative imports only within tight module clusters to avoid long paths.
Applied to files:
docs/patterns/utility_directory_structure.md
📚 Learning: 2025-11-24T16:33:32.747Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T16:33:32.747Z
Learning: Applies to **/*.py : Import models from shared core paths using `omnibase.model.core.model_*` pattern
Applied to files:
docs/patterns/utility_directory_structure.md
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to src/omninode_bridge/nodes/**/*.py : Import mixins from omnibase_core.mixins.* and use Mixin* naming pattern (e.g., MixinHealthCheck, MixinMetrics, MixinEventBus) - never use local custom mixins unless experimental and documented
Applied to files:
src/omnibase_infra/mixins/mixin_node_introspection.py
📚 Learning: 2025-12-06T22:21:32.649Z
Learnt from: CR
Repo: OmniNode-ai/omniagent PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T22:21:32.649Z
Learning: Applies to nodes/**/*.py : Use event bus mixins from `omnibase_core` for Kafka publishing instead of direct Kafka clients
Applied to files:
src/omnibase_infra/mixins/mixin_node_introspection.pytests/integration/registration/e2e/test_full_orchestrator_flow.pytests/integration/registration/e2e/test_runtime_e2e.py
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/introspection.py : All ONEX nodes must include an `introspection.py` file implementing standards-compliant introspection logic
Applied to files:
src/omnibase_infra/mixins/mixin_node_introspection.py
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Node Introspection Security - use Python reflection for service discovery, but prefix internal/sensitive methods with `_`, use generic parameter names, and configure Kafka topic ACLs for introspection topics
Applied to files:
src/omnibase_infra/mixins/mixin_node_introspection.pytests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-24T16:32:55.606Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T16:32:55.606Z
Learning: Node implementations must use mixin-based composition from `omnibase_core.mixins` (e.g., `MixinHealthCheck`, `MixinNodeExecutor`) to add capabilities
Applied to files:
src/omnibase_infra/mixins/mixin_node_introspection.py
📚 Learning: 2025-11-24T16:32:55.606Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T16:32:55.606Z
Learning: Node services must implement dependency injection using `ModelONEXContainer` from `omnibase_core.models.container.model_onex_container`
Applied to files:
docs/design/POLICY_REGISTRY_DI_INTEGRATION.md
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/*.py : All ONEX node implementations must follow dependency injection and protocol-first design patterns as established in the node_cli canonical reference
Applied to files:
docs/design/POLICY_REGISTRY_DI_INTEGRATION.mddocs/design/POLICY_REGISTRY_DI_EXAMPLES.mdtests/unit/plugins/test_onex_architecture_compliance.py
📚 Learning: 2026-01-14T01:38:17.497Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-14T01:38:17.497Z
Learning: Applies to src/omnibase_core/**/*.py : Use protocol names (e.g., 'ProtocolEventBus', 'ProtocolLogger') for service resolution via container.get_service(), never use concrete class names.
Applied to files:
docs/design/POLICY_REGISTRY_DI_INTEGRATION.md
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contracts/contract_*.yaml : All ONEX node contract definitions must use the new subcontract architecture pattern, breaking down complex contracts into separate contract_actions.yaml, contract_models.yaml, contract_validation.yaml, and optional contract_cli.yaml and contract_capabilities.yaml files for separation of concerns, maintainability, reusability, modularity, and future tool-as-a-service readiness
Applied to files:
docs/patterns/security_patterns.md
📚 Learning: 2025-11-24T16:32:55.606Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T16:32:55.606Z
Learning: Applies to **/*contract*.yaml : All ONEX nodes must have validated YAML contracts following the contract-driven development pattern with input_state and output_state schema definitions
Applied to files:
docs/patterns/security_patterns.md
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/contract.yaml : All ONEX node contract definitions must follow the linked document architecture pattern with contract.yaml linking to node_config.yaml and deployment_config.yaml as associated documents
Applied to files:
docs/patterns/security_patterns.md
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/*.py : Correlation IDs must be propagated from incoming requests, auto-generated with `uuid4()` if missing, and included in all error contexts
Applied to files:
docs/patterns/security_patterns.md
📚 Learning: 2025-12-03T16:55:49.755Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-03T16:55:49.755Z
Learning: Applies to agents/**/*.py : Use correlation_id UUID for end-to-end traceability across all agent routing, manifest injection, and execution events
Applied to files:
docs/patterns/security_patterns.md
📚 Learning: 2025-12-03T16:55:49.755Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-03T16:55:49.755Z
Learning: Applies to agents/**/*.py : Implement agent observability using three-layer traceability with correlation_id tracking through agent_routing_decisions, agent_manifest_injections, and agent_execution_logs tables
Applied to files:
docs/patterns/security_patterns.md
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/*.py : Infrastructure error handling must use `OnexError` base class and never expose passwords, API keys, PII, or connection strings with credentials in error messages
Applied to files:
docs/patterns/security_patterns.mddocs/patterns/handler_plugin_loader.mddocs/patterns/policy_registry_trust_model.md
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to src/**/{config,settings}/**/*.py : Environment variables MUST include: POSTGRES_HOST, POSTGRES_PORT, POSTGRES_DATABASE, POSTGRES_USER, POSTGRES_PASSWORD, KAFKA_BOOTSTRAP_SERVERS, CONSUL_HOST, CONSUL_PORT, LOG_LEVEL. Use secrets manager for production passwords.
Applied to files:
docs/patterns/security_patterns.md
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/*.py : Use `InfraConnectionError`, `InfraTimeoutError`, `InfraAuthenticationError`, `InfraUnavailableError` for transport failures with proper `ModelInfraErrorContext`
Applied to files:
docs/patterns/security_patterns.mddocs/patterns/policy_registry_trust_model.mddocs/patterns/retry_backoff_compensation_strategy.md
📚 Learning: 2025-11-24T16:33:32.747Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T16:33:32.747Z
Learning: Use Protocol for interface definitions when implementations may live outside core codebase; use Pydantic models only for base classes with shared logic
Applied to files:
docs/patterns/security_patterns.md
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/handler_contract.yaml : Handlers must be discovered and loaded dynamically via YAML contracts using plugin pattern, not hardcoded registries
Applied to files:
docs/patterns/security_patterns.mddocs/patterns/handler_plugin_loader.md
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Deviations from omnibase_core standards are only acceptable for: (1) Orchestrator/Reducer nodes (ModelService* disabled), (2) Experimental features being prototyped for upstream, (3) Performance-critical optimizations with benchmark proof, (4) Bridge-specific unique patterns. All deviations require explicit documentation and justification.
Applied to files:
src/omnibase_infra/validation/validation_exemptions.yaml
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to src/omninode_bridge/events/**/*.py : Kafka event publishing MUST use OnexEnvelopeV1 format with 13 topics for event streaming at all workflow lifecycle stages
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.pytests/integration/registration/e2e/test_runtime_e2e.py
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/node_tests/**/*.py : All ONEX node tests must be organized in a `node_tests/` directory using scenario-driven testing patterns with fixture-injected tests
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.pytests/unit/plugins/test_onex_architecture_compliance.py
📚 Learning: 2025-11-29T17:13:38.776Z
Learnt from: CR
Repo: OmniNode-ai/omniarchon PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T17:13:38.776Z
Learning: Applies to **/*.py : All Kafka topics must use the prefix `dev.archon-intelligence` for development/staging environments.
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-12-03T16:55:49.755Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-03T16:55:49.755Z
Learning: Applies to **/*.py : Publish intelligence requests to Kafka event bus using topics: dev.archon-intelligence.intelligence.code-analysis-{requested,completed,failed}.v1 for consistency and event-driven architecture
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.pytests/integration/event_bus/conftest.pytests/helpers/kafka_utils.py
📚 Learning: 2025-12-03T16:55:49.755Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-03T16:55:49.755Z
Learning: Applies to scripts/tests/**/*.sh : Implement comprehensive test suites in scripts/tests/ with separate test files for Kafka, PostgreSQL, Intelligence, and Routing functionality
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-29T17:13:38.776Z
Learnt from: CR
Repo: OmniNode-ai/omniarchon PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T17:13:38.776Z
Learning: Applies to {services/**/*.py,scripts/bulk_ingest_repository.py} : Implement fail-closed configuration for security hardening. All external requests must validate URLs, implement DLQ routing, and handle failures gracefully.
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.pydocs/patterns/handler_plugin_loader.md
📚 Learning: 2026-01-14T01:38:17.497Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-14T01:38:17.497Z
Learning: Applies to src/**/*.py : All TODO comments must reference a Linear ticket in the format '# TODO(OMN-XXX): Description', or use '# TODO(OMN-TBD): Description [NEEDS TICKET]' during triage.
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-24T17:24:41.687Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T17:24:41.687Z
Learning: Applies to **/template_*.py : Generated template files and stubs must include [AI_PROMPT] comments to guide AI agents in implementation, using token-based placeholders
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-24T16:33:32.747Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T16:33:32.747Z
Learning: Applies to **/*template*.py : AI_PROMPT comments must provide actionable guidance and reference tokens that correspond to fields in ModelTemplateContext
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-24T16:33:32.747Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T16:33:32.747Z
Learning: Applies to **/*template*.py : Generated code templates must include AI_PROMPT comments with clear implementation guidance using token-based patterns
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-24T16:32:55.606Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T16:32:55.606Z
Learning: Node communication must use event-driven patterns through `ModelEventEnvelope` from `omnibase_core.models.events.model_event_envelope`
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-28T18:58:53.781Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-28T18:58:53.781Z
Learning: Applies to **/*.py : Implement Node classes by inheriting from `NodeBase` with proper UUID and `ModelSemVer` fields
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to src/omninode_bridge/nodes/**/{models,node}.py : Bridge nodes MUST implement FSM states: PENDING, PROCESSING, COMPLETED, FAILED. Use Pydantic v2 models with proper state enum validation
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-24T16:32:55.606Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T16:32:55.606Z
Learning: Applies to tests/unit/infrastructure/**/test_*.py : All node implementations must have comprehensive unit tests following the testing pattern in `tests/unit/infrastructure/` with tests for node initialization and node execution
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-24T16:33:51.604Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T16:33:51.604Z
Learning: Applies to tests/**/*.py : Test files must follow the naming convention `test_[module_name].py` (examples: `test_enum_acknowledgment_type.py`, `test_model_node_status.py`, `test_mixin_hash_computation.py`)
Applied to files:
tests/integration/registration/e2e/test_full_orchestrator_flow.py
📚 Learning: 2025-11-28T18:58:53.781Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-28T18:58:53.781Z
Learning: Applies to **/*.py : Use direct field access in validators instead of `info.data` fallbacks in Pydantic models
Applied to files:
src/omnibase_infra/mixins/mixin_dict_like_accessors.py
📚 Learning: 2025-11-28T18:58:53.781Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-28T18:58:53.781Z
Learning: Applies to **/*.py : Use proper Pydantic model inheritance patterns extending from BaseModel
Applied to files:
src/omnibase_infra/mixins/mixin_dict_like_accessors.py
📚 Learning: 2025-11-28T18:58:53.781Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-28T18:58:53.781Z
Learning: Applies to **/*.py : Use Field() from Pydantic with appropriate constraints (ge, le, etc.) in model definitions
Applied to files:
src/omnibase_infra/mixins/mixin_dict_like_accessors.py
📚 Learning: 2026-01-14T01:38:17.497Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-14T01:38:17.497Z
Learning: Applies to src/omnibase_core/models/**/*.py : Frozen Pydantic models MUST include from_attributes=True in ConfigDict for pytest-xdist worker compatibility.
Applied to files:
tests/unit/handlers/test_handler_mcp.py
📚 Learning: 2025-11-29T22:07:25.230Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: migration_sources/omniarchon/CLAUDE.md:0-0
Timestamp: 2025-11-29T22:07:25.230Z
Learning: Applies to migration_sources/omniarchon/**/*.py : For host scripts (bulk_ingest_repository.py, test scripts running outside Docker), use `KAFKA_BOOTSTRAP_SERVERS = os.getenv('KAFKA_BOOTSTRAP_SERVERS', '192.168.86.200:29092')` to connect to remote Redpanda on external port 29092.
Applied to files:
tests/integration/event_bus/conftest.py
📚 Learning: 2025-11-30T21:55:10.298Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-30T21:55:10.298Z
Learning: Applies to src/**/{config,settings,kafka,events}/**/*.py : Kafka Bootstrap Servers configuration depends on context: Docker services use 'omninode-bridge-redpanda:9092' (internal), host scripts use '192.168.86.200:29092' (external). Verify correct bootstrap server for your context.
Applied to files:
tests/integration/event_bus/conftest.py
📚 Learning: 2025-11-24T17:23:49.777Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T17:23:49.777Z
Learning: Applies to **/node_*/v[0-9]*_[0-9]*_[0-9]*/models/error_codes.py : All ONEX node error handling must use auto-generated error codes defined in `models/error_codes.py` from contract definitions
Applied to files:
docs/patterns/handler_plugin_loader.mddocs/patterns/policy_registry_trust_model.md
📚 Learning: 2025-11-28T18:58:53.781Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-28T18:58:53.781Z
Learning: Applies to **/*.py : Use `EnumCoreErrorCode` with `ModelOnexError` for proper error code usage
Applied to files:
docs/patterns/handler_plugin_loader.md
📚 Learning: 2026-01-14T01:38:17.497Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-14T01:38:17.497Z
Learning: Applies to src/omnibase_core/**/*.py : Use exception group constants from omnibase_core.errors.exception_groups (e.g., PYDANTIC_MODEL_ERRORS, FILE_IO_ERRORS, VALIDATION_ERRORS) for consistent exception handling.
Applied to files:
docs/patterns/handler_plugin_loader.md
📚 Learning: 2025-11-28T18:58:53.781Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-28T18:58:53.781Z
Learning: Applies to **/*.py : Do not use `except ValueError: ... = Enum.UNKNOWN` patterns; raise explicit errors instead
Applied to files:
docs/patterns/handler_plugin_loader.md
📚 Learning: 2025-11-24T17:22:32.195Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-24T17:22:32.195Z
Learning: Applies to **/*.py : All error handling must use OnexError exception class with specific error codes from error enum, never raise generic Exception or ValueError
Applied to files:
docs/patterns/handler_plugin_loader.mddocs/patterns/policy_registry_trust_model.md
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: When both `handler_contract.yaml` and `contract.yaml` exist in the same directory, the loader must raise an error (AMBIGUOUS_CONTRACT_CONFIGURATION)
Applied to files:
docs/patterns/handler_plugin_loader.md
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/handler_contract.yaml : Handler contract files must declare handler routing with `routing_strategy`, event models, handler classes, and handler modules
Applied to files:
docs/patterns/handler_plugin_loader.md
📚 Learning: 2025-11-24T17:24:41.687Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T17:24:41.687Z
Learning: Applies to **/models/model_contract_*.py : Contract-backed model files must follow the naming pattern `model_contract_<domain>.py` and be located in `*/models/` directories
Applied to files:
docs/patterns/handler_plugin_loader.md
📚 Learning: 2025-11-24T17:22:32.195Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-24T17:22:32.195Z
Learning: Applies to **/v[0-9]_[0-9]_[0-9]/registry/registry_*.py : Registry classes must inherit from BaseOnexRegistry and define CANONICAL_TOOLS dictionary with default tool implementations
Applied to files:
docs/patterns/policy_registry_trust_model.md
📚 Learning: 2026-01-14T01:38:17.497Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-14T01:38:17.497Z
Learning: Applies to src/omnibase_core/**/*.py : Use ModelOnexError with structured error codes for ONEX-specific domain errors that need serialization/logging. Use ValueError only for simple input validation at function boundaries.
Applied to files:
docs/patterns/policy_registry_trust_model.md
📚 Learning: 2025-11-24T17:22:32.195Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/canonical_patterns.mdc:0-0
Timestamp: 2025-11-24T17:22:32.195Z
Learning: Applies to **/v[0-9]_[0-9]_[0-9]/{tools,registry}/**.py : Constructor-based dependency injection must be used for all tool and node classes; validate that required dependencies are not None, raising OnexError with specific error code if missing
Applied to files:
docs/patterns/policy_registry_trust_model.md
📚 Learning: 2026-01-11T17:31:33.550Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_infra PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-11T17:31:33.550Z
Learning: Applies to **/handler_*.py : Handlers must NOT have direct event bus access - only orchestrators may have bus parameters and publish events
Applied to files:
src/omnibase_infra/runtime/handler_registry.py
📚 Learning: 2025-11-29T17:13:38.776Z
Learnt from: CR
Repo: OmniNode-ai/omniarchon PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T17:13:38.776Z
Learning: Applies to **/*.py : Implement retry logic with 3 attempts and exponential backoff (1s → 2s → 4s) for resilient service communication.
Applied to files:
docs/patterns/retry_backoff_compensation_strategy.md
📚 Learning: 2025-11-24T17:24:41.687Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: .cursor/rules/standards.mdc:0-0
Timestamp: 2025-11-24T17:24:41.687Z
Learning: Applies to **/*.py : Do not remove [AI_PROMPT] comments from generated code; they provide actionable guidance for future AI implementation
Applied to files:
tests/unit/plugins/test_onex_architecture_compliance.py
📚 Learning: 2025-12-07T17:50:13.678Z
Learnt from: CR
Repo: OmniNode-ai/omniintelligence PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T17:50:13.678Z
Learning: Applies to **/nodes/**/*compute*.py : Enforce ONEX node purity by preventing compute nodes from importing network/database clients (confluent_kafka, httpx, asyncpg, etc.), accessing environment variables (os.environ, os.getenv), or performing file system operations (open(), Path.read_text(), FileHandler)
Applied to files:
tests/unit/plugins/test_onex_architecture_compliance.py
📚 Learning: 2025-12-03T16:55:49.755Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-03T16:55:49.755Z
Learning: Applies to agents/**/*.py : Implement ONEX-compliant agent architecture with four node types: Effect (External I/O), Compute (Pure transforms), Reducer (State/persistence), and Orchestrator (Workflow coordination)
Applied to files:
tests/unit/plugins/test_onex_architecture_compliance.py
📚 Learning: 2025-11-24T16:33:51.604Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T16:33:51.604Z
Learning: All Python code must have comprehensive test coverage following ONEX Core testing patterns with tests organized by domain, using proper fixtures, and achieving high coverage while maintaining code quality
Applied to files:
tests/unit/plugins/test_onex_architecture_compliance.py
📚 Learning: 2025-11-24T16:32:55.606Z
Learnt from: CR
Repo: OmniNode-ai/omninode_bridge PR: 0
File: .cursor/rules/node_standards.mdc:0-0
Timestamp: 2025-11-24T16:32:55.606Z
Learning: All ONEX nodes must conform to the 4-Node Architecture pattern with clear separation of concerns and unidirectional data flow (EFFECT → COMPUTE → REDUCER → ORCHESTRATOR)
Applied to files:
tests/unit/plugins/test_onex_architecture_compliance.py
📚 Learning: 2025-12-03T16:55:49.755Z
Learnt from: CR
Repo: OmniNode-ai/omniclaude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-03T16:55:49.755Z
Learning: Applies to agents/**/*.py : Implement quality gates with <200ms execution target and performance metrics logging to PostgreSQL agent_execution_logs table
Applied to files:
tests/integration/registration/e2e/test_runtime_e2e.py
🧬 Code graph analysis (2)
src/omnibase_infra/mixins/mixin_node_introspection.py (1)
src/omnibase_infra/enums/enum_introspection_reason.py (1)
EnumIntrospectionReason(18-151)
tests/helpers/kafka_utils.py (1)
src/omnibase_infra/event_bus/kafka_event_bus.py (1)
KafkaEventBus(208-2318)
Code Review: PR #143 - Infrastructure Integration with Handler Contracts🎯 Overall Assessment: Strong Approve with Security RecommendationsThis PR represents a significant architectural improvement enabling contract-driven handler discovery. The implementation quality is high with excellent documentation, but requires addressing critical security defaults before merge. ✅ Strengths1. Handler Contracts - Excellent StructureAll 6 handler contracts (
2. Fail-Fast Validation - Critical ImprovementThe no-handlers fail-fast validation in
3. Pydantic Serialization Fix - Correct ImplementationThe enum serialization fix in # Enum-first pattern (lines 1419-1437)
if isinstance(reason, EnumIntrospectionReason):
reason_enum = reason
elif isinstance(reason, str):
reason_enum = EnumIntrospectionReason(reason.strip().lower())
4. Production-Safe MigrationMigration
5. E2E Test ReliabilityMajor improvements to test infrastructure:
6. Documentation Quality - Exceptional
🚨 Critical Issues1. Handler Plugin Loader Security DefaultFile: Issue: The loader defaults to def __init__(self, allowed_namespaces: list[str] | None = None) -> None:
# If None (default), no namespace restriction is applied and any
# importable module can be loaded.Security Impact:
Recommendation: def __init__(self, allowed_namespaces: list[str] | None = None) -> None:
if allowed_namespaces is None:
logger.warning(
"HandlerPluginLoader initialized without namespace restrictions. "
"All modules can be loaded. Set allowed_namespaces for production.",
extra={"correlation_id": str(uuid4())}
)
self._allowed_namespaces = allowed_namespacesProduction Deployment MUST set this: loader = HandlerPluginLoader(
allowed_namespaces=["omnibase_infra.", "omnibase_core."]
)2. Backwards Compatibility Policy ConflictFile: Issue: The code includes
Conflict: ENV_CONTRACTS_DIR_LEGACY = "CONTRACTS_DIR" # Deprecated: will be removed in v2.0.0 (Q2 2026)Recommendation: Either:
|
…ing, polish) Documentation: - Add correlation_id to AuthorizationContext in security_patterns.md - Clarify error code domains in handler_plugin_loader.md - Add error code usage guidance to policy_registry_trust_model.md - Clarify transport_type is configurable in retry_backoff_compensation_strategy.md - Remove backwards compatibility phases in POLICY_REGISTRY_DI_CHECKLIST.md - Fix checklist numbering in POLICY_REGISTRY_DI_INTEGRATION.md - Clarify migration slot availability in migrations/README.md - Clarify Scenario 1 for fresh deployments in MIGRATION_UPGRADE_003a_to_004.md - Clarify "companion" terminology in MIGRATION_WIRE_DEFAULT_HANDLERS.md Code: - Use ProtocolConfigurationError for empty protocol_type validation - Add success logging with protocol_type context for debugging - Add noqa F401 for string annotation import false positive
PR #143 Comprehensive Review: Handler Contracts & E2E Infrastructure IntegrationExecutive SummaryThis is a substantial infrastructure enhancement PR (194 files, 7,952 additions, 985 deletions) that successfully implements contract-based handler discovery, runtime fail-fast validation, and E2E testing improvements. The PR demonstrates strong adherence to CLAUDE.md guidelines with excellent security considerations and comprehensive testing. Recommendation: ✅ APPROVE with minor observations The PR successfully achieves its stated goals with no blocking issues found. All critical CLAUDE.md requirements are met, and the implementation follows ONEX architectural patterns correctly. ✅ CLAUDE.md Compliance Analysis1. Code Quality & Type Safety ✅
Pydantic Models: COMPLIANT ✅
PEP 604 Unions: COMPLIANT ✅
No Backwards Compatibility Code: COMPLIANT ✅
2. Security Concerns ✅ EXCELLENTHandler Plugin Loader Security: EXCELLENT ✅ Defense-in-depth implementation:
Security Metadata in Contracts: EXCELLENT ✅ All 6 handler contracts include security configuration: security:
trusted_namespace: omnibase_infra.handlers
audit_logging: true
requires_authentication: true # Vault handler onlyEnvironment Variable Handling: COMPLIANT ✅
3. Architecture & Performance ✅Handler Contract Loading Efficiency: EXCELLENT ✅
Protocol Type Registry Keys: FIXED ✅
Kafka Topic Subscription: IMPROVED ✅
Database Migration Strategy: WELL-DOCUMENTED ✅
Valkey Integration: MINIMAL IMPACT ✅
4. Test Coverage ✅E2E Test Quality: EXCELLENT ✅
Integration Test Updates: COMPREHENSIVE ✅
5. Container-Based Dependency Injection ✅Proper DI Patterns: COMPLIANT ✅
🔍 Critical Files Analysis
|
| Category | Status | Notes |
|---|---|---|
| YAML Deserialization | ✅ SECURE | yaml.safe_load() used |
| File Size Limits | ✅ SECURE | 10MB max contract size |
| Namespace Validation | ✅ OPTIONAL | allowed_namespaces parameter |
| Protocol Enforcement | ✅ SECURE | 5-method validation |
| Error Sanitization | ✅ SECURE | Path redaction implemented |
| Secret Management | ✅ SECURE | Vault handler requires auth |
| Environment Variables | ✅ SECURE | Proper sanitization |
Overall Security Grade: A (Excellent)
🚀 Recommendations
Before Merge: None (all requirements met)
Post-Merge Considerations:
-
Production Deployment Checklist:
- ✅ Verify
ONEX_CONTRACTS_DIRpoints to read-only mount - ✅ Enable
allowed_namespacesin production - ✅ Configure Kafka topic ACLs for introspection
- ✅ Review handler capabilities for sensitive method names
- ✅ Verify
-
Migration Execution:
- Use
003_capability_fields.sqlfor dev/staging - Use
004_capability_fields_concurrent.sqlfor production (>100K rows) - Monitor with provided SQL queries
- Use
-
Observability:
- Watch for DEGRADED_MODE warnings in logs
- Monitor handler discovery timing metrics
- Track
no_handlers_registeredhealth check field
✅ Final Verdict
APPROVE - This PR successfully implements contract-driven handler discovery with:
- ✅ Excellent security considerations
- ✅ Comprehensive testing (50 E2E tests passing)
- ✅ Production-ready migration strategy
- ✅ Full CLAUDE.md compliance
- ✅ Zero blocking issues
The implementation demonstrates mature engineering practices with defense-in-depth security, graceful degradation, and exceptional documentation quality.
Excellent work on this infrastructure enhancement! The contract-based handler discovery is well-architected with strong security guarantees and comprehensive testing. The fail-fast validation and detailed error messages will significantly improve developer experience. Migration documentation is production-ready. 🚀
Review conducted via Claude Code with comprehensive analysis of 194 changed files against CLAUDE.md requirements.
Summary
ProtocolConfigurationError)ONEX_CONTRACTS_DIRwith legacy fallback)mixin_node_introspection(proper enum conversion)Test Plan
Files Changed
contracts/handlers/{db,consul,http,vault,filesystem,mcp}/handler_contract.yamlkernel.py,runtime_host_process.pymixin_node_introspection.pydocker-compose.e2e.yml,docker-compose.runtime.yml,Dockerfile.runtimetest_full_orchestrator_flow.py,test_two_way_registration_e2e.py004_capability_fields_concurrent.sql(renamed from 003a)Summary by CodeRabbit
New Features
Configuration Changes
Behavior Changes
Tests
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.