Skip to content

Add support for native Codex telemetry - #31

Merged
dagardner-nv merged 41 commits into
NVIDIA:mainfrom
dagardner-nv:david-expand-codex-otel
Jul 3, 2026
Merged

Add support for native Codex telemetry#31
dagardner-nv merged 41 commits into
NVIDIA:mainfrom
dagardner-nv:david-expand-codex-otel

Conversation

@dagardner-nv

@dagardner-nv dagardner-nv commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator
  • Add a new telemetry.provider configuration attribute, for compatibility when unset the value default's to "relay"
  • Currently the only known/valid values are "relay" and "native"
  • Update the Codex CLI adapter to support Codex's built-in OTel exporter
  • build_command now only builds the command, writing out configuration files is moved to write_config_files
  • A named tuple CodexSettings added as a container for the various parameters passed around

Summary by CodeRabbit

  • New Features
    • Added support for selecting a telemetry provider (Relay or Native) and propagate this choice through runtime telemetry metadata.
    • Added example profiles for Native OpenTelemetry and Relay variants, and improved Codex runs with generated runtime profiles for Relay telemetry.
  • Bug Fixes
    • Relay observability artifacts now consistently include the run’s runtime ID in their output paths.
    • Hermes adapters now validate that only Relay telemetry is used, failing fast for Native.
  • Tests
    • Expanded coverage for provider selection behavior, output path normalization, and Codex command/profile generation.

Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
…based upon it being named 'plugins.toml' and being in the same directory as the config.toml. There is no way to provide an explicit path to the plugin toml

Signed-off-by: David Gardner <dagardner@nvidia.com>
…trings not a path to a toml file, fix placement of the codex --config flag to not conflict with relay's flags

Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
…rmes specific. Update codex adapter to use it

Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
@dagardner-nv dagardner-nv added the enhancement New feature or request label Jul 2, 2026
@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Adds explicit relay/native telemetry selection across schemas, core runtime, SDK normalization, and Hermes validation. Centralizes shared payload and relay-config helpers. Reworks the Codex CLI adapter for generated config files and relay gateway lifecycle. Adds new relay and native example profiles.

Changes

Telemetry provider concept (schema, core, SDK)

Layer / File(s) Summary
JSON schema updates for telemetry provider
schemas/adapter-invocation.schema.json, schemas/agent.schema.json, schemas/effective-config.schema.json, schemas/run-plan.schema.json
Adds provider and TelemetryProvider definitions to telemetry config and plan schemas, and requires provider in the run plan.
Rust TelemetryProvider enum and plan resolution
crates/fabric-core/src/config.rs, crates/fabric-core/src/lib.rs, crates/fabric-core/src/runtime.rs
Adds TelemetryProvider, threads it through config and plan resolution, re-exports it, and records telemetry_provider in runtime metadata with tests.
Python SDK telemetry normalization
python/src/nemo_fabric/types.py, tests/test_sdk_contract.py
TelemetryRef._normalize reads telemetry_provider from metadata and preserves native provider values in contract tests.
Hermes telemetry provider validation
adapters/common/src/nemo_fabric_adapters/common/hermes.py, adapters/hermes-cli/src/nemo_fabric_adapters/hermes_cli/adapter.py, adapters/hermes-sdk/src/nemo_fabric_adapters/hermes_sdk/adapter.py, tests/test_adapaters_common_hermes.py, tests/test_hermes_cli.py, tests/test_hermes_sdk_adapter.py
Adds relay-only provider validation in Hermes adapters and updates their tests to reject native telemetry.
Estimated code review effort: 4 (Complex) ~60 minutes

Common payload/session/relay-config utilities

Layer / File(s) Summary
load_payload, runtime_session_id, telemetry helpers, write_relay_configs
adapters/common/src/nemo_fabric_adapters/common/utils.py, adapters/common/src/nemo_fabric_adapters/common/hermes.py, tests/test_adapaters_common_hermes.py
Adds payload loading, runtime session derivation, telemetry helpers, runtime-id-aware relay output directories, and dual-file relay config writing; removes the local Hermes session helper and updates tests.
Adapter entrypoints use common load_payload/runtime_session_id
adapters/hermes-cli/src/nemo_fabric_adapters/hermes_cli/adapter.py, adapters/hermes-sdk/src/nemo_fabric_adapters/hermes_sdk/adapter.py
Hermes CLI/SDK adapters switch to shared payload loading and session-id helpers.
Estimated code review effort: 3 (Moderate) ~25 minutes

Codex CLI adapter relay gateway and profile generation

Layer / File(s) Summary
CodexSettings contract and constants
adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py
Adds CodexSettings and related constants used to carry profile, telemetry, and relay state.
Config override, telemetry config, and profile/relay file writing
adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py
Builds native OTEL config, merges overrides, writes generated Codex and relay config files, and derives the generated profile path.
build_command and build_env using CodexSettings
adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py
build_command derives profile and bypass-trust flags from CodexSettings; build_env injects NEMO_RELAY_GATEWAY_URL; relay gateway helpers use the generated config paths.
run_codex orchestration, relay lifecycle, and output
adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py
Generates config files, starts and stops the relay gateway, runs Codex with the generated settings, and attaches relay runtime/artifacts to output.
Codex CLI adapter and harbor runner test updates
tests/test_codex_cli.py, tests/test_harbor_runner.py, pyproject.toml
Updates fixtures, command/config assertions, relay lifecycle tests, harbor runner wiring, and the TOML dependency fallback.
Estimated code review effort: 4 (Complex) ~75 minutes

New composable telemetry example profiles

Layer / File(s) Summary
New profile YAML files
examples/code-review-agent/profiles/relay.yaml, examples/code-review-agent/profiles/relay-otel.yaml, examples/code-review-agent/profiles/relay-openinference.yaml, examples/code-review-agent/profiles/native-otel.yaml
Adds standalone relay and native telemetry profile YAML files under examples/code-review-agent/profiles.
Estimated code review effort: 2 (Simple) ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant main
  participant write_config_files
  participant start_relay_gateway
  participant CodexProcess
  main->>write_config_files: payload
  write_config_files-->>main: CodexSettings
  main->>start_relay_gateway: cwd, CodexSettings
  start_relay_gateway-->>main: relay process ready
  main->>CodexProcess: build_command + build_env
  CodexProcess-->>main: output
  main->>start_relay_gateway: stop after cleanup
Loading
sequenceDiagram
  participant TelemetryConfig
  participant resolve_telemetry_plan
  participant TelemetryPlan
  participant runtime_telemetry_context
  participant telemetry_ref
  TelemetryConfig->>resolve_telemetry_plan: provider, enabled
  resolve_telemetry_plan->>TelemetryPlan: provider, relay_enabled
  TelemetryPlan->>runtime_telemetry_context: telemetry metadata
  runtime_telemetry_context->>telemetry_ref: runtime telemetry
  telemetry_ref->>TelemetryPlan: provider in metadata
Loading

Related issues: None found in the provided context.

Related PRs: None found in the provided context.

Suggested labels: telemetry, codex-cli, relay, schema-change

Suggested reviewers: Reviewers familiar with fabric-core telemetry config, Codex CLI relay integration, and common adapter utilities.

Poem

Relay and native paths now part,
Profiles, schemas, runtime, heart.
Configs write, gateways start,
Metadata keeps provider smart.


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error)

Check name Status Explanation Resolution
Title check ❌ Error The title matches the change, but it does not use the required Conventional Commits format. Rewrite it as Conventional Commits, e.g. "feat(codex-cli): add native Codex telemetry support".
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@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.

Actionable comments posted: 6

🤖 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.

Inline comments:
In `@adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py`:
- Around line 285-296: `write_config_files()` and `get_codex_profile_path()`
ignore `settings["codex_profile"]`, so the configured profile is never used and
docs are now misleading. Update the Codex CLI adapter to either read and honor
`harness.settings.codex_profile` when building the profile path, or remove that
setting consistently from the README and any related fixture/config references.
Use the existing symbols `write_config_files`, `get_codex_profile_path`, and
`common_utils.settings_payload` to keep the behavior and documentation aligned.

In `@adapters/common/src/nemo_fabric_adapters/common/utils.py`:
- Around line 41-47: `load_payload` currently falls back to `sys.stdin` even
when `FABRIC_INVOCATION` is set to an invalid path, which hides
misconfiguration. Update `load_payload` in the utils module so that if
`FABRIC_INVOCATION` is present but `Path(invocation_path).is_file()` is false,
it raises a clear error instead of reading from stdin; keep the stdin path only
for the case where `FABRIC_INVOCATION` is unset.

