Skip to content

feat(evaluator): Harbor runner target + agent-eval job list & create-serialization fixes - #723

Merged
SandyChapman merged 3 commits into
mainfrom
harbor-runner-target-and-evaluator-fixes/schapman
Jul 21, 2026
Merged

feat(evaluator): Harbor runner target + agent-eval job list & create-serialization fixes#723
SandyChapman merged 3 commits into
mainfrom
harbor-runner-target-and-evaluator-fixes/schapman

Conversation

@SandyChapman

@SandyChapman SandyChapman commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Three related changes to the evaluator plugin's agent-eval path:

1. Harbor runner target (feature)

  • Adds HarborRunnerTarget to the agent-eval runner-target union and wires it through _resolve_target (native HarborAgentTaskRunner, jobs_dir injected from job storage) and result-entity trait extraction (also fills in the previously-missing Fabric trait branch).
  • Declares a marker-gated harbor extra on nemo-evaluator-sdk: harbor = ["harbor>=0.16.1; python_version >= '3.12'"]. Harbor requires Python ≥3.12; the marker scopes it to the 3.12 slice of the universal lock so pip install nemo-evaluator-sdk[harbor] works on 3.12 while the workspace floor stays 3.11 (no floor bump). harbor stays lazily imported, so importing the SDK / resolving a Harbor target is valid on 3.11 — only executing a run needs the extra.

2. Mixed-job list-endpoint 500 (bug fix — reported by Studio)

The evaluator plugin owns two job types (evaluate + agent-evaluate) that shared one source tag. The list endpoints filter by source, so in a workspace with both, each collection returned the other type's records and 500'd rendering the foreign spec (dozens of validation errors). Fix: give AgentEvalJob a distinct source via add_job_routes(service_name=AGENT_EVAL_JOB_SOURCE). EvaluateJob keeps its derived nemo-evaluator source so existing records still match.

Pre-GA caveat: agent-evaluate records persisted before this change keep the old shared source and will still cross-render into the evaluate list until re-sourced. agent-evaluate is pre-GA with negligible persisted data, so no migration ships here (documented in service.py).

3. Plugin job create serialization for bytes-bearing specs (latent bug fix)

The shared job factory coerced the transformed spec with model_dump() (python mode), leaving raw bytes (e.g. an inline cloudpickle metric bundle) that the typed jobs client couldn't JSON-encode — PydanticSerializationError: invalid utf-8 on the \x80 pickle marker. Fix: dump mode="json" so nested payload models' ser_json_bytes="base64" runs and the blob round-trips. This is in the shared api_factory, so it fixes create for any plugin/job type whose spec carries bytes. (Latent because the opt-in E2E suite that exercises it isn't in CI.)

Testing

  • Unit: Harbor resolve/compile/run_local (faked evaluator) across target types; harbor/fabric result traits; distinct-source list-filter forwarding; nemo-evaluator-sdk source distinctness; create-path bytes-serialization regression driving the real POST /jobs route.
  • Integration (opt-in): mixed-job list partitioning against a live subprocess platform; a real Docker-backed Harbor e2e via NemoJobScheduler().run_local(...) (gated on harbor + Docker; oracle solves hello-world, reward 1.0 persisted).
  • Validated on both Python 3.11 (CI's default) and 3.12.13; uv lock --check clean; ruff + ty clean for changed files.

Follow-up

  • AALGO-343 (related) — Harbor targets under containerized job backends (docker/k8s). Harbor works via the host daemon (in-process run_local / subprocess backend) but not inside the cpu-tasks container; direction is to route Harbor at a remote/k8s sandbox rather than plugin-side DinD.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added agent-evaluation support for Harbor runner targets (agent selection, model overlays, execution/retry/concurrency settings, artifacts/traces, and reward scoring).
    • Updated OpenAPI to expose Harbor runner targets in both the input and canonical spec.
  • Bug Fixes
    • Improved job-spec JSON transport for create requests containing binary payloads (safe encoding for round-tripping).
    • Isolated agent-evaluation job listing to prevent cross-type validation/rendering.
  • Tests
    • Added unit and integration coverage for Harbor target resolution, persistence mapping, mixed listing behavior, and local Harbor execution.

@SandyChapman
SandyChapman requested review from a team as code owners July 16, 2026 14:29
@github-actions github-actions Bot added the feat label Jul 16, 2026
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: d46fa914-cc2b-4999-a197-d34b4101a23c

📥 Commits

Reviewing files that changed from the base of the PR and between 5afb9ce and eb90d2e.

📒 Files selected for processing (1)
  • plugins/nemo-evaluator/tests/integration/test_harbor_plugin_run.py

📝 Walkthrough

Walkthrough

Adds Harbor-backed agent evaluation targets and runtime wiring, separates agent-evaluate job records, adds Harbor execution coverage, and validates JSON-mode serialization of byte-containing job specifications.

Changes

Harbor evaluation integration

Layer / File(s) Summary
Harbor target contract and runtime
plugins/nemo-evaluator/src/nemo_evaluator/jobs/agent_spec.py, plugins/nemo-evaluator/src/nemo_evaluator/jobs/agent_evaluate.py, plugins/nemo-evaluator/openapi/openapi.yaml, packages/nemo_evaluator_sdk/pyproject.toml
Adds HarborRunnerTarget, exposes it in OpenAPI, enables the Python 3.12+ optional dependency, and resolves Harbor settings into HarborAgentTaskRunner.
Agent-evaluate record identity and persistence
plugins/nemo-evaluator/src/nemo_evaluator/service.py, plugins/nemo-evaluator/src/nemo_evaluator/jobs/result_persistence.py
Uses a distinct agent-evaluate source tag and persists Fabric and Harbor target traits.
Harbor and mixed-job validation
plugins/nemo-evaluator/tests/test_agent_evaluate.py, plugins/nemo-evaluator/tests/test_result_persistence.py, plugins/nemo-evaluator/tests/integration/*
Covers target resolution, compilation, local and real Harbor execution, reward persistence, target metadata, and endpoint separation.

Created job serialization

Layer / File(s) Summary
JSON-compatible create requests
packages/nemo_platform_plugin/src/nemo_platform_plugin/jobs/api_factory.py, packages/nemo_platform_plugin/tests/test_jobs_filter.py
Documents JSON-mode specification dumping and verifies base64 serialization of byte payloads in create requests.

Sequence Diagram(s)

sequenceDiagram
  participant AgentEvalJob
  participant HarborAgentTaskRunner
  participant HarborRuntimeConfig
  participant LocalJobResults
  AgentEvalJob->>HarborAgentTaskRunner: resolve HarborRunnerTarget
  AgentEvalJob->>HarborRuntimeConfig: configure Harbor runtime
  HarborAgentTaskRunner->>LocalJobResults: persist evaluation artifacts and reward scores
Loading

Possibly related PRs

Suggested labels: fix

Suggested reviewers: ngoncharenko, arpitsardhana

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 35.00% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main Harbor support, list endpoint, and serialization fixes in the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch harbor-runner-target-and-evaluator-fixes/schapman

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: 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-evaluator/src/nemo_evaluator/service.py`:
- Around line 52-55: Update the agent-evaluate setup around add_job_routes and
AGENT_EVAL_JOB_SOURCE to include a migration or re-sourcing path for existing
agent-evaluate records currently tagged nemo-evaluator. Ensure legacy records
are moved to the dedicated agent-evaluate source before relying on the new
source partition, while preserving EvaluateJob’s derived nemo-evaluator source.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 70cf17da-2486-411d-bce3-0377229079a5

📥 Commits

Reviewing files that changed from the base of the PR and between 1a0589b and 22941af.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (11)
  • packages/nemo_evaluator_sdk/pyproject.toml
  • packages/nemo_platform_plugin/src/nemo_platform_plugin/jobs/api_factory.py
  • packages/nemo_platform_plugin/tests/test_jobs_filter.py
  • plugins/nemo-evaluator/src/nemo_evaluator/jobs/agent_evaluate.py
  • plugins/nemo-evaluator/src/nemo_evaluator/jobs/agent_spec.py
  • plugins/nemo-evaluator/src/nemo_evaluator/jobs/result_persistence.py
  • plugins/nemo-evaluator/src/nemo_evaluator/service.py
  • plugins/nemo-evaluator/tests/integration/test_agent_evaluate_job.py
  • plugins/nemo-evaluator/tests/integration/test_harbor_plugin_run.py
  • plugins/nemo-evaluator/tests/test_agent_evaluate.py
  • plugins/nemo-evaluator/tests/test_result_persistence.py

Comment thread plugins/nemo-evaluator/src/nemo_evaluator/service.py
@github-actions

github-actions Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor
Suite Lines Covered Line Rate Branch Rate
Unit Tests 26387/34035 77.5% 61.8%
Integration Tests 15176/32660 46.5% 18.7%

Comment thread plugins/nemo-evaluator/src/nemo_evaluator/jobs/agent_spec.py
SandyChapman and others added 2 commits July 20, 2026 17:16
…create serialization

Add HarborRunnerTarget to the agent-eval runner-target union and wire it through
_resolve_target (native HarborAgentTaskRunner, jobs_dir injected from job storage)
and result-entity trait extraction. Declare a marker-gated `harbor` extra on
nemo-evaluator-sdk (`harbor>=0.16.1; python_version >= '3.12'`) so it installs on
3.12 without raising the 3.11 workspace floor; harbor stays lazily imported.

Fix a 500 on the agent-evaluate/evaluate job list endpoints in a mixed workspace:
the evaluator plugin owns two job types that shared one `source` tag, so each
collection's list returned the other type's records and 500'd rendering the foreign
spec. Give AgentEvalJob a distinct source via `add_job_routes(service_name=...)`;
EvaluateJob keeps its derived source (existing records still match).

Fix plugin job create for bytes-bearing specs (inline cloudpickle metric bundles):
the factory coerced the transformed spec with model_dump() (python mode), leaving
raw bytes the typed client couldn't JSON-encode (invalid utf-8 on the pickle
marker). Dump mode="json" so nested payload models base64-encode and round-trip.

Tests: Harbor resolve/compile/run_local unit coverage plus a real Docker-backed
plugin e2e via NemoJobScheduler().run_local (gated on harbor + docker); mixed-job
list partitioning against a live platform; and a create-path bytes-serialization
regression driving the real POST /jobs route.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Sandy Chapman <schapman@nvidia.com>
The HarborRunnerTarget added to the agent-eval Target union flows into the
evaluator plugin's OpenAPI spec (consumed by the web SDK generation check).
Regenerated via 'make refresh-openapi'; no web SDK TS diff results.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Sandy Chapman <schapman@nvidia.com>
@SandyChapman
SandyChapman force-pushed the harbor-runner-target-and-evaluator-fixes/schapman branch from e87ad66 to 5afb9ce Compare July 20, 2026 20:18
@SandyChapman
SandyChapman enabled auto-merge July 20, 2026 20:18

@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

🤖 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-evaluator/openapi/openapi.yaml`:
- Around line 3152-3196: Update the OpenAPI schema properties agent_name,
agent_import_path, agent_model_name, and trace_dir to accept both string and
null values, matching their str | None definitions in agent_spec.py. Preserve
their existing descriptions, defaults, and other validation settings while
adding the nullable type alternative.

In `@plugins/nemo-evaluator/tests/integration/test_harbor_plugin_run.py`:
- Around line 43-46: Update _docker_available to pass a short timeout to the
subprocess.run Docker probe, and catch subprocess.TimeoutExpired to return
False. Preserve the existing unavailable result for missing Docker or nonzero
docker info exit codes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: b511b381-b580-4a74-91e5-144a7446e5d3

📥 Commits

Reviewing files that changed from the base of the PR and between 22941af and 5afb9ce.

📒 Files selected for processing (12)
  • packages/nemo_evaluator_sdk/pyproject.toml
  • packages/nemo_platform_plugin/src/nemo_platform_plugin/jobs/api_factory.py
  • packages/nemo_platform_plugin/tests/test_jobs_filter.py
  • plugins/nemo-evaluator/openapi/openapi.yaml
  • plugins/nemo-evaluator/src/nemo_evaluator/jobs/agent_evaluate.py
  • plugins/nemo-evaluator/src/nemo_evaluator/jobs/agent_spec.py
  • plugins/nemo-evaluator/src/nemo_evaluator/jobs/result_persistence.py
  • plugins/nemo-evaluator/src/nemo_evaluator/service.py
  • plugins/nemo-evaluator/tests/integration/test_agent_evaluate_job.py
  • plugins/nemo-evaluator/tests/integration/test_harbor_plugin_run.py
  • plugins/nemo-evaluator/tests/test_agent_evaluate.py
  • plugins/nemo-evaluator/tests/test_result_persistence.py
🚧 Files skipped from review as they are similar to previous changes (7)
  • plugins/nemo-evaluator/src/nemo_evaluator/service.py
  • plugins/nemo-evaluator/src/nemo_evaluator/jobs/agent_evaluate.py
  • packages/nemo_evaluator_sdk/pyproject.toml
  • plugins/nemo-evaluator/src/nemo_evaluator/jobs/agent_spec.py
  • plugins/nemo-evaluator/src/nemo_evaluator/jobs/result_persistence.py
  • plugins/nemo-evaluator/tests/test_agent_evaluate.py
  • packages/nemo_platform_plugin/tests/test_jobs_filter.py

Comment thread plugins/nemo-evaluator/openapi/openapi.yaml
Comment thread plugins/nemo-evaluator/tests/integration/test_harbor_plugin_run.py Outdated
A wedged Docker daemon could make the 'docker info' skip probe hang until
the test-level timeout. Pass a short timeout and treat TimeoutExpired as
Docker unavailable so the test skips cleanly instead of blocking.

Signed-off-by: Sandy Chapman <schapman@nvidia.com>
@SandyChapman
SandyChapman added this pull request to the merge queue Jul 21, 2026
Merged via the queue into main with commit c1ec34a Jul 21, 2026
60 checks passed
@SandyChapman
SandyChapman deleted the harbor-runner-target-and-evaluator-fixes/schapman branch July 21, 2026 11:18
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