Skip to content

feat(tier3): upgrade Harbor to 0.24.0 - #83

Merged
rng1995 merged 43 commits into
mainfrom
feat/christopherk/issue-79-harbor-upgrade
Oct 6, 2026
Merged

rng1995 merged 43 commits into
mainfrom
feat/christopherk/issue-79-harbor-upgrade

Conversation

@chrisknvidia

@chrisknvidia chrisknvidia commented Aug 26, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #79

Summary

This PR moves SkillEvaluator's optional Tier 3 backend from Harbor 0.13.2 to Harbor 0.24.0, the current stable release. Release notes: v0.24.0, v0.23.0.

It adapts SkillEvaluator to Harbor's current agent, environment, task, verifier, reward and trajectory contracts, without weakening SkillEvaluator's isolation, credential handling or scoring guarantees.

What changes for users

  • Environments: --env-mode selects any of 23 Harbor-native backends or SkillEvaluator's own local mode.
  • Backend settings: operator-only --environment-kwarg / --ek passes non-secret backend constructor options, with runtime-policy fields reserved.
  • Native tasks: native Harbor tasks (BYOT) support multi-step tasks, step-local tests and Harbor 0.24's separate-verifier rules.
  • Reports: reports keep task selectors, logical case IDs and display names distinct. They carry real token totals and correct attempt accounting, and multimodal tool output is rendered as text.
  • Wandb mode: --env-mode wandb keeps working. It now runs Harbor's merged cwsandbox backend with W&B authentication.
  • Codex: Codex keeps running with reasoning_effort=high, Harbor 0.22's default, so scores stay comparable.

How SkillEvaluator runs Harbor

flowchart LR
    subgraph SE["SkillEvaluator (operator process)"]
        CMD["tier3 evaluate / validate / doctor"] --> STAGE["Stage tasks<br/>generated or native"]
        STAGE --> ENV["Allowlisted child environment<br/>PYTHON_DOTENV_DISABLED=1<br/>HARBOR_TELEMETRY=0"]
        ENV --> RUN["harbor run<br/>from an empty SE-owned directory<br/>absolute paths, --ak / --ek"]
    end
    RUN --> H["Harbor 0.24.0"]
    H --> DOCKER["Hardened Docker<br/>Docker runtime pinned<br/>no SSH stream or GPU reservations"]
    H --> LOCAL["Local mode<br/>Seatbelt or bubblewrap"]
    H --> CLOUD["Harbor-native backends<br/>Daytona, Modal, E2B, ...<br/>wandb runs cwsandbox"]
    DOCKER --> ART["Job and trial artifacts<br/>rewards, ATIF v1.8"]
    LOCAL --> ART
    CLOUD --> ART
    ART --> COL["Collector<br/>identity, rewards, failures"] --> REP["JSON / HTML / Markdown reports"]
Loading

Harbor 0.23 and later load .env.local from their working directory, and Harbor and LiteLLM call load_dotenv() on import. Every Harbor process (runs, runtime preflight, harbor view and the ACK probe) therefore starts in an empty directory that SkillEvaluator owns.

  • Dotenv loading and telemetry are disabled at launch.
  • The tier3 extra now requires python-dotenv 1.2.0, the first release that honors PYTHON_DOTENV_DISABLED.
  • Relative host paths such as KUBECONFIG are anchored, so they keep their meaning.

Changes

Harbor 0.24 integration

  • Pin and lock:
    • harbor==0.24.0 is pinned and locked;
    • the lock change is harbor plus semver 3.1.0;
    • the environment-kwarg table matches the installed Harbor sources, and an AST parity test enforces this.
  • Unified selectors:
    • agents and environments use Harbor's unified --agent / --env flags;
    • --agent-import-path is gone;
    • only the OpenAI-compatible gateway Codex wrapper may run on Harbor-native cloud backends.
  • Codex: every Codex path gets --ak reasoning_effort=high.
  • OpenCode: remote MCP servers set oauth: false, matching Harbor.

Environments

  • Hardened Docker:
    • pins the Docker runtime;
    • reports stream=False and gpus=False;
    • downloads through its own Compose copy path, never Harbor's raw docker cp fallback.
  • Reserved kwargs:
    • stream, enable_environment_dir_upload and the cwsandbox auth selector are reserved;
    • SkillEvaluator sets auth=wandb itself for the alias;
    • Modal's removed modal_sandbox_v2 is rejected.
  • cwsandbox: SkillEvaluator checks the cwsandbox SDK and credentials itself, because Harbor 0.24 removed that preflight.