In `@tests/test_adapaters_common_hermes.py`:
- Around line 96-121: Remove the explicit `-> None` return annotations from the
test functions `test_validate_hermes_telemetry_provider_accepts_relay` and
`test_validate_hermes_telemetry_provider_rejects_native` in the Hermes test
module, and keep the rest of the test logic unchanged. Follow the test-style
rule for `tests/**/*.py` by leaving pytest test function signatures unannotated
while preserving the existing `hermes_common.validate_hermes_telemetry_provider`
assertions and parameterization.

In `@tests/test_adapaters_common_utils.py`:
- Around line 210-246: Add a test for write_relay_configs covering the (None,
None) case to lock down the expected behavior when no configs are provided. In
test_write_relay_configs, include a parameter set where both relay_config and
plugin_config are None and assert whether FABRIC_RELAY_CONFIG_PATH is still
required or whether the function should return empty/None paths. Use the
existing write_relay_configs symbol and keep the assertions aligned with the
current config-file path handling.
- Around line 232-234: The test is violating the environment փոփոխation
guideline by using monkeypatch.setenv in the test setup. Update the fixture or
test around the FABRIC_RELAY_CONFIG_PATH assignment to write directly to
os.environ instead of calling monkeypatch.setenv, and keep the change localized
in the same test helper block so restore_environ_fixture can handle cleanup.
- Around line 59-81: Update the two `test_load_payload_*` tests to modify
environment variables through `os.environ` rather than `monkeypatch.setenv` and
`monkeypatch.delenv`, since `restore_environ_fixture` already resets env state
between tests. In `test_load_payload_reads_fabric_invocation`, assign
`FABRIC_INVOCATION` directly in `os.environ` before calling
`common_utils.load_payload()`, and in `test_load_payload_falls_back_to_stdin`,
remove that key from `os.environ` before exercising the stdin fallback; keep the
existing `common_utils.load_payload` assertions unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: f146c4ff-c0b2-4b79-bcff-2154b33b537d

📥 Commits

Reviewing files that changed from the base of the PR and between a7bc73a and 2b2696a.

📒 Files selected for processing (33)
  • .agents/skills/python-tests/SKILL.md
  • adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/hermes.py
  • adapters/common/src/nemo_fabric_adapters/common/utils.py
  • adapters/hermes-cli/src/nemo_fabric_adapters/hermes_cli/adapter.py
  • adapters/hermes-sdk/src/nemo_fabric_adapters/hermes_sdk/adapter.py
  • crates/fabric-core/src/config.rs
  • crates/fabric-core/src/lib.rs
  • crates/fabric-core/src/runtime.rs
  • examples/code-review-agent/profiles/hermes-cli-relay-otel.yaml
  • examples/code-review-agent/profiles/hermes-cli-relay.yaml
  • examples/code-review-agent/profiles/hermes-relay-cli-openinference.yaml
  • examples/code-review-agent/profiles/hermes-relay-openinference.yaml
  • examples/code-review-agent/profiles/hermes-relay-otel.yaml
  • examples/code-review-agent/profiles/hermes-relay.yaml
  • examples/code-review-agent/profiles/native-otel.yaml
  • examples/code-review-agent/profiles/relay-openinference.yaml
  • examples/code-review-agent/profiles/relay-otel.yaml
  • examples/code-review-agent/profiles/relay.yaml
  • python/src/nemo_fabric/types.py
  • schemas/adapter-invocation.schema.json
  • schemas/agent.schema.json
  • schemas/effective-config.schema.json
  • schemas/run-plan.schema.json
  • tests/smoke_cli.py
  • tests/smoke_relay_integration.py
  • tests/test_adapaters_common_hermes.py
  • tests/test_adapaters_common_utils.py
  • tests/test_codex_cli.py
  • tests/test_hermes_cli.py
  • tests/test_hermes_e2e.py
  • tests/test_hermes_sdk_adapter.py
  • tests/test_sdk_contract.py
💤 Files with no reviewable changes (6)
  • examples/code-review-agent/profiles/hermes-relay-openinference.yaml
  • examples/code-review-agent/profiles/hermes-relay-otel.yaml
  • examples/code-review-agent/profiles/hermes-relay-cli-openinference.yaml
  • examples/code-review-agent/profiles/hermes-relay.yaml
  • examples/code-review-agent/profiles/hermes-cli-relay.yaml
  • examples/code-review-agent/profiles/hermes-cli-relay-otel.yaml
📜 Review details
⚠️ CI failures not shown inline (2)

GitHub Actions: Rust / 0_Test.txt: Add support for native Codex telemetry

Conclusion: failure

View job details

