Skip to content

fix(OMN-13994): registry-aware ONEX_CC_REPO_PATH fallback in integration_sweep/dod_sweep - #1624

Merged
jonahgabriel merged 1 commit into
devfrom
jonah/omn-13994-onex-cc-repo-path-registry-fallback
Jul 5, 2026
Merged

jonahgabriel merged 1 commit into
devfrom
jonah/omn-13994-onex-cc-repo-path-registry-fallback

Conversation

@jonahgabriel

@jonahgabriel jonahgabriel commented Jul 5, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Makes the integration_sweep and dod_sweep orchestrator skills runnable from the canonical infra venv. Both resolve their contracts/artifact root from ONEX_CC_REPO_PATH via _resolve_root. A stale/container value (the in-container mount /onex_change_control) leaks into local runs where it has no contracts/ dir on the host, so _resolve_root raised RuntimeError and the sweep hard-failed before doing any work.

Fix

In _resolve_root (both handlers), when ONEX_CC_REPO_PATH is set but the resolved dir lacks a contracts/ subdir, fall back to Path(os.environ["OMNI_HOME"]) / "onex_change_control" (the canonical registry clone) before raising.

  • src/omnimarket/nodes/node_integration_sweep_orchestrator/handlers/handler_integration_sweep_orchestrator.py
  • src/omnimarket/nodes/node_dod_sweep_orchestrator/handlers/handler_dod_sweep_orchestrator.py