Native tasks and identity

  • Identity:

    • selectors, logical dataset IDs, display names and structural attempt ordinals stay separate;
    • without a runner-owned selector map, Harbor's persisted task path outranks task names;
    • grader-authored rewards cannot set collector-owned identity fields.
  • Paired-baseline isolation: these are rejected wherever they could contaminate standard grading:

    • skill-controlled setup and healthchecks;
    • prior trajectories;
    • step workdirs and step tests;
    • verifier controls, including task-authored judge retry and evidence-budget values;
    • collect hooks.

    custom_only keeps Harbor-native ownership.

Verifiers and rewards

  • Native tasks follow Harbor 0.24's separate-verifier resolution, shown below.
  • Harbor 0.24 requires numeric reward.json values. SkillEvaluator's verifier and wrapped graders already write them. A native task's own test script must too, and the docs say so.
  • When Harbor records a failure on a step, the failed job now names that exception instead of reporting only a trial count.
flowchart TD
    subgraph Wrapped["Generated tasks, or native tasks with tests/grader.py"]
        EVAL["SE verifier: standard metrics + LLM judges"] --> SIDE["skill_evaluator_reward.json<br/>rich details"]
        GRADER["Custom grader via custom_grader_runner.py"] --> CUST["custom_reward.json"]
        SIDE --> NUM["reward.json: numeric values only"]
        CUST --> NUM
    end
    subgraph Own["custom_only native task with its own test script"]
        SCRIPT["Task test.sh"] --> OWN["reward.json: must be numeric"]
    end
    NUM --> PARSE["Harbor verifier<br/>rejects non-numeric values"]
    OWN --> PARSE
    PARSE --> COLLECT["Collector: numeric keys other than overall become custom metrics<br/>failed jobs name Harbor's recorded exception"]
Loading
flowchart TD
    STEP["Native task step"] --> Q{"Verifier image, or a Dockerfile or<br/>docker-compose.yaml in the step or task tests/?"}
    Q -- yes --> DED["Dedicated verifier<br/>runs its bundled tests/test.sh<br/>never receives SE's grader"]
    Q -- no --> FB["Verifier built from environment/<br/>tests uploaded<br/>Compose model checked against the verifier allowlist"]
    YML["docker-compose.yml only"] --> REJ["Rejected: Harbor ignores .yml"]
Loading

Collection, reports and redaction

  • Collection:
    • accepts Harbor 0.24 job, trial and reward artifacts and ATIF v1.8;
    • multimodal tool output reaches judges and reports as text with [image]/[audio] markers;
    • merged trajectories carry the newest source schema version.
  • Redaction and bounds:
    • diagnostics and artifacts are hardened against credential and URI user-info leakage;
    • report and error payloads are bounded;
    • timeout values must be finite;
    • mixed metric contracts and unavailable telemetry are explicit;
    • short credential-named flags no longer erase counts in summaries.

Merge with current main

Supported environments

Mode Status in this PR
docker Default. Hardened Docker backend. Live-tested on Harbor 0.24.
local SkillEvaluator host mode with an OS sandbox. Live-tested on Harbor 0.24 with OpenCode 1.2.26 and 1.18.34.
daytona, e2b, modal, runloop, langsmith, ec2, gke, ack, openshift, novita, apple-container, singularity, islo, tensorlake, cwsandbox, wandb, use-computer, blaxel, beam, skypilot, hyperbrowser, vercel Selectable with the mapped Harbor extra or system CLI. Credentials and kwargs follow per-backend allowlists. Unit-tested; no live accounts.
kata Added in follow-up #182: hardened Docker with each task service in a Kata microVM.
runta, mosaic Added in follow-up #183.
podman, prime, smol, cua-cloud, opensandbox, hf-sandbox Rejected before a run. These backends need a runtime-aware hardened Compose runner (Podman) or a trusted, published task image.

Verification

Live Harbor 0.24 parity

All four real Harbor paths pass:

  • Provider: NVIDIA Build. Codex and OpenCode run nvidia/nemotron-3-super-120b-a12b, with the default nv_build judges.
  • Host: macOS, Docker 29.8.1, Compose v5.5.1.
  • Code: paths 1, 2 and 4 ran at b17af2a; path 3 ran at 772e764, which differs only in failure messages and docs.
  • Timeout: Docker runs used --timeout-multiplier 2, because Harbor's in-container Codex install took 289–447 s on this network against a 360 s default. Harbor 0.22 installs Codex the same way.
Path Harbor 0.24 result
1. Native BYOT, Docker, Codex, custom_only, --skip-baseline overall=1.0, native_quality=1.0, 1/1 scored. Selector selector-attempt2, logical ID logical-attempt9 and display name publisher/display-attempt7 stayed distinct. Codex ran with model_reasoning_effort=high.
2. Generated dataset via validate --tier3, Docker, Codex, runtime_env + two pre_agent_setup commands, custom_only canary_protocol=1.0, runtime_setup=1.0, 1/1 scored. JSON, HTML and Markdown reports written, with no lift synthesized without a baseline.
3. Native BYOT, local, OpenCode, NVIDIA Build, custom_only Both steps ran and were verified on OpenCode 1.2.26 and 1.18.34, with per-step ATIF and real token totals; 1/1 attempts scored.
4. Generated dataset, Docker, Codex, paired baseline, default_plus_custom Both arms scored with standard and custom metrics; lift +0.02 (0.43 vs 0.41).

After the runs:

  • a sentinel .env.local in the launch directory reached none of the 503 retained files;
  • no exact credential appeared in any retained artifact;
  • no containers or processes were left behind.

The runs found the numeric-reward requirement described above. Details are in the PR comments.

Automated

  • Full suites: Python 3.12 and 3.13 each pass 11,250 tests with 20 skipped at a05e859. All 17 CI checks pass at b17af2a.
  • Harbor 0.24 contract tests:
    • environment-kwarg parity read from Harbor's sources;
    • the wandb alias against Harbor's registry;
    • separate-verifier resolution through Harbor's own resolver;
    • the Docker runtime pin and download routing;
    • a real .env.local sentinel;
    • Codex --ak decoded with Harbor's own parser;
    • ATIF content-part parity between host and verifier template;
    • step-exception diagnostics on failed jobs.
  • Lint and lock: Ruff, git diff --check and uv lock --check pass.
  • Packaging: wheel and sdist build, twine check --strict passes, and the OSS boundary scan passes for the source and both archives.
  • Wheel smoke installs: pass on Python 3.12 and 3.13 with [tier3], and harbor.__version__ == "0.24.0".
  • Runtime container image: builds and runs as uid 10001.
  • Security: Bandit reports no high-severity findings. pip-audit finds nothing new from this PR. The pyjwt, anyio and urllib3 advisories also affect main and are tracked separately.
  • Flaky tests: three timing-sensitive tests each failed once under heavy local load and pass in isolation and in CI:
    • test_streamed_timeout_callback_matches_result_and_contains_descendants;
    • test_slow_drip_request_line_and_headers_obey_an_absolute_deadline;
    • test_bedrock_model_probe_classifies_malformed_effective_proxy_as_fatal.

Remaining verification gaps

  • Managed cloud backends were not exercised, for lack of isolated credentials. The gateway Codex wrapper on cloud backends and the wandb alias are unit-tested only.
  • Native Windows execution was not available; Windows behavior remains fail-closed.

Follow-ups

All commits carry DCO sign-offs. Please do not merge until maintainer review is complete.

🤖 Generated with Claude Code

Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>

@rng1995 rng1995 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Re-reviewed the complete PR at 173bea9 after merging current main and addressing all nine findings. The unsupported cua-cloud, opensandbox, and hf-sandbox modes now fail closed; canonical ranking and custom evidence precedence are aligned; positional compatibility and mode-scoped runtime environment validation are restored; unsafe trial roots retain distinct logical identities; empty Docker environments work; and Compose YAML limits are enforced before object construction. All review threads are resolved, the local full suite passed (7,265 passed, 20 skipped, 9 deselected), release/docs/security checks passed, all 17 GitHub checks are green, and GitHub reports the PR mergeable.

rng1995 and others added 8 commits October 5, 2026 12:48
…ue-79-harbor-upgrade

Bring the Harbor upgrade up to date with main (v0.4.0 and later).

Conflict resolutions:
- Case identity: the runner's trusted selector map stays authoritative.
  Main's staged-task resolver (#161) applies only to callers without a map,
  where task_id.path now outranks task_name. Grader-authored rewards can no
  longer set collector-owned identity flags.
- Agent import paths: only the OpenAI-compatible gateway Codex wrapper
  (#152) may run on Harbor-native cloud backends. It is passed through
  Harbor's unified --agent selector, not the deprecated --agent-import-path.
- Verifier env: under standard grading, native tasks still may not author
  judge retry or evidence-budget values (#145, #160). Operators stage them as
  ${NAME} placeholders, which are forwarded with the other provider controls.
- Native task TOML edits stay structural and Harbor-validated; main's
  line-based helpers are removed.
- Redaction keeps main's linear-time private-key handling and terminal-control
  stripping plus the PR's URI userinfo masking. Whole environment values
  shorter than four characters are no longer exact secrets, so flags such as
  "1" cannot erase counts in result summaries; short URI userinfo fragments
  are still redacted.
- The tier3 workflow (#152) forwards --environment-kwarg to preflight and
  defers remote ack and openshift checks. Parallel catalog children forward
  --environment-kwarg.
- CHANGELOG: the PR's entries move back under Unreleased.

Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Harbor 0.23 and later load `.env.local` from their working directory. Harbor
and LiteLLM also call `load_dotenv()` on import. Before this change, SkillEvaluator
started Harbor in the operator's directory, so a stray dotenv file could
re-add credentials or Docker settings that the allowlisted child environment
had stripped.

Each Harbor process now:
- runs from a fresh, empty, evaluator-owned temporary directory: `harbor run`,
  runtime preflight, `harbor view`, and the ACK readiness probe, which also
  runs with `python -P`;
- gets `PYTHON_DOTENV_DISABLED=1` and `HARBOR_TELEMETRY=0`, applied at launch
  outside the secret-tracked environment so they cannot be overridden;
- receives the dataset and jobs paths, host-path constructor kwargs, and
  path-valued host variables (for example `KUBECONFIG`) anchored to the
  operator's directory, so relative paths keep their meaning.

The `tier3` extra now requires python-dotenv 1.2.0, the first release that
honors `PYTHON_DOTENV_DISABLED`. Prerequisites reject older installs.

Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Harbor's ATIF v1.8 content can be a list of text, image, and audio parts.
Codex tool outputs now arrive in that form. SkillEvaluator flattened such
content with `str()`, so judges, evidence bundles, and reports saw Python
list reprs, including agent-chosen media paths. Dataset refinement also
crashed on list-valued messages.

- A dependency-free `atif_content_text` helper joins text parts and renders
  media as `[image]`/`[audio]` without source paths. It is used by the host
  evidence helpers, the standalone verifier template, dataset generation,
  and runtime-failure detection.
- Merged multi-step and continuation trajectories carry the newest source
  ATIF version (at least v1.7) instead of always claiming v1.7.
- The collector imports Harbor's trajectory model only when validating, so
  `create-eval-dataset --refine` works without the `tier3` extra.
- Tests pin Harbor's verifier and environment-start failure types as
  unscored trials, not agent runtime failures.

Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Harbor's OpenCode agent writes remote MCP servers with `oauth: false`
because headless trials cannot complete an interactive OAuth flow.
SkillEvaluator's NVIDIA Build OpenCode configuration builds the same entries
itself. It now writes the same flag, so a remote MCP server cannot stall a
trial waiting for authorization.

Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Harbor 0.22's Codex agent passed `-c model_reasoning_effort=high` by default.
Harbor 0.23 dropped that default, so Codex would otherwise run at its own,
lower default effort and shift scores and cost relative to the validated
integration.

SkillEvaluator now passes `--ak reasoning_effort=high` whenever the agent is
codex: the stock agent, the NVIDIA Build and gateway wrappers, and local
mode. Runtime preflight builds its command the same way. Claude Code and
OpenCode receive no agent kwargs.

Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Pin the optional Tier 3 backend to Harbor 0.24.0. The lockfile changes only
Harbor and its new `semver` dependency.

Environment contract:
- `HARBOR_VERSION` replaces version-specific names, and the static
  constructor-kwarg table matches Harbor 0.24: new `stream` and
  `enable_environment_dir_upload` base options, cwsandbox `auth`,
  hyperbrowser builder sizing, and tensorlake `dind_image`. Modal's
  `modal_sandbox_v2` is gone.
- Harbor 0.24 merged its W&B sandbox into `cwsandbox`. `--env-mode wandb`
  keeps working as an alias for Harbor `cwsandbox` with `auth=wandb` and the
  existing W&B credential allowlist. Operators cannot set `auth`.
- `stream` (SSH streaming into the sandbox) and
  `enable_environment_dir_upload` are reserved runtime-policy kwargs.
- Harbor 0.24 dropped the cwsandbox preflight. SkillEvaluator now checks the
  SDK and the CwSandbox or W&B credential itself before a run.
- New Harbor backends (podman, kata, runta, prime, mosaic, smol) stay
  unexposed, like cua-cloud, opensandbox, and hf-sandbox.

Separate verifiers follow Harbor 0.24's precedence. A verifier image, or a
Dockerfile or docker-compose.yaml in the step or task tests directory, is a
dedicated verifier that bundles its own tests. Otherwise Harbor builds from
`environment/` and uploads the tests.
- Compose validation now covers the definition Harbor actually builds,
  including the `environment/` fallback, against the verifier allowlist.
- `docker-compose.yml` verifier definitions, which Harbor ignores, are
  rejected.
- In custom_only, every dedicated verifier must ship its own test script,
  and SkillEvaluator's grader is never injected where Harbor would not
  upload it.

Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Harbor 0.24's Docker environment gained a container-runtime abstraction
(Podman), SSH streaming into the sandbox, GPU device reservations, and a raw
`docker cp` fallback for downloads. SkillEvaluator's hardened Docker backend
assumes the Docker CLI and routes every container operation through its
scrubbed, bounded Compose runner. Each of these new paths could bypass that
runner.

The hardened backend now:
- pins its runtime to Docker;
- reports `stream=False` and `gpus=False`, so Harbor refuses stream mode and
  GPU tasks, as it did on Harbor 0.22;
- downloads from the main container through its own Compose copy path, never
  Harbor's raw `docker ps`/`docker cp` fallback.

Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Describe the final Harbor 0.24.0 state under Unreleased:
- the wandb alias and its cwsandbox extra;
- the new reserved and removed backend options;
- Harbor launch isolation and the python-dotenv floor;
- the Codex effort pin;
- separate-verifier precedence;
- multimodal trajectories;
- the redaction and dataset-refinement fixes from the merge.

Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rng1995 rng1995 changed the title feat(tier3): upgrade Harbor to 0.22.0 feat(tier3): upgrade Harbor to 0.24.0 Oct 5, 2026
@rng1995

rng1995 commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator

Update: merged main and upgraded to Harbor 0.24.0 (a05e859)

Merge with main (6bab56e, v0.4.0 and later)

16 files conflicted. collector.py, runner.py and adapter.py were rebuilt function by function rather than hunk by hunk. Decisions:

Harbor 0.24 commits

Commit Change
1d1faee Harbor runs from an empty evaluator-owned directory with PYTHON_DOTENV_DISABLED=1 and HARBOR_TELEMETRY=0 set at launch. Harbor 0.23+ loads <cwd>/.env.local. Covers harbor run, runtime preflight, harbor view and the ACK probe (python -P).
12b0b91 ATIF list content (text, image, audio) is flattened safely. The merged schema version is the newest source. The collector imports Harbor's trajectory model lazily, so --refine works without the tier3 extra.
8ddce18 OpenCode remote MCP entries get oauth: false, matching Harbor.
e49ca89 --ak reasoning_effort=high for every Codex path (Harbor 0.23 dropped the default).
fc6449f Pin and lock 0.24.0. Kwarg table matches the installed Harbor (AST parity test). wandb alias runs cwsandbox with auth=wandb. stream, enable_environment_dir_upload and auth are reserved. SkillEvaluator checks cwsandbox itself. Separate-verifier precedence follows Harbor's resolver. Docs updated.
64fc44f Hardened Docker pins the Docker runtime, reports stream=False and gpus=False, and downloads through its own Compose copy path.
a05e859 CHANGELOG.

Live Harbor 0.24 parity on the four paths in the description is pending an NVIDIA Build credential. Fixtures are prepared and I will post results here.

Gitleaks' generic-api-key rule flags the fake CWSANDBOX_API_KEY value in
tests/test_harbor_environment_contract.py. Gitleaks scans full history,
so scope an exact-value, single-file allowlist like the existing
synthetic Harbor entries, and pin it in the CI workflow test.

Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
chrisknvidia added a commit that referenced this pull request Oct 6, 2026
PR #28 pinned Harbor 0.13.2. Its trajectory conversion drops data the
plugin checks read: Codex per-step tokens (check 25), Claude Code
subagent steps and their MCP calls (checks 18, 19, 22, 24, 28), and
parallel Codex calls in one step (check 18's same-step guard).

This commit carries PR #83's Harbor port (0.13.2 to 0.22, with its
conflicts against the plugin code resolved), then moves on to Harbor
0.24.0 and LiteLLM 1.92+. On top of the port:
- native Claude Code loading knows Harbor's new launch shape;
- Codex runs convert the main thread when the agent spawns a subagent,
  and fold child threads in as sidechain steps;
- the environment kwarg contract and native staging follow 0.24
  (cwsandbox owns the W&B backend; separate-verifier rule).

Fixes proof H4 and the Codex child-rollout part of L26.

Overlap with #180: both sides stopped oversized usage counters and
rewards from aborting collection (#180 b1c3410, 7608e96). The tree
keeps one finite_number() helper and the port's fail-closed reward
rule; the collector's private copy is gone.

This branch is cut per file. collector.py lands here whole, so it also
holds the security attribution (runtime security commit), codex.txt
call pairing (MCP execution), lift arms (lift) and usage (context cost)
hunks; adapter.py holds the agent HOME variables for the verifier;
runner.py holds the long plugin name and MCP input-schema hunks;
metrics.py holds a shared lift basis hunk. PR #83's hunks in
tier3_report.py and cli.py land with the lift and gate commits, and its
docs land in the docs commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
chrisknvidia added a commit that referenced this pull request Oct 6, 2026
…l runs

- The no-skill arm gets no skill_execution or skill_efficiency score.
  Lift compares both arms only on the dimensions both can score, and
  the headline shows that basis (pass@k and mixed metric contracts too).
- One failed trial keeps the interval and the Integration verdict: the
  run is marked partial with "n of m pairs" and names the failed arm.
- The Integration headline and its interval use the same weights, and
  the verdict uses the whole interval.
- Small-sample intervals are widened; "adequate" needs 10 cases.
- Integration-only runs file the members' lift as Integration, never
  as Skill Lift; multi-agent runs get one named block per agent.
- evaluate-plugin, Markdown, HTML and BENCHMARK show one lift on one
  basis, and never a partial one as final.

Fixes proof H5, M10, M12, M13, L18, L24; M4 except the measured-cost
half; M14 except the census-merge half. M4 is partly fixed: a case
missing from the Harbor job itself still drops the arm (the reason now
names the arm).

#180 removed the private _finite_number and _non_negative helpers;
result_display.py and stats.py now call its shared finite_number().

This branch is cut per file. tier3_report.py lands here whole, so it
also holds PR #83's Harbor report hunks, the gate commit's verdict
helpers and the top argument failures (MCP execution). stats.py holds
the measured context cost (context cost commit). markdown.py and
plugin_sections.html.j2 hold small report hunks of most areas. The
no-skill rule in the verifier is in the runtime security commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
chrisknvidia added a commit that referenced this pull request Oct 6, 2026
- Without --block-on-agent-eval, Tier 3 is advisory and BENCHMARK says
  so. With it, a FAIL verdict fails validate (exit 1), INCOMPLETE and
  skipped runs fail, and NEUTRAL does not.
- A lift in the FAIL band warns, and with the flag a confirmed
  regression blocks; the BENCHMARK legend says what the code does.
- Blocking Findings lists only CRITICAL and HIGH, and says how many
  more there are.
- The CLI footer says INCOMPLETE for an INCOMPLETE run.
- Tier 3 cards and dimension verdicts use one set of thresholds, and
  INCOMPLETE runs do not show a security % next to "no baseline".

Fixes proof H1, M15, L4, L5 and the report half of L32.

Overlap with #180: its fix that stops an INCOMPLETE Tier 3 verdict card
from showing green (e65b531, 620e816) is merged with our gate states:
one computed verdict and tone, used by both cards. The template lands
in the Harbor commit.

This branch is cut per file. cli.py lands here whole, so it also holds
PR #83's --environment-kwarg plumbing, evaluate-plugin --policy (MCP
execution), the dependency skip path and repo root (dependencies) and
the content-relative error strings (reports); the golden CLI surface
follows it. benchmark.py and reporting/cli.py hold lift, canary and
coverage lines of other areas.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
chrisknvidia added a commit that referenced this pull request Oct 6, 2026
Brings the docs in line with the fixes in this branch: plugin
evaluation (manifests, inventory, hooks, MCP static policy and
endpoints, dependencies, runtime security, MCP proof, signals, lift,
coverage, context cost, verdicts), the CLI reference, reports, Tier 1
validation, benchmark rollout, and PR #83's Harbor 0.24 docs (Tier 3
live evaluation, agents and sandboxes, configuration, custom graders,
eval datasets).

CHANGELOG: one Unreleased line per user-visible fix, appended at the
end, including the follow-ups from the merge with #180.

Where #180 and this branch edited the same docs row, the rows are
merged: the shell -c row, the floating-version row, the unreadable
manifest paragraph (it still fails closed when nothing parses), and
the reserved plugin MCP servers file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Christopher Kevin <christopherk@nvidia.com>
Harbor 0.24 rejects a reward.json whose top-level values are not all
numbers, raising VerifierOutputParseError on the failing step. For a
multi-step trial it records the exception on the step, leaves the
trial-level exception empty, and still counts the trial as completed,
so the job failed with only "statistics account for 0/1 completed
trials". Append the first trial or step exception Harbor recorded,
using the published trial label and the existing redaction.

Document that a native task's own Harbor test script must write numeric
reward.json values; tests/grader.py keeps SkillEvaluator's richer
reward format because SkillEvaluator wraps it.

Found by the live Harbor 0.24 parity run of path 1.

Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rng1995

rng1995 commented Oct 6, 2026

Copy link
Copy Markdown
Collaborator

Live Harbor 0.24 parity results

All four paths pass on Harbor 0.24.0 through NVIDIA Build. Codex and OpenCode ran nvidia/nemotron-3-super-120b-a12b with the default nv_build judges, on macOS with Docker 29.8.1 and Compose v5.5.1. Paths 1, 2 and 4 ran at b17af2a. Path 3 ran at 772e764, which differs only in failure messages and docs.

Path Result
1. Native BYOT, Docker, Codex, custom_only, --skip-baseline Pass. overall=1.0, native_quality=1.0, 1/1 scored. Selector selector-attempt2, logical ID logical-attempt9 and display name publisher/display-attempt7 stayed distinct. Codex ran with model_reasoning_effort=high.
2. Generated dataset via validate --tier3, Docker, Codex, runtime_env + two pre_agent_setup commands, custom_only, --skip-baseline Pass. canary_protocol=1.0, runtime_setup=1.0, 1/1 scored. JSON, HTML and Markdown reports were written, with no lift synthesized without a baseline. validate exits 1 only because the synthetic skill fails Tier 1 checks.
3. Native BYOT, local (Seatbelt), OpenCode, NVIDIA Build, custom_only Pass on OpenCode 1.2.26 and 1.18.34. Both steps ran and were verified, with per-step ATIF v1.7 and real token totals (for example 37,409/516 and 50,105/440 on 1.2.26), and 1/1 attempts scored. Both scored 0.0 because the model wrote the instruction text instead of alpha; the verifier result is correct.
4. Generated dataset, Docker, Codex, paired baseline, default_plus_custom Pass. Both arms scored (2/2), with standard metrics and the custom canary_protocol merged. Overall was 0.43 with the skill vs 0.41 without (lift +0.02). The judges now return parseable output, which they did not on Harbor 0.22.

Checks

  • A sentinel .env.local and .env in the launch directory reached none of the 503 retained files.
  • An exact-key scan found no NVIDIA_API_KEY match in retained artifacts.
  • No SkillEvaluator containers, Compose projects or processes were left behind.

Found during the runs

  • Harbor 0.24 requires numeric rewards. Harbor now rejects a reward.json with non-numeric values, raising VerifierOutputParseError.
    • A native task's own test script that writes SkillEvaluator's nested custom_metrics format worked on 0.22 and fails on 0.24. tests/grader.py is unaffected because SkillEvaluator wraps it.
    • Harbor records the error on the step and still counts the trial as completed, so the job reported only "statistics account for 0/1 completed trials".
    • b17af2a appends the recorded trial or step exception to that message and documents the rule.
    • My path 1 and 3 test tasks used the nested format; the passing runs use flat rewards.
  • Codex setup time. Harbor's Codex installer took 289–447 s per container on this network: apt nodejs npm, then nvm and npm install -g @openai/codex. That exceeds Harbor's 360 s default. Harbor 0.22 uses the same installer, so this is environmental. The passing Docker runs used --timeout-multiplier 2, which also scales agent setup.
  • Test grader bug. My first path 4 grader merged SkillEvaluator's reward back into its own output, so it overwrote reserved metrics, and SkillEvaluator failed closed as documented. The passing run uses a grader that writes only its custom metric.

@rng1995
rng1995 merged commit b393053 into main Oct 6, 2026
17 checks passed
@rng1995
rng1995 deleted the feat/christopherk/issue-79-harbor-upgrade branch October 6, 2026 17:14
@rng1995 rng1995 mentioned this pull request Oct 6, 2026
11 tasks done
rng1995 added a commit that referenced this pull request Oct 6, 2026
Bring main's v0.5.0 into this branch, including the Harbor 0.24.0
upgrade from #83, and resolve the 40 conflicting files.

This branch had moved plugin evaluation to Harbor 0.24.0 on its own.
Where that work and #83 changed the same code, #83's reviewed version
is kept for Harbor and runtime plumbing, and this branch's
plugin-evaluation work is kept on top:
- runtime: Harbor launches from an evaluator-owned directory with .env
  loading and telemetry off; hardened Docker stays on Docker; failed
  jobs name Harbor's recorded trial or step exception; multimodal ATIF
  content reaches judges and checks as text.
- environments: `--env-mode wandb` is kept as an alias that runs
  cwsandbox with W&B authentication, operators cannot set `--ek auth`,
  and W&B credentials reach only wandb mode.
- collection: grader-written rewards cannot set the collector's
  identity keys; every arm goes through the one collection pipeline.
- verifier: eval.py and eval_core stay byte-identical where shared and
  Python 3.9-compatible.
- CHANGELOG: v0.5.0 reads as released; Unreleased keeps only this
  branch's own entries.

Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
rng1995 added a commit that referenced this pull request Oct 16, 2026
The Unreleased Fixed entry for omitting unmeasured token usage describes
behaviour main shipped in v0.5.0 (#83), and this PR changes no producer; the
second Fixed entry describes the dashboard, which is itself new. Fold both into
one Added entry that names what the dashboard compares, where time and cost come
from, and how inputs are cached.

In the reports guide, describe a performance row and the pairing rule
precisely (same report and agent, dataset digest and attempt policy), drop the
advice to regenerate canonical JSON (no command does that), describe multi-step
trials as v0.5.0 canonical JSON writes them, document the agent_result token
fallback, and list the accepted harness_features forms and their precedence.
Two tests pin the precedence and the accepted forms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
chrisknvidia pushed a commit that referenced this pull request Oct 19, 2026
The Unreleased Fixed entry for omitting unmeasured token usage describes
behaviour main shipped in v0.5.0 (#83), and this PR changes no producer; the
second Fixed entry describes the dashboard, which is itself new. Fold both into
one Added entry that names what the dashboard compares, where time and cost come
from, and how inputs are cached.

In the reports guide, describe a performance row and the pairing rule
precisely (same report and agent, dataset digest and attempt policy), drop the
advice to regenerate canonical JSON (no command does that), describe multi-step
trials as v0.5.0 canonical JSON writes them, document the agent_result token
fallback, and list the accepted harness_features forms and their precedence.
Two tests pin the precedence and the accepted forms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEA]: Upgrade Tier 3 Harbor backend from 0.13.2 to 0.20+

2 participants