##[group]Run cargo test --workspace --locked
 �[36;1mcargo test --workspace --locked�[0m
 shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0}
 env:
   CARGO_INCREMENTAL: 0
   CARGO_PROFILE_DEV_DEBUG: 0
   CARGO_TERM_COLOR: always
   RUST_BACKTRACE: short
   RUSTFLAGS: -D warnings
   CARGO_UNSTABLE_SPARSE_REGISTRY: true
   CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
   CACHE_ON_FAILURE: false
 ##[endgroup]
 �[1m�[92m Downloading�[0m crates ...
 �[1m�[92m  Downloaded�[0m cfg-if v1.0.4
 �[1m�[92m  Downloaded�[0m strsim v0.11.1
 �[1m�[92m  Downloaded�[0m clap_lex v1.1.0
 �[1m�[92m  Downloaded�[0m bitflags v2.13.0
 �[1m�[92m  Downloaded�[0m anstyle-query v1.1.5
 �[1m�[92m  Downloaded�[0m utf8parse v0.2.2
 �[1m�[92m  Downloaded�[0m cfg_aliases v0.2.1
 �[1m�[92m  Downloaded�[0m anstyle-parse v1.0.0
 �[1m�[92m  Downloaded�[0m clap_derive v4.6.1
 �[1m�[92m  Downloaded�[0m clap v4.6.1
 �[1m�[92m  Downloaded�[0m anstyle v1.0.14
 �[1m�[92m  Downloaded�[0m anstream v1.0.0
 �[1m�[92m  Downloaded�[0m is_terminal_polyfill v1.70.2
 �[1m�[92m  Downloaded�[0m ctrlc v3.5.2
 �[1m�[92m  Downloaded�[0m colorchoice v1.0.5
 �[1m�[92m  Downloaded�[0m clap_builder v4.6.0
 �[1m�[92m  Downloaded�[0m nix v0.31.3
 �[1m�[92m   Compiling�[0m serde_core v1.0.228
 �[1m�[92m   Compiling�[0m itoa v1.0.18
 �[1m�[92m   Compiling�[0m zmij v1.0.21
 �[1m�[92m   Compiling�[0m equivalent v1.0.2
 �[1m�[92m   Compiling�[0m memchr v2.8.1
 �[1m�[92m   Compiling�[0m hashbrown v0.17.1
 �[1m�[92m   Compiling�[0m indexmap v2.14.0
 �[1m�[92m   Compiling�[0m ref-cast v1.0.25
 �[1m�[92m   Compiling�[0m unsafe-libyaml v0.2.11
 �[1m�[92m   Compiling�[0m serde v1.0.228
 �[1m�[92m   Compiling�[0m serde_json v1.0.150
 �[1m�[92m   Compiling�[0m utf8parse v0.2.2
 �[1m�[92m   Compiling�[0m cfg_aliases v0.2.1
 �[1m�[92m   Compiling�[0m libc v0.2.186
 �[1m�[92m   Compiling�[0m dyn-clone v1.0.20
 �[1m�[92m   Compiling�[0m ryu v1.0.23
 �[1m�[92m   Compiling�[0m serde_yaml v0.9.34+deprecated
 �[1m�[92m   Compiling�[0m sche...

GitHub Actions: Rust / Test: Add support for native Codex telemetry

Conclusion: failure

View job details

##[group]Run cargo test --workspace --locked
 �[36;1mcargo test --workspace --locked�[0m
 shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0}
 env:
   CARGO_INCREMENTAL: 0
   CARGO_PROFILE_DEV_DEBUG: 0
   CARGO_TERM_COLOR: always
   RUST_BACKTRACE: short
   RUSTFLAGS: -D warnings
   CARGO_UNSTABLE_SPARSE_REGISTRY: true
   CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
   CACHE_ON_FAILURE: false
 ##[endgroup]
 �[1m�[92m Downloading�[0m crates ...
 �[1m�[92m  Downloaded�[0m cfg-if v1.0.4
 �[1m�[92m  Downloaded�[0m strsim v0.11.1
 �[1m�[92m  Downloaded�[0m clap_lex v1.1.0
 �[1m�[92m  Downloaded�[0m bitflags v2.13.0
 �[1m�[92m  Downloaded�[0m anstyle-query v1.1.5
 �[1m�[92m  Downloaded�[0m utf8parse v0.2.2
 �[1m�[92m  Downloaded�[0m cfg_aliases v0.2.1
 �[1m�[92m  Downloaded�[0m anstyle-parse v1.0.0
 �[1m�[92m  Downloaded�[0m clap_derive v4.6.1
 �[1m�[92m  Downloaded�[0m clap v4.6.1
 �[1m�[92m  Downloaded�[0m anstyle v1.0.14
 �[1m�[92m  Downloaded�[0m anstream v1.0.0
 �[1m�[92m  Downloaded�[0m is_terminal_polyfill v1.70.2
 �[1m�[92m  Downloaded�[0m ctrlc v3.5.2
 �[1m�[92m  Downloaded�[0m colorchoice v1.0.5
 �[1m�[92m  Downloaded�[0m clap_builder v4.6.0
 �[1m�[92m  Downloaded�[0m nix v0.31.3
 �[1m�[92m   Compiling�[0m serde_core v1.0.228
 �[1m�[92m   Compiling�[0m itoa v1.0.18
 �[1m�[92m   Compiling�[0m zmij v1.0.21
 �[1m�[92m   Compiling�[0m equivalent v1.0.2
 �[1m�[92m   Compiling�[0m memchr v2.8.1
 �[1m�[92m   Compiling�[0m hashbrown v0.17.1
 �[1m�[92m   Compiling�[0m indexmap v2.14.0
 �[1m�[92m   Compiling�[0m ref-cast v1.0.25
 �[1m�[92m   Compiling�[0m unsafe-libyaml v0.2.11
 �[1m�[92m   Compiling�[0m serde v1.0.228
 �[1m�[92m   Compiling�[0m serde_json v1.0.150
 �[1m�[92m   Compiling�[0m utf8parse v0.2.2
 �[1m�[92m   Compiling�[0m cfg_aliases v0.2.1
 �[1m�[92m   Compiling�[0m libc v0.2.186
 �[1m�[92m   Compiling�[0m dyn-clone v1.0.20
 �[1m�[92m   Compiling�[0m ryu v1.0.23
 �[1m�[92m   Compiling�[0m serde_yaml v0.9.34+deprecated
 �[1m�[92m   Compiling�[0m sche...
🧰 Additional context used
📓 Path-based instructions (7)
{adapters/**,examples/**}

⚙️ CodeRabbit configuration file

{adapters/**,examples/**}: Review adapter and example changes for command correctness, config/schema consistency, artifact handling, and compatibility with the public Fabric contracts.

Files:

  • examples/code-review-agent/profiles/relay.yaml
  • examples/code-review-agent/profiles/relay-otel.yaml
  • examples/code-review-agent/profiles/native-otel.yaml
  • examples/code-review-agent/profiles/relay-openinference.yaml
  • adapters/hermes-sdk/src/nemo_fabric_adapters/hermes_sdk/adapter.py
  • adapters/hermes-cli/src/nemo_fabric_adapters/hermes_cli/adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/hermes.py
  • adapters/common/src/nemo_fabric_adapters/common/utils.py
  • adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py
.agents/skills/python-tests/**

⚙️ CodeRabbit configuration file

.agents/skills/python-tests/**: ---
name: python-tests
description: Python tests for Fabric; use this when writing tests
author: NVIDIA Corporation and Affiliates
license: Apache-2.0

Python Test Style

  • Pytest is used to run tests.
  • Do not add @pytest.mark.asyncio to any test. Async tests are automatically detected and run by the async runner; the decorator is unnecessary clutter.
  • Do not add a -> None return type annotation to test functions. This is not a common convention in pytest and adds unnecessary verbosity.
  • When mocking a class, do not define a new class. Use unittest.mock.MagicMock or unittest.mock.AsyncMock, with the spec constructor argument when necessary.
  • The name of the mocked class should be prefixed with mock, not fake.
  • Prefer pytest fixtures over helper methods.
  • Do not repeat fixtures, if a fixture is needed in multiple test files, place it in a conftest.py file.
  • When creating a fixture follow this pattern:
    `@pytest.fixture`(name="<fixture_name>"[, scope="<scope>"])
    def <fixture_name>_fixture() -> <return_type>:
        ...
    Only specify the scope argument when the value is something other than "function".
  • Prefer pytest.mark.parametrize over creating individual tests for
    different input types.
  • If a fixture is needed for a test, but either does not return a value or the value is not used in the test, use the @pytest.mark.usefixtures decorator.

Common Commands

# Focused test loop
uv run pytest -k "<pattern>"

# Run all tests
uv run pytest

References

  • pyproject.toml
  • tests/conftest.py

Files:

  • .agents/skills/python-tests/SKILL.md
**/tests/**/*.py

📄 CodeRabbit inference engine (.agents/skills/python-tests/SKILL.md)

**/tests/**/*.py: Use Pytest for Fabric Python tests.
Do not add @pytest.mark.asyncio to tests; async tests are auto-detected and run by the async runner.
Do not add a -> None return type annotation to test functions.
When mocking a class, use unittest.mock.MagicMock or unittest.mock.AsyncMock (with spec when needed) instead of defining a new mock class.
Name mocked classes with the mock prefix, not fake.
Prefer pytest fixtures over helper methods.
Do not repeat fixtures across test files; if a fixture is needed in multiple test files, place it in a conftest.py file.
When creating a fixture, use @pytest.fixture(name="<fixture_name>"[, scope="<scope>"]) with def <fixture_name>_fixture() -> <return_type>:; only specify scope when it is not function.
Prefer pytest.mark.parametrize over creating individual tests for different input types.
If a fixture is needed for a test but does not return a value, or its value is unused, use @pytest.mark.usefixtures.
If a test needs to modify environment variables, use os.environ; tests/conftest.py provides an autouse restore_environ_fixture that restores the environment after each test, so monkeypatch.setenv is unnecessary.

Files:

  • tests/test_hermes_cli.py
  • tests/test_hermes_sdk_adapter.py
  • tests/smoke_cli.py
  • tests/test_sdk_contract.py
  • tests/smoke_relay_integration.py
  • tests/test_adapaters_common_hermes.py
  • tests/test_adapaters_common_utils.py
  • tests/test_hermes_e2e.py
  • tests/test_codex_cli.py
{tests/**,python/tests/**}

⚙️ CodeRabbit configuration file

{tests/**,python/tests/**}: Tests should cover the behavior promised by the changed API surface, including error paths, lifecycle cleanup, and SDK/native parity where relevant.

Files:

  • tests/test_hermes_cli.py
  • tests/test_hermes_sdk_adapter.py
  • tests/smoke_cli.py
  • tests/test_sdk_contract.py
  • tests/smoke_relay_integration.py
  • tests/test_adapaters_common_hermes.py
  • tests/test_adapaters_common_utils.py
  • tests/test_hermes_e2e.py
  • tests/test_codex_cli.py
python/src/nemo_fabric/**/*

⚙️ CodeRabbit configuration file

python/src/nemo_fabric/**/*: Review Python SDK changes for typed API consistency, import-time dependency neutrality, async/session behavior, and parity with the native extension.
Stubs and runtime implementations should stay aligned.

Files:

  • python/src/nemo_fabric/types.py
crates/fabric-core/src/**/*.rs

⚙️ CodeRabbit configuration file

crates/fabric-core/src/**/*.rs: Review the Rust core for runtime lifecycle correctness, handle validation, capability routing accuracy, schema stability, and error semantics.
Public API changes should match committed schemas, tests, and documentation.

Files:

  • crates/fabric-core/src/lib.rs
  • crates/fabric-core/src/runtime.rs
  • crates/fabric-core/src/config.rs
schemas/**/*

⚙️ CodeRabbit configuration file

schemas/**/*: Schemas are generated public contract snapshots. Check that schema diffs correspond to intentional Rust type changes and are covered by core tests.

Files:

  • schemas/effective-config.schema.json
  • schemas/agent.schema.json
  • schemas/adapter-invocation.schema.json
  • schemas/run-plan.schema.json
🧠 Learnings (2)
📚 Learning: 2026-06-28T04:03:32.877Z
Learnt from: AjayThorve
Repo: NVIDIA/NeMo-Fabric PR: 26
File: python/tests/smoke_typed_config.py:163-177
Timestamp: 2026-06-28T04:03:32.877Z
Learning: In NVIDIA NeMo Fabric Python SDK serialization of `RuntimeCapabilities` (to satisfy the “parity contract” with Rust core and the CLI), do not emit metadata keys when the corresponding metadata is absent. Instead, omit those fields entirely so the produced JSON matches the Rust/CLI output (e.g., avoid `null`, empty objects, or placeholder metadata). During review, verify the serializer/builders follow this omission rule and that Python outputs/parity tests reflect the same shape.

Applied to files:

  • python/src/nemo_fabric/types.py
📚 Learning: 2026-06-29T22:34:57.500Z
Learnt from: AjayThorve
Repo: NVIDIA/NeMo-Fabric PR: 27
File: tests/smoke_codex_cli.py:19-31
Timestamp: 2026-06-29T22:34:57.500Z
Learning: In NVIDIA/NeMo-Fabric, treat files in `tests/` named `smoke_*.py` as directly executed (gated) smoke scripts rather than pytest-collected tests. When reviewing or adding code to these files, keep them runnable as standalone scripts (e.g., via a script `main`/entrypoint) and avoid patterns that would make pytest collect them as normal test cases (e.g., defining pytest-style `test_*` functions/classes meant for collection). For Codex CLI adapter behavioral/pytest coverage, use the separate `tests/test_codex_cli.py` rather than adding pytest tests into `tests/smoke_*.py`.

Applied to files:

  • tests/smoke_cli.py
  • tests/smoke_relay_integration.py
🪛 ast-grep (0.44.0)
tests/test_adapaters_common_utils.py

[info] 65-65: use jsonify instead of json.dumps for JSON output
Context: json.dumps({"request": {"input": "from file"}})
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)

tests/test_codex_cli.py

[warning] 408-408: Do not make http calls without encryption
Context: f"http://{gateway_host}"
Note: [CWE-319] Cleartext Transmission of Sensitive Information.

(requests-http)

adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py

[warning] 309-309: Do not make http calls without encryption
Context: f"http://{relay_gateway_host}"
Note: [CWE-319] Cleartext Transmission of Sensitive Information.

(requests-http)


[error] 546-558: Command coming from incoming request
Context: subprocess.Popen(
[
relay_command,
"--config",
str(codex_settings.relay_config_path),
"--bind",
codex_settings.relay_gateway_host,
],
cwd=cwd,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
start_new_session=True,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(subprocess-from-request)


[warning] 515-515: Request-controlled URL passed to urlopen; validate against an allowlist to prevent SSRF.
Context: urllib.request.urlopen(health_url, timeout=1)
Note: [CWE-918] Server-Side Request Forgery (SSRF).

(urlopen-unsanitized-data)


[error] 618-630: Command coming from incoming request
Context: subprocess.run(
command,
cwd=cwd,
env=build_env(
payload,
relay_gateway_url=codex_settings.relay_gateway_url,
),
input=request_to_prompt(payload),
text=True,
capture_output=True,
check=False,
timeout=timeout,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(subprocess-from-request)


[error] 618-630: Use of unsanitized data to create processes
Context: subprocess.run(
command,
cwd=cwd,
env=build_env(
payload,
relay_gateway_url=codex_settings.relay_gateway_url,
),
input=request_to_prompt(payload),
text=True,
capture_output=True,
check=False,
timeout=timeout,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(os-system-unsanitized-data)


[info] 712-712: use jsonify instead of json.dumps for JSON output
Context: json.dumps(output, sort_keys=True)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)

🪛 Ruff (0.15.20)
adapters/common/src/nemo_fabric_adapters/common/hermes.py

[warning] 44-44: Avoid specifying long messages outside the exception class

(TRY003)

adapters/common/src/nemo_fabric_adapters/common/utils.py

[warning] 356-356: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 372-372: Consider moving this statement to an else block

(TRY300)


[warning] 374-374: Avoid specifying long messages outside the exception class

(TRY003)

tests/test_hermes_e2e.py

[warning] 61-61: Async functions should not use pathlib.Path methods, use trio.Path or anyio.path

(ASYNC240)

tests/test_codex_cli.py

[warning] 166-166: Unused function argument: tmp_path

(ARG001)


[warning] 180-180: Yoda condition detected

(SIM300)


[warning] 181-181: Yoda condition detected

(SIM300)


[warning] 183-183: Yoda condition detected

Rewrite as command[-3:-1] == ["--model", "gpt-5.4"]

(SIM300)


[warning] 297-297: Unused function argument: tmp_path

(ARG001)


[error] 526-526: Possible hardcoded password assigned to: "FABRIC_UNRELATED_SECRET"

(S105)

adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py

[warning] 213-213: Prefer TypeError exception for invalid type

(TRY004)


[warning] 213-213: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 252-254: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 273-273: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 278-280: Prefer TypeError exception for invalid type

(TRY004)


[warning] 278-280: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 319-321: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 389-391: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 489-489: Prefer TypeError exception for invalid type

(TRY004)


[warning] 489-489: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 512-514: Avoid specifying long messages outside the exception class

(TRY003)


[error] 516-516: Audit URL open for permitted schemes. Allowing use of file: or custom schemes is often unexpected.

(S310)


[warning] 522-522: Avoid specifying long messages outside the exception class

(TRY003)


[error] 547-547: subprocess call: check for execution of untrusted input

(S603)


[warning] 564-564: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 593-593: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 602-602: Avoid specifying long messages outside the exception class

(TRY003)


[error] 619-619: subprocess call: check for execution of untrusted input

(S603)

🔇 Additional comments (39)
.agents/skills/python-tests/SKILL.md (1)

28-28: LGTM!

adapters/common/src/nemo_fabric_adapters/common/utils.py (3)

80-88: LGTM!


50-64: LGTM!


346-375: 🎯 Functional Correctness

No change needed: this helper only runs on Relay-enabled paths. Current call sites pass relay config data when Relay is enabled, so the FABRIC_RELAY_CONFIG_PATH check is not gating a no-op path.

			> Likely an incorrect or invalid review comment.
tests/test_adapaters_common_utils.py (2)

84-97: LGTM!


7-16: LGTM!

adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py (5)

217-262: 🎯 Functional Correctness | 💤 Low value

Empty otel table still emits a profile.

When telemetry is native/enabled but the observability component has neither deployment.environment nor endpoint, this returns {"otel": {}}. write_config_files then treats config as truthy and writes a profile containing an empty [otel] table. Harmless if Codex ignores it, but worth confirming it doesn't trip Codex validation.


162-205: LGTM!


496-566: LGTM!


589-651: LGTM!


269-282: 🎯 Functional Correctness

No issue: toml_value(value) is validation-only

toml_value() only checks TOML-serializability and finite numbers; it returns an encoded TOML literal, not a normalized value. Dropping the return is intentional because config is serialized later from the original values.

			> Likely an incorrect or invalid review comment.
tests/test_codex_cli.py (4)

164-167: 📐 Maintainability & Code Quality | ⚡ Quick win

Unused tmp_path parameter.

tmp_path isn't referenced here (the codex_payload fixture already consumes it); Ruff flags ARG001. Drop it. Same applies at line 297 (test_native_otel_profile_writes_codex_telemetry_config).

🧹 Proposed fix
 def test_oneshot_command_uses_fabric_overrides_and_codex_owned_auth(
     codex_payload,
-    tmp_path,
 ):

Source: Linters/SAST tools


331-393: LGTM!


442-473: LGTM!


503-551: LGTM!

schemas/adapter-invocation.schema.json (1)

869-869: LGTM!

Also applies to: 892-964

schemas/agent.schema.json (1)

362-362: LGTM!

Also applies to: 385-408

schemas/effective-config.schema.json (1)

449-449: LGTM!

Also applies to: 472-495

schemas/run-plan.schema.json (1)

945-945: LGTM!

Also applies to: 968-972, 987-990, 1021-1040

adapters/hermes-sdk/src/nemo_fabric_adapters/hermes_sdk/adapter.py (1)

74-74: LGTM!

Also applies to: 188-188

tests/test_hermes_cli.py (1)

41-67: LGTM!

tests/test_hermes_sdk_adapter.py (1)

13-14: LGTM!

Also applies to: 23-33

crates/fabric-core/src/config.rs (2)

634-677: LGTM!

Also applies to: 1291-1307, 1513-1533


1635-1707: LGTM!

Good coverage of the default-relay, native-skips-relay, and unknown-provider-rejection paths.

crates/fabric-core/src/lib.rs (1)

19-23: LGTM!

crates/fabric-core/src/runtime.rs (2)

1291-1300: LGTM!

telemetry_provider is consistently threaded into both the invocation-side and result-side metadata maps, matching the Python SDK's metadata.get("telemetry_provider", "relay") lookup.

Also applies to: 1764-1773


2006-2066: LGTM!

Solid end-to-end coverage: verifies relay is skipped, no relay_config artifact is written, and both telemetry_plan.provider and runtime_context.telemetry.metadata.telemetry_provider reflect "native".

python/src/nemo_fabric/types.py (1)

789-800: LGTM!

metadata.get("telemetry_provider", "relay") correctly preserves backward compatibility for existing relay-only payloads while honoring the new provider metadata from Rust core.

tests/test_sdk_contract.py (1)

608-621: LGTM!

adapters/hermes-cli/src/nemo_fabric_adapters/hermes_cli/adapter.py (1)

30-35: LGTM!

Consolidating payload loading and session-id resolution onto the shared common_utils helpers, and validating the telemetry provider before building settings, matches the intended layering for this cohort.

Also applies to: 55-65

adapters/common/src/nemo_fabric_adapters/common/hermes.py (2)

156-159: 🗄️ Data Integrity & Integration

Tuple order is correct. write_relay_configs(...) returns (relay_config_path, plugin_config_path), so unpacking the second element into relay_plugins_toml_path sets HERMES_NEMO_RELAY_PLUGINS_TOML from the plugins TOML path.

			> Likely an incorrect or invalid review comment.

42-45: 🎯 Functional Correctness

Telemetry provider is intentionally fixed to relay Hermes rejects any non-relay telemetry provider regardless of telemetry.enabled; provider: native is already covered as invalid.

			> Likely an incorrect or invalid review comment.
examples/code-review-agent/profiles/relay-openinference.yaml (1)

16-34: 📐 Maintainability & Code Quality

Duplicates relay.yaml's atif/atof block verbatim.

Same concern as flagged on relay.yaml — see that comment for details on the composability/duplication tradeoff.

examples/code-review-agent/profiles/native-otel.yaml (1)

1-24: LGTM!

examples/code-review-agent/profiles/relay-otel.yaml (1)

1-31: LGTM!

tests/smoke_cli.py (1)

63-98: LGTM!

Multi-profile expansion and assertions correctly track the new composable relay profile model. Based on learnings, this file correctly stays a standalone script (def main()) rather than pytest-style tests, consistent with prior guidance for smoke_*.py files.

Source: Learnings

tests/smoke_relay_integration.py (1)

37-53: LGTM!

Switch to stacked hermes_sdk + relay profiles matches the new composable profile model.

tests/test_hermes_e2e.py (1)

24-24: LGTM!

profile_names migration and relay_artifact_root derivation are consistent with relay.yaml's fixed ./artifacts/relay output_dir across all tested profile combinations.

Also applies to: 52-65, 124-124, 145-147, 192-194, 211-241

examples/code-review-agent/profiles/relay.yaml (1)

13-30: 📐 Maintainability & Code Quality

The shared Relay artifact block is intentional
relay-openinference.yaml still needs ATOF/ATIF output, and relay-otel.yaml is an OTel-only profile. config.components arrays replace earlier values, so stacked profiles would not inherit Relay observability anyway.

			> Likely an incorrect or invalid review comment.

Comment thread adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py
Comment thread adapters/common/src/nemo_fabric_adapters/common/utils.py
Comment thread tests/test_adapaters_common_hermes.py
Comment thread tests/test_adapaters_common_utils.py
Comment thread tests/test_adapaters_common_utils.py
Comment on lines +232 to +234
monkeypatch.setenv(
"FABRIC_RELAY_CONFIG_PATH", str(tmp_path / "nested" / "relay.json")
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Same monkeypatch.setenv guideline violation.

As per coding guidelines, environment variable changes in tests should use os.environ directly rather than monkeypatch.setenv, since restore_environ_fixture in conftest.py already restores state.

🔧 Proposed fix
-    monkeypatch.setenv(
-        "FABRIC_RELAY_CONFIG_PATH", str(tmp_path / "nested" / "relay.json")
-    )
+    os.environ["FABRIC_RELAY_CONFIG_PATH"] = str(tmp_path / "nested" / "relay.json")
📝 Committable suggestion

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

Suggested change
monkeypatch.setenv(
"FABRIC_RELAY_CONFIG_PATH", str(tmp_path / "nested" / "relay.json")
)
os.environ["FABRIC_RELAY_CONFIG_PATH"] = str(tmp_path / "nested" / "relay.json")
🤖 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 `@tests/test_adapaters_common_utils.py` around lines 232 - 234, The test is
violating the environment փոփոխation guideline by using monkeypatch.setenv in
the test setup. Update the fixture or test around the FABRIC_RELAY_CONFIG_PATH
assignment to write directly to os.environ instead of calling
monkeypatch.setenv, and keep the change localized in the same test helper block
so restore_environ_fixture can handle cleanup.

Source: Coding guidelines

…d-codex

Signed-off-by: David Gardner <dagardner@nvidia.com>
…file

Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
…ric into david-expand-codex-otel

Signed-off-by: David Gardner <dagardner@nvidia.com>
…d-codex-otel

Signed-off-by: David Gardner <dagardner@nvidia.com>
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>

@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.

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
adapters/common/src/nemo_fabric_adapters/common/utils.py (1)

138-160: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

runtime_context(payload)["runtime_id"] will raise KeyError when runtime_id is absent.

This file's own runtime_session_id() helper (added in this same PR) exists precisely because runtime_context may contain only session_id, only runtime_id, or neither — its test coverage explicitly asserts it returns None when neither is present. Yet normalize_relay_output_dirs indexes runtime_context(payload)["runtime_id"] directly, with no .get() fallback, so any payload lacking runtime_id (a state the adjacent helper is designed to tolerate) will crash load_relay_plugin_config() with an unhandled KeyError instead of degrading gracefully.

🐛 Proposed fix
-    runtime_id = runtime_context(payload)["runtime_id"]
+    runtime_id = runtime_session_id(payload) or runtime_context(payload).get("runtime_id")
+    if not runtime_id:
+        raise RuntimeError("runtime_context.runtime_id is required to scope relay output directories")
🤖 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 `@adapters/common/src/nemo_fabric_adapters/common/utils.py` around lines 138 -
160, The `normalize_relay_output_dirs` helper currently reads
`runtime_context(payload)["runtime_id"]` directly, which can raise `KeyError`
for payloads that only have `session_id` or neither. Update this function to use
the same tolerant lookup behavior as `runtime_session_id()` and fall back
gracefully when `runtime_id` is missing, so `load_relay_plugin_config()` does
not crash. Keep the change localized in `normalize_relay_output_dirs` and
preserve the existing output directory creation logic.
🤖 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.

Inline comments:
In `@tests/test_harbor_runner.py`:
- Around line 4-10: The test file imports tomllib directly, which breaks Python
3.10 compatibility during collection. Update the import in the test helper to
use the same Python-version fallback pattern already used elsewhere in the repo,
with tomli as the 3.10-compatible fallback and tomllib only when available. Make
the change near the existing imports in the test module so the TOML parsing
logic continues to work across supported interpreters.

---

Outside diff comments:
In `@adapters/common/src/nemo_fabric_adapters/common/utils.py`:
- Around line 138-160: The `normalize_relay_output_dirs` helper currently reads
`runtime_context(payload)["runtime_id"]` directly, which can raise `KeyError`
for payloads that only have `session_id` or neither. Update this function to use
the same tolerant lookup behavior as `runtime_session_id()` and fall back
gracefully when `runtime_id` is missing, so `load_relay_plugin_config()` does
not crash. Keep the change localized in `normalize_relay_output_dirs` and
preserve the existing output directory creation logic.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 062bdf53-7327-47a7-b9f2-cfb4396d36e1

📥 Commits

Reviewing files that changed from the base of the PR and between 2b2696a and dc57ffb.

📒 Files selected for processing (5)
  • adapters/common/src/nemo_fabric_adapters/common/utils.py
  • python/src/nemo_fabric/types.py
  • tests/test_adapaters_common_hermes.py
  • tests/test_adapaters_common_utils.py
  • tests/test_harbor_runner.py
📜 Review details
⚠️ CI failures not shown inline (2)

GitHub Actions: Fern Docs / Build and publish docs: Merge branch 'david-expand-codex' of github.com:dagardner-nv/nemo-fab…

Conclusion: failure

View job details

##[group]Run set -euo pipefail
 �[36;1mset -euo pipefail�[0m
 �[36;1mpr_number="${GITHUB_REF_NAME#pull-request/}"�[0m
 �[36;1mif output="$(fern generate --docs --preview --id "pull-request-${pr_number}" 2>&1)"; then�[0m
 �[36;1m  fern_exit=0�[0m
 �[36;1melse�[0m
 �[36;1m  fern_exit=$?�[0m
 �[36;1mfi�[0m
 �[36;1mprintf '%s\n' "$output"�[0m
 �[36;1mif [ "$fern_exit" -ne 0 ]; then�[0m
 �[36;1m  echo "::error::Fern docs preview generation failed"�[0m

GitHub Actions: Fern Docs / 0_Build and publish docs.txt: Merge branch 'david-expand-codex' of github.com:dagardner-nv/nemo-fab…

Conclusion: failure

View job details

##[group]Run set -euo pipefail
 �[36;1mset -euo pipefail�[0m
 �[36;1mpr_number="${GITHUB_REF_NAME#pull-request/}"�[0m
 �[36;1mif output="$(fern generate --docs --preview --id "pull-request-${pr_number}" 2>&1)"; then�[0m
 �[36;1m  fern_exit=0�[0m
 �[36;1melse�[0m
 �[36;1m  fern_exit=$?�[0m
 �[36;1mfi�[0m
 �[36;1mprintf '%s\n' "$output"�[0m
 �[36;1mif [ "$fern_exit" -ne 0 ]; then�[0m
 �[36;1m  echo "::error::Fern docs preview generation failed"�[0m
🧰 Additional context used
📓 Path-based instructions (4)
python/src/nemo_fabric/**/*

⚙️ CodeRabbit configuration file

python/src/nemo_fabric/**/*: Review Python SDK changes for typed API consistency, import-time dependency neutrality, async/session behavior, and parity with the native extension.
Stubs and runtime implementations should stay aligned.

Files:

  • python/src/nemo_fabric/types.py
tests/**/*.py

📄 CodeRabbit inference engine (.agents/skills/python-tests/SKILL.md)

tests/**/*.py: Use Pytest to run Python tests; this style guide applies to Fabric test files.
Do not add @pytest.mark.asyncio to test functions; async tests are auto-detected by the async runner.
Do not add a -> None return type annotation to test functions.
When mocking a class, do not define a new class; use unittest.mock.MagicMock or unittest.mock.AsyncMock, adding spec when needed.
Name mocked classes with the mock prefix rather than fake.
Prefer pytest fixtures over helper methods.
Do not repeat fixtures; if a fixture is needed in multiple test files, move it to conftest.py.
When creating a fixture, use @pytest.fixture(name="<fixture_name>"[, scope="<scope>"]) on a function named <fixture_name>_fixture; only specify scope when it is not function.
Prefer pytest.mark.parametrize over creating separate tests for different input types.
If a fixture is needed for a test but does not return a value or its value is unused, use @pytest.mark.usefixtures.
If you need to modify environment variables in a test, use os.environ; restore_environ_fixture will reset them after the test, so do not use monkeypatch.setenv for that purpose.

Files:

  • tests/test_harbor_runner.py
  • tests/test_adapaters_common_utils.py
  • tests/test_adapaters_common_hermes.py
{tests/**,python/tests/**}

⚙️ CodeRabbit configuration file

{tests/**,python/tests/**}: Tests should cover the behavior promised by the changed API surface, including error paths, lifecycle cleanup, and SDK/native parity where relevant.

Files:

  • tests/test_harbor_runner.py
  • tests/test_adapaters_common_utils.py
  • tests/test_adapaters_common_hermes.py
{adapters/**,examples/**}

⚙️ CodeRabbit configuration file

{adapters/**,examples/**}: Review adapter and example changes for command correctness, config/schema consistency, artifact handling, and compatibility with the public Fabric contracts.

Files:

  • adapters/common/src/nemo_fabric_adapters/common/utils.py
🧠 Learnings (1)
📚 Learning: 2026-06-28T04:03:32.877Z
Learnt from: AjayThorve
Repo: NVIDIA/NeMo-Fabric PR: 26
File: python/tests/smoke_typed_config.py:163-177
Timestamp: 2026-06-28T04:03:32.877Z
Learning: In NVIDIA NeMo Fabric Python SDK serialization of `RuntimeCapabilities` (to satisfy the “parity contract” with Rust core and the CLI), do not emit metadata keys when the corresponding metadata is absent. Instead, omit those fields entirely so the produced JSON matches the Rust/CLI output (e.g., avoid `null`, empty objects, or placeholder metadata). During review, verify the serializer/builders follow this omission rule and that Python outputs/parity tests reflect the same shape.

Applied to files:

  • python/src/nemo_fabric/types.py
🪛 ast-grep (0.44.0)
tests/test_harbor_runner.py

[warning] 245-245: Do not make http calls without encryption
Context: "http://host.docker.internal:6006/v1/traces"
Note: [CWE-319] Cleartext Transmission of Sensitive Information.

(requests-http)


[info] 99-99: use jsonify instead of json.dumps for JSON output
Context: json.dumps(config.to_mapping())
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)

🪛 Ruff (0.15.20)
tests/test_harbor_runner.py

[warning] 50-50: Assertion should be broken down into multiple parts

Break down assertion into multiple parts

(PT018)

🔇 Additional comments (6)
tests/test_harbor_runner.py (1)

56-263: LGTM!

tests/test_adapaters_common_utils.py (1)

133-235: LGTM!

tests/test_adapaters_common_hermes.py (1)

197-295: LGTM!

Also applies to: 396-464

adapters/common/src/nemo_fabric_adapters/common/utils.py (1)

111-135: LGTM!

Also applies to: 328-346

python/src/nemo_fabric/types.py (2)

1000-1016: 🗄️ Data Integrity & Integration

Confirm telemetry_provider matches the config key This normalizer reads metadata.get("telemetry_provider", "relay"), so the native/runtime layer must populate metadata["telemetry_provider"] for the relay_enabled path. If it uses provider instead, telemetry.provider will be ignored and the code will fall back to "relay".


123-136: 🎯 Functional Correctness

No action needed_plain() already recursively copies mappings/lists and deep-copies scalar leaves, so extra_fields and to_mapping() both return detached JSON-compatible data.

			> Likely an incorrect or invalid review comment.

@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

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
adapters/common/src/nemo_fabric_adapters/common/utils.py (1)

138-160: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

runtime_context(payload)["runtime_id"] will raise KeyError when runtime_id is absent.

This file's own runtime_session_id() helper (added in this same PR) exists precisely because runtime_context may contain only session_id, only runtime_id, or neither — its test coverage explicitly asserts it returns None when neither is present. Yet normalize_relay_output_dirs indexes runtime_context(payload)["runtime_id"] directly, with no .get() fallback, so any payload lacking runtime_id (a state the adjacent helper is designed to tolerate) will crash load_relay_plugin_config() with an unhandled KeyError instead of degrading gracefully.

🐛 Proposed fix
-    runtime_id = runtime_context(payload)["runtime_id"]
+    runtime_id = runtime_session_id(payload) or runtime_context(payload).get("runtime_id")
+    if not runtime_id:
+        raise RuntimeError("runtime_context.runtime_id is required to scope relay output directories")
🤖 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 `@adapters/common/src/nemo_fabric_adapters/common/utils.py` around lines 138 -
160, The `normalize_relay_output_dirs` helper currently reads
`runtime_context(payload)["runtime_id"]` directly, which can raise `KeyError`
for payloads that only have `session_id` or neither. Update this function to use
the same tolerant lookup behavior as `runtime_session_id()` and fall back
gracefully when `runtime_id` is missing, so `load_relay_plugin_config()` does
not crash. Keep the change localized in `normalize_relay_output_dirs` and
preserve the existing output directory creation logic.
🤖 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.

Inline comments:
In `@tests/test_harbor_runner.py`:
- Around line 4-10: The test file imports tomllib directly, which breaks Python
3.10 compatibility during collection. Update the import in the test helper to
use the same Python-version fallback pattern already used elsewhere in the repo,
with tomli as the 3.10-compatible fallback and tomllib only when available. Make
the change near the existing imports in the test module so the TOML parsing
logic continues to work across supported interpreters.

---

Outside diff comments:
In `@adapters/common/src/nemo_fabric_adapters/common/utils.py`:
- Around line 138-160: The `normalize_relay_output_dirs` helper currently reads
`runtime_context(payload)["runtime_id"]` directly, which can raise `KeyError`
for payloads that only have `session_id` or neither. Update this function to use
the same tolerant lookup behavior as `runtime_session_id()` and fall back
gracefully when `runtime_id` is missing, so `load_relay_plugin_config()` does
not crash. Keep the change localized in `normalize_relay_output_dirs` and
preserve the existing output directory creation logic.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 062bdf53-7327-47a7-b9f2-cfb4396d36e1

📥 Commits

Reviewing files that changed from the base of the PR and between 2b2696a and dc57ffb.

📒 Files selected for processing (5)
  • adapters/common/src/nemo_fabric_adapters/common/utils.py
  • python/src/nemo_fabric/types.py
  • tests/test_adapaters_common_hermes.py
  • tests/test_adapaters_common_utils.py
  • tests/test_harbor_runner.py
📜 Review details
🔇 Additional comments (6)
tests/test_harbor_runner.py (1)

56-263: LGTM!

tests/test_adapaters_common_utils.py (1)

133-235: LGTM!

tests/test_adapaters_common_hermes.py (1)

197-295: LGTM!

Also applies to: 396-464

adapters/common/src/nemo_fabric_adapters/common/utils.py (1)

111-135: LGTM!

Also applies to: 328-346

python/src/nemo_fabric/types.py (2)

1000-1016: 🗄️ Data Integrity & Integration

Confirm telemetry_provider matches the config key This normalizer reads metadata.get("telemetry_provider", "relay"), so the native/runtime layer must populate metadata["telemetry_provider"] for the relay_enabled path. If it uses provider instead, telemetry.provider will be ignored and the code will fall back to "relay".


123-136: 🎯 Functional Correctness

No action needed_plain() already recursively copies mappings/lists and deep-copies scalar leaves, so extra_fields and to_mapping() both return detached JSON-compatible data.

			> Likely an incorrect or invalid review comment.
🛑 Comments failed to post (1)
tests/test_harbor_runner.py (1)

4-10: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check declared Python version support and existing tomllib fallback patterns
fd pyproject.toml | xargs -I{} cat {}
rg -n 'requires-python' 
rg -n 'import tomllib' -B2 -A2
rg -n 'import tomli' -B2 -A2

Repository: NVIDIA/NeMo-Fabric

Length of output: 2123


Use a Python 3.10-compatible TOML import here. tomllib is only in Python 3.11+, but this repo supports Python 3.10 and already includes tomli for older interpreters. Importing tomllib directly will break test collection on 3.10; use the same fallback pattern as the other test helper.

🤖 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 `@tests/test_harbor_runner.py` around lines 4 - 10, The test file imports
tomllib directly, which breaks Python 3.10 compatibility during collection.
Update the import in the test helper to use the same Python-version fallback
pattern already used elsewhere in the repo, with tomli as the 3.10-compatible
fallback and tomllib only when available. Make the change near the existing
imports in the test module so the TOML parsing logic continues to work across
supported interpreters.

@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.

Actionable comments posted: 1

🤖 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.

Inline comments:
In `@tests/test_harbor_runner.py`:
- Line 167: The test mutates CODEX_HOME directly via os.environ, which can leak
state into later tests. Update the test in test_harbor_runner to use the
monkeypatch fixture and call monkeypatch.setenv("CODEX_HOME", str(tmp_path))
instead of assigning to os.environ, so the environment is automatically restored
after the test.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 46bcbec7-8f55-4993-a967-89822d599523

📥 Commits

Reviewing files that changed from the base of the PR and between dc57ffb and 60d843b.

📒 Files selected for processing (1)
  • tests/test_harbor_runner.py
📜 Review details
⚠️ CI failures not shown inline (4)

GitHub Actions: Rust / Test: Add support for native Codex telemetry

Conclusion: failure

View job details

##[group]Run cargo test --workspace --locked
 �[36;1mcargo test --workspace --locked�[0m
 shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0}
 env:
   CARGO_INCREMENTAL: 0
   CARGO_PROFILE_DEV_DEBUG: 0
   CARGO_TERM_COLOR: always
   RUST_BACKTRACE: short
   RUSTFLAGS: -D warnings
   CARGO_UNSTABLE_SPARSE_REGISTRY: true
   CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
   CACHE_ON_FAILURE: false
 ##[endgroup]
 �[1m�[92m   Compiling�[0m fabric-core v0.1.0 (/home/runner/work/NeMo-Fabric/NeMo-Fabric/crates/fabric-core)
 �[1m�[92m   Compiling�[0m fabric-cli v0.1.0 (/home/runner/work/NeMo-Fabric/NeMo-Fabric/crates/fabric-cli)
 �[1m�[92m    Finished�[0m `test` profile [unoptimized] target(s) in 5.75s
 �[1m�[92m     Running�[0m unittests src/main.rs (target/debug/deps/fabric-c3572a4d481471cf)
 running 0 tests
 test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
 �[1m�[92m     Running�[0m unittests src/lib.rs (target/debug/deps/fabric_core-9b081566c1d472c1)
 running 45 tests
 test config::tests::errors_for_unknown_manifest_profile ... ok

GitHub Actions: Rust / 0_Test.txt: Add support for native Codex telemetry

Conclusion: failure

View job details

##[group]Run cargo test --workspace --locked
 �[36;1mcargo test --workspace --locked�[0m
 shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0}
 env:
   CARGO_INCREMENTAL: 0
   CARGO_PROFILE_DEV_DEBUG: 0
   CARGO_TERM_COLOR: always
   RUST_BACKTRACE: short
   RUSTFLAGS: -D warnings
   CARGO_UNSTABLE_SPARSE_REGISTRY: true
   CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
   CACHE_ON_FAILURE: false
 ##[endgroup]
 �[1m�[92m   Compiling�[0m fabric-core v0.1.0 (/home/runner/work/NeMo-Fabric/NeMo-Fabric/crates/fabric-core)
 �[1m�[92m   Compiling�[0m fabric-cli v0.1.0 (/home/runner/work/NeMo-Fabric/NeMo-Fabric/crates/fabric-cli)
 �[1m�[92m    Finished�[0m `test` profile [unoptimized] target(s) in 5.75s
 �[1m�[92m     Running�[0m unittests src/main.rs (target/debug/deps/fabric-c3572a4d481471cf)
 running 0 tests
 test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
 �[1m�[92m     Running�[0m unittests src/lib.rs (target/debug/deps/fabric_core-9b081566c1d472c1)
 running 45 tests
 test config::tests::errors_for_unknown_manifest_profile ... ok

GitHub Actions: Fern Docs / Build and publish docs: Update test

Conclusion: failure

View job details

##[group]Run set -euo pipefail
 �[36;1mset -euo pipefail�[0m
 �[36;1mpr_number="${GITHUB_REF_NAME#pull-request/}"�[0m
 �[36;1mif output="$(fern generate --docs --preview --id "pull-request-${pr_number}" 2>&1)"; then�[0m
 �[36;1m  fern_exit=0�[0m
 �[36;1melse�[0m
 �[36;1m  fern_exit=$?�[0m
 �[36;1mfi�[0m
 �[36;1mprintf '%s\n' "$output"�[0m
 �[36;1mif [ "$fern_exit" -ne 0 ]; then�[0m
 �[36;1m  echo "::error::Fern docs preview generation failed"�[0m

GitHub Actions: Fern Docs / 0_Build and publish docs.txt: Update test

Conclusion: failure

View job details

##[group]Run set -euo pipefail
 �[36;1mset -euo pipefail�[0m
 �[36;1mpr_number="${GITHUB_REF_NAME#pull-request/}"�[0m
 �[36;1mif output="$(fern generate --docs --preview --id "pull-request-${pr_number}" 2>&1)"; then�[0m
 �[36;1m  fern_exit=0�[0m
 �[36;1melse�[0m
 �[36;1m  fern_exit=$?�[0m
 �[36;1mfi�[0m
 �[36;1mprintf '%s\n' "$output"�[0m
 �[36;1mif [ "$fern_exit" -ne 0 ]; then�[0m
 �[36;1m  echo "::error::Fern docs preview generation failed"�[0m
🧰 Additional context used
📓 Path-based instructions (2)
tests/**/*.py

📄 CodeRabbit inference engine (.agents/skills/python-tests/SKILL.md)

tests/**/*.py: Use pytest to run tests.
Do not add @pytest.mark.asyncio to test functions; async tests are detected and run automatically by the async runner.
Do not add a -> None return type annotation to test functions.
When mocking a class, use unittest.mock.MagicMock or unittest.mock.AsyncMock (with spec when needed) instead of defining a new class.
Name mocked classes with a mock prefix, not fake.
Prefer pytest fixtures over helper methods.
Do not repeat fixtures across test files; if a fixture is needed in multiple test files, place it in conftest.py.
Define fixtures with @pytest.fixture(name="<fixture_name>"[, scope="<scope>"]) and def <fixture_name>_fixture() -> <return_type>:; only specify scope when it is not Preferpytest.mark.parametrizeover creating individual tests for different input types. If a fixture is needed for a test but does not return a value or the value is unused, use@pytest.mark.usefixtures`.

Files:

  • tests/test_harbor_runner.py
{tests/**,python/tests/**}

⚙️ CodeRabbit configuration file

{tests/**,python/tests/**}: Tests should cover the behavior promised by the changed API surface, including error paths, lifecycle cleanup, and SDK/native parity where relevant.

Files:

  • tests/test_harbor_runner.py
🔇 Additional comments (2)
tests/test_harbor_runner.py (2)

6-6: LGTM!

Also applies to: 175-193


168-174: 🎯 Functional Correctness

Profile name matches helper get_codex_profile_path() already builds fabric-{runtime_id}, so fabric-harbor-test is the expected profile name here.

			> Likely an incorrect or invalid review comment.

Comment thread tests/test_harbor_runner.py

@AjayThorve AjayThorve left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

looks good, the provider option for telemetry makes sense!

Signed-off-by: David Gardner <dagardner@nvidia.com>

@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.

Actionable comments posted: 1

🤖 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.

Inline comments:
In `@tests/test_codex_cli.py`:
- Around line 42-48: The codex_payload_fixture currently mutates CODEX_HOME
directly and leaves it set for the rest of the test session. Update the fixture
to use pytest’s monkeypatch (or an equivalent yield-based teardown) so
CODEX_HOME is automatically restored after each test, and keep the setup for the
workspace/codex-home plus team.toml creation inside codex_payload_fixture. This
will preserve the unset-environment behavior needed by the default-path tests
and prevent cross-test leakage.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 89103c14-d589-40c0-b4b9-d520af00db93

📥 Commits

Reviewing files that changed from the base of the PR and between 60d843b and e1547db.

📒 Files selected for processing (3)
  • adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py
  • pyproject.toml
  • tests/test_codex_cli.py
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
  • GitHub Check: Test
  • GitHub Check: Build and publish docs
⚠️ CI failures not shown inline (2)

GitHub Actions: Rust / Test: Add support for native Codex telemetry

Conclusion: failure

View job details

##[group]Run cargo test --workspace --locked
 �[36;1mcargo test --workspace --locked�[0m
 shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0}
 env:
   CARGO_INCREMENTAL: 0
   CARGO_PROFILE_DEV_DEBUG: 0
   CARGO_TERM_COLOR: always
   RUST_BACKTRACE: short
   RUSTFLAGS: -D warnings
   CARGO_UNSTABLE_SPARSE_REGISTRY: true
   CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
   CACHE_ON_FAILURE: false
 ##[endgroup]
 �[1m�[92m   Compiling�[0m fabric-core v0.1.0 (/home/runner/work/NeMo-Fabric/NeMo-Fabric/crates/fabric-core)
 �[1m�[92m   Compiling�[0m fabric-cli v0.1.0 (/home/runner/work/NeMo-Fabric/NeMo-Fabric/crates/fabric-cli)
 �[1m�[92m    Finished�[0m `test` profile [unoptimized] target(s) in 5.86s
 �[1m�[92m     Running�[0m unittests src/main.rs (target/debug/deps/fabric-c3572a4d481471cf)
 running 0 tests
 �[1m�[92m     Running�[0m unittests src/lib.rs (target/debug/deps/fabric_core-9b081566c1d472c1)
 test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
 running 45 tests
 test config::tests::errors_for_unknown_manifest_profile ... ok

GitHub Actions: Rust / 0_Test.txt: Add support for native Codex telemetry

Conclusion: failure

View job details

##[group]Run cargo test --workspace --locked
 �[36;1mcargo test --workspace --locked�[0m
 shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0}
 env:
   CARGO_INCREMENTAL: 0
   CARGO_PROFILE_DEV_DEBUG: 0
   CARGO_TERM_COLOR: always
   RUST_BACKTRACE: short
   RUSTFLAGS: -D warnings
   CARGO_UNSTABLE_SPARSE_REGISTRY: true
   CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
   CACHE_ON_FAILURE: false
 ##[endgroup]
 �[1m�[92m   Compiling�[0m fabric-core v0.1.0 (/home/runner/work/NeMo-Fabric/NeMo-Fabric/crates/fabric-core)
 �[1m�[92m   Compiling�[0m fabric-cli v0.1.0 (/home/runner/work/NeMo-Fabric/NeMo-Fabric/crates/fabric-cli)
 �[1m�[92m    Finished�[0m `test` profile [unoptimized] target(s) in 5.86s
 �[1m�[92m     Running�[0m unittests src/main.rs (target/debug/deps/fabric-c3572a4d481471cf)
 running 0 tests
 �[1m�[92m     Running�[0m unittests src/lib.rs (target/debug/deps/fabric_core-9b081566c1d472c1)
 test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
 running 45 tests
 test config::tests::errors_for_unknown_manifest_profile ... ok
🧰 Additional context used
📓 Path-based instructions (3)
{adapters/**,examples/**}

⚙️ CodeRabbit configuration file

{adapters/**,examples/**}: Review adapter and example changes for command correctness, config/schema consistency, artifact handling, and compatibility with the public Fabric contracts.

Files:

  • adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py
tests/**/*.py

📄 CodeRabbit inference engine (.agents/skills/python-tests/SKILL.md)

tests/**/*.py: Use pytest to run tests.
Do not add @pytest.mark.asyncio to test functions; async tests are detected and run automatically by the async runner.
Do not add a -> None return type annotation to test functions.
When mocking a class, use unittest.mock.MagicMock or unittest.mock.AsyncMock (with spec when needed) instead of defining a new class.
Name mocked classes with a mock prefix, not fake.
Prefer pytest fixtures over helper methods.
Do not repeat fixtures across test files; if a fixture is needed in multiple test files, place it in conftest.py.
Define fixtures with @pytest.fixture(name="<fixture_name>"[, scope="<scope>"]) and def <fixture_name>_fixture() -> <return_type>:; only specify scope when it is not Preferpytest.mark.parametrizeover creating individual tests for different input types. If a fixture is needed for a test but does not return a value or the value is unused, use@pytest.mark.usefixtures`.

Files:

  • tests/test_codex_cli.py
{tests/**,python/tests/**}

⚙️ CodeRabbit configuration file

{tests/**,python/tests/**}: Tests should cover the behavior promised by the changed API surface, including error paths, lifecycle cleanup, and SDK/native parity where relevant.

Files:

  • tests/test_codex_cli.py
🧬 Code graph analysis (1)
adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py (1)
tests/test_codex_cli.py (2)
  • get_codex_profile_path (254-254)
  • write_config_files (173-173)
🔇 Additional comments (10)
tests/test_codex_cli.py (1)

196-231: LGTM!

pyproject.toml (1)

16-19: LGTM!

adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py (8)

290-313: LGTM!


315-408: LGTM!


452-486: LGTM!


504-518: LGTM!


527-558: LGTM!


594-605: LGTM!


25-29: 🩺 Stability & Availability

tomli is already declared for Python < 3.11
pyproject.toml includes tomli>=2; python_version < '3.11' in the codex extras, so the fallback import is covered.

			> Likely an incorrect or invalid review comment.

411-419: 🎯 Functional Correctness

Codex profile path matches --profile. --profile fabric-{runtime_id} resolves to $CODEX_HOME/fabric-{runtime_id}.config.toml, so the generated file name is correct.

			> Likely an incorrect or invalid review comment.

Comment thread tests/test_codex_cli.py
@dagardner-nv
dagardner-nv merged commit 6f9ab09 into NVIDIA:main Jul 3, 2026
5 checks passed
@dagardner-nv
dagardner-nv deleted the david-expand-codex-otel branch July 9, 2026 15:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants