Skip to content

Add support for an ADAPTER_PYTHON environment variable as a shortcut for setting python_env in the config - #45

Merged
dagardner-nv merged 13 commits into
NVIDIA:mainfrom
dagardner-nv:david-gen-python
Jul 9, 2026
Merged

Add support for an ADAPTER_PYTHON environment variable as a shortcut for setting python_env in the config#45
dagardner-nv merged 13 commits into
NVIDIA:mainfrom
dagardner-nv:david-gen-python

Conversation

@dagardner-nv

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

Copy link
Copy Markdown
Collaborator

Overview

  • Expands on the HERMES_PYTHON idea used in the Hermes Agent example
  • ADAPTER_PYTHON functions as the default value for the python_env setting, when unset follows existing fallback rules.
  • CLI adapters now determine if they are in a virtualenv and set PATH and other environment variables to ensure sub-processes are run within the virtualenv.

Unrelated changes:

  • Add a --show-output flag to examples/code_review_agent/__main__.py, to make reading the output easier
  • Ensure that the packages are all installed as editable

Where should the reviewer start?

crates/fabric-core/src/runtime.rs

Related Issues: (use one of the action keywords Closes / Fixes / Resolves / Relates to)

  • Closes FABRIC-56

  • I confirm this contribution is my own work, or I have the right to submit it under this project's license.

  • I searched existing issues and open pull requests, and this does not duplicate existing work.

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Added a --show-output option to display the adapter response after the normalized result.
    • Added ADAPTER_PYTHON support for selecting the adapter Python interpreter.
  • Bug Fixes

    • Added preflight validation for the adapter interpreter path (must exist and be a file).
    • Refined interpreter precedence and fallback behavior across harness settings and ADAPTER_PYTHON.
    • Improved adapter subprocess environment handling to better honor active virtual environments.
  • Documentation

    • Updated quick start and example instructions to use ADAPTER_PYTHON and clarified precedence.
  • Chores / Tests

    • Updated editable install configuration and expanded coverage for adapter selection and environment behavior.

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

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

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Renames the adapter Python interpreter env var to ADAPTER_PYTHON, adds runtime preflight validation and error reporting, updates virtualenv subprocess environment handling, switches local installs to editable sources, and expands the code review example and tests.

Changes

ADAPTER_PYTHON runtime and preflight

Layer / File(s) Summary
New InvalidAdapterPython error variant
crates/fabric-core/src/error.rs, docs/reference/api/rust-library-reference/fabric-core/error/enum-fabricerror.mdx
Adds FabricError::InvalidAdapterPython { value, path } and documents the new variant in the API reference.
Python interpreter resolution and preflight validation
crates/fabric-core/src/runtime.rs
Adds ADAPTER_PYTHON_ENV, PythonCommand, preflight validation before adapter start, refactors interpreter resolution to return both path and source value, and adds unit tests for resolution and invalid-path handling.
Virtualenv subprocess environment helpers
adapters/common/src/nemo_fabric_adapters/common/utils.py, adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py, adapters/hermes-cli/src/nemo_fabric_adapters/hermes_cli/adapter.py, tests/adapters/test_adapaters_common_utils.py, tests/adapters/test_codex_cli.py
Adds virtualenv detection and subprocess env helpers, then updates adapter env assembly to apply virtualenv values before overrides and defaults; adds tests for the helper behavior and adjusts Codex env assertions.
Editable workspace install configuration
pyproject.toml, adapters/codex-cli/pyproject.toml, adapters/hermes-cli/pyproject.toml, adapters/hermes-sdk/pyproject.toml, justfile
Switches local package sources and build-python editable installs to use editable workspace paths.
code_review_agent example: ADAPTER_PYTHON config and --show-output
examples/code_review_agent/config.py, examples/code_review_agent/__main__.py, examples/code_review_agent/README.md, tests/fixtures/file-config-agent/profiles/hermes-sdk.yaml, tests/python/test_code_review_example.py
Removes python_env from the Hermes SDK config, adds --show-output printing the adapter response or error message, updates example docs, and adds a test for the new output path.
Top-level docs and integration tests
README.md, tests/e2e/test_hermes_e2e.py, tests/e2e/test_hermes_runtime.py, tests/python/test_native_sdk.py
Updates the top-level README, end-to-end harness setup, runtime skip text, and native SDK tests to reference ADAPTER_PYTHON and validate interpreter selection behavior.

Estimated code review effort: 3 (Moderate) | ~25 minutes


Important

Pre-merge checks failed

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

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
Title check ❌ Error The title is descriptive, but it does not use the required Conventional Commits format. Rewrite it as something like feat(runtime): add ADAPTER_PYTHON shortcut for python_env.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The description includes an overview, reviewer start point, related issue, and required confirmations.
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.

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown

@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: 3

🤖 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 `@README.md`:
- Line 103: The README has inconsistent Markdown formatting for the
ADAPTER_PYTHON identifier, using double backticks in the relevant sentence while
nearby references use single backticks. Update the documentation text so the
ADAPTER_PYTHON reference matches the surrounding style, and keep the same
identifier formatting consistent wherever it appears in this section.
- Line 108: The README sentence in the adapter guidance contains a comma splice
before “however”; update the text in the ADAPTER_PYTHON guidance so the two
independent clauses are separated correctly, preferably by splitting into two
sentences rather than using a semicolon. Keep the meaning the same while fixing
the punctuation around the clause describing the adapter package and the note
that adapters are small and self-contained.

In `@tests/python/test_code_review_example.py`:
- Around line 121-145: Add a test for the `main_module.main` fallback path where
the Fabric result has no `"response"` in `output.output`, so the `else:
print(output.error.message)` branch is exercised. Use the existing
`test_example_entrypoint_shows_response_after_normalized_output` as the
reference point and create a parametrized or separate case that mocks
`Fabric.run` to return a result whose normalized output lacks `"response"` and
provides an `error` object with a `message`, then assert the printed fallback
message and JSON output behavior.
🪄 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: 661f7789-b595-4006-a10a-8387e72cc7b9

📥 Commits

Reviewing files that changed from the base of the PR and between 5ceb133 and 80091a0.

📒 Files selected for processing (12)
  • README.md
  • crates/fabric-core/src/error.rs
  • crates/fabric-core/src/runtime.rs
  • docs/reference/api/rust-library-reference/fabric-core/error/enum-fabricerror.mdx
  • examples/code_review_agent/README.md
  • examples/code_review_agent/__main__.py
  • examples/code_review_agent/config.py
  • tests/e2e/test_hermes_e2e.py
  • tests/e2e/test_hermes_runtime.py
  • tests/fixtures/file-config-agent/profiles/hermes-sdk.yaml
  • tests/python/test_code_review_example.py
  • tests/python/test_native_sdk.py
💤 Files with no reviewable changes (2)
  • examples/code_review_agent/config.py
  • tests/fixtures/file-config-agent/profiles/hermes-sdk.yaml
📜 Review details
🧰 Additional context used
📓 Path-based instructions (18)
{README.md,docs/index.yml,docs/**/*.{md,mdx}}

📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)

Update entry-point docs when examples or reading paths change

Files:

  • README.md
  • docs/reference/api/rust-library-reference/fabric-core/error/enum-fabricerror.mdx
{README.md,docs/index.yml}

📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)

Update README.md or docs/index.yml when entry points changed

Files:

  • README.md
**/README.md

📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)

Update relevant adapter or example README.md files when examples or adapters have changed

Files:

  • README.md
  • examples/code_review_agent/README.md
**/*.{md,mdx}

📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-brand-terminology.md)

**/*.{md,mdx}: Spell NVIDIA in all caps; do not use Nvidia, nvidia, nVidia, nVIDIA, or NV.
Use an NVIDIA before a noun because NVIDIA starts with an "en" sound.
Do not add a registered trademark symbol after NVIDIA when referring to the company.
Use trademark symbols with product names only when the document type or legal guidance requires them.
Verify official capitalization, spacing, and hyphenation for NVIDIA product names.
Precede NVIDIA product names with NVIDIA on first mention when it is natural and accurate.
Link the first mention of a product name when the destination helps the reader.
Do not rewrite product names for grammar or title-case rules.
Preserve third-party product names according to the owner's spelling.
Include the company name and full model qualifier on first use when it helps identify the model.
Preserve the official capitalization and punctuation of model names.
Use shorter family names only after the full model name is established.
For learning-oriented docs, technical blog posts, GTC sessions, tutorials, and developer guides: do not force trademark symbols unless the source, platform, or legal guidance explicitly requires them.
For learning-oriented docs, technical blog posts, GTC sessions, tutorials, and developer guides: keep the product name accurate and consistent.
For press releases, product landing pages, packaging, sales content, or legal copy: follow the current NVIDIA trademark and copyright guidance.
For press releases, product landing pages, packaging, sales content, or legal copy: attribute trademarks on first use when required.
For press releases, product landing pages, packaging, sales content, or legal copy: use the required trademark symbol for the specific product or service.
For press releases, product landing pages, packaging, sales content, or legal copy: do not invent trademark attributions; verify current legal copy.
If the platform requires legal copy, confirm the current source of truth instead...

Files:

  • README.md
  • docs/reference/api/rust-library-reference/fabric-core/error/enum-fabricerror.mdx
  • examples/code_review_agent/README.md
**/*.{md,mdx,rst}

📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-technical-docs.md)

**/*.{md,mdx,rst}: When reviewing technical documentation, verify that commands, examples, paths, APIs, and support claims match the current repository.
Make technical documents easy to scan by fixing headings, lead-in sentences, lists, tables, and procedure shape.
Preserve exact code, command, API, package, and UI strings unless they are factually wrong.
Prefer focused findings over broad rewrites.
Use title case consistently in technical documentation headings.
Avoid quotation marks, ampersands, and exclamation marks in technical documentation headings.
Keep product, event, research, and whitepaper names in their official title case.
Use title case for table headers.
Do not force social-media sentence case into technical documentation.
Format code elements, commands, parameters, package names, and expressions in monospace.
Format directories, file names, and paths in monospace.
Use angle brackets inside monospace for variables inside paths.
Format error messages and strings with quotation marks, using code formatting when that is clearer.
Format UI buttons, menus, fields, and labels in bold.
Use angle brackets between UI labels for menu paths.
Use italics on first use for new terms, and only when the term is introduced.
Italicize publication titles.
Write keyboard shortcuts in plain text.
Use Owner/repo link text for GitHub repositories.
Introduce every code block with a complete sentence.
Do not make a code block complete the grammar of the previous sentence.
Do not continue a sentence after a code block.
Use syntax highlighting when the format supports it.
Avoid the word "snippet" unless the surrounding documentation already uses it as a term of art.
Keep inline method, function, and class references consistent with nearby docs, and omit empty parentheses in prose when no call is shown.
Use descriptive anchor text that matches the destination title when possible.
Avoid raw URLs in running text.
Avoid generic anchors such as "here," "this page," and "read more....

Files:

  • README.md
  • docs/reference/api/rust-library-reference/fabric-core/error/enum-fabricerror.mdx
  • examples/code_review_agent/README.md
**/*.{md,mdx,rst,txt}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

**/*.{md,mdx,rst,txt}: If documentation or examples changed, run just docs when practical and verify documented commands against the current repository.
For documentation-only changes, use contribute-docs and review-doc-style; run just docs for docs-site or generated-reference changes.

Files:

  • README.md
  • docs/reference/api/rust-library-reference/fabric-core/error/enum-fabricerror.mdx
  • examples/code_review_agent/README.md
**/*

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

For CI or packaging changes, use maintain-ci or maintain-packaging, then run the recipes and checks whose behavior changed.

Files:

  • README.md
  • examples/code_review_agent/__main__.py
  • tests/e2e/test_hermes_runtime.py
  • tests/e2e/test_hermes_e2e.py
  • crates/fabric-core/src/error.rs
  • docs/reference/api/rust-library-reference/fabric-core/error/enum-fabricerror.mdx
  • examples/code_review_agent/README.md
  • tests/python/test_code_review_example.py
  • tests/python/test_native_sdk.py
  • crates/fabric-core/src/runtime.rs
{docs/**,README.md,AGENTS.md}

⚙️ CodeRabbit configuration file

{docs/**,README.md,AGENTS.md}: Review documentation for technical accuracy against the current API, command correctness, and consistency with generated schemas.

Files:

  • README.md
  • docs/reference/api/rust-library-reference/fabric-core/error/enum-fabricerror.mdx
**/*.{py,pyi}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

**/*.{py,pyi}: If Python code or a Python-facing adapter changed, run just test-python.
For Python SDK or PyO3 binding changes, use python-tests, run focused pytest tests first, then run just test-python; rebuild with just build-python when native code or packaging changed.

Files:

  • examples/code_review_agent/__main__.py
  • tests/e2e/test_hermes_runtime.py
  • tests/e2e/test_hermes_e2e.py
  • tests/python/test_code_review_example.py
  • tests/python/test_native_sdk.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:

  • examples/code_review_agent/__main__.py
  • examples/code_review_agent/README.md
tests/**/*.py

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

