Skip to content

feat(optimization): Agents-owned Fabric Optuna HPO with Hermes + MCP (AALGO-277) - #608

Merged
soluwalana merged 35 commits into
mainfrom
aalgo-277/solu
Aug 6, 2026
Merged

feat(optimization): Agents-owned Fabric Optuna HPO with Hermes + MCP (AALGO-277)#608
soluwalana merged 35 commits into
mainfrom
aalgo-277/solu

Conversation

@soluwalana

@soluwalana soluwalana commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Introduce Fabric-backed numeric hyperparameter optimization as an Agents-owned surface (nemo agents optimizeagents.optimize), with nemo-optimization as the shared Optuna library — not a Customizer Tune contributor (RFC Alt 5).

  • Agents primary CLI/API: nemo agents optimize run|submit|explain; job registration mounted by the agents plugin. No nemo customization optimize, no OptimizationContributor.
  • Optuna study driver: typed search space (type + path), config overlays, trial selection, early stop, and artifacts (study_summary.json, CSV, Pareto plots, optional ATIF trial_trace_map.json).
  • Real trial path: FabricTrialEvaluatorAgentEvaluator + FabricAgentRuntime (no NAT in the hot path). Agent-eval/audit failures raise StudyDriverError so Optuna fails that trial and continues.
  • --agent resolve: fetch platform nemo-agents-spec-v1, translate to Fabric, merge overlay models (e.g. judge) from --optimize-config.
  • Golden-path harness: Fabric Hermes (nvidia.fabric.hermes). Examples under plugins/nemo-optimization/examples/hermes-optimize/ (optimize-*.yaml for --optimize-config).
  • MCP (path-first): platform hook eval.run_hook.type: mcp_run_binding — agent checkout agent_src + agent-venv executable; mcp.servers.*.env / top-level args/env stay on the package; hook rebinds url and runs create/verify/cleanup.
  • Eval SDK: tunable_rag_evaluator for judge-based scoring; Fabric task-hook loading (ref / path+attr / nemo.fabric.task_hooks entry points).
  • Cutover: remove nvidia-nat-config-optimizer and the legacy agents optimize job; reject NAT-shaped optimize configs.

Fabric pin: uv.sources locks NeMo-Fabric to 55450ff… (includes FABRIC-167 MCP extensions fix). Plain uv sync --package nemo-agents-plugin is enough — no local wheel build / --no-sync workaround required for the locked SHA.


Prerequisites (Hermes / Fabric)

From the nemo-platform repo root. Full QA steps:
plugins/nemo-optimization/examples/hermes-optimize/README.md.

uv sync --package nemo-agents-plugin
source .venv/bin/activate

# hermes-agent is not in the lock (pin conflict). Install once (and again after any fresh uv sync):
uv pip install --python .venv/bin/python "hermes-agent==0.18.2" --no-deps
python -c "import hermes_cli; print('ok')"

export ADAPTER_PYTHON="$(pwd)/.venv/bin/python"   # required; else system Python misses nemo_fabric_adapters
export NMP_BASE_URL="${NMP_BASE_URL:-http://localhost:8080}"
export NEMO_BASE_URL="${NEMO_BASE_URL:-$NMP_BASE_URL}"
export NVIDIA_API_KEY=...   # required for inference-api examples

Run Hermes optimize (Agents CLI)

--optimize-config must be an absolute path; dataset / base_dir paths in the YAML are relative to process CWD (repo root).

1. Chat-only smoke (optimize-chatonly.yaml)

nemo agents optimize run \
  --optimize-config "$(pwd)/plugins/nemo-optimization/examples/hermes-optimize/optimize-chatonly.yaml" \
  --workspace default

Expected: status: completed, n_trials: 2.

2. Chat-only via platform --agent

nemo agents create \
  --name hermes-optimize-chatonly \
  --agent-config "$(pwd)/plugins/nemo-optimization/examples/hermes-optimize/agents/chatonly/agent.yaml" \
  --workspace default

nemo agents optimize run \
  --optimize-config "$(pwd)/plugins/nemo-optimization/examples/hermes-optimize/optimize-chatonly-via-agent.yaml" \
  --agent hermes-optimize-chatonly \
  --workspace default

Use the slim agents/chatonly/ dir only (parent hermes-optimize/ includes artifacts/ and fails fileset limits). Recreate with nemo agents delete hermes-optimize-chatonly -y after editing agent.yaml.

Expected: Resolved agent 'hermes-optimize-chatonly'…, status: completed, n_trials: 2.

3. MCP e2e (optimize-mcp.yaml)

Requires a phishing-analyzer agent checkout with its own venv (do not pip-install that agent into the platform venv):

export PHISHING_AGENT_ROOT="${PHISHING_AGENT_ROOT:-$HOME/work/email-phishing-analyzer-harnesses}"
export PHISHING_AGENT_SRC="$PHISHING_AGENT_ROOT/src"
export PHISHING_MCP_BIN="$PHISHING_AGENT_ROOT/.venv/bin/email-phishing-analyzer-mcp"
# Once in the agent checkout: cd "$PHISHING_AGENT_ROOT" && uv sync
test -d "$PHISHING_AGENT_SRC" && test -x "$PHISHING_MCP_BIN"

nemo agents optimize run \
  --optimize-config "$(pwd)/plugins/nemo-optimization/examples/hermes-optimize/optimize-mcp.yaml" \
  --workspace default

Expected: status: completed, n_trials: 4, best score near 1.0 when the harness calls the analyzer once.

Known flake: a single dataset row with an empty Hermes response marks that sample failed and fails the Optuna trial; if all trials fail you get no completed trials. Inspect examples/hermes-optimize/artifacts/.fabric/hermes/runtimes/*/logs/ and retry.

Optional ATIF live smoke (not CI)

Point FABRIC_QWEN_* at a reachable OpenAI-compatible endpoint (local IGW or otherwise); do not hardcode workbox hosts in configs.

RUN_NEMO_OPTIMIZE_ATIF_E2E=1 \
NEMO_FABRIC_REPO=/path/to/NeMo-Fabric \
FABRIC_QWEN_BASE_URL="$NMP_BASE_URL/apis/inference-gateway/v2/workspaces/default/openai/-/v1" \
FABRIC_QWEN_MODEL=<your-igw-model-id> \
uv run --package nemo-optimization-plugin \
  pytest plugins/nemo-optimization/tests/smoke_fabric_optimize_atif.py -q

Test plan

  • Unit: pytest plugins/nemo-optimization/tests -q (ignore live smoke)
  • Unit: Fabric hook / MCP binding tests under packages/nemo_evaluator_sdk/tests/agent_eval/
  • Chat-only Hermes smoke → status: completed (optimize-chatonly.yaml)
  • Chat-only --agent path → create slim agent + optimize-chatonly-via-agent.yamlstatus: completed
  • MCP e2e (optimize-mcp.yaml) → currently flaky on empty Hermes responses for individual dataset rows (retry / shrink dataset); previously green on this branch
  • Optional ATIF smoke against local IGW virtual model
  • Confirm docs preview: Agents optimize points at Hermes optimize-*.yaml examples, not Customizer Tune

Summary by CodeRabbit

  • New Features

    • Added Fabric-backed numeric optimization with Optuna, configurable search spaces, early stopping, multi-objective selection, and result artifacts.
    • Added tunable RAG evaluation with weighted and custom scoring.
    • Added task lifecycle hooks, including MCP binding, credential handoff, verification, and cleanup.
    • Added trajectory and trial metadata for improved traceability.
    • Improved Docker GPU detection, networking, and platform connectivity.
    • Unified API schemas across evaluation, optimization, deployment, and configuration workflows.
  • Documentation

    • Updated optimization guidance and added Hermes/Fabric examples, configurations, and datasets.
  • Tests

    • Added comprehensive coverage for optimization, evaluation, hooks, routing, and configuration validation.

@github-actions github-actions Bot added the feat label Jul 8, 2026
@soluwalana soluwalana changed the title feat(optimization): Fabric-backed Optuna study with Qwen IGW trial ex… feat(optimization): Fabric-backed Optuna study with Qwen IGW trial execution (AALGO-277) Jul 8, 2026
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor
Suite Lines Covered Line Rate Branch Rate
Unit Tests 31256/39866 78.4% 62.8%
Integration Tests 18203/37818 48.1% 20.6%

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

@soluwalana
soluwalana marked this pull request as ready for review August 4, 2026 22:27
@soluwalana
soluwalana requested review from a team as code owners August 4, 2026 22:27
@soluwalana soluwalana changed the title feat(optimization): Fabric-backed Optuna study with Qwen IGW trial execution (AALGO-277) feat(optimization): Agents-owned Fabric Optuna HPO with Hermes + MCP (AALGO-277) Aug 4, 2026
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

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

Walkthrough

The pull request adds Fabric-native numeric optimization with Optuna, task-scoped Fabric hooks, MCP bindings, tunable RAG evaluation, updated job wiring, Docker handling, examples, tests, and migration documentation.

Changes

Fabric optimization platform

Layer / File(s) Summary
Optimization runtime and study execution
plugins/nemo-optimization/src/nemo_optimization/..., plugins/nemo-optimization/tests/...
Adds Fabric validation, agent and model resolution, backend discovery, OptimizeJob, routing, Optuna studies, search spaces, overlays, artifacts, ATIF metadata, and evaluation orchestration.
Evaluator hooks, MCP bindings, and RAG metrics
packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/..., packages/nemo_evaluator_sdk/tests/...
Adds task-hook loading and lifecycle execution, MCP binding management, trajectory metadata, and tunable RAG scoring.
Job migration, packaging, and API contracts
packages/nemo_platform/pyproject.toml, plugins/nemo-agents/..., plugins/nemo-optimization/pyproject.toml, pyproject.toml, third_party/*
Moves agents.optimize to OptimizeJob, adds optimization entry points and workspace packaging, removes legacy optimizer wiring, and updates dependency metadata.
Documentation, examples, and deployment integration
docs/agents/*, plugins/nemo-optimization/examples/hermes-optimize/*, plugins/nemo-deployments/..., services/core/models/...
Documents Fabric and Hermes workflows, adds optimization examples, updates Docker connectivity, and uses configured reserved GPU IDs.

Possibly related PRs

Suggested labels: test

Suggested reviewers: svvarom, ngoncharenko, arpitsardhana

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 24.82% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: Agents-owned Fabric Optuna HPO with Hermes and MCP integration.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch aalgo-277/solu

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 8

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

🟡 Minor comments (14)
docs/agents/index.mdx-57-63 (1)

57-63: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Remove optimize from the NAT-only table.

nemo agents optimize run now requires a Fabric-native package. This row directs users to submit NAT tuning configurations that the job rejects. Keep evaluate as legacy, or describe optimize as Fabric-backed.

🤖 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 `@docs/agents/index.mdx` around lines 57 - 63, Remove the Legacy NAT-only table
row for the `nemo agents optimize run` command in the documentation, leaving the
`evaluate` row unchanged; do not present NAT optimization as NAT-only, since
optimization now requires a Fabric-native package.
plugins/nemo-agents/tests/unit/usage/test_usage_cli.py-204-220 (1)

204-220: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

chmod(0o000) does not block reads for root. Many CI containers run tests as UID 0, where the open succeeds and the command exits 0. The test then fails on exit_code == 1. Skip the test when os.geteuid() == 0, or force the read error by patching the read path instead.

Proposed guard
+@pytest.mark.skipif(hasattr(os, "geteuid") and os.geteuid() == 0, reason="root bypasses file mode checks")
 def test_usage_show_unreadable_result_json_exits_cleanly(app, tmp_path: Path) -> None:
🤖 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 `@plugins/nemo-agents/tests/unit/usage/test_usage_cli.py` around lines 204 -
220, Update test_usage_show_unreadable_result_json_exits_cleanly to avoid
relying on chmod-based unreadability when running as root: skip the test when
os.geteuid() == 0, or patch the file-reading path to deterministically raise the
expected read error. Preserve the existing assertions for non-root execution.
plugins/nemo-optimization/README.md-16-19 (1)

16-19: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove or fix the examples/hermes-optimize/hooks/ reference. The directory does not exist in this repository, so the README link is broken.

🤖 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 `@plugins/nemo-optimization/README.md` around lines 16 - 19, Remove the
nonexistent examples/hermes-optimize/hooks/ reference from the README, or
replace it with a valid repository path that documents the per-task Fabric
lifecycle hooks. Keep the surrounding hook configuration references and
explanation intact.
plugins/nemo-optimization/src/nemo_optimization/router.py-65-68 (1)

65-68: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Return OptimizeRouterError when discovery misses a backend.

Line 67 indexes the discovery map directly. If optuna or ga is not registered, dispatch_payload() raises KeyError. Match the guarded .get() path in dispatch() and add a missing-backend test.

🤖 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 `@plugins/nemo-optimization/src/nemo_optimization/router.py` around lines 65 -
68, Update dispatch_payload() to retrieve the selected backend with the same
guarded lookup used by dispatch(), and return OptimizeRouterError when discovery
does not contain the backend instead of allowing KeyError. Add a test covering a
missing optuna or ga registration and verify the expected error response.
plugins/nemo-optimization/src/nemo_optimization/preflight.py-31-50 (1)

31-50: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Merge each LLM configuration before validation.

Lines 32-35 replace an agent LLM mapping when the optimize YAML overrides the same key. If the YAML only changes llms.default.model_name, _type is removed and Lines 43-49 skip validation.

Use the same deep-merge semantics as build_optimize_payload(). Add a test with a partial LLM override.

🤖 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 `@plugins/nemo-optimization/src/nemo_optimization/preflight.py` around lines 31
- 50, The LLM collection in the preflight flow must deep-merge agent and
optimize configurations before validation, rather than replacing entries by key.
Reuse the existing merge behavior or helper used by build_optimize_payload()
when combining llms, then validate the merged _type and model_name in the
existing loop. Add coverage for a partial override such as
llms.default.model_name that preserves the base _type and triggers validation.
plugins/nemo-optimization/tests/test_selection.py-28-31 (1)

28-31: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

This assertion cannot fail.

All three input trials are on the Pareto front, so in {(0.1, 0.9), (0.2, 0.2), (0.9, 0.1)} holds for any return value. Assert the exact trial that harmonic scoring selects.

🤖 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 `@plugins/nemo-optimization/tests/test_selection.py` around lines 28 - 31,
Update test_pick_trial_harmonic_returns_pareto_member to assert the exact values
of the trial selected by harmonic scoring, rather than accepting every input
trial. Determine the expected harmonic winner from the provided study data and
assert that specific result.
plugins/nemo-optimization/src/nemo_optimization/backends/optuna/selection.py-28-52 (1)

28-52: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

weights is ignored for harmonic and chebyshev.

study_driver.run_numeric_study passes weights=[metric.weight for metric in config.metrics] on every call, and harmonic is the default mode. A user who sets weight in optimizer.eval_metrics gets it silently dropped. Log a warning, or raise when non-uniform weights arrive with a mode that cannot use them.

Also move the mode check to the top of the function so an invalid mode fails before the matrix and normalization work.

🤖 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 `@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/selection.py`
around lines 28 - 52, Update the selection function around _SUPPORTED_MODES to
validate mode.lower() before computing the Pareto matrix or normalization, then
reject or warn when non-uniform weights are supplied to harmonic or chebyshev;
ensure configured weights are not silently ignored while preserving weighted
behavior for sum.
plugins/nemo-optimization/src/nemo_optimization/backends/optuna/config_overlay.py-54-61 (1)

54-61: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Lines 58-61 are unreachable.

Line 56-57 pops optimizer from config. config.get("optimizer") at Line 58 therefore always returns None, so the nested search_space / optimizable_params cleanup never runs. Pick one behavior: remove the whole key, or keep optimizer and strip only its tuning fields.

🔧 Proposed fix (full removal, matching current effective behavior)
 def strip_optimizer_only_fields(config: dict[str, Any]) -> None:
     """Remove optimizer metadata from a trial config artifact (in-place)."""
     for key in _OPTIMIZER_ONLY_TOP_LEVEL_KEYS:
         config.pop(key, None)
-    optimizer = config.get("optimizer")
-    if isinstance(optimizer, dict):
-        optimizer.pop("search_space", None)
-        optimizer.pop("optimizable_params", None)
🤖 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
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/config_overlay.py`
around lines 54 - 61, Update strip_optimizer_only_fields to use one consistent
optimizer-cleanup strategy: since _OPTIMIZER_ONLY_TOP_LEVEL_KEYS already removes
the top-level optimizer entry, remove the now-unreachable
config.get("optimizer") block and retain the existing full-removal behavior.
plugins/nemo-optimization/src/nemo_optimization/backends/optuna/search_space.py-96-105 (1)

96-105: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Validate that low and high are numbers.

A YAML config can supply low: "0.1". The comparison at Line 104 then raises TypeError on mixed types, or compares strings lexically when both are strings. Both escape the SearchSpaceError contract that callers catch.

🛡️ Proposed fix
     if low is None or high is None:
         raise SearchSpaceError(
             "Search space entry must define either 'values' or both 'low' and 'high'."
         )
+    if isinstance(low, bool) or isinstance(high, bool) or not isinstance(low, (int, float)) or not isinstance(high, (int, float)):
+        raise SearchSpaceError(
+            f"Search space entry {name!r} requires numeric 'low' and 'high'; "
+            f"got low={low!r}, high={high!r}."
+        )
     if low >= high:
🤖 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
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/search_space.py`
around lines 96 - 105, Validate that low and high in the search-space parsing
logic are numeric before evaluating low >= high, and raise SearchSpaceError for
non-numeric values. Preserve the existing requirement that both bounds are
present and ensure valid numeric bounds continue through the current range
validation.
plugins/nemo-optimization/tests/smoke_fabric_optimize_atif.py-130-131 (1)

130-131: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use the correct variable in the assertion message.

entry is the loop variable from Lines 125-128. At Line 131 it still holds the last entry, while atif_path comes from trace_map[0]. The failure message can name a different trace.

🐛 Proposed fix
-    atif_path = Path(trace_map[0]["trace_ref"])
-    assert atif_path.is_file(), entry["trace_ref"]
+    atif_path = Path(trace_map[0]["trace_ref"])
+    assert atif_path.is_file(), trace_map[0]["trace_ref"]
🤖 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 `@plugins/nemo-optimization/tests/smoke_fabric_optimize_atif.py` around lines
130 - 131, Update the assertion message in the trace-file validation near
atif_path to reference the same trace_map[0] entry used to construct atif_path,
rather than the stale loop variable entry, so failures identify the correct
trace.
plugins/nemo-optimization/src/nemo_optimization/backends/optuna/fabric_trial.py-63-63 (1)

63-63: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Guard eval.general before attribute access.

If eval.general is present but null, self._eval_config.get("general", {}) returns None and .get(...) raises AttributeError. _load_dataset_rows at Line 233 guards the same key with isinstance. Use the same guard here.

🐛 Proposed fix
-        self._parallelism = int(self._eval_config.get("general", {}).get("max_concurrency", default_parallelism))
+        general = self._eval_config.get("general")
+        general = general if isinstance(general, Mapping) else {}
+        self._parallelism = int(general.get("max_concurrency", default_parallelism))
🤖 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
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/fabric_trial.py`
at line 63, Update the parallelism initialization in the trial setup to validate
that the value from self._eval_config.get("general") is a mapping before calling
.get("max_concurrency"). Match the isinstance-based guard used by
_load_dataset_rows, and fall back to default_parallelism when eval.general is
null or otherwise invalid.
plugins/nemo-optimization/tests/smoke_fabric_optimize_atif.py-86-86 (1)

86-86: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add pytest-timeout to the plugin's dev dependency group. The root pytest.ini enables --strict-markers, so this test fails when the package-specific environment omits the plugin.

🤖 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 `@plugins/nemo-optimization/tests/smoke_fabric_optimize_atif.py` at line 86,
Add pytest-timeout to the plugin's dev dependency group so the
`@pytest.mark.timeout` marker in smoke_fabric_optimize_atif.py is available in the
package-specific environment under the root strict-marker configuration.
packages/nemo_evaluator_sdk/tests/metrics/test_tunable_rag_evaluator.py-26-29 (1)

26-29: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Allow string payloads in _judge_response.

Line 116 passes a str, which conflicts with dict[str, Any]. Use dict[str, Any] | str.

🤖 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 `@packages/nemo_evaluator_sdk/tests/metrics/test_tunable_rag_evaluator.py`
around lines 26 - 29, Update the _judge_response parameter annotation to accept
either dict[str, Any] or str, while preserving its existing JSON serialization
and response structure.

Source: Coding guidelines

packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_hook_loading.py-57-57 (1)

57-57: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove the temporary __init__.py fixtures.

  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_hook_loading.py#L57-L57: Remove the write call. Import author_hooks.hook as a namespace package.
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_mcp_run_binding_hook.py#L245-L245: Remove the write call. Import agent_pkg.audit as a namespace package.

As per coding guidelines, “Do not add __init__.py files to Python packages; prefer implicit namespace packages.”

🤖 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 `@packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_hook_loading.py` at
line 57, Remove the temporary __init__.py write call in
packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_hook_loading.py at
lines 57-57 and update the related import to use author_hooks.hook as an
implicit namespace package; likewise remove the write call in
packages/nemo_evaluator_sdk/tests/agent_eval/test_mcp_run_binding_hook.py at
lines 245-245 and import agent_pkg.audit as an implicit namespace package. Do
not add replacement __init__.py files.

Source: Coding guidelines

🧹 Nitpick comments (14)
plugins/nemo-optimization/README.md (1)

6-6: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Drop the internal label. "(Alt 5)" refers to an internal design alternative and gives readers no information.

Proposed edit
-Primary user surface (Alt 5):
+Primary user surface:
🤖 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 `@plugins/nemo-optimization/README.md` at line 6, Remove the internal “(Alt 5)”
label from the “Primary user surface” heading in the README, leaving the
user-facing heading text unchanged.
plugins/nemo-optimization/examples/hermes-optimize/README.md (1)

22-30: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Note the risk of --no-deps. Installing hermes-agent==0.18.2 with --no-deps into the project venv leaves its runtime requirements unresolved, so failures appear later as import errors. Add the required imports or a one-line "if imports fail, install X" note next to the confirm step.

🤖 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 `@plugins/nemo-optimization/examples/hermes-optimize/README.md` around lines 22
- 30, Update the “hermes-agent” harness setup section in the README to
explicitly warn that installing with --no-deps may leave runtime requirements
unresolved, and add a concise troubleshooting note beside the verification step
instructing users to install the missing dependencies if imports fail.
plugins/nemo-agents/tests/unit/usage/test_usage_cli.py (1)

105-111: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Pin the exit code. assert result.exit_code in (0, 2) accepts both behaviors, so a regression in the no-args path stays green. Assert the single code the app produces today.

🤖 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 `@plugins/nemo-agents/tests/unit/usage/test_usage_cli.py` around lines 105 -
111, Update test_usage_with_no_args_prints_help to assert the specific current
exit code produced by runner.invoke(app, ["usage"]) instead of accepting both 0
and 2; keep the help-output assertion unchanged.
plugins/nemo-agents/tests/unit/test_optimize_skills_analyze_only.py (1)

254-287: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Assertions can pass on unrelated failures. Both tests accept any nonzero exit code and only match a substring. A crash before the guard (for example config parsing) still yields nonzero, and the substring check is the only discriminator. Pin the exit code the guard produces, and assert the error text, so a regression that moves the failure earlier is visible.

🤖 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 `@plugins/nemo-agents/tests/unit/test_optimize_skills_analyze_only.py` around
lines 254 - 287, Strengthen test_cli_analyze_only_requires_initial_batch_flag
and test_cli_analyze_only_from_config_file_requires_initial_batch by asserting
the exact nonzero exit code produced by the validation guard and matching the
complete expected error text, rather than accepting any nonzero result or a
partial initial-batch substring. Keep the tests focused on confirming the
analyze-only initial-batch guard is reached.
plugins/nemo-optimization/src/nemo_optimization/registry.py (1)

10-13: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Import OptimizationBackend at module scope.

OptimizationBackend has no shown import path back to registry.py. Remove the TYPE_CHECKING block and use a regular import.

Proposed change
-from typing import TYPE_CHECKING
-
-if TYPE_CHECKING:
-    from nemo_optimization.backends.protocol import OptimizationBackend
+from nemo_optimization.backends.protocol import OptimizationBackend
@@
 def discover_optimization_backends() -> dict[str, OptimizationBackend]:
-    from nemo_optimization.backends.protocol import OptimizationBackend

As per coding guidelines, do not import types only under TYPE_CHECKING when a regular import is possible.

Also applies to: 23-24

🤖 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 `@plugins/nemo-optimization/src/nemo_optimization/registry.py` around lines 10
- 13, Update registry.py to remove the TYPE_CHECKING-only import block and
import OptimizationBackend regularly from nemo_optimization.backends.protocol at
module scope, including the other referenced occurrence.

Source: Coding guidelines

plugins/nemo-optimization/src/nemo_optimization/backends/optuna/backend.py (2)

44-58: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Parsing happens twice.

run_study calls parse_numeric_study_config(payload["optimizer"]), and run_numeric_study parses the same optimizer mapping again at study_driver.py Line 171. Pass the parsed config into run_numeric_study, or read metric_names from the returned result only. Duplicate parsing lets the two paths diverge if validation changes.

🤖 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 `@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/backend.py`
around lines 44 - 58, Update run_study and run_numeric_study so the optimizer
configuration is parsed only once: pass the already parsed config from run_study
into run_numeric_study and reuse it there, including for metric handling. Remove
the second parse in run_numeric_study while preserving existing validation and
study execution behavior.

82-88: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Unannotated parameters in new modules. Both functions omit concrete type hints, so ty cannot check the callers.

  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/backend.py#L82-L88: annotate output_dir: Path and add the return type as the TrialEvaluator protocol.
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/atif_metadata.py#L18-L18: annotate generate_id: Callable[[], str].
🤖 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 `@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/backend.py`
around lines 82 - 88, Annotate _build_trial_evaluator in
plugins/nemo-optimization/src/nemo_optimization/backends/optuna/backend.py:82-88
with output_dir: Path and return type TrialEvaluator. Annotate generate_id in
plugins/nemo-optimization/src/nemo_optimization/backends/optuna/atif_metadata.py:18-18
as Callable[[], str], adding or reusing the necessary imports.

Source: Coding guidelines

plugins/nemo-optimization/src/nemo_optimization/backends/optuna/study_driver.py (1)

86-126: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Duplicate evaluator_name values collapse metrics silently.

Two eval_metrics entries can resolve to the same metric_name at Line 104. metric_names then contains duplicates while directions keeps both entries, so the study optimizes the same score twice under different directions. Reject duplicate resolved metric names.

🤖 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
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/study_driver.py`
around lines 86 - 126, Update parse_numeric_study_config so each resolved
MetricSpec.name, including evaluator_name fallbacks, is unique before appending
it to metrics. Track previously resolved names and raise StudyDriverError when a
duplicate occurs, preventing duplicate entries from reaching the study
configuration.
plugins/nemo-optimization/tests/test_atif_metadata.py (1)

30-37: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a case without row_id.

build_atif_trial_tags omits ATIF_ROW_ID when row_id is falsy. No test covers that branch, and no test covers whitespace stripping in resolve_experiment_id.

🤖 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 `@plugins/nemo-optimization/tests/test_atif_metadata.py` around lines 30 - 37,
Extend test_build_atif_trial_tags with a case where row_id is omitted or falsy,
asserting ATIF_ROW_ID is absent from the returned tags. Add a separate test for
resolve_experiment_id using whitespace-padded input and assert the experiment ID
is stripped as expected.
plugins/nemo-optimization/tests/test_search_space.py (1)

115-127: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a path-collision test.

suggestions_by_path raises when two logical names share one path. That branch is untested. Also add a case for the low >= high rejection.

🤖 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 `@plugins/nemo-optimization/tests/test_search_space.py` around lines 115 - 127,
Add tests in test_suggestions_by_path_maps_logical_names covering two logical
names mapped to the same path and asserting suggestions_by_path raises the
expected exception, plus a search-space case with low >= high asserting the
parser rejects it. Reuse the existing parse_search_space and suggestions_by_path
setup and preserve the current valid mapping assertion.
plugins/nemo-optimization/src/nemo_optimization/backends/optuna/config_overlay.py (1)

36-51: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Collision detection is order-dependent.

nest_dotted_paths({"a": 2, "a.b": 1}) raises KeyError, but the reverse order {"a.b": 1, "a": 2} silently overwrites the nested dict with 2. Reject the scalar-over-mapping case too if the collision must always fail.

🤖 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
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/config_overlay.py`
around lines 36 - 51, Update nest_dotted_paths to detect collisions in both
insertion orders: when assigning a leaf value, reject replacing an existing
mapping, while preserving the current error for traversing through a scalar.
Ensure inputs such as {"a": 2, "a.b": 1} and the reverse order consistently
raise KeyError instead of overwriting data.
plugins/nemo-optimization/src/nemo_optimization/backends/optuna/artifacts.py (1)

169-176: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the dead n_metrics == 1 branch.

_plot_pairwise is only called from maybe_write_pareto_plots after the len(metric_names) < 2 early return. Lines 172-173 and the if n_metrics > 1 fallback at Line 176 are unreachable.

🤖 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 `@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/artifacts.py`
around lines 169 - 176, Remove the unreachable single-metric handling from
_plot_pairwise: delete the n_metrics == 1 axes reassignment and use direct
axes[row_index][col_index] access in the plotting loop. Preserve the existing
caller guard in maybe_write_pareto_plots.
plugins/nemo-optimization/tests/test_fabric.py (1)

37-39: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add a case for the schema-less rejection branch.

require_fabric_agent_config has a second failure path for configs that are neither Fabric nor NAT shaped (must declare schema_version). No test covers it.

🤖 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 `@plugins/nemo-optimization/tests/test_fabric.py` around lines 37 - 39, Add a
test alongside test_require_fabric_agent_rejects_nat that passes a schema-less,
non-Fabric/non-NAT configuration to require_fabric_agent_config and asserts
FabricOptimizeError with a match for “must declare schema_version”.
plugins/nemo-optimization/src/nemo_optimization/backends/optuna/fabric_trial.py (1)

48-60: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Collapse the redundant isinstance checks.

Line 48 already normalizes fabric_eval to a Mapping or {}. The isinstance(fabric_eval, Mapping) guards at Lines 55, 57, and 59 are always true.

🤖 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
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/fabric_trial.py`
around lines 48 - 60, Remove the redundant isinstance(fabric_eval, Mapping)
guards from the _fabric_base_dir, _timeout_s, and _capture_trajectory
assignments in the surrounding initialization flow. Since fabric_eval is already
normalized to a Mapping or empty dictionary, access its values directly while
preserving the existing defaults.
🤖 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
`@packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hooks_mcp_binding.py`:
- Around line 287-305: Update the binding setup flow in prepare so each created
binding and handoff is registered before config.add_mcp_server or any subsequent
setup that may fail, allowing self.cleanup(session) to release resources from
partially completed entries. In the cleanup path, ensure failures from an
individual binding.cleanup() or handoff.close() are isolated so cleanup
continues for all remaining entries. Add regression tests covering
rebinding/setup failure and independent cleanup failures.

In `@plugins/nemo-agents/src/nemo_agents_plugin/utils.py`:
- Around line 433-435: Update the OptimizeJob.run preflight call to pass
Path(spec.optimize_config) into preflight_validate_llm_models instead of the
loaded configuration dict, matching that function’s read_text-based interface
and allowing SDK optimization runs to reach dispatch.

In
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/artifacts.py`:
- Around line 62-64: Update the plotting data preparation around _trial_values
and pareto_indexes so both values and Pareto indices are built in one pass over
the same trials filtered to exactly n_metrics values. Preserve the existing
value normalization and conversion behavior, append each Pareto index using the
filtered values list position, and update the corresponding call sites such as
_plot_points usage so failed or pruned trials cannot shift highlighting.

In
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/fabric_trial.py`:
- Around line 66-85: Update the trial evaluation flow around evaluate and
apply_suggestions to convert logical suggestion names into path-keyed
suggestions via path_suggestions before applying them. Use the same
path_suggestions mapping when building optimized_config from best_trial.params
so both trial configs and the final optimized configuration update nested paths
such as models.default.temperature.

In
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/study_driver.py`:
- Around line 232-242: Update the study completion flow before selecting
best_trial or calling pick_trial to detect when no trials completed
successfully. Count failed trials, and raise StudyDriverError with that failure
count when the completed-trial set is empty; otherwise preserve the existing
single-objective study.best_trial and multi-objective pick_trial selection
paths.
- Around line 244-245: Update the optimized-config flow around apply_suggestions
and best_trial.params to translate logical parameter names through the same
suggestions_by_path mapping used when constructing trial configs, then apply the
resulting Fabric-path suggestions to base_config before write_optimized_config.
Preserve the existing optimized output behavior while ensuring entries such as
temperature update their configured model paths.

In `@plugins/nemo-optimization/src/nemo_optimization/fabric.py`:
- Around line 63-69: In the branch where agent_config is set, validate
optimize_config with looks_like_nat_config before copying the optimizer and eval
overlays, and reject it instead of silently discarding NAT-specific keys.
Preserve the existing require_fabric_agent_config handling and overlay behavior
for valid Fabric-shaped configurations, and add a test covering a valid Fabric
agent_config combined with a NAT-shaped optimize_config.

In `@plugins/nemo-optimization/src/nemo_optimization/jobs/optimize.py`:
- Around line 107-120: Update _expand_env and the artifact serialization flow so
environment-backed secret values are not written as expanded plaintext in either
trial or optimized configuration artifacts. Preserve ${ENV_VAR} references or
redact secret-bearing fields before yaml.safe_dump, while retaining expanded
values for runtime dispatch. Add sentinel-secret coverage for both artifact
types.

---

Minor comments:
In `@docs/agents/index.mdx`:
- Around line 57-63: Remove the Legacy NAT-only table row for the `nemo agents
optimize run` command in the documentation, leaving the `evaluate` row
unchanged; do not present NAT optimization as NAT-only, since optimization now
requires a Fabric-native package.

In `@packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_hook_loading.py`:
- Line 57: Remove the temporary __init__.py write call in
packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_hook_loading.py at
lines 57-57 and update the related import to use author_hooks.hook as an
implicit namespace package; likewise remove the write call in
packages/nemo_evaluator_sdk/tests/agent_eval/test_mcp_run_binding_hook.py at
lines 245-245 and import agent_pkg.audit as an implicit namespace package. Do
not add replacement __init__.py files.

In `@packages/nemo_evaluator_sdk/tests/metrics/test_tunable_rag_evaluator.py`:
- Around line 26-29: Update the _judge_response parameter annotation to accept
either dict[str, Any] or str, while preserving its existing JSON serialization
and response structure.

In `@plugins/nemo-agents/tests/unit/usage/test_usage_cli.py`:
- Around line 204-220: Update
test_usage_show_unreadable_result_json_exits_cleanly to avoid relying on
chmod-based unreadability when running as root: skip the test when os.geteuid()
== 0, or patch the file-reading path to deterministically raise the expected
read error. Preserve the existing assertions for non-root execution.

In `@plugins/nemo-optimization/README.md`:
- Around line 16-19: Remove the nonexistent examples/hermes-optimize/hooks/
reference from the README, or replace it with a valid repository path that
documents the per-task Fabric lifecycle hooks. Keep the surrounding hook
configuration references and explanation intact.

In
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/config_overlay.py`:
- Around line 54-61: Update strip_optimizer_only_fields to use one consistent
optimizer-cleanup strategy: since _OPTIMIZER_ONLY_TOP_LEVEL_KEYS already removes
the top-level optimizer entry, remove the now-unreachable
config.get("optimizer") block and retain the existing full-removal behavior.

In
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/fabric_trial.py`:
- Line 63: Update the parallelism initialization in the trial setup to validate
that the value from self._eval_config.get("general") is a mapping before calling
.get("max_concurrency"). Match the isinstance-based guard used by
_load_dataset_rows, and fall back to default_parallelism when eval.general is
null or otherwise invalid.

In
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/search_space.py`:
- Around line 96-105: Validate that low and high in the search-space parsing
logic are numeric before evaluating low >= high, and raise SearchSpaceError for
non-numeric values. Preserve the existing requirement that both bounds are
present and ensure valid numeric bounds continue through the current range
validation.

In
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/selection.py`:
- Around line 28-52: Update the selection function around _SUPPORTED_MODES to
validate mode.lower() before computing the Pareto matrix or normalization, then
reject or warn when non-uniform weights are supplied to harmonic or chebyshev;
ensure configured weights are not silently ignored while preserving weighted
behavior for sum.

In `@plugins/nemo-optimization/src/nemo_optimization/preflight.py`:
- Around line 31-50: The LLM collection in the preflight flow must deep-merge
agent and optimize configurations before validation, rather than replacing
entries by key. Reuse the existing merge behavior or helper used by
build_optimize_payload() when combining llms, then validate the merged _type and
model_name in the existing loop. Add coverage for a partial override such as
llms.default.model_name that preserves the base _type and triggers validation.

In `@plugins/nemo-optimization/src/nemo_optimization/router.py`:
- Around line 65-68: Update dispatch_payload() to retrieve the selected backend
with the same guarded lookup used by dispatch(), and return OptimizeRouterError
when discovery does not contain the backend instead of allowing KeyError. Add a
test covering a missing optuna or ga registration and verify the expected error
response.

In `@plugins/nemo-optimization/tests/smoke_fabric_optimize_atif.py`:
- Around line 130-131: Update the assertion message in the trace-file validation
near atif_path to reference the same trace_map[0] entry used to construct
atif_path, rather than the stale loop variable entry, so failures identify the
correct trace.
- Line 86: Add pytest-timeout to the plugin's dev dependency group so the
`@pytest.mark.timeout` marker in smoke_fabric_optimize_atif.py is available in the
package-specific environment under the root strict-marker configuration.

In `@plugins/nemo-optimization/tests/test_selection.py`:
- Around line 28-31: Update test_pick_trial_harmonic_returns_pareto_member to
assert the exact values of the trial selected by harmonic scoring, rather than
accepting every input trial. Determine the expected harmonic winner from the
provided study data and assert that specific result.

---

Nitpick comments:
In `@plugins/nemo-agents/tests/unit/test_optimize_skills_analyze_only.py`:
- Around line 254-287: Strengthen
test_cli_analyze_only_requires_initial_batch_flag and
test_cli_analyze_only_from_config_file_requires_initial_batch by asserting the
exact nonzero exit code produced by the validation guard and matching the
complete expected error text, rather than accepting any nonzero result or a
partial initial-batch substring. Keep the tests focused on confirming the
analyze-only initial-batch guard is reached.

In `@plugins/nemo-agents/tests/unit/usage/test_usage_cli.py`:
- Around line 105-111: Update test_usage_with_no_args_prints_help to assert the
specific current exit code produced by runner.invoke(app, ["usage"]) instead of
accepting both 0 and 2; keep the help-output assertion unchanged.

In `@plugins/nemo-optimization/examples/hermes-optimize/README.md`:
- Around line 22-30: Update the “hermes-agent” harness setup section in the
README to explicitly warn that installing with --no-deps may leave runtime
requirements unresolved, and add a concise troubleshooting note beside the
verification step instructing users to install the missing dependencies if
imports fail.

In `@plugins/nemo-optimization/README.md`:
- Line 6: Remove the internal “(Alt 5)” label from the “Primary user surface”
heading in the README, leaving the user-facing heading text unchanged.

In
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/artifacts.py`:
- Around line 169-176: Remove the unreachable single-metric handling from
_plot_pairwise: delete the n_metrics == 1 axes reassignment and use direct
axes[row_index][col_index] access in the plotting loop. Preserve the existing
caller guard in maybe_write_pareto_plots.

In `@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/backend.py`:
- Around line 44-58: Update run_study and run_numeric_study so the optimizer
configuration is parsed only once: pass the already parsed config from run_study
into run_numeric_study and reuse it there, including for metric handling. Remove
the second parse in run_numeric_study while preserving existing validation and
study execution behavior.
- Around line 82-88: Annotate _build_trial_evaluator in
plugins/nemo-optimization/src/nemo_optimization/backends/optuna/backend.py:82-88
with output_dir: Path and return type TrialEvaluator. Annotate generate_id in
plugins/nemo-optimization/src/nemo_optimization/backends/optuna/atif_metadata.py:18-18
as Callable[[], str], adding or reusing the necessary imports.

In
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/config_overlay.py`:
- Around line 36-51: Update nest_dotted_paths to detect collisions in both
insertion orders: when assigning a leaf value, reject replacing an existing
mapping, while preserving the current error for traversing through a scalar.
Ensure inputs such as {"a": 2, "a.b": 1} and the reverse order consistently
raise KeyError instead of overwriting data.

In
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/fabric_trial.py`:
- Around line 48-60: Remove the redundant isinstance(fabric_eval, Mapping)
guards from the _fabric_base_dir, _timeout_s, and _capture_trajectory
assignments in the surrounding initialization flow. Since fabric_eval is already
normalized to a Mapping or empty dictionary, access its values directly while
preserving the existing defaults.

In
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/study_driver.py`:
- Around line 86-126: Update parse_numeric_study_config so each resolved
MetricSpec.name, including evaluator_name fallbacks, is unique before appending
it to metrics. Track previously resolved names and raise StudyDriverError when a
duplicate occurs, preventing duplicate entries from reaching the study
configuration.

In `@plugins/nemo-optimization/src/nemo_optimization/registry.py`:
- Around line 10-13: Update registry.py to remove the TYPE_CHECKING-only import
block and import OptimizationBackend regularly from
nemo_optimization.backends.protocol at module scope, including the other
referenced occurrence.

In `@plugins/nemo-optimization/tests/test_atif_metadata.py`:
- Around line 30-37: Extend test_build_atif_trial_tags with a case where row_id
is omitted or falsy, asserting ATIF_ROW_ID is absent from the returned tags. Add
a separate test for resolve_experiment_id using whitespace-padded input and
assert the experiment ID is stripped as expected.

In `@plugins/nemo-optimization/tests/test_fabric.py`:
- Around line 37-39: Add a test alongside test_require_fabric_agent_rejects_nat
that passes a schema-less, non-Fabric/non-NAT configuration to
require_fabric_agent_config and asserts FabricOptimizeError with a match for
“must declare schema_version”.

In `@plugins/nemo-optimization/tests/test_search_space.py`:
- Around line 115-127: Add tests in test_suggestions_by_path_maps_logical_names
covering two logical names mapped to the same path and asserting
suggestions_by_path raises the expected exception, plus a search-space case with
low >= high asserting the parser rejects it. Reuse the existing
parse_search_space and suggestions_by_path setup and preserve the current valid
mapping assertion.
🪄 Autofix

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: CHILL

Plan: Enterprise

Run ID: 0ba54a52-d6d6-4dc2-9eae-26c83c0522f3

📥 Commits

Reviewing files that changed from the base of the PR and between 9ca0b38 and 801a093.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (84)
  • docs/agents/index.mdx
  • docs/agents/optimization.mdx
  • packages/nemo_evaluator_sdk/pyproject.toml
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/__init__.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hook_loading.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hooks.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hooks_mcp_binding.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/runtime.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/enums.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/tunable_rag_defaults.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/tunable_rag_evaluator.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/types.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/__init__.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/metrics.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_hook_loading.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_runtime.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_mcp_run_binding_hook.py
  • packages/nemo_evaluator_sdk/tests/metrics/test_tunable_rag_evaluator.py
  • packages/nemo_platform/pyproject.toml
  • packages/nemo_platform_plugin/tests/test_dispatcher.py
  • plugins/nemo-agents/pyproject.toml
  • plugins/nemo-agents/src/nemo_agents_plugin/cli.py
  • plugins/nemo-agents/src/nemo_agents_plugin/jobs/optimize_agent.py
  • plugins/nemo-agents/src/nemo_agents_plugin/leaderboard/render.py
  • plugins/nemo-agents/src/nemo_agents_plugin/service.py
  • plugins/nemo-agents/src/nemo_agents_plugin/utils.py
  • plugins/nemo-agents/tests/unit/test_cli.py
  • plugins/nemo-agents/tests/unit/test_improvement_jobs.py
  • plugins/nemo-agents/tests/unit/test_optimize_agent_job.py
  • plugins/nemo-agents/tests/unit/test_optimize_skills_analyze_only.py
  • plugins/nemo-agents/tests/unit/test_service.py
  • plugins/nemo-agents/tests/unit/test_utils.py
  • plugins/nemo-agents/tests/unit/usage/test_usage_cli.py
  • plugins/nemo-optimization/README.md
  • plugins/nemo-optimization/examples/hermes-optimize/.gitignore
  • plugins/nemo-optimization/examples/hermes-optimize/README.md
  • plugins/nemo-optimization/examples/hermes-optimize/agent.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/analyzer.inference-api.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/dataset-phishing.json
  • plugins/nemo-optimization/examples/hermes-optimize/dataset.json
  • plugins/nemo-optimization/examples/hermes-optimize/optimize.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/package.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/phishing.optimize.fabric-chatonly.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/phishing.optimize.fabric-mcp.e2e.yaml
  • plugins/nemo-optimization/pyproject.toml
  • plugins/nemo-optimization/src/nemo_optimization/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/agents.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/ga/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/ga/backend.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/artifacts.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/atif_metadata.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/backend.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/config_overlay.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/early_stop.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/fabric_trial.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/search_space.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/selection.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/study_driver.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/protocol.py
  • plugins/nemo-optimization/src/nemo_optimization/config.py
  • plugins/nemo-optimization/src/nemo_optimization/fabric.py
  • plugins/nemo-optimization/src/nemo_optimization/jobs/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/jobs/optimize.py
  • plugins/nemo-optimization/src/nemo_optimization/preflight.py
  • plugins/nemo-optimization/src/nemo_optimization/registry.py
  • plugins/nemo-optimization/src/nemo_optimization/router.py
  • plugins/nemo-optimization/src/nemo_optimization/schemas/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/schemas/optimize.py
  • plugins/nemo-optimization/src/nemo_optimization/tasks/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/tasks/optimize.py
  • plugins/nemo-optimization/tests/conftest.py
  • plugins/nemo-optimization/tests/smoke_fabric_optimize_atif.py
  • plugins/nemo-optimization/tests/test_atif_metadata.py
  • plugins/nemo-optimization/tests/test_config_overlay.py
  • plugins/nemo-optimization/tests/test_fabric.py
  • plugins/nemo-optimization/tests/test_fabric_trial.py
  • plugins/nemo-optimization/tests/test_optimize_job.py
  • plugins/nemo-optimization/tests/test_router.py
  • plugins/nemo-optimization/tests/test_search_space.py
  • plugins/nemo-optimization/tests/test_selection.py
  • plugins/nemo-optimization/tests/test_study_driver.py
  • pyproject.toml
💤 Files with no reviewable changes (3)
  • plugins/nemo-agents/tests/unit/test_optimize_agent_job.py
  • plugins/nemo-agents/src/nemo_agents_plugin/jobs/optimize_agent.py
  • plugins/nemo-agents/tests/unit/test_utils.py

Comment thread plugins/nemo-agents/src/nemo_agents_plugin/utils.py
Comment thread plugins/nemo-optimization/src/nemo_optimization/backends/optuna/study_driver.py Outdated
Comment thread plugins/nemo-optimization/src/nemo_optimization/fabric.py
Comment thread plugins/nemo-optimization/src/nemo_optimization/jobs/optimize.py
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 9

🧹 Nitpick comments (4)
plugins/nemo-optimization/src/nemo_optimization/backends/optuna/backend.py (1)

82-88: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Annotate output_dir and the return type.

output_dir has no annotation, and _build_trial_evaluator has no return type. The guidelines require concrete type hints.

♻️ Proposed refactor
+from pathlib import Path
+
+from nemo_optimization.backends.optuna.study_driver import TrialEvaluator
+
 def _build_trial_evaluator(
     payload: dict[str, Any],
     *,
     metric_names: tuple[str, ...],
-    output_dir,
+    output_dir: Path,
     experiment_id: str,
-):
+) -> TrialEvaluator:

As per coding guidelines: "Prefer concrete type hints over string-based type hints".

🤖 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 `@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/backend.py`
around lines 82 - 88, Update _build_trial_evaluator by adding a concrete type
annotation for output_dir and an explicit concrete return-type annotation.
Follow the existing project typing conventions and avoid string-based forward
references.

Source: Coding guidelines

plugins/nemo-optimization/src/nemo_optimization/backends/optuna/config_overlay.py (1)

54-61: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Lines 58-61 are dead code.

_OPTIMIZER_ONLY_TOP_LEVEL_KEYS contains "optimizer", so the loop at Line 56 already removes it. config.get("optimizer") is always None at Line 58. If you intended to keep the optimizer block and strip only its search fields, remove "optimizer" from the top-level key set instead.

♻️ Proposed cleanup (keeps current behavior)
 def strip_optimizer_only_fields(config: dict[str, Any]) -> None:
     """Remove optimizer metadata from a trial config artifact (in-place)."""
     for key in _OPTIMIZER_ONLY_TOP_LEVEL_KEYS:
         config.pop(key, None)
-    optimizer = config.get("optimizer")
-    if isinstance(optimizer, dict):
-        optimizer.pop("search_space", None)
-        optimizer.pop("optimizable_params", None)
🤖 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
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/config_overlay.py`
around lines 54 - 61, Remove the unreachable optimizer cleanup block from
strip_optimizer_only_fields, since _OPTIMIZER_ONLY_TOP_LEVEL_KEYS already
removes the optimizer entry before it is accessed. Preserve the current behavior
of removing the entire optimizer block.
plugins/nemo-agents/tests/unit/usage/test_usage_cli.py (1)

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

Remove postponed annotations from both test modules.

The direct imports already provide concrete types. Remove from __future__ import annotations after confirming the declared Python target.

  • plugins/nemo-agents/tests/unit/usage/test_usage_cli.py#L6-L6: remove the postponed-annotations import.
  • plugins/nemo-optimization/tests/test_optimize_job.py#L4-L4: remove the postponed-annotations import.

As per coding guidelines, “Prefer concrete type hints over string-based type hints.”

🤖 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 `@plugins/nemo-agents/tests/unit/usage/test_usage_cli.py` at line 6, Remove the
from __future__ import annotations statement from both test modules:
plugins/nemo-agents/tests/unit/usage/test_usage_cli.py at lines 6-6 and
plugins/nemo-optimization/tests/test_optimize_job.py at lines 4-4. Confirm the
declared Python target supports this removal and leave the existing concrete
type hints unchanged.

Source: Coding guidelines

plugins/nemo-optimization/tests/test_optimize_job.py (1)

35-37: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Run the task module through uv run.

Line 37 locks the platform task to python -m. Update OptimizeJob.compile and this assertion to invoke the module through uv run. Confirm that the task image includes uv.

As per coding guidelines, “Run Python scripts and tools through uv.”

🤖 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 `@plugins/nemo-optimization/tests/test_optimize_job.py` around lines 35 - 37,
Update OptimizeJob.compile to invoke the optimize task module through uv run
instead of python -m, and update the corresponding command assertion in
test_optimize_job.py to expect the new invocation. Verify the task image used by
OptimizeJob includes uv so the generated command is executable.

Source: Coding guidelines

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

Inline comments:
In `@packages/nemo_evaluator_sdk/tests/agent_eval/test_mcp_run_binding_hook.py`:
- Around line 242-246: Remove the `(pkg / "__init__.py").write_text(...)` setup
from `test_mcp_run_binding_path_based_ref`; the temporary `agent_pkg` directory
must rely on an implicit namespace package while leaving the rest of the test
fixture unchanged.

In `@plugins/nemo-agents/tests/unit/usage/test_usage_cli.py`:
- Around line 204-220: Update
test_usage_show_unreadable_result_json_exits_cleanly to mock the result-file
read operation so it raises PermissionError instead of relying on chmod(0o000).
Remove the permission-changing setup and cleanup, while preserving the
assertions for exit code 1, no traceback, and the “cannot read file” message.
- Around line 105-112: Update test_usage_with_no_args_prints_help to assert a
non-zero result.exit_code directly, replacing the current acceptance of both 0
and 2; keep the help-output assertion unchanged.

In
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/artifacts.py`:
- Around line 111-114: Handle studies with no completed trials consistently:
update _pareto_trial_numbers to return an empty set instead of accessing
best_trial or best_trials when no completed result exists, and update
run_numeric_study to avoid raising before artifact writers in the same state.
Preserve existing Pareto selection for studies with completed trials, and add a
regression test covering all trials failing or being pruned.

In `@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/backend.py`:
- Around line 44-47: Update the exception handling around payload access in the
optimizer configuration flow to handle a missing payload["optimizer"] key
explicitly, raising StudyDriverError with contextual information that identifies
the missing optimizer configuration instead of the bare quoted key. Preserve the
existing parse_numeric_study_config handling for StudyDriverError and other
parsing failures.

In
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/fabric_trial.py`:
- Line 47: Update the trial evaluation flow around build_agent_eval_tasks,
_tasks, and evaluate() so evaluator tasks are rebuilt from each trial’s
suggestion-resolved payload rather than the base payload. Pass those per-trial
tasks to run_sync, ensuring eval.evaluators search-space settings affect
scoring, and add a regression test covering an evaluator setting.
- Around line 219-229: Update the model URL validation in the surrounding
model-construction logic before new_inference_client creates AsyncOpenAI: reject
credentialed judge configurations using an HTTP URL, while permitting HTTPS URLs
and non-credentialed HTTP URLs as appropriate. Use the existing secret_ref and
parsed URL values, and raise StudyDriverError with the model name when the
invalid combination is detected.

In
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/search_space.py`:
- Around line 96-105: Update the range-bound validation in the search-space
parsing logic around low and high so both values are numeric before comparing
them or passing them to suggest_float. Raise SearchSpaceError for non-numeric
bounds, while preserving the existing requirement that both bounds are present
and low is less than high.

In `@plugins/nemo-optimization/tests/test_fabric_trial.py`:
- Around line 184-199: Update the test invocation in
FabricTrialEvaluator.evaluate to pass the logical suggestion name temperature
instead of the Fabric path models.default.temperature, and keep the expected
configuration assertion unchanged. In evaluate, resolve each logical suggestion
through suggestions_by_path before applying it so run_numeric_study inputs map
to the correct dotted configuration path.

---

Nitpick comments:
In `@plugins/nemo-agents/tests/unit/usage/test_usage_cli.py`:
- Line 6: Remove the from __future__ import annotations statement from both test
modules: plugins/nemo-agents/tests/unit/usage/test_usage_cli.py at lines 6-6 and
plugins/nemo-optimization/tests/test_optimize_job.py at lines 4-4. Confirm the
declared Python target supports this removal and leave the existing concrete
type hints unchanged.

In `@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/backend.py`:
- Around line 82-88: Update _build_trial_evaluator by adding a concrete type
annotation for output_dir and an explicit concrete return-type annotation.
Follow the existing project typing conventions and avoid string-based forward
references.

In
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/config_overlay.py`:
- Around line 54-61: Remove the unreachable optimizer cleanup block from
strip_optimizer_only_fields, since _OPTIMIZER_ONLY_TOP_LEVEL_KEYS already
removes the optimizer entry before it is accessed. Preserve the current behavior
of removing the entire optimizer block.

In `@plugins/nemo-optimization/tests/test_optimize_job.py`:
- Around line 35-37: Update OptimizeJob.compile to invoke the optimize task
module through uv run instead of python -m, and update the corresponding command
assertion in test_optimize_job.py to expect the new invocation. Verify the task
image used by OptimizeJob includes uv so the generated command is executable.
🪄 Autofix

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: CHILL

Plan: Enterprise

Run ID: f6064e55-1f90-446f-a738-ac0abcbb398f

📥 Commits

Reviewing files that changed from the base of the PR and between bb7357c and f8a7aa6.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (84)
  • docs/agents/index.mdx
  • docs/agents/optimization.mdx
  • packages/nemo_evaluator_sdk/pyproject.toml
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/__init__.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hook_loading.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hooks.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hooks_mcp_binding.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/runtime.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/enums.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/tunable_rag_defaults.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/tunable_rag_evaluator.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/types.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/__init__.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/metrics.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_hook_loading.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_runtime.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_mcp_run_binding_hook.py
  • packages/nemo_evaluator_sdk/tests/metrics/test_tunable_rag_evaluator.py
  • packages/nemo_platform/pyproject.toml
  • packages/nemo_platform_plugin/tests/test_dispatcher.py
  • plugins/nemo-agents/pyproject.toml
  • plugins/nemo-agents/src/nemo_agents_plugin/cli.py
  • plugins/nemo-agents/src/nemo_agents_plugin/jobs/optimize_agent.py
  • plugins/nemo-agents/src/nemo_agents_plugin/leaderboard/render.py
  • plugins/nemo-agents/src/nemo_agents_plugin/service.py
  • plugins/nemo-agents/src/nemo_agents_plugin/utils.py
  • plugins/nemo-agents/tests/unit/test_cli.py
  • plugins/nemo-agents/tests/unit/test_improvement_jobs.py
  • plugins/nemo-agents/tests/unit/test_optimize_agent_job.py
  • plugins/nemo-agents/tests/unit/test_optimize_skills_analyze_only.py
  • plugins/nemo-agents/tests/unit/test_service.py
  • plugins/nemo-agents/tests/unit/test_utils.py
  • plugins/nemo-agents/tests/unit/usage/test_usage_cli.py
  • plugins/nemo-optimization/README.md
  • plugins/nemo-optimization/examples/hermes-optimize/.gitignore
  • plugins/nemo-optimization/examples/hermes-optimize/README.md
  • plugins/nemo-optimization/examples/hermes-optimize/agent.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/analyzer.inference-api.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/dataset-phishing.json
  • plugins/nemo-optimization/examples/hermes-optimize/dataset.json
  • plugins/nemo-optimization/examples/hermes-optimize/optimize.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/package.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/phishing.optimize.fabric-chatonly.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/phishing.optimize.fabric-mcp.e2e.yaml
  • plugins/nemo-optimization/pyproject.toml
  • plugins/nemo-optimization/src/nemo_optimization/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/agents.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/ga/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/ga/backend.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/artifacts.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/atif_metadata.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/backend.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/config_overlay.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/early_stop.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/fabric_trial.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/search_space.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/selection.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/study_driver.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/protocol.py
  • plugins/nemo-optimization/src/nemo_optimization/config.py
  • plugins/nemo-optimization/src/nemo_optimization/fabric.py
  • plugins/nemo-optimization/src/nemo_optimization/jobs/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/jobs/optimize.py
  • plugins/nemo-optimization/src/nemo_optimization/preflight.py
  • plugins/nemo-optimization/src/nemo_optimization/registry.py
  • plugins/nemo-optimization/src/nemo_optimization/router.py
  • plugins/nemo-optimization/src/nemo_optimization/schemas/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/schemas/optimize.py
  • plugins/nemo-optimization/src/nemo_optimization/tasks/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/tasks/optimize.py
  • plugins/nemo-optimization/tests/conftest.py
  • plugins/nemo-optimization/tests/smoke_fabric_optimize_atif.py
  • plugins/nemo-optimization/tests/test_atif_metadata.py
  • plugins/nemo-optimization/tests/test_config_overlay.py
  • plugins/nemo-optimization/tests/test_fabric.py
  • plugins/nemo-optimization/tests/test_fabric_trial.py
  • plugins/nemo-optimization/tests/test_optimize_job.py
  • plugins/nemo-optimization/tests/test_router.py
  • plugins/nemo-optimization/tests/test_search_space.py
  • plugins/nemo-optimization/tests/test_selection.py
  • plugins/nemo-optimization/tests/test_study_driver.py
  • pyproject.toml
💤 Files with no reviewable changes (3)
  • plugins/nemo-agents/tests/unit/test_optimize_agent_job.py
  • plugins/nemo-agents/src/nemo_agents_plugin/jobs/optimize_agent.py
  • plugins/nemo-agents/tests/unit/test_utils.py
🚧 Files skipped from review as they are similar to previous changes (63)
  • pyproject.toml
  • plugins/nemo-optimization/examples/hermes-optimize/analyzer.inference-api.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/dataset.json
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/init.py
  • plugins/nemo-optimization/src/nemo_optimization/tasks/init.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/init.py
  • plugins/nemo-agents/tests/unit/test_service.py
  • packages/nemo_platform/pyproject.toml
  • plugins/nemo-optimization/src/nemo_optimization/init.py
  • plugins/nemo-agents/src/nemo_agents_plugin/service.py
  • packages/nemo_evaluator_sdk/pyproject.toml
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/init.py
  • plugins/nemo-optimization/src/nemo_optimization/jobs/init.py
  • plugins/nemo-optimization/tests/test_search_space.py
  • plugins/nemo-optimization/examples/hermes-optimize/dataset-phishing.json
  • plugins/nemo-optimization/tests/test_config_overlay.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/protocol.py
  • plugins/nemo-optimization/examples/hermes-optimize/agent.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/.gitignore
  • plugins/nemo-optimization/src/nemo_optimization/schemas/optimize.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/enums.py
  • plugins/nemo-agents/tests/unit/test_improvement_jobs.py
  • plugins/nemo-optimization/src/nemo_optimization/registry.py
  • plugins/nemo-optimization/tests/conftest.py
  • plugins/nemo-optimization/examples/hermes-optimize/package.yaml
  • plugins/nemo-optimization/tests/test_selection.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/types.py
  • plugins/nemo-optimization/src/nemo_optimization/tasks/optimize.py
  • plugins/nemo-optimization/src/nemo_optimization/schemas/init.py
  • plugins/nemo-agents/src/nemo_agents_plugin/utils.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_runtime.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/ga/init.py
  • packages/nemo_platform_plugin/tests/test_dispatcher.py
  • plugins/nemo-agents/pyproject.toml
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/atif_metadata.py
  • plugins/nemo-optimization/examples/hermes-optimize/phishing.optimize.fabric-mcp.e2e.yaml
  • plugins/nemo-optimization/src/nemo_optimization/jobs/optimize.py
  • plugins/nemo-optimization/README.md
  • plugins/nemo-optimization/tests/test_atif_metadata.py
  • docs/agents/optimization.mdx
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hook_loading.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/early_stop.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/selection.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/ga/backend.py
  • plugins/nemo-optimization/tests/test_router.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hooks.py
  • plugins/nemo-agents/src/nemo_agents_plugin/leaderboard/render.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/tunable_rag_defaults.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/metrics.py
  • plugins/nemo-optimization/src/nemo_optimization/preflight.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/init.py
  • plugins/nemo-optimization/src/nemo_optimization/router.py
  • plugins/nemo-agents/src/nemo_agents_plugin/cli.py
  • plugins/nemo-optimization/examples/hermes-optimize/README.md
  • plugins/nemo-optimization/tests/test_study_driver.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_hook_loading.py
  • plugins/nemo-optimization/src/nemo_optimization/agents.py
  • plugins/nemo-optimization/examples/hermes-optimize/phishing.optimize.fabric-chatonly.yaml
  • plugins/nemo-optimization/tests/test_fabric.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hooks_mcp_binding.py
  • plugins/nemo-optimization/pyproject.toml
  • plugins/nemo-optimization/src/nemo_optimization/fabric.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/tunable_rag_evaluator.py

Comment thread plugins/nemo-optimization/src/nemo_optimization/backends/optuna/backend.py Outdated
Comment thread plugins/nemo-optimization/src/nemo_optimization/backends/optuna/fabric_trial.py Outdated
Comment thread plugins/nemo-optimization/tests/test_fabric_trial.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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: 9

🧹 Nitpick comments (4)
plugins/nemo-optimization/src/nemo_optimization/backends/optuna/backend.py (1)

82-88: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Annotate output_dir and the return type.

output_dir has no annotation, and _build_trial_evaluator has no return type. The guidelines require concrete type hints.

♻️ Proposed refactor
+from pathlib import Path
+
+from nemo_optimization.backends.optuna.study_driver import TrialEvaluator
+
 def _build_trial_evaluator(
     payload: dict[str, Any],
     *,
     metric_names: tuple[str, ...],
-    output_dir,
+    output_dir: Path,
     experiment_id: str,
-):
+) -> TrialEvaluator:

As per coding guidelines: "Prefer concrete type hints over string-based type hints".

🤖 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 `@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/backend.py`
around lines 82 - 88, Update _build_trial_evaluator by adding a concrete type
annotation for output_dir and an explicit concrete return-type annotation.
Follow the existing project typing conventions and avoid string-based forward
references.

Source: Coding guidelines

plugins/nemo-optimization/src/nemo_optimization/backends/optuna/config_overlay.py (1)

54-61: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Lines 58-61 are dead code.

_OPTIMIZER_ONLY_TOP_LEVEL_KEYS contains "optimizer", so the loop at Line 56 already removes it. config.get("optimizer") is always None at Line 58. If you intended to keep the optimizer block and strip only its search fields, remove "optimizer" from the top-level key set instead.

♻️ Proposed cleanup (keeps current behavior)
 def strip_optimizer_only_fields(config: dict[str, Any]) -> None:
     """Remove optimizer metadata from a trial config artifact (in-place)."""
     for key in _OPTIMIZER_ONLY_TOP_LEVEL_KEYS:
         config.pop(key, None)
-    optimizer = config.get("optimizer")
-    if isinstance(optimizer, dict):
-        optimizer.pop("search_space", None)
-        optimizer.pop("optimizable_params", None)
🤖 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
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/config_overlay.py`
around lines 54 - 61, Remove the unreachable optimizer cleanup block from
strip_optimizer_only_fields, since _OPTIMIZER_ONLY_TOP_LEVEL_KEYS already
removes the optimizer entry before it is accessed. Preserve the current behavior
of removing the entire optimizer block.
plugins/nemo-agents/tests/unit/usage/test_usage_cli.py (1)

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

Remove postponed annotations from both test modules.

The direct imports already provide concrete types. Remove from __future__ import annotations after confirming the declared Python target.

  • plugins/nemo-agents/tests/unit/usage/test_usage_cli.py#L6-L6: remove the postponed-annotations import.
  • plugins/nemo-optimization/tests/test_optimize_job.py#L4-L4: remove the postponed-annotations import.

As per coding guidelines, “Prefer concrete type hints over string-based type hints.”

🤖 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 `@plugins/nemo-agents/tests/unit/usage/test_usage_cli.py` at line 6, Remove the
from __future__ import annotations statement from both test modules:
plugins/nemo-agents/tests/unit/usage/test_usage_cli.py at lines 6-6 and
plugins/nemo-optimization/tests/test_optimize_job.py at lines 4-4. Confirm the
declared Python target supports this removal and leave the existing concrete
type hints unchanged.

Source: Coding guidelines

plugins/nemo-optimization/tests/test_optimize_job.py (1)

35-37: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Run the task module through uv run.

Line 37 locks the platform task to python -m. Update OptimizeJob.compile and this assertion to invoke the module through uv run. Confirm that the task image includes uv.

As per coding guidelines, “Run Python scripts and tools through uv.”

🤖 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 `@plugins/nemo-optimization/tests/test_optimize_job.py` around lines 35 - 37,
Update OptimizeJob.compile to invoke the optimize task module through uv run
instead of python -m, and update the corresponding command assertion in
test_optimize_job.py to expect the new invocation. Verify the task image used by
OptimizeJob includes uv so the generated command is executable.

Source: Coding guidelines

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

Inline comments:
In `@packages/nemo_evaluator_sdk/tests/agent_eval/test_mcp_run_binding_hook.py`:
- Around line 242-246: Remove the `(pkg / "__init__.py").write_text(...)` setup
from `test_mcp_run_binding_path_based_ref`; the temporary `agent_pkg` directory
must rely on an implicit namespace package while leaving the rest of the test
fixture unchanged.

In `@plugins/nemo-agents/tests/unit/usage/test_usage_cli.py`:
- Around line 204-220: Update
test_usage_show_unreadable_result_json_exits_cleanly to mock the result-file
read operation so it raises PermissionError instead of relying on chmod(0o000).
Remove the permission-changing setup and cleanup, while preserving the
assertions for exit code 1, no traceback, and the “cannot read file” message.
- Around line 105-112: Update test_usage_with_no_args_prints_help to assert a
non-zero result.exit_code directly, replacing the current acceptance of both 0
and 2; keep the help-output assertion unchanged.

In
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/artifacts.py`:
- Around line 111-114: Handle studies with no completed trials consistently:
update _pareto_trial_numbers to return an empty set instead of accessing
best_trial or best_trials when no completed result exists, and update
run_numeric_study to avoid raising before artifact writers in the same state.
Preserve existing Pareto selection for studies with completed trials, and add a
regression test covering all trials failing or being pruned.

In `@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/backend.py`:
- Around line 44-47: Update the exception handling around payload access in the
optimizer configuration flow to handle a missing payload["optimizer"] key
explicitly, raising StudyDriverError with contextual information that identifies
the missing optimizer configuration instead of the bare quoted key. Preserve the
existing parse_numeric_study_config handling for StudyDriverError and other
parsing failures.

In
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/fabric_trial.py`:
- Line 47: Update the trial evaluation flow around build_agent_eval_tasks,
_tasks, and evaluate() so evaluator tasks are rebuilt from each trial’s
suggestion-resolved payload rather than the base payload. Pass those per-trial
tasks to run_sync, ensuring eval.evaluators search-space settings affect
scoring, and add a regression test covering an evaluator setting.
- Around line 219-229: Update the model URL validation in the surrounding
model-construction logic before new_inference_client creates AsyncOpenAI: reject
credentialed judge configurations using an HTTP URL, while permitting HTTPS URLs
and non-credentialed HTTP URLs as appropriate. Use the existing secret_ref and
parsed URL values, and raise StudyDriverError with the model name when the
invalid combination is detected.

In
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/search_space.py`:
- Around line 96-105: Update the range-bound validation in the search-space
parsing logic around low and high so both values are numeric before comparing
them or passing them to suggest_float. Raise SearchSpaceError for non-numeric
bounds, while preserving the existing requirement that both bounds are present
and low is less than high.

In `@plugins/nemo-optimization/tests/test_fabric_trial.py`:
- Around line 184-199: Update the test invocation in
FabricTrialEvaluator.evaluate to pass the logical suggestion name temperature
instead of the Fabric path models.default.temperature, and keep the expected
configuration assertion unchanged. In evaluate, resolve each logical suggestion
through suggestions_by_path before applying it so run_numeric_study inputs map
to the correct dotted configuration path.

---

Nitpick comments:
In `@plugins/nemo-agents/tests/unit/usage/test_usage_cli.py`:
- Line 6: Remove the from __future__ import annotations statement from both test
modules: plugins/nemo-agents/tests/unit/usage/test_usage_cli.py at lines 6-6 and
plugins/nemo-optimization/tests/test_optimize_job.py at lines 4-4. Confirm the
declared Python target supports this removal and leave the existing concrete
type hints unchanged.

In `@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/backend.py`:
- Around line 82-88: Update _build_trial_evaluator by adding a concrete type
annotation for output_dir and an explicit concrete return-type annotation.
Follow the existing project typing conventions and avoid string-based forward
references.

In
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/config_overlay.py`:
- Around line 54-61: Remove the unreachable optimizer cleanup block from
strip_optimizer_only_fields, since _OPTIMIZER_ONLY_TOP_LEVEL_KEYS already
removes the optimizer entry before it is accessed. Preserve the current behavior
of removing the entire optimizer block.

In `@plugins/nemo-optimization/tests/test_optimize_job.py`:
- Around line 35-37: Update OptimizeJob.compile to invoke the optimize task
module through uv run instead of python -m, and update the corresponding command
assertion in test_optimize_job.py to expect the new invocation. Verify the task
image used by OptimizeJob includes uv so the generated command is executable.
🪄 Autofix

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: CHILL

Plan: Enterprise

Run ID: f6064e55-1f90-446f-a738-ac0abcbb398f

📥 Commits

Reviewing files that changed from the base of the PR and between bb7357c and f8a7aa6.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (84)
  • docs/agents/index.mdx
  • docs/agents/optimization.mdx
  • packages/nemo_evaluator_sdk/pyproject.toml
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/__init__.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hook_loading.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hooks.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hooks_mcp_binding.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/runtime.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/enums.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/tunable_rag_defaults.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/tunable_rag_evaluator.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/types.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/__init__.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/metrics.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_hook_loading.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_runtime.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_mcp_run_binding_hook.py
  • packages/nemo_evaluator_sdk/tests/metrics/test_tunable_rag_evaluator.py
  • packages/nemo_platform/pyproject.toml
  • packages/nemo_platform_plugin/tests/test_dispatcher.py
  • plugins/nemo-agents/pyproject.toml
  • plugins/nemo-agents/src/nemo_agents_plugin/cli.py
  • plugins/nemo-agents/src/nemo_agents_plugin/jobs/optimize_agent.py
  • plugins/nemo-agents/src/nemo_agents_plugin/leaderboard/render.py
  • plugins/nemo-agents/src/nemo_agents_plugin/service.py
  • plugins/nemo-agents/src/nemo_agents_plugin/utils.py
  • plugins/nemo-agents/tests/unit/test_cli.py
  • plugins/nemo-agents/tests/unit/test_improvement_jobs.py
  • plugins/nemo-agents/tests/unit/test_optimize_agent_job.py
  • plugins/nemo-agents/tests/unit/test_optimize_skills_analyze_only.py
  • plugins/nemo-agents/tests/unit/test_service.py
  • plugins/nemo-agents/tests/unit/test_utils.py
  • plugins/nemo-agents/tests/unit/usage/test_usage_cli.py
  • plugins/nemo-optimization/README.md
  • plugins/nemo-optimization/examples/hermes-optimize/.gitignore
  • plugins/nemo-optimization/examples/hermes-optimize/README.md
  • plugins/nemo-optimization/examples/hermes-optimize/agent.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/analyzer.inference-api.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/dataset-phishing.json
  • plugins/nemo-optimization/examples/hermes-optimize/dataset.json
  • plugins/nemo-optimization/examples/hermes-optimize/optimize.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/package.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/phishing.optimize.fabric-chatonly.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/phishing.optimize.fabric-mcp.e2e.yaml
  • plugins/nemo-optimization/pyproject.toml
  • plugins/nemo-optimization/src/nemo_optimization/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/agents.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/ga/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/ga/backend.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/artifacts.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/atif_metadata.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/backend.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/config_overlay.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/early_stop.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/fabric_trial.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/search_space.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/selection.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/study_driver.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/protocol.py
  • plugins/nemo-optimization/src/nemo_optimization/config.py
  • plugins/nemo-optimization/src/nemo_optimization/fabric.py
  • plugins/nemo-optimization/src/nemo_optimization/jobs/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/jobs/optimize.py
  • plugins/nemo-optimization/src/nemo_optimization/preflight.py
  • plugins/nemo-optimization/src/nemo_optimization/registry.py
  • plugins/nemo-optimization/src/nemo_optimization/router.py
  • plugins/nemo-optimization/src/nemo_optimization/schemas/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/schemas/optimize.py
  • plugins/nemo-optimization/src/nemo_optimization/tasks/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/tasks/optimize.py
  • plugins/nemo-optimization/tests/conftest.py
  • plugins/nemo-optimization/tests/smoke_fabric_optimize_atif.py
  • plugins/nemo-optimization/tests/test_atif_metadata.py
  • plugins/nemo-optimization/tests/test_config_overlay.py
  • plugins/nemo-optimization/tests/test_fabric.py
  • plugins/nemo-optimization/tests/test_fabric_trial.py
  • plugins/nemo-optimization/tests/test_optimize_job.py
  • plugins/nemo-optimization/tests/test_router.py
  • plugins/nemo-optimization/tests/test_search_space.py
  • plugins/nemo-optimization/tests/test_selection.py
  • plugins/nemo-optimization/tests/test_study_driver.py
  • pyproject.toml
💤 Files with no reviewable changes (3)
  • plugins/nemo-agents/tests/unit/test_optimize_agent_job.py
  • plugins/nemo-agents/src/nemo_agents_plugin/jobs/optimize_agent.py
  • plugins/nemo-agents/tests/unit/test_utils.py
🚧 Files skipped from review as they are similar to previous changes (63)
  • pyproject.toml
  • plugins/nemo-optimization/examples/hermes-optimize/analyzer.inference-api.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/dataset.json
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/init.py
  • plugins/nemo-optimization/src/nemo_optimization/tasks/init.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/init.py
  • plugins/nemo-agents/tests/unit/test_service.py
  • packages/nemo_platform/pyproject.toml
  • plugins/nemo-optimization/src/nemo_optimization/init.py
  • plugins/nemo-agents/src/nemo_agents_plugin/service.py
  • packages/nemo_evaluator_sdk/pyproject.toml
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/init.py
  • plugins/nemo-optimization/src/nemo_optimization/jobs/init.py
  • plugins/nemo-optimization/tests/test_search_space.py
  • plugins/nemo-optimization/examples/hermes-optimize/dataset-phishing.json
  • plugins/nemo-optimization/tests/test_config_overlay.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/protocol.py
  • plugins/nemo-optimization/examples/hermes-optimize/agent.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/.gitignore
  • plugins/nemo-optimization/src/nemo_optimization/schemas/optimize.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/enums.py
  • plugins/nemo-agents/tests/unit/test_improvement_jobs.py
  • plugins/nemo-optimization/src/nemo_optimization/registry.py
  • plugins/nemo-optimization/tests/conftest.py
  • plugins/nemo-optimization/examples/hermes-optimize/package.yaml
  • plugins/nemo-optimization/tests/test_selection.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/types.py
  • plugins/nemo-optimization/src/nemo_optimization/tasks/optimize.py
  • plugins/nemo-optimization/src/nemo_optimization/schemas/init.py
  • plugins/nemo-agents/src/nemo_agents_plugin/utils.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_runtime.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/ga/init.py
  • packages/nemo_platform_plugin/tests/test_dispatcher.py
  • plugins/nemo-agents/pyproject.toml
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/atif_metadata.py
  • plugins/nemo-optimization/examples/hermes-optimize/phishing.optimize.fabric-mcp.e2e.yaml
  • plugins/nemo-optimization/src/nemo_optimization/jobs/optimize.py
  • plugins/nemo-optimization/README.md
  • plugins/nemo-optimization/tests/test_atif_metadata.py
  • docs/agents/optimization.mdx
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hook_loading.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/early_stop.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/selection.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/ga/backend.py
  • plugins/nemo-optimization/tests/test_router.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hooks.py
  • plugins/nemo-agents/src/nemo_agents_plugin/leaderboard/render.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/tunable_rag_defaults.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/metrics.py
  • plugins/nemo-optimization/src/nemo_optimization/preflight.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/init.py
  • plugins/nemo-optimization/src/nemo_optimization/router.py
  • plugins/nemo-agents/src/nemo_agents_plugin/cli.py
  • plugins/nemo-optimization/examples/hermes-optimize/README.md
  • plugins/nemo-optimization/tests/test_study_driver.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_hook_loading.py
  • plugins/nemo-optimization/src/nemo_optimization/agents.py
  • plugins/nemo-optimization/examples/hermes-optimize/phishing.optimize.fabric-chatonly.yaml
  • plugins/nemo-optimization/tests/test_fabric.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hooks_mcp_binding.py
  • plugins/nemo-optimization/pyproject.toml
  • plugins/nemo-optimization/src/nemo_optimization/fabric.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/tunable_rag_evaluator.py
🛑 Comments failed to post (2)
plugins/nemo-agents/tests/unit/usage/test_usage_cli.py (2)

105-112: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Assert the documented exit behavior.

Line 106 says this command exits non-zero. Line 110 accepts zero. Assert a non-zero exit code so a success exit does not mask a CLI contract regression.

🤖 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 `@plugins/nemo-agents/tests/unit/usage/test_usage_cli.py` around lines 105 -
112, Update test_usage_with_no_args_prints_help to assert a non-zero
result.exit_code directly, replacing the current acceptance of both 0 and 2;
keep the help-output assertion unchanged.

204-220: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Make the read-error test deterministic.

chmod(0o000) does not deny reads to privileged processes and has platform-dependent behavior. Mock the result-file read path to raise PermissionError so this test always verifies the intended error handling.

🤖 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 `@plugins/nemo-agents/tests/unit/usage/test_usage_cli.py` around lines 204 -
220, Update test_usage_show_unreadable_result_json_exits_cleanly to mock the
result-file read operation so it raises PermissionError instead of relying on
chmod(0o000). Remove the permission-changing setup and cleanup, while preserving
the assertions for exit code 1, no traceback, and the “cannot read file”
message.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@plugins/nemo-deployments/src/nemo_deployments_plugin/backends/docker/gpu.py`:
- Around line 206-214: Update the reservation-loading logic around
Configuration.get_service_config and NemoPlatformConfig so optional import
failures are handled separately, while ValueError and other configuration errors
from get_reserved_gpu_ids() propagate after appropriate logging. Do not fall
back to detect_gpu_device_ids() when reservation configuration is invalid; only
use that fallback when the optional configuration module is unavailable or no
reservation is configured.
🪄 Autofix

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: CHILL

Plan: Enterprise

Run ID: b5d55fea-361e-4883-aa56-2356fd789f4a

📥 Commits

Reviewing files that changed from the base of the PR and between f8a7aa6 and 7be038b.

📒 Files selected for processing (1)
  • plugins/nemo-deployments/src/nemo_deployments_plugin/backends/docker/gpu.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 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
`@plugins/nemo-deployments/src/nemo_deployments_plugin/backends/docker/backend.py`:
- Around line 482-488: The Docker run configuration around the network and
extra_hosts setup must make host.docker.internal reachable from netns sidecars,
since Docker rejects extra_hosts with network="container:<primary>". Update the
sidecar/primary networking design to provide a shared reachable platform-host
address while preserving the existing healthcheck behavior, and add a Linux
Docker Engine integration test covering the auth-proxy sidecar request path.

In `@plugins/nemo-optimization/examples/hermes-optimize/README.md`:
- Around line 59-62: Add Python SDK counterparts in the README for both the
chat-only and bound-MCP optimization workflows alongside their existing CLI
commands, organizing each pair in the repository’s supported tab-set format.
Ensure the SDK examples are tested and remain functionally equivalent to the
corresponding CLI examples; alternatively, move the paired examples to a
documentation page that supports tab sets.
- Around line 40-43: Update the setup instructions in the Hermes optimization
README to sync/install nemo-agents-plugin, then install the matching Fabric
wheel into .venv using an explicit wheel path instead of the placeholder
command. Retain the uv run --no-sync usage for subsequent commands so the
installed Fabric version is preserved.
🪄 Autofix

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: CHILL

Plan: Enterprise

Run ID: b3a207d3-d712-4145-b524-861da88cb883

📥 Commits

Reviewing files that changed from the base of the PR and between 7be038b and 07329cc.

📒 Files selected for processing (4)
  • plugins/nemo-deployments/src/nemo_deployments_plugin/backends/docker/backend.py
  • plugins/nemo-optimization/examples/hermes-optimize/README.md
  • services/core/models/src/nmp/core/models/controllers/backends/deployments_plugin/compiler.py
  • services/core/models/tests/unit/controllers/backends/deployments_plugin/test_compiler.py

Comment thread plugins/nemo-optimization/examples/hermes-optimize/README.md Outdated
Comment thread plugins/nemo-optimization/examples/hermes-optimize/README.md Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
plugins/nemo-optimization/tests/test_study_driver.py (1)

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

Use concrete mapping type hints.

Replace bare dict annotations with parameterized mapping types that match TrialEvaluator. Verify with uv run --frozen ty check plugins/nemo-optimization/tests/test_study_driver.py.

As per coding guidelines, use concrete type hints and uv run --frozen ty check for Python type checking.

🤖 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 `@plugins/nemo-optimization/tests/test_study_driver.py` at line 175, Update the
evaluate method signature in the TrialEvaluator implementation to replace bare
dict annotations for suggestions and trial_overlay with concrete parameterized
mapping types matching TrialEvaluator. Preserve the existing return annotation,
then verify the file with uv run --frozen ty check
plugins/nemo-optimization/tests/test_study_driver.py.

Source: Coding guidelines

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

Nitpick comments:
In `@plugins/nemo-optimization/tests/test_study_driver.py`:
- Line 175: Update the evaluate method signature in the TrialEvaluator
implementation to replace bare dict annotations for suggestions and
trial_overlay with concrete parameterized mapping types matching TrialEvaluator.
Preserve the existing return annotation, then verify the file with uv run
--frozen ty check plugins/nemo-optimization/tests/test_study_driver.py.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: c0113f00-7977-4f24-be9b-92044eb05f02

📥 Commits

Reviewing files that changed from the base of the PR and between 07329cc and 1f436eb.

📒 Files selected for processing (11)
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hooks_mcp_binding.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_mcp_run_binding_hook.py
  • plugins/nemo-deployments/src/nemo_deployments_plugin/backends/docker/gpu.py
  • plugins/nemo-deployments/tests/unit/backends/docker/test_gpu.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/artifacts.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/fabric_trial.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/study_driver.py
  • plugins/nemo-optimization/src/nemo_optimization/fabric.py
  • plugins/nemo-optimization/tests/test_fabric.py
  • plugins/nemo-optimization/tests/test_fabric_trial.py
  • plugins/nemo-optimization/tests/test_study_driver.py
🚧 Files skipped from review as they are similar to previous changes (6)
  • plugins/nemo-optimization/tests/test_fabric.py
  • plugins/nemo-deployments/src/nemo_deployments_plugin/backends/docker/gpu.py
  • plugins/nemo-optimization/src/nemo_optimization/fabric.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/artifacts.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/fabric_trial.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hooks_mcp_binding.py

Comment thread plugins/nemo-optimization/src/nemo_optimization/jobs/optimize.py
Comment thread plugins/nemo-optimization/src/nemo_optimization/agents.py
Comment thread plugins/nemo-optimization/src/nemo_optimization/fabric.py
Comment thread plugins/nemo-optimization/src/nemo_optimization/router.py Outdated
Comment thread plugins/nemo-optimization/src/nemo_optimization/backends/optuna/study_driver.py Outdated
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (1)
plugins/nemo-optimization/src/nemo_optimization/backends/optuna/artifacts.py (1)

62-64: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Build Pareto indexes in the filtered value index space.

_trial_values skips failed and pruned trials. pareto_indexes enumerates unfiltered study.trials. A skipped trial shifts later indexes and marks the wrong points as Pareto-optimal.

Build values and Pareto indexes in one filtered pass. Add a regression test with a failed or pruned trial before a completed Pareto trial.

Proposed fix
-    values = _trial_values(study.trials, len(metric_names))
     pareto_numbers = _pareto_trial_numbers(study)
-    pareto_indexes = [index for index, trial in enumerate(study.trials) if trial.number in pareto_numbers]
+    values, pareto_indexes = _plot_points(
+        study.trials, len(metric_names), pareto_numbers
+    )
🤖 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 `@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/artifacts.py`
around lines 62 - 64, Update the logic around _trial_values and pareto_indexes
to filter failed and pruned trials once, then derive both metric values and
Pareto indexes from that same filtered trial sequence. Preserve the existing
Pareto membership check using trial.number, and add a regression test covering a
failed or pruned trial before a completed Pareto trial.
🧹 Nitpick comments (1)
plugins/nemo-optimization/examples/hermes-optimize/README.md (1)

203-212: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a Next Steps section.

Add ## Next Steps with links to docs/agents/optimization.mdx and the Fabric MCP workflow.

🤖 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 `@plugins/nemo-optimization/examples/hermes-optimize/README.md` around lines
203 - 212, Add a “Next Steps” section to the README after the existing Notes,
linking to docs/agents/optimization.mdx and the Fabric MCP workflow
documentation.

Source: Coding guidelines

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

Inline comments:
In `@docs/agents/index.mdx`:
- Around line 57-63: Remove the Optimize row from the “Legacy NAT-only commands”
table in the agents documentation, since `nemo agents optimize run` belongs to
the Fabric workflow. Add or update the surrounding documentation to direct users
to the Fabric optimization workflow, while keeping the NAT evaluation entry
unchanged.

In `@plugins/nemo-agents/tests/unit/usage/test_usage_cli.py`:
- Around line 210-216: Update the test around the usage CLI invocation to mock
the parser’s file-read operation so it raises PermissionError, rather than
relying on chmod(0o000) for bad. Remove the permission-bit manipulation and
retain the assertion coverage for handling the read failure through
runner.invoke.

---

Duplicate comments:
In
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/artifacts.py`:
- Around line 62-64: Update the logic around _trial_values and pareto_indexes to
filter failed and pruned trials once, then derive both metric values and Pareto
indexes from that same filtered trial sequence. Preserve the existing Pareto
membership check using trial.number, and add a regression test covering a failed
or pruned trial before a completed Pareto trial.

---

Nitpick comments:
In `@plugins/nemo-optimization/examples/hermes-optimize/README.md`:
- Around line 203-212: Add a “Next Steps” section to the README after the
existing Notes, linking to docs/agents/optimization.mdx and the Fabric MCP
workflow documentation.
🪄 Autofix

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: CHILL

Plan: Enterprise

Run ID: d67004fd-d1d8-4754-ab90-7fd8a89cde5d

📥 Commits

Reviewing files that changed from the base of the PR and between a6904bd and 06ec8d1.

⛔ Files ignored due to path filters (12)
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/__init__.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/agent_eval/runtimes/fabric/hook_loading.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/agent_eval/runtimes/fabric/hooks.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/agent_eval/runtimes/fabric/hooks_mcp_binding.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/agent_eval/runtimes/fabric/runtime.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/enums.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/metrics/tunable_rag_defaults.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/metrics/tunable_rag_evaluator.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/metrics/types.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/values/__init__.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/values/metrics.py is excluded by !sdk/**
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (93)
  • docs/agents/index.mdx
  • docs/agents/optimization.mdx
  • packages/nemo_evaluator_sdk/pyproject.toml
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/__init__.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hook_loading.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hooks.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hooks_mcp_binding.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/runtime.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/enums.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/tunable_rag_defaults.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/tunable_rag_evaluator.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/types.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/__init__.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/metrics.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_hook_loading.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_runtime.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_mcp_run_binding_hook.py
  • packages/nemo_evaluator_sdk/tests/metrics/test_tunable_rag_evaluator.py
  • packages/nemo_platform/pyproject.toml
  • packages/nemo_platform_plugin/tests/test_dispatcher.py
  • plugins/nemo-agents/openapi/openapi.yaml
  • plugins/nemo-agents/pyproject.toml
  • plugins/nemo-agents/src/nemo_agents_plugin/cli.py
  • plugins/nemo-agents/src/nemo_agents_plugin/jobs/optimize_agent.py
  • plugins/nemo-agents/src/nemo_agents_plugin/leaderboard/render.py
  • plugins/nemo-agents/src/nemo_agents_plugin/service.py
  • plugins/nemo-agents/src/nemo_agents_plugin/utils.py
  • plugins/nemo-agents/tests/unit/test_cli.py
  • plugins/nemo-agents/tests/unit/test_improvement_jobs.py
  • plugins/nemo-agents/tests/unit/test_optimize_agent_job.py
  • plugins/nemo-agents/tests/unit/test_optimize_skills_analyze_only.py
  • plugins/nemo-agents/tests/unit/test_service.py
  • plugins/nemo-agents/tests/unit/test_utils.py
  • plugins/nemo-agents/tests/unit/usage/test_usage_cli.py
  • plugins/nemo-deployments/src/nemo_deployments_plugin/backends/docker/backend.py
  • plugins/nemo-deployments/src/nemo_deployments_plugin/backends/docker/gpu.py
  • plugins/nemo-deployments/tests/unit/backends/docker/test_gpu.py
  • plugins/nemo-optimization/README.md
  • plugins/nemo-optimization/examples/hermes-optimize/.gitignore
  • plugins/nemo-optimization/examples/hermes-optimize/README.md
  • plugins/nemo-optimization/examples/hermes-optimize/agent.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/analyzer.inference-api.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/dataset-phishing.json
  • plugins/nemo-optimization/examples/hermes-optimize/dataset.json
  • plugins/nemo-optimization/examples/hermes-optimize/optimize.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/package.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/phishing.optimize.fabric-chatonly.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/phishing.optimize.fabric-mcp.e2e.yaml
  • plugins/nemo-optimization/pyproject.toml
  • plugins/nemo-optimization/src/nemo_optimization/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/agents.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/ga/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/ga/backend.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/artifacts.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/atif_metadata.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/backend.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/config_overlay.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/early_stop.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/fabric_trial.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/search_space.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/selection.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/study_driver.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/protocol.py
  • plugins/nemo-optimization/src/nemo_optimization/config.py
  • plugins/nemo-optimization/src/nemo_optimization/fabric.py
  • plugins/nemo-optimization/src/nemo_optimization/jobs/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/jobs/optimize.py
  • plugins/nemo-optimization/src/nemo_optimization/preflight.py
  • plugins/nemo-optimization/src/nemo_optimization/registry.py
  • plugins/nemo-optimization/src/nemo_optimization/router.py
  • plugins/nemo-optimization/src/nemo_optimization/schemas/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/schemas/optimize.py
  • plugins/nemo-optimization/src/nemo_optimization/tasks/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/tasks/optimize.py
  • plugins/nemo-optimization/tests/conftest.py
  • plugins/nemo-optimization/tests/smoke_fabric_optimize_atif.py
  • plugins/nemo-optimization/tests/test_atif_metadata.py
  • plugins/nemo-optimization/tests/test_config_overlay.py
  • plugins/nemo-optimization/tests/test_fabric.py
  • plugins/nemo-optimization/tests/test_fabric_trial.py
  • plugins/nemo-optimization/tests/test_optimize_job.py
  • plugins/nemo-optimization/tests/test_router.py
  • plugins/nemo-optimization/tests/test_search_space.py
  • plugins/nemo-optimization/tests/test_selection.py
  • plugins/nemo-optimization/tests/test_study_driver.py
  • pyproject.toml
  • services/core/models/src/nmp/core/models/controllers/backends/deployments_plugin/compiler.py
  • services/core/models/tests/unit/controllers/backends/deployments_plugin/test_compiler.py
  • third_party/licenses.jsonl
  • third_party/osv-licenses.json
  • third_party/requirements-main.txt
💤 Files with no reviewable changes (3)
  • plugins/nemo-agents/tests/unit/test_optimize_agent_job.py
  • plugins/nemo-agents/src/nemo_agents_plugin/jobs/optimize_agent.py
  • plugins/nemo-agents/tests/unit/test_utils.py
🚧 Files skipped from review as they are similar to previous changes (68)
  • plugins/nemo-optimization/examples/hermes-optimize/dataset-phishing.json
  • plugins/nemo-optimization/examples/hermes-optimize/dataset.json
  • plugins/nemo-optimization/src/nemo_optimization/init.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/enums.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/init.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/init.py
  • plugins/nemo-optimization/examples/hermes-optimize/package.yaml
  • plugins/nemo-optimization/tests/test_atif_metadata.py
  • plugins/nemo-optimization/examples/hermes-optimize/analyzer.inference-api.yaml
  • plugins/nemo-deployments/src/nemo_deployments_plugin/backends/docker/backend.py
  • packages/nemo_platform_plugin/tests/test_dispatcher.py
  • plugins/nemo-optimization/src/nemo_optimization/jobs/init.py
  • plugins/nemo-optimization/src/nemo_optimization/tasks/init.py
  • plugins/nemo-optimization/tests/test_optimize_job.py
  • plugins/nemo-optimization/examples/hermes-optimize/optimize.yaml
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_hook_loading.py
  • plugins/nemo-optimization/src/nemo_optimization/schemas/init.py
  • plugins/nemo-optimization/README.md
  • plugins/nemo-optimization/src/nemo_optimization/backends/protocol.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/atif_metadata.py
  • plugins/nemo-optimization/src/nemo_optimization/tasks/optimize.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hook_loading.py
  • plugins/nemo-optimization/examples/hermes-optimize/phishing.optimize.fabric-chatonly.yaml
  • plugins/nemo-optimization/pyproject.toml
  • plugins/nemo-optimization/tests/test_router.py
  • plugins/nemo-agents/src/nemo_agents_plugin/utils.py
  • plugins/nemo-optimization/src/nemo_optimization/schemas/optimize.py
  • plugins/nemo-optimization/examples/hermes-optimize/agent.yaml
  • plugins/nemo-optimization/src/nemo_optimization/registry.py
  • plugins/nemo-optimization/tests/conftest.py
  • plugins/nemo-optimization/src/nemo_optimization/fabric.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/early_stop.py
  • plugins/nemo-optimization/examples/hermes-optimize/phishing.optimize.fabric-mcp.e2e.yaml
  • pyproject.toml
  • plugins/nemo-optimization/src/nemo_optimization/agents.py
  • plugins/nemo-optimization/src/nemo_optimization/preflight.py
  • plugins/nemo-optimization/src/nemo_optimization/router.py
  • plugins/nemo-optimization/examples/hermes-optimize/.gitignore
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/selection.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_runtime.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/tunable_rag_evaluator.py
  • plugins/nemo-optimization/tests/test_search_space.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/types.py
  • plugins/nemo-optimization/tests/test_config_overlay.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/ga/init.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/ga/backend.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/tunable_rag_defaults.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/study_driver.py
  • plugins/nemo-deployments/src/nemo_deployments_plugin/backends/docker/gpu.py
  • plugins/nemo-optimization/src/nemo_optimization/jobs/optimize.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/init.py
  • plugins/nemo-agents/src/nemo_agents_plugin/cli.py
  • plugins/nemo-agents/tests/unit/test_improvement_jobs.py
  • packages/nemo_evaluator_sdk/pyproject.toml
  • plugins/nemo-agents/pyproject.toml
  • plugins/nemo-agents/src/nemo_agents_plugin/leaderboard/render.py
  • services/core/models/src/nmp/core/models/controllers/backends/deployments_plugin/compiler.py
  • plugins/nemo-agents/src/nemo_agents_plugin/service.py
  • plugins/nemo-optimization/tests/test_fabric.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/init.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hooks.py
  • plugins/nemo-optimization/tests/test_selection.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hooks_mcp_binding.py
  • plugins/nemo-deployments/tests/unit/backends/docker/test_gpu.py
  • plugins/nemo-agents/tests/unit/test_service.py
  • docs/agents/optimization.mdx
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/metrics.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/search_space.py

Comment thread docs/agents/index.mdx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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: 2

♻️ Duplicate comments (1)
plugins/nemo-optimization/src/nemo_optimization/backends/optuna/artifacts.py (1)

62-64: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Build Pareto indexes in the filtered value index space.

_trial_values skips failed and pruned trials. pareto_indexes enumerates unfiltered study.trials. A skipped trial shifts later indexes and marks the wrong points as Pareto-optimal.

Build values and Pareto indexes in one filtered pass. Add a regression test with a failed or pruned trial before a completed Pareto trial.

Proposed fix
-    values = _trial_values(study.trials, len(metric_names))
     pareto_numbers = _pareto_trial_numbers(study)
-    pareto_indexes = [index for index, trial in enumerate(study.trials) if trial.number in pareto_numbers]
+    values, pareto_indexes = _plot_points(
+        study.trials, len(metric_names), pareto_numbers
+    )
🤖 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 `@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/artifacts.py`
around lines 62 - 64, Update the logic around _trial_values and pareto_indexes
to filter failed and pruned trials once, then derive both metric values and
Pareto indexes from that same filtered trial sequence. Preserve the existing
Pareto membership check using trial.number, and add a regression test covering a
failed or pruned trial before a completed Pareto trial.
🧹 Nitpick comments (1)
plugins/nemo-optimization/examples/hermes-optimize/README.md (1)

203-212: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a Next Steps section.

Add ## Next Steps with links to docs/agents/optimization.mdx and the Fabric MCP workflow.

🤖 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 `@plugins/nemo-optimization/examples/hermes-optimize/README.md` around lines
203 - 212, Add a “Next Steps” section to the README after the existing Notes,
linking to docs/agents/optimization.mdx and the Fabric MCP workflow
documentation.

Source: Coding guidelines

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

Inline comments:
In `@docs/agents/index.mdx`:
- Around line 57-63: Remove the Optimize row from the “Legacy NAT-only commands”
table in the agents documentation, since `nemo agents optimize run` belongs to
the Fabric workflow. Add or update the surrounding documentation to direct users
to the Fabric optimization workflow, while keeping the NAT evaluation entry
unchanged.

In `@plugins/nemo-agents/tests/unit/usage/test_usage_cli.py`:
- Around line 210-216: Update the test around the usage CLI invocation to mock
the parser’s file-read operation so it raises PermissionError, rather than
relying on chmod(0o000) for bad. Remove the permission-bit manipulation and
retain the assertion coverage for handling the read failure through
runner.invoke.

---

Duplicate comments:
In
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/artifacts.py`:
- Around line 62-64: Update the logic around _trial_values and pareto_indexes to
filter failed and pruned trials once, then derive both metric values and Pareto
indexes from that same filtered trial sequence. Preserve the existing Pareto
membership check using trial.number, and add a regression test covering a failed
or pruned trial before a completed Pareto trial.

---

Nitpick comments:
In `@plugins/nemo-optimization/examples/hermes-optimize/README.md`:
- Around line 203-212: Add a “Next Steps” section to the README after the
existing Notes, linking to docs/agents/optimization.mdx and the Fabric MCP
workflow documentation.
🪄 Autofix

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: CHILL

Plan: Enterprise

Run ID: d67004fd-d1d8-4754-ab90-7fd8a89cde5d

📥 Commits

Reviewing files that changed from the base of the PR and between a6904bd and 06ec8d1.

⛔ Files ignored due to path filters (12)
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/__init__.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/agent_eval/runtimes/fabric/hook_loading.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/agent_eval/runtimes/fabric/hooks.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/agent_eval/runtimes/fabric/hooks_mcp_binding.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/agent_eval/runtimes/fabric/runtime.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/enums.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/metrics/tunable_rag_defaults.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/metrics/tunable_rag_evaluator.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/metrics/types.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/values/__init__.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/values/metrics.py is excluded by !sdk/**
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (93)
  • docs/agents/index.mdx
  • docs/agents/optimization.mdx
  • packages/nemo_evaluator_sdk/pyproject.toml
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/__init__.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hook_loading.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hooks.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hooks_mcp_binding.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/runtime.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/enums.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/tunable_rag_defaults.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/tunable_rag_evaluator.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/types.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/__init__.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/metrics.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_hook_loading.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_runtime.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_mcp_run_binding_hook.py
  • packages/nemo_evaluator_sdk/tests/metrics/test_tunable_rag_evaluator.py
  • packages/nemo_platform/pyproject.toml
  • packages/nemo_platform_plugin/tests/test_dispatcher.py
  • plugins/nemo-agents/openapi/openapi.yaml
  • plugins/nemo-agents/pyproject.toml
  • plugins/nemo-agents/src/nemo_agents_plugin/cli.py
  • plugins/nemo-agents/src/nemo_agents_plugin/jobs/optimize_agent.py
  • plugins/nemo-agents/src/nemo_agents_plugin/leaderboard/render.py
  • plugins/nemo-agents/src/nemo_agents_plugin/service.py
  • plugins/nemo-agents/src/nemo_agents_plugin/utils.py
  • plugins/nemo-agents/tests/unit/test_cli.py
  • plugins/nemo-agents/tests/unit/test_improvement_jobs.py
  • plugins/nemo-agents/tests/unit/test_optimize_agent_job.py
  • plugins/nemo-agents/tests/unit/test_optimize_skills_analyze_only.py
  • plugins/nemo-agents/tests/unit/test_service.py
  • plugins/nemo-agents/tests/unit/test_utils.py
  • plugins/nemo-agents/tests/unit/usage/test_usage_cli.py
  • plugins/nemo-deployments/src/nemo_deployments_plugin/backends/docker/backend.py
  • plugins/nemo-deployments/src/nemo_deployments_plugin/backends/docker/gpu.py
  • plugins/nemo-deployments/tests/unit/backends/docker/test_gpu.py
  • plugins/nemo-optimization/README.md
  • plugins/nemo-optimization/examples/hermes-optimize/.gitignore
  • plugins/nemo-optimization/examples/hermes-optimize/README.md
  • plugins/nemo-optimization/examples/hermes-optimize/agent.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/analyzer.inference-api.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/dataset-phishing.json
  • plugins/nemo-optimization/examples/hermes-optimize/dataset.json
  • plugins/nemo-optimization/examples/hermes-optimize/optimize.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/package.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/phishing.optimize.fabric-chatonly.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/phishing.optimize.fabric-mcp.e2e.yaml
  • plugins/nemo-optimization/pyproject.toml
  • plugins/nemo-optimization/src/nemo_optimization/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/agents.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/ga/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/ga/backend.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/artifacts.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/atif_metadata.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/backend.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/config_overlay.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/early_stop.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/fabric_trial.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/search_space.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/selection.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/study_driver.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/protocol.py
  • plugins/nemo-optimization/src/nemo_optimization/config.py
  • plugins/nemo-optimization/src/nemo_optimization/fabric.py
  • plugins/nemo-optimization/src/nemo_optimization/jobs/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/jobs/optimize.py
  • plugins/nemo-optimization/src/nemo_optimization/preflight.py
  • plugins/nemo-optimization/src/nemo_optimization/registry.py
  • plugins/nemo-optimization/src/nemo_optimization/router.py
  • plugins/nemo-optimization/src/nemo_optimization/schemas/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/schemas/optimize.py
  • plugins/nemo-optimization/src/nemo_optimization/tasks/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/tasks/optimize.py
  • plugins/nemo-optimization/tests/conftest.py
  • plugins/nemo-optimization/tests/smoke_fabric_optimize_atif.py
  • plugins/nemo-optimization/tests/test_atif_metadata.py
  • plugins/nemo-optimization/tests/test_config_overlay.py
  • plugins/nemo-optimization/tests/test_fabric.py
  • plugins/nemo-optimization/tests/test_fabric_trial.py
  • plugins/nemo-optimization/tests/test_optimize_job.py
  • plugins/nemo-optimization/tests/test_router.py
  • plugins/nemo-optimization/tests/test_search_space.py
  • plugins/nemo-optimization/tests/test_selection.py
  • plugins/nemo-optimization/tests/test_study_driver.py
  • pyproject.toml
  • services/core/models/src/nmp/core/models/controllers/backends/deployments_plugin/compiler.py
  • services/core/models/tests/unit/controllers/backends/deployments_plugin/test_compiler.py
  • third_party/licenses.jsonl
  • third_party/osv-licenses.json
  • third_party/requirements-main.txt
💤 Files with no reviewable changes (3)
  • plugins/nemo-agents/tests/unit/test_optimize_agent_job.py
  • plugins/nemo-agents/src/nemo_agents_plugin/jobs/optimize_agent.py
  • plugins/nemo-agents/tests/unit/test_utils.py
🚧 Files skipped from review as they are similar to previous changes (68)
  • plugins/nemo-optimization/examples/hermes-optimize/dataset-phishing.json
  • plugins/nemo-optimization/examples/hermes-optimize/dataset.json
  • plugins/nemo-optimization/src/nemo_optimization/init.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/enums.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/init.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/init.py
  • plugins/nemo-optimization/examples/hermes-optimize/package.yaml
  • plugins/nemo-optimization/tests/test_atif_metadata.py
  • plugins/nemo-optimization/examples/hermes-optimize/analyzer.inference-api.yaml
  • plugins/nemo-deployments/src/nemo_deployments_plugin/backends/docker/backend.py
  • packages/nemo_platform_plugin/tests/test_dispatcher.py
  • plugins/nemo-optimization/src/nemo_optimization/jobs/init.py
  • plugins/nemo-optimization/src/nemo_optimization/tasks/init.py
  • plugins/nemo-optimization/tests/test_optimize_job.py
  • plugins/nemo-optimization/examples/hermes-optimize/optimize.yaml
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_hook_loading.py
  • plugins/nemo-optimization/src/nemo_optimization/schemas/init.py
  • plugins/nemo-optimization/README.md
  • plugins/nemo-optimization/src/nemo_optimization/backends/protocol.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/atif_metadata.py
  • plugins/nemo-optimization/src/nemo_optimization/tasks/optimize.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hook_loading.py
  • plugins/nemo-optimization/examples/hermes-optimize/phishing.optimize.fabric-chatonly.yaml
  • plugins/nemo-optimization/pyproject.toml
  • plugins/nemo-optimization/tests/test_router.py
  • plugins/nemo-agents/src/nemo_agents_plugin/utils.py
  • plugins/nemo-optimization/src/nemo_optimization/schemas/optimize.py
  • plugins/nemo-optimization/examples/hermes-optimize/agent.yaml
  • plugins/nemo-optimization/src/nemo_optimization/registry.py
  • plugins/nemo-optimization/tests/conftest.py
  • plugins/nemo-optimization/src/nemo_optimization/fabric.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/early_stop.py
  • plugins/nemo-optimization/examples/hermes-optimize/phishing.optimize.fabric-mcp.e2e.yaml
  • pyproject.toml
  • plugins/nemo-optimization/src/nemo_optimization/agents.py
  • plugins/nemo-optimization/src/nemo_optimization/preflight.py
  • plugins/nemo-optimization/src/nemo_optimization/router.py
  • plugins/nemo-optimization/examples/hermes-optimize/.gitignore
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/selection.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_runtime.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/tunable_rag_evaluator.py
  • plugins/nemo-optimization/tests/test_search_space.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/types.py
  • plugins/nemo-optimization/tests/test_config_overlay.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/ga/init.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/ga/backend.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/tunable_rag_defaults.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/study_driver.py
  • plugins/nemo-deployments/src/nemo_deployments_plugin/backends/docker/gpu.py
  • plugins/nemo-optimization/src/nemo_optimization/jobs/optimize.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/init.py
  • plugins/nemo-agents/src/nemo_agents_plugin/cli.py
  • plugins/nemo-agents/tests/unit/test_improvement_jobs.py
  • packages/nemo_evaluator_sdk/pyproject.toml
  • plugins/nemo-agents/pyproject.toml
  • plugins/nemo-agents/src/nemo_agents_plugin/leaderboard/render.py
  • services/core/models/src/nmp/core/models/controllers/backends/deployments_plugin/compiler.py
  • plugins/nemo-agents/src/nemo_agents_plugin/service.py
  • plugins/nemo-optimization/tests/test_fabric.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/init.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hooks.py
  • plugins/nemo-optimization/tests/test_selection.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hooks_mcp_binding.py
  • plugins/nemo-deployments/tests/unit/backends/docker/test_gpu.py
  • plugins/nemo-agents/tests/unit/test_service.py
  • docs/agents/optimization.mdx
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/metrics.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/search_space.py
🛑 Comments failed to post (1)
plugins/nemo-agents/tests/unit/usage/test_usage_cli.py (1)

210-216: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Mock the read failure.

Line 212 does not block reads for privileged runners. Windows also does not enforce these mode bits consistently. Mock the parser file-read operation to raise PermissionError instead.

🤖 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 `@plugins/nemo-agents/tests/unit/usage/test_usage_cli.py` around lines 210 -
216, Update the test around the usage CLI invocation to mock the parser’s
file-read operation so it raises PermissionError, rather than relying on
chmod(0o000) for bad. Remove the permission-bit manipulation and retain the
assertion coverage for handling the read failure through runner.invoke.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

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

⚠️ Outside diff range comments (1)
plugins/nemo-optimization/examples/hermes-optimize/README.md (1)

203-217: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add a final Next Steps section.

The README ends with Notes. Add Next Steps with cross-links to the related Optimize Agents documentation.

🤖 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 `@plugins/nemo-optimization/examples/hermes-optimize/README.md` around lines
203 - 217, Add a final “Next Steps” section after “Notes” in the README,
including cross-links to the related Optimize Agents documentation. Keep the
existing Notes content unchanged and use the repository’s established
documentation link targets where available.

Source: Coding guidelines

♻️ Duplicate comments (2)
plugins/nemo-optimization/examples/hermes-optimize/README.md (1)

71-114: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use tab sets for the CLI and SDK variants.

These parallel recipes use repeated CLI and Python SDK headings. They violate the tab-set requirement and trigger MD024. Put each recipe pair in a supported tab set, or link to the tabbed documentation page instead.

Also applies to: 144-196

🤖 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 `@plugins/nemo-optimization/examples/hermes-optimize/README.md` around lines 71
- 114, Update the “Clean chat-only run” documentation and the corresponding
recipe section around the referenced later block to wrap each CLI/Python SDK
pair in the repository’s supported tab-set format. Replace the repeated
standalone CLI and Python SDK headings with tab labels consistent with existing
tabbed documentation, while preserving both command and SDK examples unchanged.

Sources: Coding guidelines, Linters/SAST tools

plugins/nemo-optimization/src/nemo_optimization/backends/optuna/artifacts.py (1)

62-64: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Keep Pareto indexes in the filtered plot index space.

_trial_values skips failed, pruned, and incomplete trials. Line 64 indexes unfiltered study.trials. A skipped trial before a Pareto trial marks the wrong plot point. Build values and Pareto indexes in one filtered pass.

Proposed fix
-    values = _trial_values(study.trials, len(metric_names))
     pareto_numbers = _pareto_trial_numbers(study)
-    pareto_indexes = [index for index, trial in enumerate(study.trials) if trial.number in pareto_numbers]
+    values, pareto_indexes = _plot_points(study.trials, len(metric_names), pareto_numbers)
def _plot_points(
    trials: Sequence[optuna.trial.FrozenTrial],
    n_metrics: int,
    pareto_numbers: set[int],
) -> tuple[list[list[float]], list[int]]:
    values: list[list[float]] = []
    pareto_indexes: list[int] = []

    for trial in trials:
        trial_values = list(trial.values or ([] if trial.value is None else [trial.value]))
        if len(trial_values) != n_metrics:
            continue
        if trial.number in pareto_numbers:
            pareto_indexes.append(len(values))
        values.append([float(value) for value in trial_values])

    return values, pareto_indexes
🤖 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 `@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/artifacts.py`
around lines 62 - 64, Update the plotting preparation around _trial_values and
pareto_indexes to use one filtered pass over study.trials, retaining only
complete trials with exactly len(metric_names) values. Build values and append
each Pareto trial’s index based on the filtered values list position, then use
both results for plotting so skipped trials cannot shift Pareto indexes.
🧹 Nitpick comments (3)
plugins/nemo-optimization/src/nemo_optimization/backends/optuna/fabric_trial.py (1)

47-59: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Drop the redundant isinstance re-checks on fabric_eval.

Line 47 already guarantees fabric_eval is a Mapping (or {}). The isinstance(fabric_eval, Mapping) guards on Lines 54, 56, and 58 can never be false.

♻️ Proposed change
-        fabric_eval = self._eval_config.get("fabric") if isinstance(self._eval_config.get("fabric"), Mapping) else {}
+        raw_fabric = self._eval_config.get("fabric")
+        fabric_eval: Mapping[str, Any] = raw_fabric if isinstance(raw_fabric, Mapping) else {}
         run_hook_spec = self._eval_config.get("run_hook")
         try:
             self._task_hook = load_fabric_task_hook(run_hook_spec if isinstance(run_hook_spec, Mapping) else None)
         except FabricTaskHookLoadError as exc:
             raise StudyDriverError(str(exc)) from exc
-        self._fabric_base_dir = _optional_path(
-            fabric_eval.get("base_dir") if isinstance(fabric_eval, Mapping) else None
-        )
-        self._timeout_s = int(fabric_eval.get("timeout_s", 600) if isinstance(fabric_eval, Mapping) else 600)
-        self._capture_trajectory = bool(
-            fabric_eval.get("capture_trajectory", True) if isinstance(fabric_eval, Mapping) else True
-        )
+        self._fabric_base_dir = _optional_path(fabric_eval.get("base_dir"))
+        self._timeout_s = int(fabric_eval.get("timeout_s", 600))
+        self._capture_trajectory = bool(fabric_eval.get("capture_trajectory", True))
🤖 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
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/fabric_trial.py`
around lines 47 - 59, Remove the redundant isinstance(fabric_eval, Mapping)
checks in the _fabric_base_dir, _timeout_s, and _capture_trajectory
initialization within the constructor. Use fabric_eval directly for these .get
calls, preserving the existing defaults and behavior.
plugins/nemo-agents/tests/unit/test_optimize_skills_analyze_only.py (1)

231-251: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add return and parameter type hints.

The repository guideline requires concrete type hints. _agents_cli_with_jobs has no return type and _guard_message has an untyped result parameter.

♻️ Proposed change
-def _agents_cli_with_jobs():
+def _agents_cli_with_jobs() -> typer.Typer:
-def _guard_message(result) -> str:
+def _guard_message(result: Result) -> str:

Import typer and from click.testing import Result at module scope.

As per coding guidelines: "Prefer concrete type hints over string-based type hints".

🤖 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 `@plugins/nemo-agents/tests/unit/test_optimize_skills_analyze_only.py` around
lines 231 - 251, Update _agents_cli_with_jobs with a concrete return type and
annotate _guard_message’s result parameter with click.testing.Result; add the
required module-level imports for these types, including typer if needed for the
CLI return annotation, while preserving both helpers’ behavior.

Source: Coding guidelines

plugins/nemo-optimization/src/nemo_optimization/backends/optuna/backend.py (1)

89-89: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Annotate result and output_dir.

_study_debug_payload(result) and _build_trial_evaluator(..., output_dir) have untyped parameters and _build_trial_evaluator has no return type. Use the concrete study-result type and Path.

As per coding guidelines: "Prefer concrete type hints over string-based type hints".

Also applies to: 119-125

🤖 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 `@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/backend.py`
at line 89, Update _study_debug_payload to annotate result with the concrete
study-result type, and update _build_trial_evaluator to annotate output_dir as
Path and add its concrete return type. Use direct imported type hints rather
than string-based annotations, preserving the existing behavior.

Source: Coding guidelines

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

Inline comments:
In `@plugins/nemo-agents/tests/unit/usage/test_usage_cli.py`:
- Around line 204-216: Update
test_usage_show_unreadable_result_json_exits_cleanly to mock the parser’s
file-read operation so it raises PermissionError instead of relying on
chmod(0o000); preserve the existing runner invocation and CLI assertions
unchanged.

In
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/fabric_trial.py`:
- Line 62: Update the parallelism initialization in the trial setup to validate
that the eval_config “general” value is a mapping before reading
max_concurrency. Reuse the existing validation pattern from the guard around
line 240, and raise StudyDriverError for null or non-mapping values instead of
calling .get on them.

In
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/selection.py`:
- Around line 42-44: Update the harmonic branch in the selection logic around
normalized_mode to compute the harmonic mean over utilities (1 - norm), then
select the trial with the maximum utility harmonic mean instead of minimizing
hmean(norm). Add a regression test covering [0.0, 1.0] versus [0.4, 0.4],
asserting the balanced compromise is selected.

In `@plugins/nemo-optimization/tests/smoke_fabric_optimize_atif.py`:
- Around line 130-131: Update the assertion message immediately after
constructing atif_path to reference the same trace_ref used to create and
validate that path, rather than the stale entry loop variable. Keep the is_file
assertion behavior unchanged.

---

Outside diff comments:
In `@plugins/nemo-optimization/examples/hermes-optimize/README.md`:
- Around line 203-217: Add a final “Next Steps” section after “Notes” in the
README, including cross-links to the related Optimize Agents documentation. Keep
the existing Notes content unchanged and use the repository’s established
documentation link targets where available.

---

Duplicate comments:
In `@plugins/nemo-optimization/examples/hermes-optimize/README.md`:
- Around line 71-114: Update the “Clean chat-only run” documentation and the
corresponding recipe section around the referenced later block to wrap each
CLI/Python SDK pair in the repository’s supported tab-set format. Replace the
repeated standalone CLI and Python SDK headings with tab labels consistent with
existing tabbed documentation, while preserving both command and SDK examples
unchanged.

In
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/artifacts.py`:
- Around line 62-64: Update the plotting preparation around _trial_values and
pareto_indexes to use one filtered pass over study.trials, retaining only
complete trials with exactly len(metric_names) values. Build values and append
each Pareto trial’s index based on the filtered values list position, then use
both results for plotting so skipped trials cannot shift Pareto indexes.

---

Nitpick comments:
In `@plugins/nemo-agents/tests/unit/test_optimize_skills_analyze_only.py`:
- Around line 231-251: Update _agents_cli_with_jobs with a concrete return type
and annotate _guard_message’s result parameter with click.testing.Result; add
the required module-level imports for these types, including typer if needed for
the CLI return annotation, while preserving both helpers’ behavior.

In `@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/backend.py`:
- Line 89: Update _study_debug_payload to annotate result with the concrete
study-result type, and update _build_trial_evaluator to annotate output_dir as
Path and add its concrete return type. Use direct imported type hints rather
than string-based annotations, preserving the existing behavior.

In
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/fabric_trial.py`:
- Around line 47-59: Remove the redundant isinstance(fabric_eval, Mapping)
checks in the _fabric_base_dir, _timeout_s, and _capture_trajectory
initialization within the constructor. Use fabric_eval directly for these .get
calls, preserving the existing defaults and behavior.
🪄 Autofix

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: CHILL

Plan: Enterprise

Run ID: 3851d6b3-65bb-459f-b436-6506f341d4ec

📥 Commits

Reviewing files that changed from the base of the PR and between 9fa8b8a and d7d4657.

⛔ Files ignored due to path filters (12)
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/__init__.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/agent_eval/runtimes/fabric/hook_loading.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/agent_eval/runtimes/fabric/hooks.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/agent_eval/runtimes/fabric/hooks_mcp_binding.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/agent_eval/runtimes/fabric/runtime.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/enums.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/metrics/tunable_rag_defaults.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/metrics/tunable_rag_evaluator.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/metrics/types.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/values/__init__.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/values/metrics.py is excluded by !sdk/**
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (93)
  • docs/agents/index.mdx
  • docs/agents/optimization.mdx
  • packages/nemo_evaluator_sdk/pyproject.toml
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/__init__.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hook_loading.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hooks.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hooks_mcp_binding.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/runtime.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/enums.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/tunable_rag_defaults.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/tunable_rag_evaluator.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/types.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/__init__.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/metrics.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_hook_loading.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_runtime.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_mcp_run_binding_hook.py
  • packages/nemo_evaluator_sdk/tests/metrics/test_tunable_rag_evaluator.py
  • packages/nemo_platform/pyproject.toml
  • packages/nemo_platform_plugin/tests/test_dispatcher.py
  • plugins/nemo-agents/openapi/openapi.yaml
  • plugins/nemo-agents/pyproject.toml
  • plugins/nemo-agents/src/nemo_agents_plugin/cli.py
  • plugins/nemo-agents/src/nemo_agents_plugin/jobs/optimize_agent.py
  • plugins/nemo-agents/src/nemo_agents_plugin/leaderboard/render.py
  • plugins/nemo-agents/src/nemo_agents_plugin/service.py
  • plugins/nemo-agents/src/nemo_agents_plugin/utils.py
  • plugins/nemo-agents/tests/unit/test_cli.py
  • plugins/nemo-agents/tests/unit/test_improvement_jobs.py
  • plugins/nemo-agents/tests/unit/test_optimize_agent_job.py
  • plugins/nemo-agents/tests/unit/test_optimize_skills_analyze_only.py
  • plugins/nemo-agents/tests/unit/test_service.py
  • plugins/nemo-agents/tests/unit/test_utils.py
  • plugins/nemo-agents/tests/unit/usage/test_usage_cli.py
  • plugins/nemo-deployments/src/nemo_deployments_plugin/backends/docker/backend.py
  • plugins/nemo-deployments/src/nemo_deployments_plugin/backends/docker/gpu.py
  • plugins/nemo-deployments/tests/unit/backends/docker/test_gpu.py
  • plugins/nemo-optimization/README.md
  • plugins/nemo-optimization/examples/hermes-optimize/.gitignore
  • plugins/nemo-optimization/examples/hermes-optimize/README.md
  • plugins/nemo-optimization/examples/hermes-optimize/agent.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/analyzer.inference-api.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/dataset-phishing.json
  • plugins/nemo-optimization/examples/hermes-optimize/dataset.json
  • plugins/nemo-optimization/examples/hermes-optimize/optimize.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/package.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/phishing.optimize.fabric-chatonly.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/phishing.optimize.fabric-mcp.e2e.yaml
  • plugins/nemo-optimization/pyproject.toml
  • plugins/nemo-optimization/src/nemo_optimization/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/agents.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/ga/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/ga/backend.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/artifacts.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/atif_metadata.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/backend.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/config_overlay.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/early_stop.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/fabric_trial.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/search_space.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/selection.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/study_driver.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/protocol.py
  • plugins/nemo-optimization/src/nemo_optimization/config.py
  • plugins/nemo-optimization/src/nemo_optimization/fabric.py
  • plugins/nemo-optimization/src/nemo_optimization/jobs/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/jobs/optimize.py
  • plugins/nemo-optimization/src/nemo_optimization/preflight.py
  • plugins/nemo-optimization/src/nemo_optimization/registry.py
  • plugins/nemo-optimization/src/nemo_optimization/router.py
  • plugins/nemo-optimization/src/nemo_optimization/schemas/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/schemas/optimize.py
  • plugins/nemo-optimization/src/nemo_optimization/tasks/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/tasks/optimize.py
  • plugins/nemo-optimization/tests/conftest.py
  • plugins/nemo-optimization/tests/smoke_fabric_optimize_atif.py
  • plugins/nemo-optimization/tests/test_atif_metadata.py
  • plugins/nemo-optimization/tests/test_config_overlay.py
  • plugins/nemo-optimization/tests/test_fabric.py
  • plugins/nemo-optimization/tests/test_fabric_trial.py
  • plugins/nemo-optimization/tests/test_optimize_job.py
  • plugins/nemo-optimization/tests/test_router.py
  • plugins/nemo-optimization/tests/test_search_space.py
  • plugins/nemo-optimization/tests/test_selection.py
  • plugins/nemo-optimization/tests/test_study_driver.py
  • pyproject.toml
  • services/core/models/src/nmp/core/models/controllers/backends/deployments_plugin/compiler.py
  • services/core/models/tests/unit/controllers/backends/deployments_plugin/test_compiler.py
  • third_party/licenses.jsonl
  • third_party/osv-licenses.json
  • third_party/requirements-main.txt
💤 Files with no reviewable changes (3)
  • plugins/nemo-agents/src/nemo_agents_plugin/jobs/optimize_agent.py
  • plugins/nemo-agents/tests/unit/test_optimize_agent_job.py
  • plugins/nemo-agents/tests/unit/test_utils.py
🚧 Files skipped from review as they are similar to previous changes (71)
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/init.py
  • packages/nemo_evaluator_sdk/pyproject.toml
  • plugins/nemo-agents/tests/unit/test_service.py
  • pyproject.toml
  • packages/nemo_platform_plugin/tests/test_dispatcher.py
  • plugins/nemo-optimization/examples/hermes-optimize/dataset.json
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/init.py
  • services/core/models/src/nmp/core/models/controllers/backends/deployments_plugin/compiler.py
  • plugins/nemo-optimization/src/nemo_optimization/init.py
  • plugins/nemo-agents/tests/unit/test_improvement_jobs.py
  • plugins/nemo-agents/src/nemo_agents_plugin/leaderboard/render.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_hook_loading.py
  • plugins/nemo-optimization/tests/test_search_space.py
  • plugins/nemo-optimization/examples/hermes-optimize/package.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/analyzer.inference-api.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/dataset-phishing.json
  • plugins/nemo-optimization/examples/hermes-optimize/phishing.optimize.fabric-mcp.e2e.yaml
  • plugins/nemo-deployments/src/nemo_deployments_plugin/backends/docker/backend.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/atif_metadata.py
  • plugins/nemo-agents/src/nemo_agents_plugin/utils.py
  • plugins/nemo-optimization/README.md
  • plugins/nemo-optimization/examples/hermes-optimize/optimize.yaml
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/metrics.py
  • third_party/licenses.jsonl
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_runtime.py
  • plugins/nemo-optimization/examples/hermes-optimize/.gitignore
  • plugins/nemo-optimization/tests/test_selection.py
  • plugins/nemo-agents/src/nemo_agents_plugin/cli.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/init.py
  • plugins/nemo-optimization/pyproject.toml
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/enums.py
  • plugins/nemo-agents/src/nemo_agents_plugin/service.py
  • plugins/nemo-optimization/examples/hermes-optimize/agent.yaml
  • plugins/nemo-optimization/src/nemo_optimization/backends/ga/backend.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/init.py
  • plugins/nemo-deployments/src/nemo_deployments_plugin/backends/docker/gpu.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hooks.py
  • plugins/nemo-optimization/src/nemo_optimization/agents.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hook_loading.py
  • plugins/nemo-optimization/src/nemo_optimization/config.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/ga/init.py
  • plugins/nemo-optimization/src/nemo_optimization/jobs/init.py
  • packages/nemo_platform/pyproject.toml
  • plugins/nemo-optimization/src/nemo_optimization/tasks/init.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/tunable_rag_defaults.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/tunable_rag_evaluator.py
  • plugins/nemo-optimization/tests/test_config_overlay.py
  • plugins/nemo-optimization/tests/test_atif_metadata.py
  • plugins/nemo-optimization/src/nemo_optimization/schemas/init.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/types.py
  • plugins/nemo-optimization/src/nemo_optimization/schemas/optimize.py
  • docs/agents/optimization.mdx
  • plugins/nemo-optimization/src/nemo_optimization/tasks/optimize.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/protocol.py
  • plugins/nemo-optimization/examples/hermes-optimize/phishing.optimize.fabric-chatonly.yaml
  • plugins/nemo-optimization/tests/test_fabric.py
  • plugins/nemo-agents/pyproject.toml
  • plugins/nemo-optimization/tests/test_optimize_job.py
  • plugins/nemo-optimization/src/nemo_optimization/registry.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/early_stop.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/config_overlay.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hooks_mcp_binding.py
  • plugins/nemo-optimization/tests/test_router.py
  • plugins/nemo-optimization/src/nemo_optimization/fabric.py
  • plugins/nemo-optimization/src/nemo_optimization/preflight.py
  • plugins/nemo-deployments/tests/unit/backends/docker/test_gpu.py
  • third_party/requirements-main.txt
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/search_space.py
  • plugins/nemo-optimization/src/nemo_optimization/router.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/study_driver.py
  • plugins/nemo-optimization/src/nemo_optimization/jobs/optimize.py

Comment thread plugins/nemo-optimization/src/nemo_optimization/backends/optuna/fabric_trial.py Outdated
Comment thread plugins/nemo-optimization/src/nemo_optimization/backends/optuna/selection.py Outdated
Comment thread plugins/nemo-optimization/tests/smoke_fabric_optimize_atif.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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: 4

Caution

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

⚠️ Outside diff range comments (1)
plugins/nemo-optimization/examples/hermes-optimize/README.md (1)

203-217: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add a final Next Steps section.

The README ends with Notes. Add Next Steps with cross-links to the related Optimize Agents documentation.

🤖 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 `@plugins/nemo-optimization/examples/hermes-optimize/README.md` around lines
203 - 217, Add a final “Next Steps” section after “Notes” in the README,
including cross-links to the related Optimize Agents documentation. Keep the
existing Notes content unchanged and use the repository’s established
documentation link targets where available.

Source: Coding guidelines

♻️ Duplicate comments (2)
plugins/nemo-optimization/examples/hermes-optimize/README.md (1)

71-114: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use tab sets for the CLI and SDK variants.

These parallel recipes use repeated CLI and Python SDK headings. They violate the tab-set requirement and trigger MD024. Put each recipe pair in a supported tab set, or link to the tabbed documentation page instead.

Also applies to: 144-196

🤖 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 `@plugins/nemo-optimization/examples/hermes-optimize/README.md` around lines 71
- 114, Update the “Clean chat-only run” documentation and the corresponding
recipe section around the referenced later block to wrap each CLI/Python SDK
pair in the repository’s supported tab-set format. Replace the repeated
standalone CLI and Python SDK headings with tab labels consistent with existing
tabbed documentation, while preserving both command and SDK examples unchanged.

Sources: Coding guidelines, Linters/SAST tools

plugins/nemo-optimization/src/nemo_optimization/backends/optuna/artifacts.py (1)

62-64: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Keep Pareto indexes in the filtered plot index space.

_trial_values skips failed, pruned, and incomplete trials. Line 64 indexes unfiltered study.trials. A skipped trial before a Pareto trial marks the wrong plot point. Build values and Pareto indexes in one filtered pass.

Proposed fix
-    values = _trial_values(study.trials, len(metric_names))
     pareto_numbers = _pareto_trial_numbers(study)
-    pareto_indexes = [index for index, trial in enumerate(study.trials) if trial.number in pareto_numbers]
+    values, pareto_indexes = _plot_points(study.trials, len(metric_names), pareto_numbers)
def _plot_points(
    trials: Sequence[optuna.trial.FrozenTrial],
    n_metrics: int,
    pareto_numbers: set[int],
) -> tuple[list[list[float]], list[int]]:
    values: list[list[float]] = []
    pareto_indexes: list[int] = []

    for trial in trials:
        trial_values = list(trial.values or ([] if trial.value is None else [trial.value]))
        if len(trial_values) != n_metrics:
            continue
        if trial.number in pareto_numbers:
            pareto_indexes.append(len(values))
        values.append([float(value) for value in trial_values])

    return values, pareto_indexes
🤖 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 `@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/artifacts.py`
around lines 62 - 64, Update the plotting preparation around _trial_values and
pareto_indexes to use one filtered pass over study.trials, retaining only
complete trials with exactly len(metric_names) values. Build values and append
each Pareto trial’s index based on the filtered values list position, then use
both results for plotting so skipped trials cannot shift Pareto indexes.
🧹 Nitpick comments (3)
plugins/nemo-optimization/src/nemo_optimization/backends/optuna/fabric_trial.py (1)

47-59: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Drop the redundant isinstance re-checks on fabric_eval.

Line 47 already guarantees fabric_eval is a Mapping (or {}). The isinstance(fabric_eval, Mapping) guards on Lines 54, 56, and 58 can never be false.

♻️ Proposed change
-        fabric_eval = self._eval_config.get("fabric") if isinstance(self._eval_config.get("fabric"), Mapping) else {}
+        raw_fabric = self._eval_config.get("fabric")
+        fabric_eval: Mapping[str, Any] = raw_fabric if isinstance(raw_fabric, Mapping) else {}
         run_hook_spec = self._eval_config.get("run_hook")
         try:
             self._task_hook = load_fabric_task_hook(run_hook_spec if isinstance(run_hook_spec, Mapping) else None)
         except FabricTaskHookLoadError as exc:
             raise StudyDriverError(str(exc)) from exc
-        self._fabric_base_dir = _optional_path(
-            fabric_eval.get("base_dir") if isinstance(fabric_eval, Mapping) else None
-        )
-        self._timeout_s = int(fabric_eval.get("timeout_s", 600) if isinstance(fabric_eval, Mapping) else 600)
-        self._capture_trajectory = bool(
-            fabric_eval.get("capture_trajectory", True) if isinstance(fabric_eval, Mapping) else True
-        )
+        self._fabric_base_dir = _optional_path(fabric_eval.get("base_dir"))
+        self._timeout_s = int(fabric_eval.get("timeout_s", 600))
+        self._capture_trajectory = bool(fabric_eval.get("capture_trajectory", True))
🤖 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
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/fabric_trial.py`
around lines 47 - 59, Remove the redundant isinstance(fabric_eval, Mapping)
checks in the _fabric_base_dir, _timeout_s, and _capture_trajectory
initialization within the constructor. Use fabric_eval directly for these .get
calls, preserving the existing defaults and behavior.
plugins/nemo-agents/tests/unit/test_optimize_skills_analyze_only.py (1)

231-251: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add return and parameter type hints.

The repository guideline requires concrete type hints. _agents_cli_with_jobs has no return type and _guard_message has an untyped result parameter.

♻️ Proposed change
-def _agents_cli_with_jobs():
+def _agents_cli_with_jobs() -> typer.Typer:
-def _guard_message(result) -> str:
+def _guard_message(result: Result) -> str:

Import typer and from click.testing import Result at module scope.

As per coding guidelines: "Prefer concrete type hints over string-based type hints".

🤖 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 `@plugins/nemo-agents/tests/unit/test_optimize_skills_analyze_only.py` around
lines 231 - 251, Update _agents_cli_with_jobs with a concrete return type and
annotate _guard_message’s result parameter with click.testing.Result; add the
required module-level imports for these types, including typer if needed for the
CLI return annotation, while preserving both helpers’ behavior.

Source: Coding guidelines

plugins/nemo-optimization/src/nemo_optimization/backends/optuna/backend.py (1)

89-89: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Annotate result and output_dir.

_study_debug_payload(result) and _build_trial_evaluator(..., output_dir) have untyped parameters and _build_trial_evaluator has no return type. Use the concrete study-result type and Path.

As per coding guidelines: "Prefer concrete type hints over string-based type hints".

Also applies to: 119-125

🤖 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 `@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/backend.py`
at line 89, Update _study_debug_payload to annotate result with the concrete
study-result type, and update _build_trial_evaluator to annotate output_dir as
Path and add its concrete return type. Use direct imported type hints rather
than string-based annotations, preserving the existing behavior.

Source: Coding guidelines

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

Inline comments:
In `@plugins/nemo-agents/tests/unit/usage/test_usage_cli.py`:
- Around line 204-216: Update
test_usage_show_unreadable_result_json_exits_cleanly to mock the parser’s
file-read operation so it raises PermissionError instead of relying on
chmod(0o000); preserve the existing runner invocation and CLI assertions
unchanged.

In
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/fabric_trial.py`:
- Line 62: Update the parallelism initialization in the trial setup to validate
that the eval_config “general” value is a mapping before reading
max_concurrency. Reuse the existing validation pattern from the guard around
line 240, and raise StudyDriverError for null or non-mapping values instead of
calling .get on them.

In
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/selection.py`:
- Around line 42-44: Update the harmonic branch in the selection logic around
normalized_mode to compute the harmonic mean over utilities (1 - norm), then
select the trial with the maximum utility harmonic mean instead of minimizing
hmean(norm). Add a regression test covering [0.0, 1.0] versus [0.4, 0.4],
asserting the balanced compromise is selected.

In `@plugins/nemo-optimization/tests/smoke_fabric_optimize_atif.py`:
- Around line 130-131: Update the assertion message immediately after
constructing atif_path to reference the same trace_ref used to create and
validate that path, rather than the stale entry loop variable. Keep the is_file
assertion behavior unchanged.

---

Outside diff comments:
In `@plugins/nemo-optimization/examples/hermes-optimize/README.md`:
- Around line 203-217: Add a final “Next Steps” section after “Notes” in the
README, including cross-links to the related Optimize Agents documentation. Keep
the existing Notes content unchanged and use the repository’s established
documentation link targets where available.

---

Duplicate comments:
In `@plugins/nemo-optimization/examples/hermes-optimize/README.md`:
- Around line 71-114: Update the “Clean chat-only run” documentation and the
corresponding recipe section around the referenced later block to wrap each
CLI/Python SDK pair in the repository’s supported tab-set format. Replace the
repeated standalone CLI and Python SDK headings with tab labels consistent with
existing tabbed documentation, while preserving both command and SDK examples
unchanged.

In
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/artifacts.py`:
- Around line 62-64: Update the plotting preparation around _trial_values and
pareto_indexes to use one filtered pass over study.trials, retaining only
complete trials with exactly len(metric_names) values. Build values and append
each Pareto trial’s index based on the filtered values list position, then use
both results for plotting so skipped trials cannot shift Pareto indexes.

---

Nitpick comments:
In `@plugins/nemo-agents/tests/unit/test_optimize_skills_analyze_only.py`:
- Around line 231-251: Update _agents_cli_with_jobs with a concrete return type
and annotate _guard_message’s result parameter with click.testing.Result; add
the required module-level imports for these types, including typer if needed for
the CLI return annotation, while preserving both helpers’ behavior.

In `@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/backend.py`:
- Line 89: Update _study_debug_payload to annotate result with the concrete
study-result type, and update _build_trial_evaluator to annotate output_dir as
Path and add its concrete return type. Use direct imported type hints rather
than string-based annotations, preserving the existing behavior.

In
`@plugins/nemo-optimization/src/nemo_optimization/backends/optuna/fabric_trial.py`:
- Around line 47-59: Remove the redundant isinstance(fabric_eval, Mapping)
checks in the _fabric_base_dir, _timeout_s, and _capture_trajectory
initialization within the constructor. Use fabric_eval directly for these .get
calls, preserving the existing defaults and behavior.
🪄 Autofix

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: CHILL

Plan: Enterprise

Run ID: 3851d6b3-65bb-459f-b436-6506f341d4ec

📥 Commits

Reviewing files that changed from the base of the PR and between 9fa8b8a and d7d4657.

⛔ Files ignored due to path filters (12)
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/__init__.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/agent_eval/runtimes/fabric/hook_loading.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/agent_eval/runtimes/fabric/hooks.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/agent_eval/runtimes/fabric/hooks_mcp_binding.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/agent_eval/runtimes/fabric/runtime.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/enums.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/metrics/tunable_rag_defaults.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/metrics/tunable_rag_evaluator.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/metrics/types.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/values/__init__.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/values/metrics.py is excluded by !sdk/**
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (93)
  • docs/agents/index.mdx
  • docs/agents/optimization.mdx
  • packages/nemo_evaluator_sdk/pyproject.toml
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/__init__.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hook_loading.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hooks.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hooks_mcp_binding.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/runtime.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/enums.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/tunable_rag_defaults.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/tunable_rag_evaluator.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/types.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/__init__.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/metrics.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_hook_loading.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_runtime.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_mcp_run_binding_hook.py
  • packages/nemo_evaluator_sdk/tests/metrics/test_tunable_rag_evaluator.py
  • packages/nemo_platform/pyproject.toml
  • packages/nemo_platform_plugin/tests/test_dispatcher.py
  • plugins/nemo-agents/openapi/openapi.yaml
  • plugins/nemo-agents/pyproject.toml
  • plugins/nemo-agents/src/nemo_agents_plugin/cli.py
  • plugins/nemo-agents/src/nemo_agents_plugin/jobs/optimize_agent.py
  • plugins/nemo-agents/src/nemo_agents_plugin/leaderboard/render.py
  • plugins/nemo-agents/src/nemo_agents_plugin/service.py
  • plugins/nemo-agents/src/nemo_agents_plugin/utils.py
  • plugins/nemo-agents/tests/unit/test_cli.py
  • plugins/nemo-agents/tests/unit/test_improvement_jobs.py
  • plugins/nemo-agents/tests/unit/test_optimize_agent_job.py
  • plugins/nemo-agents/tests/unit/test_optimize_skills_analyze_only.py
  • plugins/nemo-agents/tests/unit/test_service.py
  • plugins/nemo-agents/tests/unit/test_utils.py
  • plugins/nemo-agents/tests/unit/usage/test_usage_cli.py
  • plugins/nemo-deployments/src/nemo_deployments_plugin/backends/docker/backend.py
  • plugins/nemo-deployments/src/nemo_deployments_plugin/backends/docker/gpu.py
  • plugins/nemo-deployments/tests/unit/backends/docker/test_gpu.py
  • plugins/nemo-optimization/README.md
  • plugins/nemo-optimization/examples/hermes-optimize/.gitignore
  • plugins/nemo-optimization/examples/hermes-optimize/README.md
  • plugins/nemo-optimization/examples/hermes-optimize/agent.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/analyzer.inference-api.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/dataset-phishing.json
  • plugins/nemo-optimization/examples/hermes-optimize/dataset.json
  • plugins/nemo-optimization/examples/hermes-optimize/optimize.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/package.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/phishing.optimize.fabric-chatonly.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/phishing.optimize.fabric-mcp.e2e.yaml
  • plugins/nemo-optimization/pyproject.toml
  • plugins/nemo-optimization/src/nemo_optimization/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/agents.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/ga/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/ga/backend.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/artifacts.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/atif_metadata.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/backend.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/config_overlay.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/early_stop.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/fabric_trial.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/search_space.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/selection.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/study_driver.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/protocol.py
  • plugins/nemo-optimization/src/nemo_optimization/config.py
  • plugins/nemo-optimization/src/nemo_optimization/fabric.py
  • plugins/nemo-optimization/src/nemo_optimization/jobs/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/jobs/optimize.py
  • plugins/nemo-optimization/src/nemo_optimization/preflight.py
  • plugins/nemo-optimization/src/nemo_optimization/registry.py
  • plugins/nemo-optimization/src/nemo_optimization/router.py
  • plugins/nemo-optimization/src/nemo_optimization/schemas/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/schemas/optimize.py
  • plugins/nemo-optimization/src/nemo_optimization/tasks/__init__.py
  • plugins/nemo-optimization/src/nemo_optimization/tasks/optimize.py
  • plugins/nemo-optimization/tests/conftest.py
  • plugins/nemo-optimization/tests/smoke_fabric_optimize_atif.py
  • plugins/nemo-optimization/tests/test_atif_metadata.py
  • plugins/nemo-optimization/tests/test_config_overlay.py
  • plugins/nemo-optimization/tests/test_fabric.py
  • plugins/nemo-optimization/tests/test_fabric_trial.py
  • plugins/nemo-optimization/tests/test_optimize_job.py
  • plugins/nemo-optimization/tests/test_router.py
  • plugins/nemo-optimization/tests/test_search_space.py
  • plugins/nemo-optimization/tests/test_selection.py
  • plugins/nemo-optimization/tests/test_study_driver.py
  • pyproject.toml
  • services/core/models/src/nmp/core/models/controllers/backends/deployments_plugin/compiler.py
  • services/core/models/tests/unit/controllers/backends/deployments_plugin/test_compiler.py
  • third_party/licenses.jsonl
  • third_party/osv-licenses.json
  • third_party/requirements-main.txt
💤 Files with no reviewable changes (3)
  • plugins/nemo-agents/src/nemo_agents_plugin/jobs/optimize_agent.py
  • plugins/nemo-agents/tests/unit/test_optimize_agent_job.py
  • plugins/nemo-agents/tests/unit/test_utils.py
🚧 Files skipped from review as they are similar to previous changes (71)
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/init.py
  • packages/nemo_evaluator_sdk/pyproject.toml
  • plugins/nemo-agents/tests/unit/test_service.py
  • pyproject.toml
  • packages/nemo_platform_plugin/tests/test_dispatcher.py
  • plugins/nemo-optimization/examples/hermes-optimize/dataset.json
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/init.py
  • services/core/models/src/nmp/core/models/controllers/backends/deployments_plugin/compiler.py
  • plugins/nemo-optimization/src/nemo_optimization/init.py
  • plugins/nemo-agents/tests/unit/test_improvement_jobs.py
  • plugins/nemo-agents/src/nemo_agents_plugin/leaderboard/render.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_hook_loading.py
  • plugins/nemo-optimization/tests/test_search_space.py
  • plugins/nemo-optimization/examples/hermes-optimize/package.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/analyzer.inference-api.yaml
  • plugins/nemo-optimization/examples/hermes-optimize/dataset-phishing.json
  • plugins/nemo-optimization/examples/hermes-optimize/phishing.optimize.fabric-mcp.e2e.yaml
  • plugins/nemo-deployments/src/nemo_deployments_plugin/backends/docker/backend.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/atif_metadata.py
  • plugins/nemo-agents/src/nemo_agents_plugin/utils.py
  • plugins/nemo-optimization/README.md
  • plugins/nemo-optimization/examples/hermes-optimize/optimize.yaml
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/values/metrics.py
  • third_party/licenses.jsonl
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_runtime.py
  • plugins/nemo-optimization/examples/hermes-optimize/.gitignore
  • plugins/nemo-optimization/tests/test_selection.py
  • plugins/nemo-agents/src/nemo_agents_plugin/cli.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/init.py
  • plugins/nemo-optimization/pyproject.toml
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/enums.py
  • plugins/nemo-agents/src/nemo_agents_plugin/service.py
  • plugins/nemo-optimization/examples/hermes-optimize/agent.yaml
  • plugins/nemo-optimization/src/nemo_optimization/backends/ga/backend.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/init.py
  • plugins/nemo-deployments/src/nemo_deployments_plugin/backends/docker/gpu.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hooks.py
  • plugins/nemo-optimization/src/nemo_optimization/agents.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hook_loading.py
  • plugins/nemo-optimization/src/nemo_optimization/config.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/ga/init.py
  • plugins/nemo-optimization/src/nemo_optimization/jobs/init.py
  • packages/nemo_platform/pyproject.toml
  • plugins/nemo-optimization/src/nemo_optimization/tasks/init.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/tunable_rag_defaults.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/tunable_rag_evaluator.py
  • plugins/nemo-optimization/tests/test_config_overlay.py
  • plugins/nemo-optimization/tests/test_atif_metadata.py
  • plugins/nemo-optimization/src/nemo_optimization/schemas/init.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/metrics/types.py
  • plugins/nemo-optimization/src/nemo_optimization/schemas/optimize.py
  • docs/agents/optimization.mdx
  • plugins/nemo-optimization/src/nemo_optimization/tasks/optimize.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/protocol.py
  • plugins/nemo-optimization/examples/hermes-optimize/phishing.optimize.fabric-chatonly.yaml
  • plugins/nemo-optimization/tests/test_fabric.py
  • plugins/nemo-agents/pyproject.toml
  • plugins/nemo-optimization/tests/test_optimize_job.py
  • plugins/nemo-optimization/src/nemo_optimization/registry.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/early_stop.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/config_overlay.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/hooks_mcp_binding.py
  • plugins/nemo-optimization/tests/test_router.py
  • plugins/nemo-optimization/src/nemo_optimization/fabric.py
  • plugins/nemo-optimization/src/nemo_optimization/preflight.py
  • plugins/nemo-deployments/tests/unit/backends/docker/test_gpu.py
  • third_party/requirements-main.txt
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/search_space.py
  • plugins/nemo-optimization/src/nemo_optimization/router.py
  • plugins/nemo-optimization/src/nemo_optimization/backends/optuna/study_driver.py
  • plugins/nemo-optimization/src/nemo_optimization/jobs/optimize.py
🛑 Comments failed to post (1)
plugins/nemo-agents/tests/unit/usage/test_usage_cli.py (1)

204-216: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Make the unreadable-file test deterministic.

chmod(0o000) does not block reads by root and is not portable to Windows. The test can succeed instead of exercising UsageParseError.

Patch the parser file-read operation to raise PermissionError. Keep the CLI assertion unchanged.

🤖 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 `@plugins/nemo-agents/tests/unit/usage/test_usage_cli.py` around lines 204 -
216, Update test_usage_show_unreadable_result_json_exits_cleanly to mock the
parser’s file-read operation so it raises PermissionError instead of relying on
chmod(0o000); preserve the existing runner invocation and CLI assertions
unchanged.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

>
Signed-off-by: Sam Oluwalana <soluwalana@nvidia.com>
Signed-off-by: Sam Oluwalana <soluwalana@nvidia.com>
Signed-off-by: Sam O <soluwalana@nvidia.com>
Signed-off-by: Sam O <soluwalana@nvidia.com>
Signed-off-by: Sam Oluwalana <soluwalana@nvidia.com>
Signed-off-by: Sam O <soluwalana@nvidia.com>
>
Signed-off-by: Sam Oluwalana <soluwalana@nvidia.com>
Signed-off-by: Sam Oluwalana <soluwalana@nvidia.com>
Signed-off-by: Sam Oluwalana <soluwalana@nvidia.com>
0.0.19 dropped MontyRepl, which breaks pydantic-ai-harness 0.3.0 and
cascades into insights/auth unit test failures.

Signed-off-by: Sam Oluwalana <soluwalana@nvidia.com>
Signed-off-by: Sam O <soluwalana@nvidia.com>
Signed-off-by: Sam Oluwalana <soluwalana@nvidia.com>
Signed-off-by: Sam O <soluwalana@nvidia.com>
Signed-off-by: Sam Oluwalana <soluwalana@nvidia.com>
Signed-off-by: Sam O <soluwalana@nvidia.com>
Signed-off-by: Sam O <soluwalana@nvidia.com>
Signed-off-by: Sam Oluwalana <soluwalana@nvidia.com>
@gabwow

gabwow commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

/nvskills-ci

@gabwow

gabwow commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

/nvskills-ci

Signed-off-by: Sam Oluwalana <soluwalana@nvidia.com>
@soluwalana
soluwalana added this pull request to the merge queue Aug 6, 2026
Merged via the queue into main with commit 9dd75ca Aug 6, 2026
54 checks passed
@soluwalana
soluwalana deleted the aalgo-277/solu branch August 6, 2026 02:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants