Skip to content

refactor(nodes): replace print statements with structured logging [OMN-701] - #187

Merged
jonahgabriel merged 5 commits into
mainfrom
jonah/omn-701-replace-print-statements-with-structured-logging
Dec 14, 2025
Merged

jonahgabriel merged 5 commits into
mainfrom
jonah/omn-701-replace-print-statements-with-structured-logging

Conversation

@jonahgabriel

@jonahgabriel jonahgabriel commented Dec 13, 2025 •

Copy link
Copy Markdown
Contributor

Summary

  • Replace all 16 print() statements in node implementations with structured logging
  • Add pre-commit validation to prevent future print() statements

Changes

Node Files Modified

File Print Statements Replacement
node_reducer.py 7 logger.debug/info/warning()
node_orchestrator.py 7 logger.debug/info/warning()
node_effect.py 2 logger.info/error()

Log Levels Applied

  • DEBUG: Status information, state changes, counts
  • INFO: Success confirmations, workflow completion
  • WARNING: Validation failures
  • ERROR: Effect failures

Prevention

  • New scripts/validation/check_no_print_statements.py validation script
  • Pre-commit hook added to catch print() statements before commit
  • Uses AST parsing for accurate detection (ignores strings/comments)
  • Supports # print-ok: reason comments for CLI tools that need print()

Test plan

  • All print() statements removed (verified via grep)
  • Python syntax valid for all files
  • mypy type checking passes (0 errors)
  • Unit tests pass (119 tests in tests/unit/nodes/)
  • Pre-commit hooks pass (37 hooks)
  • New validation script correctly catches print() statements

Reference

  • Linear: OMN-701
  • OMNIBASE_CORE_CODE_QUALITY_AUDIT.md - Section 2

Summary by CodeRabbit

  • New Features

    • Added automated validation to detect and prevent stray print() usage in code and docstring examples, with inline exemption support and CLI reporting.
  • Refactor

    • Replaced ad-hoc print calls with structured logging across core runtime components and examples.
  • Chores

    • Added a pre-commit hook to run the print-check validation.
    • Normalized contract fingerprint strings to include a leading "v" prefix.
  • Tests

    • Added comprehensive unit tests for the print-check validator and clarified fixture docstrings.

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

@coderabbitai

coderabbitai Bot commented Dec 13, 2025 •

Copy link
Copy Markdown
Contributor

Walkthrough

Adds a pre-commit hook and a new AST-based CLI to detect print() usage (including docstrings), replaces in-repo print() calls with logger calls or explanatory comments, and prefixes many contract/example fingerprint strings with v.

Changes

Cohort / File(s) Summary
Pre-commit configuration
\.pre-commit-config.yaml
Adds check-no-print-statements hook (entry: poetry run python scripts/validation/check_no_print_statements.py) targeting ^src/.*\.py$, with exclusions for tests/, archived/, archive/, scripts/validation/, src/omnibase_core/validation/, and paths containing example; appears twice in diff (duplicate entry).
Print statement validation script + tests
scripts/validation/check_no_print_statements.py, tests/unit/scripts/validation/test_check_no_print_statements.py
New AST-based CLI script that detects direct print() calls and print() usage in docstrings, honors # print-ok: exemptions, aggregates violation metadata, prints summaries, and exits non-zero on errors. Comprehensive unit tests covering many edge cases and CLI behaviors.
Nodes: replace prints with logging
src/omnibase_core/nodes/node_effect.py, src/omnibase_core/nodes/node_orchestrator.py, src/omnibase_core/nodes/node_reducer.py
Replaced inline and example print() calls with logger.* calls (debug/info/warning/error) and added example logger initialization; no API or control-flow changes.
Fallback logger explanatory comments
src/omnibase_core/logging/core_logging.py, src/omnibase_core/utils/util_simple_fallback_logger.py
Added comment # print-ok: fallback logger intentionally uses print when logging infra unavailable above existing fallback print() usage; behavior unchanged.
Contract and example fingerprint updates
contracts/runtime/..., examples/contracts/... (multiple YAMLs, e.g., contracts/runtime/contract_loader_effect.yaml, contracts/runtime/contract_registry_reducer.yaml, examples/contracts/...)
Normalized fingerprint strings by adding a leading v (e.g., 1.1.0:... → v1.1.0:...) across many runtime and example contract YAMLs; no structural or behavioral changes.
Tests — contract fixtures comments
tests/unit/contracts/test_runtime_contracts.py
Expanded in-code fixture design discussion and clarified load_contract_data docstring to match runtime behavior; no API changes.

Sequence Diagram(s)

sequenceDiagram
    participant Dev as Developer (git)
    participant Hook as pre-commit hook
    participant CLI as check_no_print_statements.py
    participant FS as Repo files (staged `src/*.py`)
    participant Console as Console / Exit

    Dev->>Hook: git commit (pre-commit runs)
    Hook->>CLI: execute `poetry run python scripts/validation/check_no_print_statements.py` (pass filenames)
    CLI->>FS: read staged Python files (source + lines)
    CLI->>CLI: parse AST, inspect Call nodes, analyze docstrings, apply `# print-ok:` exemptions
    CLI->>Console: print errors/warnings summary
    alt errors found
      Console->>Hook: exit non-zero (block commit)
    else only warnings or none
      Console->>Hook: exit zero (allow commit)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

  • Areas needing attention:
    • AST detection edge cases in PrintStatementDetector (qualified names, imported/wrapped print).
    • Docstring extraction and line-number mapping in check_docstring_prints().
    • Duplicate .pre-commit-config.yaml hook entry — confirm deduplication intent.
    • Test coverage assertions for exact line numbers and message contents.

Poem

🐰 I hopped through code with a twitch and a spin,
Found sneaky plain prints hiding deep within.
I swapped them for loggers, tidy and bright,
Guarded commits with a pre-commit light.
Carrots for clean code — hop, commit, delight!

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the primary objective: replacing print statements with structured logging across node implementations, with specific reference to the Linear ticket OMN-701.
Docstring Coverage ✅ Passed Docstring coverage is 98.53% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch jonah/omn-701-replace-print-statements-with-structured-logging

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

@claude

claude Bot commented Dec 13, 2025

Copy link
Copy Markdown

Code Review - PR #187: Replace print statements with structured logging

Overview

This PR successfully addresses OMN-701 by removing all 16 print() statements from production node implementations and replacing them with appropriate structured logging calls. The addition of a pre-commit validation hook is a strong preventative measure.