tests/**/*.py: Use pytest to run Python tests.
Do not add @pytest.mark.asyncio to test functions; async tests should be auto-detected and run 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, using spec when necessary.
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.
When creating a fixture, use the pattern @pytest.fixture(name="<fixture_name>"[, scope="<scope>"]) followed by 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 you need to modify environment variables in a test, use os.environ; tests/conftest.py provides an autouse restore_environ_fixture that restores the environment after each test, so monkeypatch.setenv is unnecessary.
Avoid defensive programming in tests; access expected dictionary keys directly (for example, results["data"]) instead of using .get(), so failures raise loudly and clearly.

Files:

  • tests/e2e/test_hermes_runtime.py
  • tests/e2e/test_hermes_e2e.py
  • tests/python/test_code_review_example.py
  • tests/python/test_native_sdk.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/e2e/test_hermes_runtime.py
  • tests/e2e/test_hermes_e2e.py
  • tests/python/test_code_review_example.py
  • tests/python/test_native_sdk.py
**/*.rs

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

**/*.rs: If Rust code changed, run cargo fmt --all -- --check and just test-rust.
If public configuration types changed, confirm the schema snapshot tests in just test-rust pass and review generated schema diffs.
For Rust core, CLI, or shared runtime semantics changes, run Rust formatting and tests; add Python tests when the behavior is exposed through the SDK, and run relevant tests for CLI behavior.

Files:

  • crates/fabric-core/src/error.rs
  • crates/fabric-core/src/runtime.rs
crates/fabric-core/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If crates/fabric-core changed in a way exposed through Python, run both the Rust and Python suites.

Files:

  • crates/fabric-core/src/error.rs
  • crates/fabric-core/src/runtime.rs
**/*.{rs,toml}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If the PyO3 bridge or package metadata changed, run just build-python and cargo check -p fabric-python --locked.

Files:

  • crates/fabric-core/src/error.rs
  • crates/fabric-core/src/runtime.rs
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/error.rs
  • crates/fabric-core/src/runtime.rs
docs/**/*.{md,mdx}

📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)

docs/**/*.{md,mdx}: Prefer the documented public API, not internal shortcuts
Keep package names, repository references, and build commands current
Update relevant getting-started or reference docs
Ensure example commands still match current package names and paths

Files:

  • docs/reference/api/rust-library-reference/fabric-core/error/enum-fabricerror.mdx
**/*.mdx

📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)

In MDX files, top-of-file comments must use JSX comment delimiters ({/* ... */}); do not use HTML comments for MDX SPDX headers

Use {/* ... */} delimiters for top-of-file SPDX comments in MDX files; do not use HTML comment delimiters.

Files:

  • docs/reference/api/rust-library-reference/fabric-core/error/enum-fabricerror.mdx
🧬 Code graph analysis (2)
tests/python/test_native_sdk.py (1)
crates/fabric-core/src/runtime.rs (1)
  • start_runtime (412-422)
crates/fabric-core/src/runtime.rs (1)
crates/fabric-core/src/config.rs (1)
  • RunPlan (1321-1353)
🪛 Clippy (1.96.0)
crates/fabric-core/src/runtime.rs

[warning] 1339-1339: this if statement can be collapsed

(warning)

🔇 Additional comments (14)
examples/code_review_agent/__main__.py (2)

39-43: LGTM!


57-61: 🩺 Stability & Availability

No change needed here. The supported code-review variants always populate output.response on success, and RunResult.error is reserved for failures, so the fallback won’t dereference None in normal use.

			> Likely an incorrect or invalid review comment.
examples/code_review_agent/README.md (1)

25-25: LGTM!

Also applies to: 61-63, 78-79

tests/python/test_code_review_example.py (1)

9-11: LGTM!

README.md (1)

97-109: LGTM!

tests/e2e/test_hermes_e2e.py (1)

47-47: LGTM!

tests/e2e/test_hermes_runtime.py (1)

38-40: LGTM!

tests/python/test_native_sdk.py (2)

8-15: LGTM!


24-51: Solid coverage for ADAPTER_PYTHON selection and preflight rejection.

Both success and failure paths are exercised; env mutation relies on the repo's autouse restore_environ_fixture for cleanup, consistent with the tests path instructions.

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

150-159: LGTM!

docs/reference/api/rust-library-reference/fabric-core/error/enum-fabricerror.mdx (1)

12-12: LGTM!

Also applies to: 274-289

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

7-7: LGTM!

Also applies to: 28-28, 590-595, 651-651


939-939: 🩺 Stability & Availability

Preflight validation isn't reused by invoke().

start() validates the resolved ADAPTER_PYTHON interpreter once via preflight_python_adapter, but run_python_adapter (called on every invoke) independently re-resolves the interpreter via resolve_python_command(...).path and never calls validate_python_command again. If the runtime handle is invoked multiple times and the environment/interpreter changes between calls (e.g., a venv is rebuilt or removed), the second invocation bypasses preflight entirely and only fails with a generic ProcessRunner spawn error instead of InvalidAdapterPython.

Is a single preflight check at start() intended to be sufficient for the lifetime of the runtime handle, or should the validated PythonCommand be cached and reused by invoke() to avoid silent revalidation gaps?

Also applies to: 1332-1386


2566-2652: LGTM!

Comment thread README.md Outdated
Comment thread README.md Outdated
Comment thread tests/python/test_code_review_example.py
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: 3

🤖 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 491-510: The env construction in the codex CLI adapter is
bypassing the allowlist when a virtualenv is active because
virtualenv_subprocess_env() returns a full environment copy. Update the env
merge in the adapter logic that builds the subprocess environment so it only
applies the virtualenv-specific overrides needed for compatibility, while still
preserving the INHERITED_ENV_NAMES restriction and the configured payload env
handling.

In `@adapters/common/src/nemo_fabric_adapters/common/utils.py`:
- Around line 33-49: virtualenv_subprocess_env() currently mismatches its
expected contract: it returns {} when no virtualenv is active, and it returns a
full os.environ copy when one is active, which breaks the test and leaks
non-allowlisted variables downstream. Update
adapters/common/src/nemo_fabric_adapters/common/utils.py so
virtualenv_subprocess_env layers only the virtualenv-specific changes onto a
caller-provided base environment instead of always copying os.environ, and make
the no-virtualenv case preserve the incoming environment. Then adjust
build_env() to pass its allowlisted env into
virtualenv_subprocess_env(base_env=env) so the INHERITED_ENV_NAMES boundary is
preserved.

In `@tests/adapters/test_adapaters_common_utils.py`:
- Around line 61-70: The test is asserting the old behavior of
virtualenv_subprocess_env when current_virtualenv() is None, but the API now
expects an optional base_env to be preserved unchanged in that case. Update
test_virtualenv_subprocess_env_preserves_environment_outside_virtualenv in
test_adapaters_common_utils.py to pass a base environment into
common_utils.virtualenv_subprocess_env and assert that the returned env matches
that base_env and is a distinct object, rather than comparing against
os.environ.
🪄 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: bb2c385f-9ac5-4669-9680-fa63cffd3555

📥 Commits

Reviewing files that changed from the base of the PR and between 80091a0 and a6eebfb.

📒 Files selected for processing (4)
  • adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/utils.py
  • adapters/hermes-cli/src/nemo_fabric_adapters/hermes_cli/adapter.py
  • tests/adapters/test_adapaters_common_utils.py
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: Build and publish docs
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{py,pyi}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

**/*.{py,pyi}: If Python code or a Python-facing adapter changed, run just test-python.
For Python SDK or PyO3 binding changes, use python-tests, run focused pytest tests first, then run just test-python; rebuild with just build-python when native code or packaging changed.

Files:

  • adapters/common/src/nemo_fabric_adapters/common/utils.py
  • adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py
  • adapters/hermes-cli/src/nemo_fabric_adapters/hermes_cli/adapter.py
  • tests/adapters/test_adapaters_common_utils.py
**/*

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

For CI or packaging changes, use maintain-ci or maintain-packaging, then run the recipes and checks whose behavior changed.

Files:

  • adapters/common/src/nemo_fabric_adapters/common/utils.py
  • adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py
  • adapters/hermes-cli/src/nemo_fabric_adapters/hermes_cli/adapter.py
  • tests/adapters/test_adapaters_common_utils.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
  • adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py
  • adapters/hermes-cli/src/nemo_fabric_adapters/hermes_cli/adapter.py
tests/**/*.py

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

tests/**/*.py: Use pytest to run Python tests.
Do not add @pytest.mark.asyncio to test functions; async tests should be auto-detected and run 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, using spec when necessary.
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.
When creating a fixture, use the pattern @pytest.fixture(name="<fixture_name>"[, scope="<scope>"]) followed by 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 you need to modify environment variables in a test, use os.environ; tests/conftest.py provides an autouse restore_environ_fixture that restores the environment after each test, so monkeypatch.setenv is unnecessary.
Avoid defensive programming in tests; access expected dictionary keys directly (for example, results["data"]) instead of using .get(), so failures raise loudly and clearly.

Files:

  • tests/adapters/test_adapaters_common_utils.py
tests/adapters/**/*.py

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

tests/adapters/**/*.py: If an adapter or integration changed, run its focused tests.
For adapter behavior changes, run the focused adapter tests under tests/adapters, then just test-python.

Files:

  • tests/adapters/test_adapaters_common_utils.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/adapters/test_adapaters_common_utils.py
🧬 Code graph analysis (1)
adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py (1)
adapters/common/src/nemo_fabric_adapters/common/utils.py (1)
  • settings_payload (101-103)
🪛 Ruff (0.15.20)
adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py

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

(TRY004)


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

(TRY003)

🔇 Additional comments (4)
adapters/common/src/nemo_fabric_adapters/common/utils.py (1)

25-30: LGTM!

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

182-200: LGTM!

build_env already starts from a full os.environ.copy() (no allowlist), so layering virtualenv_subprocess_env() on top here is safe — no leak risk like in codex-cli's allowlisted build_env.

tests/adapters/test_adapaters_common_utils.py (2)

7-7: LGTM!


16-58: LGTM!

Comment thread adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py Outdated
Comment thread adapters/common/src/nemo_fabric_adapters/common/utils.py
Comment thread tests/adapters/test_adapaters_common_utils.py
Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
@linear

linear Bot commented Jul 9, 2026

Copy link
Copy Markdown

…ython

Signed-off-by: David Gardner <dagardner@nvidia.com>
@dagardner-nv
dagardner-nv marked this pull request as ready for review July 9, 2026 19:28
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>

@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)
crates/fabric-core/src/error.rs (1)

150-157: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Error message omits the resolved path field.

path is captured on the variant but never surfaced in the #[error(...)] message — only value is shown. If ADAPTER_PYTHON is set to a relative path, users won't see what absolute path Fabric actually tried to resolve, making the error harder to debug.

♻️ Suggested message tweak
-    #[error("environment variable `ADAPTER_PYTHON` (`{value}`) must point to a valid file")]
+    #[error("environment variable `ADAPTER_PYTHON` (`{value}`) resolved to `{path}`, which does not exist")]
🤖 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 `@crates/fabric-core/src/error.rs` around lines 150 - 157, The
InvalidAdapterPython error message currently only reports the raw ADAPTER_PYTHON
value and omits the resolved path, so update the #[error(...)] on the
InvalidAdapterPython variant in error.rs to include both value and path. Keep
the existing variant fields unchanged, but surface the path field in the
formatted message so callers can see the absolute path Fabric tried to validate.
🤖 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 `@crates/fabric-core/src/error.rs`:
- Around line 150-157: The InvalidAdapterPython error message currently only
reports the raw ADAPTER_PYTHON value and omits the resolved path, so update the
#[error(...)] on the InvalidAdapterPython variant in error.rs to include both
value and path. Keep the existing variant fields unchanged, but surface the path
field in the formatted message so callers can see the absolute path Fabric tried
to validate.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 65e39392-a122-4060-82f9-8cef18b8275c

📥 Commits

Reviewing files that changed from the base of the PR and between d937d83 and 86de65c.

📒 Files selected for processing (6)
  • README.md
  • adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/utils.py
  • adapters/hermes-cli/src/nemo_fabric_adapters/hermes_cli/adapter.py
  • crates/fabric-core/src/error.rs
  • tests/adapters/test_adapaters_common_utils.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (17)
{README.md,docs/index.yml,docs/**/*.{md,mdx}}

📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)

Update entry-point docs when examples or reading paths change

Files:

  • README.md
{README.md,docs/index.yml}

📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)

Update README.md or docs/index.yml when entry points changed

Files:

  • README.md
**/README.md

📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)

Update relevant adapter or example README.md files when examples or adapters have changed

Files:

  • README.md