Fail-fast preserved (CLAUDE.md rule #8)

  • The fallback reads os.environ["OMNI_HOME"] — raises KeyError when unset, never a silent default.
  • If OMNI_HOME is unset (or its registry lacks contracts/) and the env path is invalid, resolution still raises.
  • The pre-existing "ONEX_CC_REPO_PATH is not set at all" branch is unchanged — still fail-fast.
  • The repo Validate no silent env fallbacks pre-commit hook passes.

Proof (behavioral, local)

With ONEX_CC_REPO_PATH=/onex_change_control (container leak, no host contracts/) and OMNI_HOME set, both handlers now resolve to $OMNI_HOME/onex_change_control instead of raising:

integration_sweep -> /Users/.../omni_home/onex_change_control
dod_sweep         -> /Users/.../omni_home/onex_change_control
fail-fast OK (unset OMNI_HOME raises KeyError): 'OMNI_HOME'

Tests

tests/test_resolve_root_fail_fast.py parametrized across BOTH handlers (16 cases, all green):

  • OMNI_HOME registry fallback on nonexistent env path + on container-path leak (behavioral)
  • unset OMNI_HOME → still raises (fail-fast, rule ci: add PyPI release workflow for v0.1.0 [OMN-7647] #8)
  • OMNI_HOME set but lacks onex_change_control/contracts → still raises
  • unchanged: unset env, valid root, explicit configured root

dod_evidence

  • OMN-13994 (child of OMN-13976, WS-M dogfood/adoption rail).
  • Two-file surgical wiring + parametrized tests for both sweeps.
  • Local gates green: ruff format/check, mypy --strict, pre-commit (all hooks pass; topic-naming-lint needs OMNIBASE_INFRA_PATH due to worktree nesting and passes when set — this change touches no topics).

Closes OMN-13994

Summary by CodeRabbit

  • Bug Fixes

    • Improved root-path resolution so the app can recover from stale or container-mounted paths by falling back to the expected local registry location.
    • Error messages now include both attempted paths when no valid registry directory is found, making failures easier to diagnose.
  • Tests

    • Expanded coverage for path resolution across both sweep flows, including fallback handling, invalid paths, and missing environment settings.

Evidence-Source: OCC#3631
Evidence-Ticket: OMN-13994

…ion_sweep/dod_sweep

Both sweep orchestrators resolve their contracts/artifact root from
ONEX_CC_REPO_PATH via _resolve_root. A stale/container value (the
in-container mount /onex_change_control) leaks into local infra-venv
runs where it has no contracts/ dir, so _resolve_root raised and the
sweep never ran.

Fall back to the canonical registry clone at $OMNI_HOME/onex_change_control
when the env path lacks contracts/, before raising. Fail-fast
(CLAUDE.md rule #8) is preserved: os.environ["OMNI_HOME"] raises
KeyError when unset (never a silent default), and a fallback that
itself lacks contracts/ still raises RuntimeError. The 'ONEX_CC_REPO_PATH
not set at all' branch is unchanged.

Parametrized tests cover both handlers: OMNI_HOME registry fallback
(behavioral) + unset-OMNI_HOME fail-fast.
@jonahgabriel
jonahgabriel enabled auto-merge July 5, 2026 21:14
@coderabbitai

coderabbitai Bot commented Jul 5, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Both DoD and Integration sweep orchestrator handlers' _resolve_root methods now fall back to OMNI_HOME/onex_change_control when a resolved ONEX_CC_REPO_PATH lacks a contracts/ directory, raising RuntimeError with both paths if the fallback also fails. Tests were refactored into shared parametrized coverage for both handlers.

Changes

Resolve Root Fallback Behavior

Layer / File(s) Summary
Fallback resolution logic
src/omnimarket/nodes/node_dod_sweep_orchestrator/handlers/handler_dod_sweep_orchestrator.py, src/omnimarket/nodes/node_integration_sweep_orchestrator/handlers/handler_integration_sweep_orchestrator.py
_resolve_root in both handlers now checks OMNI_HOME/onex_change_control for contracts/ when ONEX_CC_REPO_PATH resolves but lacks it, raising RuntimeError with both resolved and fallback paths only if both fail.
Shared parametrized test coverage
tests/test_resolve_root_fail_fast.py
Test module refactored from per-handler classes into parametrized module-level tests with shared scaffolding, covering env resolution, explicit overrides, OMNI_HOME fallback, and fail-fast KeyError/RuntimeError cases for both handlers.

Estimated code review effort: 2 (Simple) | ~12 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant ResolveRoot as "_resolve_root"
  participant Env as "Environment (ONEX_CC_REPO_PATH, OMNI_HOME)"
  participant FS as "Filesystem"

  Caller->>ResolveRoot: request root path
  ResolveRoot->>Env: read ONEX_CC_REPO_PATH
  ResolveRoot->>FS: check contracts/ at resolved path
  alt contracts/ found
    ResolveRoot-->>Caller: return resolved path
  else contracts/ missing
    ResolveRoot->>Env: read OMNI_HOME
    ResolveRoot->>FS: check contracts/ at OMNI_HOME/onex_change_control
    alt fallback contracts/ found
      ResolveRoot-->>Caller: return fallback path
    else fallback also missing
      ResolveRoot-->>Caller: raise RuntimeError (both paths)
    end
  end
Loading

Related Issues: None referenced in the provided context.

Related PRs: None referenced in the provided context.

Suggested labels: bug, tests

Suggested reviewers: None specified in the provided context.

🐰 A path once lost in a container's maze,
now finds its way through OMNI_HOME's grace,
contracts sought in fallback land,
tests hop along, both handlers spanned.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: registry-aware fallback handling for ONEX_CC_REPO_PATH in both sweep orchestrators.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jonah/omn-13994-onex-cc-repo-path-registry-fallback

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

@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown

⚠️ Architectural Review — WARNINGS

Errors: 0
Warnings: 1

What this checks

Rule Description
ARCH-TOPIC-001 No hardcoded Kafka topic strings in handler code
ARCH-DI-001 No event_bus=None bypass
ARCH-DI-002 No direct Handler instantiation outside workflow_runner/adapters
ARCH-DI-003 No reinvented DI containers
ARCH-TOPIC-002 contract.yaml topics follow `onex.{cmd

ARCH-DI-002: Direct Handler instantiation (warning)\n\n\nsrc/omnimarket/nodes/node_integration_sweep_orchestrator/handlers/handler_integration_sweep_orchestrator.py:58: self._runtime_sha_handler = runtime_sha_handler or HandlerRuntimeShaVerify()\n\n\nHandler classes should be wired only in workflow_runner.py or adapter modules. Direct instantiation elsewhere bypasses the contract system.\n\n

Powered by node_pr_review_bot

@github-actions

github-actions Bot commented Jul 5, 2026 •

Copy link
Copy Markdown

✅ PR Review Bot — CLEAN

Findings: 0
Run ID: ``

Required gate: This check blocks merge when verdict is blocking_issue.


Verdict semantics

Verdict Meaning
clean No blocking findings
risks_noted Findings noted; threads passed judge verification
blocking_issue MAJOR/CRITICAL findings not resolved — do not merge

Powered by node_pr_review_bot — Qwen3-Coder-30B reviewer + DeepSeek-R1 judge (OMN-7963)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

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

⚠️ Outside diff range comments (1)
src/omnimarket/nodes/node_dod_sweep_orchestrator/handlers/handler_dod_sweep_orchestrator.py (1)

925-951: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Duplicated _resolve_root fallback logic across two node handlers.

This entire fallback implementation (env-path check, OMNI_HOME fallback, dual RuntimeError) is byte-for-byte duplicated in handler_integration_sweep_orchestrator.py (differing only in the final "not set" error message wording). The test file itself acknowledges this: "The two handlers duplicate an identical _resolve_root staticmethod." Any future fix/behavior change to this fail-fast contract now requires synchronized edits in two places, risking drift.

Consider promoting this to a shared helper (e.g. a small function in a common/shared module accessible to both nodes) that both handlers call, parameterizing only the field name used in the "not set" error message.

♻️ Suggested extraction sketch
-    `@staticmethod`
-    def _resolve_root(configured: str) -> Path:
-        if configured:
-            return Path(configured).expanduser().resolve()
-        env_root = os.environ.get("ONEX_CC_REPO_PATH")  # contract-config-ok: config  # fmt: skip
-        if env_root:
-            resolved = Path(env_root).expanduser().resolve()
-            if resolved.exists() and (resolved / "contracts").is_dir():
-                return resolved
-            fallback = (
-                Path(os.environ["OMNI_HOME"]).expanduser().resolve()
-                / "onex_change_control"
-            )
-            if fallback.exists() and (fallback / "contracts").is_dir():
-                return fallback
-            raise RuntimeError(
-                f"ONEX_CC_REPO_PATH={env_root!r} resolves to {resolved} which "
-                "does not exist or lacks a contracts/ directory, and the "
-                f"OMNI_HOME fallback {fallback} also lacks a contracts/ directory"
-            )
-        raise RuntimeError(
-            "ONEX_CC_REPO_PATH is not set and no explicit contract_root/evidence_root was provided. "
-            "Set ONEX_CC_REPO_PATH to the omni_home repo registry path."
-        )
+    `@staticmethod`
+    def _resolve_root(configured: str) -> Path:
+        return resolve_onex_cc_root(configured, unset_hint="contract_root/evidence_root")

As per coding guidelines, src/omnimarket/nodes/node_*/**/*: "Keep node logic inside src/omnimarket/nodes/node_*... promote shared types instead" of cross-node duplication.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/omnimarket/nodes/node_dod_sweep_orchestrator/handlers/handler_dod_sweep_orchestrator.py`
around lines 925 - 951, The `_resolve_root` fallback logic is duplicated in the
two sweep orchestrator handlers, so extract the shared env-path/OMNI_HOME
resolution and dual RuntimeError handling into a common helper that both
handlers call. Keep the handler-specific “not set” wording parameterized, and
update the existing `_resolve_root` staticmethods in
`handler_dod_sweep_orchestrator.py` and
`handler_integration_sweep_orchestrator.py` to delegate to that shared function.

Source: Coding guidelines

🧹 Nitpick comments (1)
src/omnimarket/nodes/node_integration_sweep_orchestrator/handlers/handler_integration_sweep_orchestrator.py (1)

325-356: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicated _resolve_root across two node handlers.

This entire _resolve_root implementation (including the new fallback branch, comments, and error messages) is byte-for-byte duplicated in HandlerDodSweepOrchestrator._resolve_root in node_dod_sweep_orchestrator. Since node-local logic shouldn't cross-import between nodes, the guideline path forward is to promote this shared resolution logic into a common module (e.g. a shared utility under a non-node-specific package) that both handlers import, rather than maintaining two independently-evolving copies of the same fail-fast/fallback contract.

As per coding guidelines, src/omnimarket/nodes/node_*/**/*: "Do not make one node import another node's private handler or model package; promote shared types instead."

♻️ Suggested extraction
+# src/omnimarket/shared/resolve_contract_root.py
+import os
+from pathlib import Path
+
+
+def resolve_contract_root(configured: str) -> Path:
+    if configured:
+        return Path(configured).expanduser().resolve()
+    env_root = os.environ.get("ONEX_CC_REPO_PATH")  # contract-config-ok: config  # fmt: skip
+    if env_root:
+        resolved = Path(env_root).expanduser().resolve()
+        if resolved.exists() and (resolved / "contracts").is_dir():
+            return resolved
+        fallback = (
+            Path(os.environ["OMNI_HOME"]).expanduser().resolve()
+            / "onex_change_control"
+        )
+        if fallback.exists() and (fallback / "contracts").is_dir():
+            return fallback
+        raise RuntimeError(
+            f"ONEX_CC_REPO_PATH={env_root!r} resolves to {resolved} which "
+            "does not exist or lacks a contracts/ directory, and the "
+            f"OMNI_HOME fallback {fallback} also lacks a contracts/ directory"
+        )
+    raise RuntimeError(
+        "ONEX_CC_REPO_PATH is not set and no explicit root was provided. "
+        "Set ONEX_CC_REPO_PATH to the omni_home repo registry path."
+    )

Both handlers would then call resolve_contract_root(...) instead of maintaining their own _resolve_root staticmethod.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/omnimarket/nodes/node_integration_sweep_orchestrator/handlers/handler_integration_sweep_orchestrator.py`
around lines 325 - 356, The `_resolve_root` logic in
`HandlerIntegrationSweepOrchestrator` is duplicated in
`HandlerDodSweepOrchestrator`, so extract this shared contract-root resolution
into a common utility module that both handlers can import instead of keeping
two copies. Move the fallback, fail-fast checks, and error messaging into a
single shared function such as `resolve_contract_root(...)`, then update each
handler to call it from their `_resolve_root`/root-resolution path and remove
the duplicated implementation.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In
`@src/omnimarket/nodes/node_dod_sweep_orchestrator/handlers/handler_dod_sweep_orchestrator.py`:
- Around line 925-951: The `_resolve_root` fallback logic is duplicated in the
two sweep orchestrator handlers, so extract the shared env-path/OMNI_HOME
resolution and dual RuntimeError handling into a common helper that both
handlers call. Keep the handler-specific “not set” wording parameterized, and
update the existing `_resolve_root` staticmethods in
`handler_dod_sweep_orchestrator.py` and
`handler_integration_sweep_orchestrator.py` to delegate to that shared function.

---

Nitpick comments:
In
`@src/omnimarket/nodes/node_integration_sweep_orchestrator/handlers/handler_integration_sweep_orchestrator.py`:
- Around line 325-356: The `_resolve_root` logic in
`HandlerIntegrationSweepOrchestrator` is duplicated in
`HandlerDodSweepOrchestrator`, so extract this shared contract-root resolution
into a common utility module that both handlers can import instead of keeping
two copies. Move the fallback, fail-fast checks, and error messaging into a
single shared function such as `resolve_contract_root(...)`, then update each
handler to call it from their `_resolve_root`/root-resolution path and remove
the duplicated implementation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 98fb346d-adb8-4f2d-8d82-50a59da1af72

📥 Commits

Reviewing files that changed from the base of the PR and between a1a0d14 and e2c4b11.

📒 Files selected for processing (3)
  • src/omnimarket/nodes/node_dod_sweep_orchestrator/handlers/handler_dod_sweep_orchestrator.py
  • src/omnimarket/nodes/node_integration_sweep_orchestrator/handlers/handler_integration_sweep_orchestrator.py
  • tests/test_resolve_root_fail_fast.py

@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown

⚠️ Hostile Reviewer — DEGRADED (informational)

Blocking findings (critical/error): 0
Total findings: 0
Models succeeded: none

Note: All reviewer models failed or were unavailable. Degraded results are informational during the pilot phase (OMN-8524) and do not block merge. Error: cli_review exited non-zero (all models failed or binary error)


Gate semantics (pilot phase)

Verdict Meaning Blocks merge?
passed No critical/error findings No
blocked CRITICAL or ERROR findings found Yes
degraded All models unavailable (infra) No (pilot)

Powered by omniintelligence.review_pairing.cli_review — node-based adversarial review via HandlerLlmCliSubprocess (OMN-8524)

@jonahgabriel
jonahgabriel added this pull request to the merge queue Jul 5, 2026
Merged via the queue into dev with commit 85241ce Jul 5, 2026
86 of 91 checks passed
@jonahgabriel
jonahgabriel deleted the jonah/omn-13994-onex-cc-repo-path-registry-fallback branch July 5, 2026 23:47
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