✅ Strengths

  1. Comprehensive Coverage

    • All print() statements removed from production code (node_reducer.py, node_orchestrator.py, node_effect.py)
    • Docstring examples updated to demonstrate best practices
    • Appropriate log levels applied (DEBUG for state info, INFO for success, WARNING for validation failures, ERROR for failures)
  2. Excellent Validation Script (scripts/validation/check_no_print_statements.py)

    • Uses AST parsing for accurate detection (ignores strings/comments)
    • Checks both code and docstrings
    • Supports # print-ok: reason escape hatch for CLI tools
    • Well-documented with clear rationale
    • Properly typed with mypy compliance
    • Good error handling (syntax errors, read errors)
    • Distinguishes errors vs warnings (docstrings are warnings only)
  3. Pre-commit Integration

    • Correctly configured in .pre-commit-config.yaml
    • Uses poetry run (follows project conventions)
    • Proper file filtering (^src/.*\.py$, excludes tests/archived/scripts)
    • Clear documentation in hook comments
  4. Follows Repository Conventions

    • Uses poetry run for execution
    • Proper type annotations for mypy strict mode
    • Clear commit message with Linear ticket reference
    • Comprehensive test plan in PR description

🔍 Issues & Recommendations

1. CRITICAL: Missing Logger Import in Docstrings (node_effect.py:126-167)

The updated docstring example in node_effect.py uses logger.info() and logger.error() but only shows:

import logging
logger = logging.getLogger(__name__)

Issue: This creates a module-level logger in the example, but the actual NodeEffect class uses self.logger from the base class.

Recommendation: Update the docstring example to either:

  • Show using self.logger within a class context, OR
  • Keep the module-level logger but add a comment explaining it's simplified for the example

Location: src/omnibase_core/nodes/node_effect.py:126-167


2. Minor: Validation Script Could Be More Robust

Issue: check_docstring_prints() has a potential edge case where multiline docstrings might calculate incorrect line numbers if the docstring contains escaped characters or raw strings.

Recommendation: Consider adding a test case for this edge case in the validation script's test suite (if one exists or will be created).

Severity: Low (unlikely to occur in practice)


3. Documentation: Pre-commit Hook Testing

Question: The PR description mentions "Pre-commit hooks pass (37 hooks)" but doesn't show evidence of the new hook being tested with actual violations.

Recommendation: Consider adding to the PR description or comments:

  • Example of the hook catching a print() statement
  • Screenshot or output showing the validation message

Severity: Low (nice-to-have for documentation)


4. Code Quality: Magic Numbers in Validation Script

Issue: Lines 218, 220 use magic number 60 for formatting width.

Recommendation: Extract to a constant:

_OUTPUT_WIDTH = 60
print(f"\n{'=' * _OUTPUT_WIDTH}")

Location: scripts/validation/check_no_print_statements.py:218-220

Severity: Very Low (style/maintainability)


🧪 Testing Recommendations

  1. Validation Script Tests (if not already covered):

    • Test with # print-ok: reason on same line
    • Test with # print-ok: reason on previous line
    • Test with print() in nested functions
    • Test with print() in lambda expressions
    • Test with multiline docstrings containing print()
  2. Integration Test:

    • Verify that the pre-commit hook actually runs in CI
    • Confirm that a commit with a print() statement is rejected

📊 Impact Assessment

Positive:

  • ✅ Improves observability (logs can be filtered, formatted, redirected)
  • ✅ Prevents future print() statements via pre-commit hook
  • ✅ Demonstrates best practices in documentation
  • ✅ Aligns with ONEX code quality standards

Risks:

  • ⚠️ Low: Docstring example in node_effect.py might confuse users about logger usage pattern

Performance: No impact (logging calls are already optimized in omnibase_core)

Security: No impact

Backwards Compatibility: No impact (internal refactoring only)


🎯 Recommendation: APPROVE with minor fix

This is a solid code quality improvement with excellent preventative tooling. The only blocker is the misleading logger example in node_effect.py docstring - once that's clarified, this is ready to merge.

Action Items:

  1. Fix the logger import example in node_effect.py:126-167 (REQUIRED)
  2. Consider extracting magic numbers in validation script (OPTIONAL)
  3. Add validation script tests for edge cases (OPTIONAL)

📚 References

  • CLAUDE.md: Error Handling & Best Practices (followed correctly)
  • CLAUDE.md: Poetry usage (followed correctly)
  • OMN-701: Linear ticket
  • OMNIBASE_CORE_CODE_QUALITY_AUDIT.md Section 2

Overall: Great work! This PR demonstrates excellent attention to detail and proactive engineering (the validation hook is particularly well done). 🎉

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 20d603d and 5118cd5.

