0

InflateRust

Fresh

Implement a DEFLATE/gzip decompressor from scratch in Rust (std-only)

Type
RL Env
Runtime
ORS
License
unknown
Size
1 tasks
Published
Jun 2026
Updated
Nov 2026

Cite

Notes

Only stored in your browser.

InflateRust

A long-horizon OpenReward environment: the agent builds a multi-format (de)compression toolkit from scratch in Rust (/workspace) — a DEFLATE/gzip codec (decode + encode) plus a bzip2 decoder. Grading is server-side: the inflate-runner producer (in the sandbox) runs the built artifact and emits its raw behaviour, and the env server grades that against answers held off the agent-readable sandbox (only the conformance corpus INPUTS are baked into the sandbox image; the expected outputs live on the server image). Published as GeneralReasoning/InflateRust.

See DESIGN.md for the full design and build/PROTOCOL.md for the artifact invocation + grading contract.

What the agent builds

One binary (inflate) with five modes on stdin→stdout:

  • decode inflate (raw DEFLATE, RFC 1951) / gunzip (gzip, RFC 1952) / bunzip2 (bzip2 — a second algorithm: BWT⁻¹ + MTF + RLE + multi-table Huffman)
  • encode deflate (raw DEFLATE) / gzip (gzip member)

No (de)compression libraries — implemented by hand (std-only, network-blocked). Safe Rust only: every run_tests does a controlled clean build with -F unsafe_code, and rejects build scripts, proc-macros, native #[link] libraries, .cargo/ config, and binaries that can launch other programs (std::process). The sandbox image ships no Python or codec CLIs. Decoders must be strict (consume the whole input; reject trailing garbage) and graceful (reject corrupt input with a non-zero exit, never crash).

Grading (463 cases)

  • Decode — byte-exact: stdout compared to the reference output (stored hash-only, so no answer leaks). The negative + large fuzz tiers (hundreds of malformed streams) must be rejected cleanly — a crash/panic FAILS.
  • Encode — round-trip + ratio: the harness decompresses the artifact's output with reference zlib, checks it equals the original and that its size is within a per-case threshold. Ratio-dominated tiers (trivial output earns little): valid/shrink (token floor) → near (≤1.1× zlib-6) → zlib (≤ zlib-6) → z9 (≤ zlib-9) → zopfli (≤ optimal — the unbounded ceiling).
  • Multi-MB inputs under a ~10s/case timeout force an efficient implementation.

Reward

run_tests always grades the full corpus. Per-build delta: +1 per case the current build passes that the previous build did not, −1 per regression. It telescopes to the credited pass count of the build the agent finishes with. paths is a display filter only (it never changes the score). finished=True only when a single build passes every case at once.

Fresh-case cap. Each build also runs 12 newly generated, never-reused inputs per group (stored/fixed/dynamic/gzip/bzip2 decode, deflate/gzip encode). A tier is credited at most ⌈(fresh pass rate + 12.5%) × tier size⌉, so a lookup table of the public inputs earns almost nothing. A real decoder isn't capped. A near-zlib encoder's ratio tiers can move by about one case between builds (the reference: 430 in 15 of 16 identical builds, 429 once). Every case's result is written to /tmp/run_tests/last.tsv in the sandbox.

Reject credit. exit 1 passes all 188 fuzz/negative cases, so they are credited per decode mode (inflate, gunzip, bunzip2) in proportion to that mode's credited valid-stream pass rate: credited_reject_M = min(reject_passed_M, ceil(valid_rate_M × reject_total_M)). An always-reject binary scores 0, a decoder that fully handles a mode is credited all of that mode's reject cases, and a build that passes everything is credited everything. The valid rate is taken after the fresh-case cap, so baked valid passes don't unlock reject credit.

Layout

FileRole
inflaterust.pythe InflateRust(Environment) class, tools, reward, anti-cheat
server.pyServer([InflateRust]).run()
Dockerfilelightweight env-server image (built by OpenReward on repo push)
sandbox.Dockerfilesandbox image (toolchain + corpus + harness; no Python/codec tools); Docker Hub generalreasoning/inflaterust, pinned by tag
harness/the inflate-runner grading binary (Rust; flate2 round-trips encode output; detects crashes so fuzz requires clean rejection)
build/filter_corpus.pyself-generates the deterministic corpus + thresholds (seeded; zlib/gzip/bz2 + zopflipy oracles; no clone/network)
build/PROTOCOL.mdthe artifact invocation + grading contract
golden_tests.pyno-Docker invariant tests (telescoping, full-corpus scoring, anti-cheat)
test_agent.pyend-to-end smoke test against a running server
reference_solution/known-good toolkit (inflate + bzip2 decoder + LZ77/Huffman compressor; catch_unwind for fuzz-safety)

Develop / test

# No-Docker invariant tests:
uv run python -m pytest golden_tests.py -v

Deploy. The env-server rebuilds when this repo is pushed (OpenReward CI). The sandbox image is built + pushed to GHCR (:latest + immutable :sha-<gitsha>) by .github/workflows/build-sandbox.yml on a path-filtered push to main (touching sandbox.Dockerfile/harness//build/). SANDBOX_IMAGE in inflaterust.py is pinned to the :sha-<gitsha> tag — NOT :latest — because OpenReward's GHCR pull-through mirror caches :latest stale; bump the pin when the corpus/harness change.

Validation

Reference toolkit graded server-side (producer in the sandbox, grade_case on the host), full 463 corpus: 437/463 — all decode tiers 100% (incl. bzip2 59/59, gzip 59/59), fuzz 179/179 (clean rejection); the misses are the top encode-ratio tiers (zlib/z9/zopfli), the intended unbounded ceiling (matching/beating tuned/optimal zlib). An empty stub scores ~0. (Identical to the prior in-sandbox grade — the producer/grade split preserves grading exactly.)

History: v1 (decode-only) was solved 236/236 by a weak model; v2 (added encoder) held kimi to 228/239, stalling at the ratio ceiling; v3 (this version) adds the bzip2 decoder, the fuzz-robustness wall, the zopfli ceiling, and ratio-dominated encode — a genuinely harder multi-algorithm marathon. See reference_solution/README.md for details.