fix(harbor): accept artifact destination and exclude from Harbor task.toml - #579
fix(harbor): accept artifact destination and exclude from Harbor task.toml#579ayushnangia wants to merge 3 commits into
Conversation
Harbor ArtifactConfig allows destination (host placement, no verifier-side effect) and exclude (tar --exclude patterns applied when downloading directory artifacts). The adapter rejected both with extra_forbidden, so valid Harbor tasks failed to adapt. Accept destination with Harbor's own validation, and prune excluded entries when staging directory artifacts so the verifier sees what Harbor's verifier would see.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 2f9b01b. Configure here.
|
On the second finding (prune follows symlink artifact roots) — fixed in a537e06 on the branch. The reorder that caused this is now inverted where it matters: The first finding's fix (staging made inert + filter-before-symlink-rejection, 2f9b01b) is unchanged. Thanks for the catch on the interaction — the follow-through order matters more than the excludes themselves. |

Problem
harbor.adapt()rejects Harbor tasks that Harbor itself accepts. Harbor'sArtifactConfig(harbor 0.20.0,harbor/models/task/config.py) has two fields the adapter'sArtifactmodel forbids:Any task directory using either field fails adaptation outright.
Fix
destination— accepted and preserved through the task args. No runtime behavior change: Harbor documents that verifier-side placement never depends ondestination(it only controls host placement under the trial's artifacts dir), and this runtime already re-mounts artifacts at their source path, which matches Harbor's verifier-side contract. Validation mirrors Harbor's: relative, forward slashes, no..,manifest.jsonreserved — so tasks Harbor would reject still fail adaptation loudly.exclude— implemented, not just accepted. Harbor applies these astar --excludeflags when downloading directory artifacts, so silently ignoring them would hand the verifier files Harbor's verifier never sees.env.pynow prunes matching entries after staging a directory artifact, following GNU tar exclusion semantics (unanchored: a pattern matches any run of trailing path components; a matched directory prunes its subtree).Artifact
sourceintentionally still requires an absolute path: this runtime mounts artifacts back at their source path for the verifier, which needs an absolute anchor. Harbor itself requires absolute sources for sidecar services; relative sources for the main container are a separate discussion.Testing
uv run pytest hud/integrations/harbor/tests/test_contract.py hud/integrations/harbor/tests/test_harbor.py— 67 passed (new: destination/exclude round-trip into task args; Harbor-invalid destinations fail adaptation)uv run pytest -m integration -k "artifact or restores_image_paths or excluded_entries"— 5 passed, including a new end-to-end test: a directory artifact withexclude = ["*.tmp", "cache"]is staged for a separate verifier without the excluded entries (nested matches included), reward 1.0ruff format --check,ruff check,ty check— cleanThe exclusion matcher follows GNU tar's documented
--excludebehavior (unanchored glob over component boundaries + subtree pruning); byte-for-byte parity with every tar edge case is not claimed.Note
Medium Risk
Changes artifact staging and symlink handling in the verifier collect path; incorrect exclude semantics could hide or leak files to graders, but scope is limited to Harbor integration.
Overview
Harbor tasks that declare
destinationorexcludeon artifacts no longer failharbor.adapt(); those fields are modeled onArtifactwith Harbor-aligned validation (relativedestination, no.., reservedmanifest.json).At collect time, directory artifacts are staged with
copytree(..., symlinks=True), thenexcludepatterns prune matching paths via newprune_excluded(GNU tar–style unanchored globs and subtree removal). Symlink checks still reject symlink roots and any symlinks left in the staged tree after pruning.Contract and Docker integration tests cover round-trip args, invalid destinations, sidecar symlink roots, and end-to-end grading when
excludedrops*.tmpandcachefrom verifier-visible artifacts.Reviewed by Cursor Bugbot for commit a537e06. Bugbot is set up for automated code reviews on this repo. Configure here.