**/*.{md,mdx}

📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-brand-terminology.md)

**/*.{md,mdx}: Spell NVIDIA in all caps; do not use Nvidia, nvidia, nVidia, nVIDIA, or NV.
Use an NVIDIA before a noun because NVIDIA starts with an "en" sound.
Do not add a registered trademark symbol after NVIDIA when referring to the company.
Use trademark symbols with product names only when the document type or legal guidance requires them.
Verify official capitalization, spacing, and hyphenation for NVIDIA product names.
Precede NVIDIA product names with NVIDIA on first mention when it is natural and accurate.
Link the first mention of a product name when the destination helps the reader.
Do not rewrite product names for grammar or title-case rules.
Preserve third-party product names according to the owner's spelling.
Include the company name and full model qualifier on first use when it helps identify the model.
Preserve the official capitalization and punctuation of model names.
Use shorter family names only after the full model name is established.
For learning-oriented docs, technical blog posts, GTC sessions, tutorials, and developer guides: do not force trademark symbols unless the source, platform, or legal guidance explicitly requires them.
For learning-oriented docs, technical blog posts, GTC sessions, tutorials, and developer guides: keep the product name accurate and consistent.
For press releases, product landing pages, packaging, sales content, or legal copy: follow the current NVIDIA trademark and copyright guidance.
For press releases, product landing pages, packaging, sales content, or legal copy: attribute trademarks on first use when required.
For press releases, product landing pages, packaging, sales content, or legal copy: use the required trademark symbol for the specific product or service.
For press releases, product landing pages, packaging, sales content, or legal copy: do not invent trademark attributions; verify current legal copy.
If the platform requires legal copy, confirm the current source of truth instead...

Files:

  • README.md
**/*.{md,mdx,rst}

📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-technical-docs.md)

**/*.{md,mdx,rst}: When reviewing technical documentation, verify that commands, examples, paths, APIs, and support claims match the current repository.
Make technical documents easy to scan by fixing headings, lead-in sentences, lists, tables, and procedure shape.
Preserve exact code, command, API, package, and UI strings unless they are factually wrong.
Prefer focused findings over broad rewrites.
Use title case consistently in technical documentation headings.
Avoid quotation marks, ampersands, and exclamation marks in technical documentation headings.
Keep product, event, research, and whitepaper names in their official title case.
Use title case for table headers.
Do not force social-media sentence case into technical documentation.
Format code elements, commands, parameters, package names, and expressions in monospace.
Format directories, file names, and paths in monospace.
Use angle brackets inside monospace for variables inside paths.
Format error messages and strings with quotation marks, using code formatting when that is clearer.
Format UI buttons, menus, fields, and labels in bold.
Use angle brackets between UI labels for menu paths.
Use italics on first use for new terms, and only when the term is introduced.
Italicize publication titles.
Write keyboard shortcuts in plain text.
Use Owner/repo link text for GitHub repositories.
Introduce every code block with a complete sentence.
Do not make a code block complete the grammar of the previous sentence.
Do not continue a sentence after a code block.
Use syntax highlighting when the format supports it.
Avoid the word "snippet" unless the surrounding documentation already uses it as a term of art.
Keep inline method, function, and class references consistent with nearby docs, and omit empty parentheses in prose when no call is shown.
Use descriptive anchor text that matches the destination title when possible.
Avoid raw URLs in running text.
Avoid generic anchors such as "here," "this page," and "read more....

Files:

  • README.md
**/*.{md,mdx,rst,txt}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

**/*.{md,mdx,rst,txt}: If documentation or examples changed, run just docs when practical and verify documented commands against the current repository.
For documentation-only changes, use contribute-docs and review-doc-style; run just docs for docs-site or generated-reference changes.

Files:

  • README.md
**/*

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

For CI or packaging changes, use maintain-ci or maintain-packaging, then run the recipes and checks whose behavior changed.

Files:

  • README.md
  • tests/adapters/test_adapaters_common_utils.py
  • adapters/common/src/nemo_fabric_adapters/common/utils.py
  • crates/fabric-core/src/error.rs
  • adapters/hermes-cli/src/nemo_fabric_adapters/hermes_cli/adapter.py
  • adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py
{docs/**,README.md,AGENTS.md}

⚙️ CodeRabbit configuration file

{docs/**,README.md,AGENTS.md}: Review documentation for technical accuracy against the current API, command correctness, and consistency with generated schemas.

Files:

  • README.md
tests/**/*.py

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

tests/**/*.py: Use pytest to run Python tests.
Do not add @pytest.mark.asyncio to test functions; async tests should be auto-detected and run 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, using spec when necessary.
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.
When creating a fixture, use the pattern @pytest.fixture(name="<fixture_name>"[, scope="<scope>"]) followed by 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 you need to modify environment variables in a test, use os.environ; tests/conftest.py provides an autouse restore_environ_fixture that restores the environment after each test, so monkeypatch.setenv is unnecessary.
Avoid defensive programming in tests; access expected dictionary keys directly (for example, results["data"]) instead of using .get(), so failures raise loudly and clearly.

Files:

  • tests/adapters/test_adapaters_common_utils.py
**/*.{py,pyi}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

**/*.{py,pyi}: If Python code or a Python-facing adapter changed, run just test-python.
For Python SDK or PyO3 binding changes, use python-tests, run focused pytest tests first, then run just test-python; rebuild with just build-python when native code or packaging changed.

Files:

  • tests/adapters/test_adapaters_common_utils.py
  • adapters/common/src/nemo_fabric_adapters/common/utils.py
  • adapters/hermes-cli/src/nemo_fabric_adapters/hermes_cli/adapter.py
  • adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py
tests/adapters/**/*.py

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

tests/adapters/**/*.py: If an adapter or integration changed, run its focused tests.
For adapter behavior changes, run the focused adapter tests under tests/adapters, then just test-python.

Files:

  • tests/adapters/test_adapaters_common_utils.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/adapters/test_adapaters_common_utils.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
  • adapters/hermes-cli/src/nemo_fabric_adapters/hermes_cli/adapter.py
  • adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py
**/*.rs

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

**/*.rs: If Rust code changed, run cargo fmt --all -- --check and just test-rust.
If public configuration types changed, confirm the schema snapshot tests in just test-rust pass and review generated schema diffs.
For Rust core, CLI, or shared runtime semantics changes, run Rust formatting and tests; add Python tests when the behavior is exposed through the SDK, and run relevant tests for CLI behavior.

Files:

  • crates/fabric-core/src/error.rs
crates/fabric-core/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If crates/fabric-core changed in a way exposed through Python, run both the Rust and Python suites.

Files:

  • crates/fabric-core/src/error.rs
**/*.{rs,toml}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If the PyO3 bridge or package metadata changed, run just build-python and cargo check -p fabric-python --locked.

Files:

  • crates/fabric-core/src/error.rs
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/error.rs
🧬 Code graph analysis (1)
adapters/common/src/nemo_fabric_adapters/common/utils.py (1)
tests/adapters/test_adapaters_common_utils.py (1)
  • virtualenv_subprocess_env (52-52)
🔇 Additional comments (5)
README.md (1)

103-108: LGTM!

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

33-54: Full os.environ copy still returned unconditionally; downstream allowlist bypass persists.

virtualenv_subprocess_env() now always starts from os.environ.copy(), fixing the earlier test-mismatch, but still gives callers the entire process environment rather than just the virtualenv delta. This was previously flagged as a critical leak vector when merged into allowlisted adapter environments (see adapters/codex-cli/.../adapter.py), and that risk is unresolved here — the suggested base_env parameter fix from the prior review was not adopted.

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

456-475: Allowlist removed entirely — codex CLI subprocess now inherits the full process environment unconditionally.

INHERITED_ENV_NAMES filtering was dropped, and build_env now seeds env from virtualenv_subprocess_env(), which returns a full os.environ copy regardless of venv state. Previously the leak was conditional on running inside a virtualenv; now every fabric process env var (potential secrets/tokens) is passed to the codex CLI subprocess unconditionally. Same root-cause concern raised previously, now broader in scope since the allowlist itself is gone rather than merely bypassed.

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

181-192: LGTM!

tests/adapters/test_adapaters_common_utils.py (1)

61-70: LGTM!

Comment thread adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py
Comment thread examples/code_review_agent/__main__.py
Comment thread examples/code_review_agent/__main__.py

@ericevans-nv ericevans-nv left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approving since the core ADAPTER_PYTHON behavior looks good and the Codex env inheritance is intentional. I left one suggested guard for --show-output so it doesn’t raise on a successful result that lacks output.response; that can be applied here or handled as a follow-up if you want to formalize response as part of the output contract separately.

Co-authored-by: Eric Evans II <194135482+ericevans-nv@users.noreply.github.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
Signed-off-by: David Gardner <dagardner@nvidia.com>
@dagardner-nv
dagardner-nv merged commit ff2a5c2 into NVIDIA:main Jul 9, 2026
5 checks passed
@dagardner-nv
dagardner-nv deleted the david-gen-python branch July 9, 2026 21:59
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.

2 participants