📒 Files selected for processing (5)
  • .pre-commit-config.yaml (1 hunks)
  • scripts/validation/check_no_print_statements.py (1 hunks)
  • src/omnibase_core/nodes/node_effect.py (2 hunks)
  • src/omnibase_core/nodes/node_orchestrator.py (4 hunks)
  • src/omnibase_core/nodes/node_reducer.py (5 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Always use Poetry for Python package management and task execution - use poetry run for all Python commands (pytest, mypy, black, isort, etc.), never use pip or direct python execution
Call super().__init__(container) in all node class constructors - this is MANDATORY and eliminates 80+ lines of boilerplate initialization code
Always raise structured errors using ModelOnexError with appropriate EnumCoreErrorCode, never use generic Exception
Use container.get_service("ProtocolName") for dependency injection - always use protocol names, never concrete class names or isinstance checks
Use @standard_error_handling decorator on methods to eliminate 6+ lines of try/catch boilerplate
Do NOT share node instances across threads - use thread-local instances or separate instances per thread for NodeCompute, NodeEffect, NodeReducer, NodeOrchestrator
Use FileRegistry for loading RuntimeHostContract YAML files - handles fail-fast error reporting with specific error codes (FILE_NOT_FOUND, CONFIGURATION_PARSE_ERROR, CONTRACT_VALIDATION_ERROR, etc.)
Use the correct container type: ModelONEXContainer for dependency injection in node constructors, ModelContainer[T] only for wrapping single values with metadata
Use EnumNodeKind for architectural classification (EFFECT, COMPUTE, REDUCER, ORCHESTRATOR) and EnumNodeType for specific implementation type (TRANSFORMER, AGGREGATOR, GATEWAY, etc.)
Format code using poetry run black and sort imports using poetry run isort before committing
Lint code using poetry run ruff check to detect issues and apply auto-fixes with poetry run ruff check --fix

Files:

  • src/omnibase_core/nodes/node_reducer.py
  • src/omnibase_core/nodes/node_orchestrator.py
  • src/omnibase_core/nodes/node_effect.py
  • scripts/validation/check_no_print_statements.py
src/omnibase_core/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

src/omnibase_core/**/*.py: Achieve and maintain 100% mypy strict mode compliance with 0 errors across all source files
Achieve and maintain pyright basic mode compliance with 0 errors (targets Python 3.12)
For immutable value objects that are nested in other Pydantic models or used in parallel test execution, add from_attributes=True to ConfigDict
Use protocol-based dependency injection with container.get_service() - no isinstance checks with protocols (rely on duck typing instead)

Files:

  • src/omnibase_core/nodes/node_reducer.py
  • src/omnibase_core/nodes/node_orchestrator.py
  • src/omnibase_core/nodes/node_effect.py
src/omnibase_core/nodes/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Import nodes from omnibase_core.nodes using the unified import path - use NodeCompute, NodeReducer, NodeOrchestrator, NodeEffect (NOT with 'Declarative' suffix)

Files:

  • src/omnibase_core/nodes/node_reducer.py
  • src/omnibase_core/nodes/node_orchestrator.py
  • src/omnibase_core/nodes/node_effect.py
🧠 Learnings (6)
📚 Learning: 2025-12-13T20:59:19.537Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T20:59:19.537Z
Learning: ModelIntent pattern should be used in REDUCER nodes for pure FSM transitions without direct side effects

Applied to files:

  • src/omnibase_core/nodes/node_reducer.py
📚 Learning: 2025-12-13T20:59:19.537Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T20:59:19.537Z
Learning: Applies to src/omnibase_core/nodes/**/*.py : Import nodes from `omnibase_core.nodes` using the unified import path - use `NodeCompute`, `NodeReducer`, `NodeOrchestrator`, `NodeEffect` (NOT with 'Declarative' suffix)

Applied to files:

  • src/omnibase_core/nodes/node_reducer.py
  • src/omnibase_core/nodes/node_orchestrator.py
  • src/omnibase_core/nodes/node_effect.py
📚 Learning: 2025-12-13T20:59:19.537Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T20:59:19.537Z
Learning: Applies to **/*.py : Format code using `poetry run black` and sort imports using `poetry run isort` before committing

Applied to files:

  • .pre-commit-config.yaml
📚 Learning: 2025-12-13T20:59:19.537Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T20:59:19.537Z
Learning: Applies to **/*.py : Lint code using `poetry run ruff check` to detect issues and apply auto-fixes with `poetry run ruff check --fix`

Applied to files:

  • .pre-commit-config.yaml
📚 Learning: 2025-12-13T20:59:19.537Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T20:59:19.537Z
Learning: Applies to **/*.py : Always use Poetry for Python package management and task execution - use `poetry run` for all Python commands (pytest, mypy, black, isort, etc.), never use pip or direct python execution

Applied to files:

  • .pre-commit-config.yaml
📚 Learning: 2025-12-13T20:59:19.537Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T20:59:19.537Z
Learning: Applies to src/omnibase_core/**/*.py : Achieve and maintain pyright basic mode compliance with 0 errors (targets Python 3.12)

Applied to files:

  • .pre-commit-config.yaml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Smoke Tests
  • GitHub Check: claude-review
🔇 Additional comments (16)
src/omnibase_core/nodes/node_effect.py (2)

129-135: LGTM! Docstring example demonstrates structured logging best practices.

The example correctly shows how to set up logging with logging.getLogger(__name__) and uses the %s placeholder format which is idiomatic for Python logging (enables lazy evaluation).


166-169: Appropriate log levels for success/failure outcomes.

Using logger.info() for success confirmations and logger.error() for failures aligns with the PR's log level guidelines.

src/omnibase_core/nodes/node_reducer.py (5)

191-193: LGTM! Debug level appropriate for state transition details.

Using logger.debug() for FSM state and intent count information is correct as these are status details useful for debugging but not critical operational info.


256-260: Appropriate log levels for validation outcomes.

logger.warning() for validation failures and logger.info() for success aligns with the PR's log level guidelines.


277-279: LGTM!

logger.info() is appropriate for FSM completion events.


292-294: LGTM!

logger.debug() is appropriate for state progression tracing.


307-309: LGTM!

logger.info() is appropriate for workflow completion notifications.

src/omnibase_core/nodes/node_orchestrator.py (4)

149-151: LGTM! Debug level appropriate for execution metrics.

Using logger.debug() for step counts and action counts is correct for detailed execution tracing.


244-246: LGTM!

Consistent use of logger.debug() for status and action counts in docstring examples.


283-287: Consistent validation logging pattern.

Same pattern as node_reducer.py using logger.warning() for failures and logger.info() for success.


341-343: LGTM!

logger.debug() is appropriate for execution order details.

scripts/validation/check_no_print_statements.py (4)

1-34: Well-documented module with clear rationale.

The docstring clearly explains the purpose, detected patterns, usage, and rationale for the validation script.


37-91: LGTM! Clean AST visitor implementation.

The PrintStatementDetector class correctly:

  • Detects direct print() calls by checking ast.Name with id == "print"
  • Supports exemptions via # print-ok: comments on same line or line above
  • Uses generic_visit() to continue traversal

156-193: LGTM! Robust file processing with proper error handling.

The check_file function correctly:

  • Handles file read errors (OSError, UnicodeDecodeError)
  • Handles syntax errors gracefully
  • Combines AST-based detection with docstring checks

196-251: CLI output correctly uses # print-ok: exemptions.

The main() function appropriately uses # print-ok: CLI output comments for its own print statements since this is a CLI tool that needs to output to stdout. The exit code logic (fail on errors only, warnings don't block) is sensible.

.pre-commit-config.yaml (1)

301-311: LGTM! Hook configuration follows established patterns.

The new check-no-print-statements hook is correctly configured:

  • Uses poetry run python per coding guidelines
  • pass_filenames: true for efficient incremental checking
  • Appropriate exclusions for tests, archived, and validation scripts
  • Pre-commit stage is appropriate for quick validation

Comment thread scripts/validation/check_no_print_statements.py
…N-701]

Replace all print() statements in node implementations with structured
logging using Python's logging module for proper observability.

Changes:
- node_reducer.py: Replace 7 print() with logger.debug/info/warning
- node_orchestrator.py: Replace 7 print() with logger.debug/info/warning
- node_effect.py: Replace 2 print() with logger.info/error

Prevention:
- Add check_no_print_statements.py validation script
- Add pre-commit hook to prevent future print() statements
- Support # print-ok: comments for CLI tools that need print()

The validation script uses AST parsing to accurately detect print()
calls while ignoring comments and string literals.

Reference: OMNIBASE_CORE_CODE_QUALITY_AUDIT.md - Section 2
@jonahgabriel
jonahgabriel force-pushed the jonah/omn-701-replace-print-statements-with-structured-logging branch from 5118cd5 to 08ea79b Compare December 13, 2025 23:54

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5118cd5 and 08ea79b.

📒 Files selected for processing (7)
  • .pre-commit-config.yaml (1 hunks)
  • scripts/validation/check_no_print_statements.py (1 hunks)
  • src/omnibase_core/logging/core_logging.py (1 hunks)
  • src/omnibase_core/nodes/node_effect.py (2 hunks)
  • src/omnibase_core/nodes/node_orchestrator.py (4 hunks)
  • src/omnibase_core/nodes/node_reducer.py (5 hunks)
  • src/omnibase_core/utils/util_simple_fallback_logger.py (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • src/omnibase_core/logging/core_logging.py
  • src/omnibase_core/utils/util_simple_fallback_logger.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • scripts/validation/check_no_print_statements.py
  • src/omnibase_core/nodes/node_effect.py
🧰 Additional context used
📓 Path-based instructions (3)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Always use Poetry for Python package management and task execution - use poetry run for all Python commands (pytest, mypy, black, isort, etc.), never use pip or direct python execution
Call super().__init__(container) in all node class constructors - this is MANDATORY and eliminates 80+ lines of boilerplate initialization code
Always raise structured errors using ModelOnexError with appropriate EnumCoreErrorCode, never use generic Exception
Use container.get_service("ProtocolName") for dependency injection - always use protocol names, never concrete class names or isinstance checks
Use @standard_error_handling decorator on methods to eliminate 6+ lines of try/catch boilerplate
Do NOT share node instances across threads - use thread-local instances or separate instances per thread for NodeCompute, NodeEffect, NodeReducer, NodeOrchestrator
Use FileRegistry for loading RuntimeHostContract YAML files - handles fail-fast error reporting with specific error codes (FILE_NOT_FOUND, CONFIGURATION_PARSE_ERROR, CONTRACT_VALIDATION_ERROR, etc.)
Use the correct container type: ModelONEXContainer for dependency injection in node constructors, ModelContainer[T] only for wrapping single values with metadata
Use EnumNodeKind for architectural classification (EFFECT, COMPUTE, REDUCER, ORCHESTRATOR) and EnumNodeType for specific implementation type (TRANSFORMER, AGGREGATOR, GATEWAY, etc.)
Format code using poetry run black and sort imports using poetry run isort before committing
Lint code using poetry run ruff check to detect issues and apply auto-fixes with poetry run ruff check --fix

Files:

  • src/omnibase_core/nodes/node_orchestrator.py
  • src/omnibase_core/nodes/node_reducer.py
src/omnibase_core/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

src/omnibase_core/**/*.py: Achieve and maintain 100% mypy strict mode compliance with 0 errors across all source files
Achieve and maintain pyright basic mode compliance with 0 errors (targets Python 3.12)
For immutable value objects that are nested in other Pydantic models or used in parallel test execution, add from_attributes=True to ConfigDict
Use protocol-based dependency injection with container.get_service() - no isinstance checks with protocols (rely on duck typing instead)

Files:

  • src/omnibase_core/nodes/node_orchestrator.py
  • src/omnibase_core/nodes/node_reducer.py
src/omnibase_core/nodes/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Import nodes from omnibase_core.nodes using the unified import path - use NodeCompute, NodeReducer, NodeOrchestrator, NodeEffect (NOT with 'Declarative' suffix)

Files:

  • src/omnibase_core/nodes/node_orchestrator.py
  • src/omnibase_core/nodes/node_reducer.py
🧠 Learnings (4)
📚 Learning: 2025-12-13T20:59:19.537Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T20:59:19.537Z
Learning: Applies to **/*.py : Format code using `poetry run black` and sort imports using `poetry run isort` before committing

Applied to files:

  • .pre-commit-config.yaml
📚 Learning: 2025-12-13T20:59:19.537Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T20:59:19.537Z
Learning: Applies to **/*.py : Lint code using `poetry run ruff check` to detect issues and apply auto-fixes with `poetry run ruff check --fix`

Applied to files:

  • .pre-commit-config.yaml
📚 Learning: 2025-12-13T20:59:19.537Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T20:59:19.537Z
Learning: Applies to **/*.py : Always use Poetry for Python package management and task execution - use `poetry run` for all Python commands (pytest, mypy, black, isort, etc.), never use pip or direct python execution

Applied to files:

  • .pre-commit-config.yaml
📚 Learning: 2025-12-13T20:59:19.537Z
Learnt from: CR
Repo: OmniNode-ai/omnibase_core PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T20:59:19.537Z
Learning: Applies to src/omnibase_core/**/*.py : Achieve and maintain pyright basic mode compliance with 0 errors (targets Python 3.12)

Applied to files:

  • .pre-commit-config.yaml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Smoke Tests
🔇 Additional comments (1)
.pre-commit-config.yaml (1)

301-314: LGTM! Well-structured print statement prevention hook.

The hook configuration is well-designed with:

  • Appropriate exclusions for CLI tools and example files
  • Clear documentation of purpose and exemption mechanism
  • Consistent with other ONEX validation hooks
  • Proper use of poetry run as per coding guidelines

Comment thread src/omnibase_core/nodes/node_orchestrator.py
Comment thread src/omnibase_core/nodes/node_reducer.py
Address PR #187 review feedback:
- Add logger initialization to docstring examples in node_orchestrator.py
- Add logger initialization to docstring examples in node_reducer.py
- Fix off-by-one error in validation script for separate-line quotes

Users copying docstring examples will no longer encounter NameError
for undefined logger variable.
The v1.1.0 contract spec requires fingerprint versions to match
contract_version format with 'v' prefix (e.g., "v1.1.0:hash").

Fixed 12 contract files that had fingerprints without the 'v' prefix:
- contracts/runtime/*.yaml (5 files)
- examples/contracts/**/*.yaml (7 files)

This resolves the CI test failure in test_fingerprint_version_matches_contract_version.
@claude

claude Bot commented Dec 14, 2025

Copy link
Copy Markdown

PR Review: Replace print statements with structured logging

Summary

This PR successfully eliminates 16 print() statements across core node implementations and adds automated prevention via pre-commit hooks. The refactoring aligns with ONEX best practices for structured logging and observability.

✅ Strengths

  1. Comprehensive Coverage: All print statements removed from production code (node_reducer.py, node_orchestrator.py, node_effect.py)

  2. Well-Designed Validation Script:

    • AST-based detection (ignores strings/comments)
    • Smart exemption system (# print-ok: reason)
    • Separate severity levels (errors vs warnings)
    • Checks both code AND docstring examples
  3. Appropriate Log Levels: Thoughtful mapping of logging severity

    • DEBUG: State changes, counts, execution order
    • INFO: Success confirmations, completions
    • WARNING: Validation failures
    • ERROR: Effect failures
  4. Future-Proof Prevention: Pre-commit hook integration ensures new print() statements can't sneak in

  5. Excellent Documentation: Updated docstrings show best practices with logger examples

  6. Proper Exemptions: Fallback loggers correctly tagged with # print-ok comments

🔍 Issues Found

1. CRITICAL: Fingerprint Format Change Without Explanation ⚠️

All contract fingerprints changed from "1.1.0:hash" to "v1.1.0:hash" (added "v" prefix):

-fingerprint: "1.1.0:423f8598810c"
+fingerprint: "v1.1.0:423f8598810c"

Affected files: 13 YAML contract files

Questions:

  • Is this an intentional format change for all contracts?
  • Does this relate to OMN-701 or is it a separate change?
  • Will this break contract validation or fingerprint matching?
  • Should this be documented in CONTRACT_STABILITY_SPEC.md?

Recommendation: If unrelated to print statement removal, consider splitting into a separate PR with clear rationale.


2. Missing Test Coverage for Validation Script

No tests found for scripts/validation/check_no_print_statements.py (262 lines of code).

Recommended tests:

# tests/unit/validation/test_check_no_print_statements.py
def test_detects_direct_print():
    """Should catch print('hello') statements."""
    
def test_allows_print_ok_comment():
    """Should skip print() with # print-ok: reason."""
    
def test_detects_docstring_prints():
    """Should warn on print() in docstring examples."""
    
def test_ignores_print_in_strings():
    """Should not flag 'print' in string literals."""

Rationale: Pre-commit hooks are critical infrastructure - they need test coverage to ensure they don't break or miss violations.


3. Minor: Inconsistent String Formatting in Docstrings

Docstrings mix f-strings (removed) with %-formatting (added):

# Before (removed)
print(f"Success: {result.result}")

# After (added)  
logger.info("Effect succeeded: %s", result.result)

Why it matters: While %-formatting is correct for logging (lazy evaluation), it's inconsistent with the codebase's general preference for f-strings.

Recommendation: Document this pattern in CLAUDE.md or ERROR_HANDLING_BEST_PRACTICES.md:

"Use %-formatting for logger calls (lazy evaluation), f-strings for regular strings"


📊 Code Quality Assessment

Category Rating Notes
Code Quality ⭐⭐⭐⭐ Clean, well-structured refactoring
Best Practices ⭐⭐⭐⭐⭐ Follows ONEX patterns perfectly
Testing ⭐⭐ Missing tests for validation script
Security ⭐⭐⭐⭐⭐ No security concerns
Performance ⭐⭐⭐⭐⭐ No performance impact
Documentation ⭐⭐⭐⭐⭐ Excellent inline documentation

🔐 Security Review

✅ No security concerns - purely refactoring logging calls


⚡ Performance Considerations

✅ No performance impact. Structured logging may be marginally slower than print(), but negligible and worth the observability benefits.


🧪 Test Coverage Review

Existing tests: 119 tests in tests/unit/nodes/ should validate that logging doesn't break functionality

Missing tests: Validation script itself (check_no_print_statements.py)

Coverage requirement: Per CLAUDE.md, minimum 60% coverage required. Validation script currently has 0% coverage.


📝 Recommendations

  1. MUST FIX: Clarify fingerprint format change ("v" prefix) - explain rationale or revert
  2. SHOULD ADD: Unit tests for validation script (at least 4-5 test cases)
  3. NICE TO HAVE: Document %-formatting convention for logging calls

✅ Approval Recommendation

Status: ⚠️ Conditional Approval

Blockers:

  1. Explain/justify fingerprint format changes

Once addressed: LGTM to merge 🚀


📚 References

  • ✅ Follows CLAUDE.md structured error handling patterns
  • ✅ Aligns with ONEX best practices for observability
  • ✅ Pre-commit integration matches existing validation patterns
  • ⚠️ Missing test coverage per CLAUDE.md 60% requirement

Reviewed by: Claude Code Agent
Review Date: 2025-12-14
Linear: OMN-701

Address PR #137 feedback on test fixture duplication:
- Add comprehensive documentation explaining fixture pattern choice
- Document why factory and parameterized alternatives were rejected
- Enhance load_contract_data() docstring explaining centralization
- Current pattern is intentional: 2-line fixtures provide clarity
@claude

claude Bot commented Dec 14, 2025

Copy link
Copy Markdown

Code Review: Print Statement to Structured Logging Migration [OMN-701]

✅ Strengths

  1. Excellent Code Quality & AST-Based Detection

    • The validation script uses proper AST parsing instead of regex, avoiding false positives
    • Handles edge cases like docstring detection with offset calculations for opening quotes
    • Clean separation of concerns: PrintStatementDetector for code, check_docstring_prints for docs
  2. Well-Designed Exemption Mechanism

    • # print-ok: reason pattern is clear and self-documenting
    • Checks both same-line and line-above comments
    • All CLI tool prints are properly annotated with justification
  3. Consistent Logging Patterns

    • Docstring examples now demonstrate best practices using logger.debug/info/warning/error()
    • Proper use of f-string style logging: logger.debug("Status: %s", result.execution_status)
    • Follows ONEX conventions for structured logging
  4. Comprehensive Documentation

    • Script header clearly explains rationale, usage, and patterns
    • Pre-commit hook includes inline documentation
    • Good example comments in docstrings
  5. Contract Fingerprint Normalization

    • Added v prefix to all fingerprints for consistency (v1.1.0:...)
    • This is a good housekeeping improvement

⚠️ Issues & Recommendations

1. CRITICAL: Missing Test Coverage

The validation script (scripts/validation/check_no_print_statements.py, 262 lines) has zero test coverage. This is a violation of the project's 60% coverage requirement and standard practice for pre-commit hooks.

Required tests:

# tests/unit/validation/test_check_no_print_statements.py
import pytest
from pathlib import Path
from scripts.validation.check_no_print_statements import (
    PrintStatementDetector,
    check_docstring_prints,
    check_file,
)

class TestPrintStatementDetector:
    def test_detects_basic_print(self):
        """Should detect simple print() calls."""
        code = 'print("hello")'
        # ... test logic

    def test_ignores_print_ok_comment(self):
        """Should ignore prints with # print-ok: comment."""
        code = 'print("hello")  # print-ok: CLI output'
        # ... test logic

    def test_detects_docstring_prints(self):
        """Should detect print() in docstring examples."""
        # ... test logic

    def test_handles_syntax_errors_gracefully(self):
        """Should return error dict for invalid Python syntax."""
        # ... test logic

Reference: CLAUDE.md Section "Testing Guide" - all code requires 60%+ coverage.

2. Security: No Shebang Execution Validation

The script has #!/usr/bin/env python3 but there's no validation that it's being run with the correct Python version or Poetry environment.

Recommendation:

# Add to top of main()
if sys.version_info < (3, 12):
    print("ERROR: Python 3.12+ required", file=sys.stderr)
    return 1

3. Performance: Redundant AST Parsing

In check_file(), the code parses the AST twice:

  • Line 182: tree = ast.parse(source) for PrintStatementDetector
  • Line 104 (check_docstring_prints): tree = ast.parse(source) again

Recommendation:

def check_file(filepath: Path) -> list[dict[str, Any]]:
    # ... (file reading code)
    
    try:
        tree = ast.parse(source)  # Parse once
    except SyntaxError as e:
        return [...]
    
    # Pass tree to both functions
    detector = PrintStatementDetector(str(filepath), source_lines)
    detector.visit(tree)
    
    docstring_violations = check_docstring_prints(
        str(filepath), tree, source_lines  # Pass tree instead of re-parsing
    )
    
    return detector.violations + docstring_violations

This would require changing check_docstring_prints signature to accept tree: ast.Module instead of source: str.

4. Type Safety: Missing Return Type Annotation

Line 76: _has_print_ok_comment has return type but visit_Call doesn't:

def visit_Call(self, node: ast.Call) -> None:  # ✅ Good
    ...

def _has_print_ok_comment(self, line_num: int) -> bool:  # ✅ Good
    ...

But the class is missing a type annotation for violations initialization (though it's declared in __init__). This is fine for mypy strict mode, but could be more explicit.

5. Minor: Docstring Line Number Edge Case

Lines 125-131 handle the "opening quotes on separate line" offset, but there's a potential edge case with mixed quote styles or raw strings:

def foo():
    r"""
    Raw docstring with print(x)
    """

The offset logic assumes standard quotes. Consider testing with raw strings (r""") and f-strings (though f-strings in docstrings are rare).

6. Documentation: Contract Fingerprint Change Undocumented

The PR changes fingerprints from 1.1.0:... to v1.1.0:... across 13 contract files, but this isn't explained in the PR description or commit message. While this appears to be a normalization fix, it should be documented:

Recommendation: Add a note to the PR description explaining:

Contract Fingerprint Normalization: Added v prefix to all contract fingerprints to match the canonical format specified in docs/architecture/CONTRACT_STABILITY_SPEC.md. This is a metadata-only change that doesn't affect contract behavior.

🔍 Code Quality Details

Validation Script (check_no_print_statements.py)

Strengths:

  • ✅ Proper use of AST visitor pattern
  • ✅ Clean error handling with try/except for SyntaxError
  • ✅ Good separation of error vs warning severity
  • ✅ Helpful CLI output with line numbers and context

Suggested Improvements:

  • Add --help flag with usage examples
  • Add --strict flag to treat warnings as errors
  • Consider adding --fix flag for auto-fixing simple cases (though this may be complex)

Pre-Commit Hook Configuration

Potential Issue:

exclude: ^(tests/|archived/|archive/|scripts/validation/|src/omnibase_core/validation/|.*example.*).*\.py$

The regex .*example.* will match files like:

  • example_node.py ✅ (intended)
  • my_example_implementation.py ✅ (intended)
  • exampleservice.py ⚠️ (probably unintended - contains "example" but not in filename)

Consider making the pattern more specific:

exclude: ^(tests/|archived/|archive/|scripts/validation/|src/omnibase_core/validation/|.*example[_\-].*|.*[_\-]example.*).*\.py$

This would match example_, _example, example-, -example but not examplenode.

📋 Test Plan Verification

PR claims:

  • ✅ All print() statements removed (verified via grep) - VERIFIED by diff
  • ✅ Python syntax valid for all files - VERIFIED (would fail otherwise)
  • ✅ mypy type checking passes (0 errors) - VERIFIED in CI
  • ✅ Unit tests pass (119 tests in tests/unit/nodes/) - VERIFIED in CI
  • ✅ Pre-commit hooks pass (37 hooks) - VERIFIED in CI
  • ✅ New validation script correctly catches print() statements - NEEDS TEST COVERAGE

🎯 Recommendations Summary

MUST FIX (blocking):

  1. Add unit tests for check_no_print_statements.py to meet 60% coverage requirement
  2. Document contract fingerprint normalization in PR description

SHOULD FIX (non-blocking but important):
3. Optimize to parse AST only once per file
4. Add Python version check to validation script
5. Improve pre-commit exclude regex to be more specific

NICE TO HAVE:
6. Add --help, --strict flags to validation script
7. Test edge cases with raw strings and unusual docstring formats

✅ Approval Recommendation

Approve with requested changes - This is excellent work that significantly improves code quality and maintainability. The logging migration is thorough and the validation script is well-designed. However, the missing test coverage for the validation script is a blocker per project standards.

Once test coverage is added, this PR will be ready to merge. Great job on the AST-based detection and comprehensive print() removal! 🎉


Reference Documents:

  • CLAUDE.md - Testing Guide (60% coverage requirement)
  • CLAUDE.md - Code Quality (mypy strict mode)
  • CLAUDE.md - Architecture Fundamentals (structured logging)

…or [OMN-701]

Add 51 unit tests covering check_no_print_statements.py validation script:
- TestPrintStatementDetector (10 tests): AST-based print() detection
- TestCheckDocstringPrints (10 tests): docstring example validation
- TestCheckFile (7 tests): file-level checking and error handling
- TestEdgeCases (12 tests): edge cases and corner scenarios
- TestMainFunction (8 tests): CLI entry point behavior
- TestPrintOkCommentVariations (6 tests): print-ok marker handling

Addresses PR #187 feedback on missing test coverage.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
tests/unit/scripts/validation/test_check_no_print_statements.py (1)

61-235: Move ast import to module level.

Multiple test methods import ast locally (lines 71, 87, 103, 120, 140, 155, 170, 184, 204, 220). For consistency and efficiency, move this import to the module level with other imports.

Apply this diff to add the import at module level:

 from unittest.mock import patch
 
+import ast
 import pytest

Then remove all local import ast statements from within test methods.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9aaf8c3 and 5366326.

📒 Files selected for processing (1)
  • tests/unit/scripts/validation/test_check_no_print_statements.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Always use Poetry for Python package management and task execution - use poetry run for all Python commands (pytest, mypy, black, isort, etc.), never use pip or direct python execution
Call super().__init__(container) in all node class constructors - this is MANDATORY and eliminates 80+ lines of boilerplate initialization code
Always raise structured errors using ModelOnexError with appropriate EnumCoreErrorCode, never use generic Exception
Use container.get_service("ProtocolName") for dependency injection - always use protocol names, never concrete class names or isinstance checks
Use @standard_error_handling decorator on methods to eliminate 6+ lines of try/catch boilerplate
Do NOT share node instances across threads - use thread-local instances or separate instances per thread for NodeCompute, NodeEffect, NodeReducer, NodeOrchestrator
Use FileRegistry for loading RuntimeHostContract YAML files - handles fail-fast error reporting with specific error codes (FILE_NOT_FOUND, CONFIGURATION_PARSE_ERROR, CONTRACT_VALIDATION_ERROR, etc.)
Use the correct container type: ModelONEXContainer for dependency injection in node constructors, ModelContainer[T] only for wrapping single values with metadata
Use EnumNodeKind for architectural classification (EFFECT, COMPUTE, REDUCER, ORCHESTRATOR) and EnumNodeType for specific implementation type (TRANSFORMER, AGGREGATOR, GATEWAY, etc.)
Format code using poetry run black and sort imports using poetry run isort before committing
Lint code using poetry run ruff check to detect issues and apply auto-fixes with poetry run ruff check --fix

Files:

  • tests/unit/scripts/validation/test_check_no_print_statements.py
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

tests/**/*.py: Maintain minimum 60% code coverage requirement for all tests
Use pytest markers (@pytest.mark.unit, @pytest.mark.integration, @pytest.mark.slow, @pytest.mark.smoke, @pytest.mark.performance) to categorize tests
Run tests with CI performance expectations: average 2m58s per split across 20 parallel runners, with acceptable range 2m30s-3m30s and critical threshold >4m30s

Files:

  • tests/unit/scripts/validation/test_check_no_print_statements.py
🧬 Code graph analysis (1)
tests/unit/scripts/validation/test_check_no_print_statements.py (1)
scripts/validation/check_no_print_statements.py (2)
  • PrintStatementDetector (37-90)
  • check_docstring_prints (93-160)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Smoke Tests
  • GitHub Check: claude-review
🔇 Additional comments (6)
tests/unit/scripts/validation/test_check_no_print_statements.py (6)

237-387: LGTM!

The docstring print detection tests are comprehensive and cover various scenarios including function, class, and module docstrings, multiline offsets, print-ok suppression, and error handling.


389-489: LGTM!

The file-level checking tests comprehensively validate the integration of AST and docstring detection, along with proper error handling for missing files, syntax errors, and encoding issues.


491-622: LGTM!

The edge case tests thoroughly validate unusual but valid scenarios, including empty files, shadowed builtins, nested contexts, and multiline calls. The test at lines 537-552 correctly documents the expected behavior for shadowed print variables.


624-738: LGTM!

The main function tests validate the CLI entry point behavior across various scenarios, properly using mocks for sys.argv and fixtures for output capture. The tests confirm correct exit codes and output formatting.


740-826: LGTM!

The print-ok comment variation tests thoroughly validate the exact string matching behavior, including whitespace handling, case sensitivity, and similar-but-different comment formats. The tests correctly document the expected matching rules.


29-55: The dynamic import using importlib.util is the correct approach for this test file and is consistent with other tests in tests/unit/scripts/validation/ that import scripts with hyphenated filenames (e.g., validate-all-exports.py, validate-no-direct-io.py). Python module names cannot contain hyphens, making importlib.util.spec_from_file_location() necessary for these scripts. While check_no_print_statements.py has a standard filename without hyphens and could technically use a simpler approach, maintaining consistency with the pattern used for other validation scripts is appropriate. No changes needed.

@claude

claude Bot commented Dec 14, 2025

Copy link
Copy Markdown

Code Review - PR #187: Replace print statements with structured logging

Summary

Excellent refactor that eliminates technical debt and enforces best practices through automation. This PR successfully addresses OMN-701 by replacing 16 print() statements across core node implementations with structured logging and adding preventative validation.


Strengths

1. Comprehensive Solution

  • Complete coverage: All 16 print() statements in production code replaced
  • Prevention mechanism: Pre-commit hook ensures the problem does not recur
  • Documentation improvements: Docstring examples now demonstrate best practices
  • Smart exemptions: print-ok comment pattern for legitimate CLI usage

2. Well-Designed Validation Script
scripts/validation/check_no_print_statements.py:

  • AST-based detection: Accurate parsing, avoids false positives
  • Dual severity levels: Errors for production code, warnings for docstrings
  • Clear user guidance: Helpful error messages
  • Proper exclusions: Skips tests, validation, and example files
  • Excellent documentation

3. Appropriate Log Levels

  • DEBUG: Status info, state changes, counts
  • INFO: Success confirmations, workflow completion
  • WARNING: Validation failures
  • ERROR: Effect failures

4. Thorough Testing
tests/unit/scripts/validation/test_check_no_print_statements.py:

  • 826 lines of tests with comprehensive edge case coverage
  • Well-structured with clear test organization
  • Edge cases: Empty files, syntax errors, nested calls, multiline docstrings

5. Clean Implementation

  • Import consistency: All examples include import logging
  • Proper logger usage: logger = logging.getLogger(name) pattern
  • Format strings: Using percent-s, percent-d formatting
  • Context preservation: Error details passed via format args

Code Quality Assessment

Category Grade Notes
Architecture A Follows ONEX patterns correctly
Type Safety A No mypy errors expected
Error Handling A Handles SyntaxError, OSError, UnicodeDecodeError
Testing A 826 lines of tests, excellent coverage
Documentation A Clear docstrings, helpful comments
Performance A Minimal pre-commit impact
Security A No security concerns

Detailed Analysis

Contract Fingerprint Updates

  • All 13 contract fingerprints now have v prefix (v1.1.0:...)
  • Consistency improvement, no breaking changes

Pre-commit Hook Integration

  • Correct placement after mypy/pyright
  • Proper exclusions for tests, validation scripts, examples
  • Clear documentation

Exemption Pattern Usage

  • Two legitimate uses in fallback loggers (core_logging.py:83, util_simple_fallback_logger.py:24)
  • Correct usage for emergency fallback when logging infrastructure unavailable

Potential Issues and Recommendations

Minor: Documentation Consistency

  • Issue: Some docstring examples use logger = logging.getLogger(name) without showing logger initialization in class context
  • Recommendation: Consider showing ONEX DI pattern with container.get_service(ProtocolLogger)
  • Impact: Low - current examples are correct for standalone usage

Security Analysis

No security concerns identified:

  • Input validation present
  • No command injection risks (AST parsing, not exec/eval)
  • No path traversal risks
  • Exception handling prevents crashes

Performance Considerations

Pre-commit Impact:

  • AST parsing: approximately 1-2ms per file
  • Only runs on src/*.py files
  • Expected overhead: less than 100ms for typical commit

Verdict: Performance impact negligible.


Test Coverage Assessment

Coverage areas (10/10):

  1. Direct print() detection
  2. Multiple prints in same file
  3. Print with arguments (sep=, end=, etc.)
  4. print-ok comment exemptions
  5. Docstring print detection
  6. Multiline docstring offset calculation
  7. Error handling
  8. Edge cases
  9. CLI integration
  10. Severity levels

Verdict: Excellent test coverage for realistic scenarios.


Conventional Commits Compliance

Title: refactor(nodes): replace print statements with structured logging [OMN-701]

Correct format:

  • Type: refactor (correct)
  • Scope: nodes (correct)
  • Reference: [OMN-701] (correct)

Adherence to CLAUDE.md Standards

  • Poetry Usage: All commands use poetry run
  • Type Checking: No new Any types, consistent annotations
  • Error Handling: Proper exit codes, follows ONEX patterns
  • Testing: Unit test markers, timeout protection
  • Documentation: Clear docstrings, updated examples

Final Verdict

Recommendation: APPROVE - Merge after CI passes

Rationale:

  1. Solves stated problem completely
  2. Prevents regressions via pre-commit hook
  3. No breaking changes
  4. Excellent code quality
  5. Follows ONEX standards
  6. Minor issues only (optional improvements)

Confidence Level: High - Low-risk, high-value refactor


Additional Comments

Appreciation:

  • Documentation as code: Using docstring examples to enforce best practices is clever
  • Developer experience: Clear error messages make violations easy to fix
  • Testing thoroughness: 826 lines of tests shows attention to quality
  • Exemption mechanism: print-ok pattern is pragmatic

Future Enhancements (Optional):

  1. Consider adding --fix mode to auto-suggest logger replacements
  2. Could integrate with IDE linters via pyproject.toml
  3. Might add metrics to track violations over time

Review Metadata:

  • Reviewer: Claude (Sonnet 4.5)
  • Review Date: 2025-12-14
  • Files Changed: 21 files (+1200, -28)
  • Core Changes: 3 node files, 1 validation script, 1 pre-commit config
  • Test Coverage: 826 lines of new tests

Great work, @jonahgabriel! This PR demonstrates excellent software engineering practices: identifying technical debt, implementing a comprehensive solution, and preventing future occurrences through automation.

cc: Related to OMNIBASE_CORE_CODE_QUALITY_AUDIT.md - Section 2

@jonahgabriel
jonahgabriel merged commit 705b4f4 into main Dec 14, 2025
10 of 12 checks passed
jonahgabriel added a commit that referenced this pull request Dec 14, 2025
…s-before-v050

Fix fingerprint version format regression introduced in main:
- Remove 'v' prefix from contract fingerprints (e.g., "v1.1.0:hash" → "1.1.0:hash")
- The test spec explicitly requires NO 'v' prefix per test_contract_v110_fields.py
- Commit b4eb25a on main incorrectly added 'v' prefix claiming it was required
- The test regex r"\d+\.\d+\.\d+" does not allow 'v' prefix

Also cleaned up:
- Remove empty tests/unit/models/service/ directory
- Remove duplicate src/omnibase_core/models/service/ directory (canonical is services/)

Merges changes from:
- PR #187: Replace print statements with structured logging
- PR #189: Remove global mutable state from compute_executor
@jonahgabriel
jonahgabriel deleted the jonah/omn-701-replace-print-statements-with-structured-logging branch December 14, 2025 17:06
jonahgabriel pushed a commit that referenced this pull request Jan 23, 2026
Rename the `handler_kind` field to `node_archetype` across omnibase_core
to align with omnibase_infra PR #187 and establish canonical vocabulary
for contract-level architectural role classification.

Changes:
- Add EnumNodeArchetype enum (COMPUTE, EFFECT, REDUCER, ORCHESTRATOR)
- Add NodeArchetypeField type alias with BeforeValidator for YAML coercion
- Update ModelHandlerBehavior field: handler_kind → node_archetype
- Update ModelHandlerContract validator for consistency checks
- Update JSON schema with node_archetype property
- Update all factory profiles to use EnumNodeArchetype enum values
- Update validators, merge engine, and execution resolver
- Update validation script (handler_contract_validator.py)
- Update all tests (15 files), docs (4 files), and YAML examples (4 files)

Breaking change: Contracts must use `node_archetype` instead of `handler_kind`.
No backwards compatibility - schema rejects `handler_kind` field.
jonahgabriel added a commit that referenced this pull request Jan 23, 2026
…#428)

* refactor(contracts): rename handler_kind to node_archetype [OMN-1465]

Rename the `handler_kind` field to `node_archetype` across omnibase_core
to align with omnibase_infra PR #187 and establish canonical vocabulary
for contract-level architectural role classification.

Changes:
- Add EnumNodeArchetype enum (COMPUTE, EFFECT, REDUCER, ORCHESTRATOR)
- Add NodeArchetypeField type alias with BeforeValidator for YAML coercion
- Update ModelHandlerBehavior field: handler_kind → node_archetype
- Update ModelHandlerContract validator for consistency checks
- Update JSON schema with node_archetype property
- Update all factory profiles to use EnumNodeArchetype enum values
- Update validators, merge engine, and execution resolver
- Update validation script (handler_contract_validator.py)
- Update all tests (15 files), docs (4 files), and YAML examples (4 files)

Breaking change: Contracts must use `node_archetype` instead of `handler_kind`.
No backwards compatibility - schema rejects `handler_kind` field.

* refactor(contracts): simplify node_archetype comparison in validator [OMN-1465]

Remove unnecessary str() cast - EnumNodeArchetype inherits from str,
so enum values compare directly with strings.

* chore: bump version to 0.9.2, fix schema reference [OMN-1465]

- Bump version from 0.9.1 to 0.9.2 in pyproject.toml and __init__.py
- Fix schema description to reference EnumNodeArchetype instead of EnumNodeKind

---------

Co-authored-by: Claude (AI Assistant) <claude@omninode.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant