Skip to content

fix(agent-challenge): resolve TB digest manifest in installed wheel - #58

Merged
echobt merged 3 commits into
mainfrom
fix/tb-digest-manifest-resolution
Jul 29, 2026
Merged

fix(agent-challenge): resolve TB digest manifest in installed wheel#58
echobt merged 3 commits into
mainfrom
fix/tb-digest-manifest-resolution

Conversation

@echobt

@echobtechobt commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Every Terminal-Bench trial was failing instantly at failure_stage: job with TaskDefNotFoundError: digest manifest missing: /usr/local/lib/python3.12/golden/dataset-digest.json (reason_code=terminal_bench_failed).
  • The miner's agent never loaded, so every submission scored 0/30 regardless of quality (confirmed on two independent hotkeys).
  • This PR closes the three compounding defects that caused the miss so TB trials can resolve the digest manifest from an installed wheel and pass cache paths into the own-runner subprocess.

Symptom

TaskDefNotFoundError: digest manifest missing: /usr/local/lib/python3.12/golden/dataset-digest.json
reason_code=terminal_bench_failed
failure_stage: job

Production path never reached agent load; score was always 0/30.

Root cause (three defects)

  1. CLI parity gapterminal_bench.own_runner_command_args did not pass --cache-root / --digest-manifest, while the equivalent builder in runner.py (~L1964–1967) already did. The production TB attempt path uses the former.
  2. Layout-unsafe default_resolve_manifest_path fell back to Path(__file__).resolve().parents[3] / "golden" / "dataset-digest.json", correct only for the src/ checkout layout; in an installed wheel it overshoots into site-packages' grandparent (/usr/local/lib/python3.12/golden/...).
  3. Missing package datagolden/dataset-digest.json was never shipped as wheel package data.

Why flags matter: pydantic-settings reads embed.env into the settings object but does not export to os.environ, so the spawned runner subprocess never inherited the correct paths. Passing them explicitly as CLI flags is the durable bridge.

Changes

  • own_runner_command_args: forward --cache-root and --digest-manifest (parity with runner.py).
  • _resolve_manifest_path: layout-safe default that works for both checkout and installed wheel.
  • pyproject.toml: ship golden/dataset-digest.json as package data so the wheel contains agent_challenge/golden/dataset-digest.json.
  • Tests covering flag emission and installed-layout / wheel resolution.

Test plan

  • Local: own_runner or terminal_bench selection — 672 passed / 3 skipped
  • Local: ruff clean on touched packages
  • Local: wheel proven to contain agent_challenge/golden/dataset-digest.json
  • Local: installed-venv default resolution proven
  • CI: required checks green on this head SHA

Prod mitigation note

A temporary symlink mitigation is currently live in production and will be removed after this deploys. This PR is the durable fix; do not leave the symlink as the long-term path.

CI

  • Waiting for required checks to go green on this head SHA.

Notes

  • Commits (do not rewrite): 6bfd68af, 98e55aeb
  • No deployment config / compose.env changes
  • Not merging from this PR flow — merge decision is manual

Summary by CodeRabbit

  • Bug Fixes

    • Improved how the digest manifest is located, working correctly in both installed (wheel) and source checkout layouts.
    • Kept support for explicitly provided and environment-specified digest manifest paths.
    • Runner commands now correctly include configured cache and digest manifest settings.
  • Reliability

    • Ensured the dataset digest manifest is bundled into built packages and included in Docker images for consistent evaluation runs.
  • Tests

    • Added coverage to prevent regressions in manifest resolution and runner argument wiring.

echobt added 2 commits July 29, 2026 06:30
In-process terminal_bench own_runner argv omitted --cache-root and
--digest-manifest that runner.py already wires. pydantic-settings does
not export CHALLENGE_* into the subprocess env, so production trials
fell back to broken defaults. Mirror runner.py before the optional
--model block.
…default
parents[3] only worked in the src checkout; installed wheels overshot into
site-packages' grandparent and lacked dataset-digest.json. force-include the
golden file and resolve via importlib.resources plus an ancestor walk.
@coderabbitai

coderabbitaiBot commented Jul 29, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The change packages dataset-digest.json, resolves it across installed and source layouts, forwards cache and digest-manifest settings to the runner command, and adds regression tests for precedence, packaging, path resolution, and overrides.

Changes

Digest manifest integration

Layer / File(s)Summary
Package and resolve digest manifest
packages/challenges/agent-challenge/pyproject.toml, packages/challenges/agent-challenge/Dockerfile, packages/challenges/agent-challenge/src/agent_challenge/evaluation/own_runner_backend.py, packages/challenges/agent-challenge/tests/test_digest_manifest_resolution.py
The wheel and Docker stages include dataset-digest.json; runtime resolution prefers packaged resources and preserves explicit, environment, and source-checkout fallbacks. Tests cover precedence, installed layouts, wheel contents, and Docker build ordering.
Wire runner paths into command arguments
packages/challenges/agent-challenge/src/agent_challenge/evaluation/terminal_bench.py, packages/challenges/agent-challenge/tests/test_evaluation.py
own_runner_command_args emits configured --cache-root and --digest-manifest values, with tests covering defaults and overrides.

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

Sequence Diagram(s)

sequenceDiagram
participant terminal_bench_settings
participant own_runner_command_args
participant own_runner_backend
participant importlib_resources
terminal_bench_settings->>own_runner_command_args: provide cache and manifest settings
own_runner_command_args->>own_runner_backend: pass --cache-root and --digest-manifest
own_runner_backend->>importlib_resources: resolve agent_challenge.golden resource
importlib_resources-->>own_runner_backend: return packaged or source-checkout manifest path
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title is concise and accurately summarizes the main fix: resolving the digest manifest from an installed wheel.
Docstring Coverage✅ PassedNo functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck 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 fix/tb-digest-manifest-resolution

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
packages/challenges/agent-challenge/tests/test_digest_manifest_resolution.py (1)

64-110: 🎯 Functional Correctness | 🔵 Trivial | 🏗️ Heavy lift

Exercise resolution from an installed wheel.

These tests inspect the wheel and resolve from the source checkout, but never execute _resolve_manifest_path(None) from an installed wheel. A parents[3] regression inside _default_digest_manifest_path() would still pass here and fail in site-packages. Build the wheel, install it into an isolated interpreter, clear the environment override, and assert the resolved path exists.

Also applies to: 113-169

🤖 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/challenges/agent-challenge/tests/test_digest_manifest_resolution.py`
around lines 64 - 110, The tests only validate default manifest resolution from
the source checkout, so a fixed parents[3] regression could still break
installed wheels. Extend the installed-wheel test coverage around
_resolve_manifest_path and _default_digest_manifest_path by building the wheel,
installing it into an isolated interpreter, clearing DIGEST_MANIFEST_ENV, and
asserting the resolved path exists and is dataset-digest.json.
🤖 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
`@packages/challenges/agent-challenge/tests/test_digest_manifest_resolution.py`:
- Around line 64-110: The tests only validate default manifest resolution from
the source checkout, so a fixed parents[3] regression could still break
installed wheels. Extend the installed-wheel test coverage around
_resolve_manifest_path and _default_digest_manifest_path by building the wheel,
installing it into an isolated interpreter, clearing DIGEST_MANIFEST_ENV, and
asserting the resolved path exists and is dataset-digest.json.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7995c940-7e42-45e2-8627-9dd46b16ec41

📥 Commits

Reviewing files that changed from the base of the PR and between fe12506 and 98e55ae.

📒 Files selected for processing (5)
  • packages/challenges/agent-challenge/pyproject.toml
  • packages/challenges/agent-challenge/src/agent_challenge/evaluation/own_runner_backend.py
  • packages/challenges/agent-challenge/src/agent_challenge/evaluation/terminal_bench.py
  • packages/challenges/agent-challenge/tests/test_digest_manifest_resolution.py
  • packages/challenges/agent-challenge/tests/test_evaluation.py

hatch force-include needs golden/dataset-digest.json at /app during
pip install; both runtime and terminal-bench-runner stages now COPY it
before install so CI image builds stop failing FileNotFoundError.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 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
`@packages/challenges/agent-challenge/tests/test_digest_manifest_resolution.py`:
- Around line 181-212: The test around the digest manifest must validate
packaging configuration and Docker stages precisely. Parse pyproject.toml and
assert golden/dataset-digest.json is a key in Hatch’s wheel force-include
mapping, then split the Dockerfile at the runtime and terminal-bench-runner
stage declarations and require each stage to contain its own COPY
golden/dataset-digest.json before that stage’s RUN pip install --no-cache-dir .;
remove the global count and cross-stage ordering checks.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0250c24f-44e1-43ff-85c1-ad2bfb97f002

📥 Commits

Reviewing files that changed from the base of the PR and between 98e55ae and 0e4493a.

📒 Files selected for processing (2)
  • packages/challenges/agent-challenge/Dockerfile
  • packages/challenges/agent-challenge/tests/test_digest_manifest_resolution.py

Comment on lines +181 to +212
dockerfile = (_PKG_ROOT / "Dockerfile").read_text(encoding="utf-8")
pyproject = (_PKG_ROOT / "pyproject.toml").read_text(encoding="utf-8")
assert '"golden/dataset-digest.json"' in pyproject or (
"golden/dataset-digest.json" in pyproject
), "pyproject must force-include golden/dataset-digest.json"
# Exact path used by hatch force-include source key.
copy_line = "COPY golden/dataset-digest.json"
assert copy_line in dockerfile, (
"Dockerfile must COPY golden/dataset-digest.json so hatch force-include "
"finds /app/golden/dataset-digest.json during pip install ."
)
assert dockerfile.count(copy_line) >= 2, (
"both runtime and terminal-bench-runner stages need the golden COPY "
f"(found {dockerfile.count(copy_line)})"
)
# Each pip install of the package must be preceded by the golden COPY in-file order.
install_marker = "RUN pip install --no-cache-dir ."
positions = []
start = 0
while True:
idx = dockerfile.find(install_marker, start)
if idx < 0:
break
positions.append(idx)
start = idx + len(install_marker)
assert positions, "expected at least one package pip install in Dockerfile"
for idx in positions:
preceding = dockerfile[:idx]
assert copy_line in preceding, (
"COPY golden/dataset-digest.json must appear before each "
"RUN pip install --no-cache-dir ."
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Make the packaging regression assertions stage-aware.

Both COPY lines could be placed in runtime while terminal-bench-runner has none: the global count and “any preceding COPY” checks would still pass. Also parse pyproject.toml and assert the entry is in Hatch’s wheel force-include mapping, rather than accepting the path anywhere in the file. Split the Dockerfile into the two named stages and require the COPY before pip install . within each stage.

🧰 Tools
🪛 ast-grep (0.45.0)

[warning] 200-200: XPath query is request-/variable-derived; use parameterized XPath to prevent injection.
Context: dockerfile.find(install_marker, start)
Note: [CWE-643] Improper Neutralization of Data within XPath Expressions ('XPath Injection').

(xpath-injection-python)

🤖 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/challenges/agent-challenge/tests/test_digest_manifest_resolution.py`
around lines 181 - 212, The test around the digest manifest must validate
packaging configuration and Docker stages precisely. Parse pyproject.toml and
assert golden/dataset-digest.json is a key in Hatch’s wheel force-include
mapping, then split the Dockerfile at the runtime and terminal-bench-runner
stage declarations and require each stage to contain its own COPY
golden/dataset-digest.json before that stage’s RUN pip install --no-cache-dir .;
remove the global count and cross-stage ordering checks.

@echobt
echobt merged commit b1cec36 into mainJul 29, 2026
45 checks passed
Sign up for freeto 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.

1 participant

@echobt