Skip to content

Commit bb3a194

Browse files
committed
Repair v34 managed Python stdlib aliases and isolate official grader setup
1 parent dfa05d1 commit bb3a194

11 files changed

Lines changed: 179 additions & 43 deletions

‎CAMPAIGN.md‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
# V100 campaign v33
1+
# V100 campaign v34
2+
3+
v34 addresses the follow-up deployment report: the sandbox exposes a managed Python runtime's complete standard library at its executable alias, not only `bin/`; official grader setup explicitly targets its own virtual environment for spaCy language-model installation. NLTK resources include stopwords and are verified locally during offline grading without a downloader/index request. Hardware acceptance retries strict helper preparation after the Windows startup opportunity, applies batch 16 and 15% request pacing only to a verified model, and preserves exact metadata differences if a semantic change is rejected. These repairs do not establish RTX reachability or hardware acceptance until the on-device checks run.
24

35
v33 repairs the deployment failures observed on Debian: systemd receives an unquoted absolute `WorkingDirectory` and validates the generated unit before starting it; the first supervisor start keeps the newly prepared configuration instead of reverting to an old failed run. NLTK downloads into an explicitly created, owner-private resource directory without disabling its security enforcement or changing the user's home permissions. Canonical helper migration checks the newly requested 32768 context and retains the old metadata snapshot; actual template, value or manifest changes still fail. Sandbox mounts include intermediate `uv` interpreter symlinks without exposing the whole project/home, and failed hardware probes preserve the full child diagnostic in `sandbox-probe.log`.
46

‎pyproject.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name = "rlms"
33
authors = [
44
{name = "Alex Zhang", email = "altzhang@mit.edu"},
55
]
6-
version = "0.1.3+v100.33"
6+
version = "0.1.3+v100.34"
77
description = "Recursive Language Models."
88
readme = "README.md"
99
license = "MIT"

‎rlm/v100/benchmark_worker.py‎

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@
77
import sys
88
from pathlib import Path
99

10+
NLTK_RESOURCES = {
11+
"punkt": "tokenizers/punkt",
12+
"punkt_tab": "tokenizers/punkt_tab",
13+
"averaged_perceptron_tagger_eng": "taggers/averaged_perceptron_tagger_eng",
14+
"stopwords": "corpora/stopwords",
15+
}
16+
1017

1118
def key(row):
1219
return "/".join(str(row[k]) for k in ("category", "task", "question_id"))
@@ -22,11 +29,25 @@ def prepare_nltk(folder):
2229
info = resources.lstat()
2330
if not stat.S_ISDIR(info.st_mode) or info.st_uid != os.geteuid() or info.st_mode & 0o022:
2431
raise ValueError("Official grader resources must use an owned private directory")
25-
for package in ("punkt", "punkt_tab", "averaged_perceptron_tagger_eng"):
32+
for package in NLTK_RESOURCES:
2633
if not nltk.download(package, download_dir=str(resources), quiet=True):
2734
raise RuntimeError("Official grader resource download failed: " + package)
2835

2936

37+
def offline_nltk():
38+
import nltk
39+
40+
def present(package, *args, **kwargs):
41+
# IFBench calls nltk.download('stopwords') even while grading. Check
42+
# the frozen local resource instead of fetching an index without network.
43+
if package not in NLTK_RESOURCES:
44+
raise ValueError("Unprepared official grader resource: " + str(package))
45+
nltk.data.find(NLTK_RESOURCES[package])
46+
return True
47+
48+
nltk.download = present
49+
50+
3051
def prepare(folder, limit, coding=False):
3152
from datasets import load_dataset
3253
from huggingface_hub import HfApi
@@ -114,6 +135,7 @@ def prepare(folder, limit, coding=False):
114135

115136

116137
def grade(request, output):
138+
offline_nltk()
117139
from livebench.common import MatchSingle
118140
from livebench.gen_ground_truth_judgment import play_a_match_gt
119141

‎rlm/v100/campaign.py‎

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,36 @@ def choose_profile(root: Path) -> Path:
6767
return max(candidates, key=lambda path: path.stat().st_mtime_ns)
6868

6969

70+
def configure_helper(root: Path) -> dict:
71+
from rlm.v100.competition import helper_client
72+
from rlm.v100.remote_helper import canonicalize_remote
73+
74+
evidence = canonicalize_remote(root, context_window=32768)
75+
helper_path = root / "research/researcher-rtx3090.json"
76+
selected = load_profile(helper_path, root)
77+
selected["runtime"]["context_window"] = 32768
78+
selected["server"]["context_per_slot"] = 32768
79+
selected["resources"].update(helper_batch_tokens=16, helper_duty_percent=15)
80+
client = helper_client(selected, root)
81+
client.identity()
82+
measured = client.loaded()
83+
atomic_json(
84+
helper_path.with_name(
85+
"researcher-rtx3090.before-campaign-" + str(time.time_ns()) + ".json"
86+
),
87+
json.loads(helper_path.read_text()),
88+
)
89+
atomic_json(helper_path, selected)
90+
return {
91+
**evidence,
92+
"context": 32768,
93+
"batch": 16,
94+
"active_request_target_percent": 15,
95+
"loaded": measured,
96+
"scope": "Helper request pacing; no hard GPU peak/power cap",
97+
}
98+
99+
70100
def prepare(
71101
root: Path,
72102
path: Path | None = None,
@@ -77,7 +107,6 @@ def prepare(
77107
from rlm.v100.mission import status
78108
from rlm.v100.public_benchmarks import current
79109
from rlm.v100.public_benchmarks import prepare as prepare_benchmarks
80-
from rlm.v100.remote_helper import canonicalize_remote
81110
from rlm.v100.self_code import prepare as prepare_code
82111

83112
if status(root)["running"]:
@@ -103,34 +132,7 @@ def stage(name, function):
103132
atomic_json(folder / "stages.json", stages)
104133
print(json.dumps({"campaign": name, **stages[name]}), flush=True)
105134

106-
def helper():
107-
evidence = canonicalize_remote(root, context_window=32768)
108-
from rlm.v100.competition import helper_client
109-
110-
helper_path = root / "research/researcher-rtx3090.json"
111-
selected = load_profile(helper_path, root)
112-
selected["runtime"]["context_window"] = 32768
113-
selected["server"]["context_per_slot"] = 32768
114-
selected["resources"].update(helper_batch_tokens=16, helper_duty_percent=15)
115-
client = helper_client(selected, root)
116-
client.identity()
117-
client.loaded()
118-
atomic_json(
119-
helper_path.with_name(
120-
"researcher-rtx3090.before-campaign-" + str(time.time_ns()) + ".json"
121-
),
122-
json.loads(helper_path.read_text()),
123-
)
124-
atomic_json(helper_path, selected)
125-
return {
126-
**evidence,
127-
"context": 32768,
128-
"batch": 16,
129-
"active_request_target_percent": 15,
130-
"scope": "Helper request pacing; no hard GPU peak/power cap",
131-
}
132-
133-
stage("helper-identity", helper)
135+
stage("helper-identity", lambda: configure_helper(root))
134136
stage("own-source-and-cpu-sandbox", lambda: prepare_code(root))
135137
if benchmarks:
136138
stage("official-public-benchmarks", lambda: current(root) or prepare_benchmarks(root, 20))

‎rlm/v100/hardware_acceptance.py‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,11 @@ def master():
120120
check("private-code-sandbox", lambda: sandbox_probe(folder))
121121

122122
def rtx():
123-
path = root / "research/researcher-rtx3090.json"
124-
selected = load_profile(path, root)
125-
client = helper_client(selected, root)
126-
client.identity()
127-
return client.loaded()
123+
from rlm.v100.campaign import configure_helper
124+
125+
# Windows may finish loading after the first preparation attempt.
126+
# Retry the strict migration now, with the mission still stopped.
127+
return configure_helper(root)
128128

129129
check("rtx-helper-identity-and-loaded-model", rtx)
130130
if desktop:

‎rlm/v100/public_benchmarks.py‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import json
44
import math
5+
import os
56
import statistics
67
import subprocess
78
import sys
@@ -50,9 +51,12 @@ def prepare(root: Path, limit: int = 20, coding: bool = False) -> Path:
5051
check=True,
5152
)
5253
worker = Path(__file__).with_name("benchmark_worker.py")
54+
resources = folder / "nltk"
55+
resources.mkdir(mode=0o700)
5356
subprocess.run(
5457
[str(python), str(worker), "prepare", str(folder), str(limit)]
5558
+ (["--coding"] if coding else []),
59+
env=preparation_environment(environment, resources),
5660
check=True,
5761
)
5862
frozen = subprocess.check_output(
@@ -76,6 +80,18 @@ def prepare(root: Path, limit: int = 20, coding: bool = False) -> Path:
7680
return folder
7781

7882

83+
def preparation_environment(environment: Path, resources: Path | None = None) -> dict:
84+
# LiveBench imports IFBench, whose official spaCy grader downloads its
85+
# compatible language model if absent. uv must target this isolated venv.
86+
selected = dict(os.environ)
87+
selected["VIRTUAL_ENV"] = str(environment)
88+
selected["UV_PYTHON"] = str(environment / "bin/python")
89+
selected["PATH"] = str(environment / "bin") + os.pathsep + selected.get("PATH", "")
90+
if resources is not None:
91+
selected["NLTK_DATA"] = str(resources)
92+
return selected
93+
94+
7995
def current(root: Path) -> Path | None:
8096
path = root / "research/public-benchmarks/current.json"
8197
return Path(json.loads(path.read_text())["snapshot"]) if path.exists() else None

‎rlm/v100/remote_helper.py‎

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,20 @@ def canonicalize_remote(root: Path, context_window: int | None = None) -> dict:
569569
info = client.identity()
570570
client.loaded()
571571
if metadata_sha(info, ORDERED_METADATA) != metadata_sha(previous, ORDERED_METADATA):
572-
raise ValueError("Metadata changed beyond parameter order/date; inspect the exact diff")
572+
changed = [
573+
key
574+
for key in sorted(set(info) | set(previous))
575+
if key != "modified_at"
576+
and metadata_sha({key: info.get(key)}, ORDERED_METADATA)
577+
!= metadata_sha({key: previous.get(key)}, ORDERED_METADATA)
578+
]
579+
audit = root / "research/helper-metadata" / f"rejected-{time.time_ns()}"
580+
atomic_json(audit / "profile-before.json", original)
581+
atomic_json(audit / "show-before.json", previous)
582+
atomic_json(audit / "show-current.json", info)
583+
raise ValueError(
584+
f"Metadata changed beyond parameter order/date; fields={changed}; audit={audit}"
585+
)
573586
audit = root / "research/helper-metadata" / f"canonical-{time.time_ns()}"
574587
atomic_json(audit / "profile-before.json", original)
575588
atomic_json(audit / "show.json", info)

‎rlm/v100/sandbox_python.py‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,15 @@ def runtime_mounts(python: Path | None = None) -> list[Path]:
2424
seen.add(current)
2525
target = Path(os.readlink(current))
2626
current = Path(os.path.abspath(target if target.is_absolute() else current.parent / target))
27-
# Bind only the interpreter's bin directories, never the whole home or
28-
# project root just to resolve an intermediate train-venv Python link.
29-
prefixes.append(current.parent)
27+
# Intermediate venv links need only bin/. A distribution alias also
28+
# needs lib/ to discover encodings instead of its compiled /install path.
29+
# Neither case exposes the whole home or project root.
30+
runtime_alias = current.parent.parent
31+
prefixes.append(
32+
runtime_alias
33+
if runtime_alias.resolve() == Path(sys.base_prefix).resolve()
34+
else current.parent
35+
)
3036
if not current.is_file():
3137
raise ValueError("Sandbox interpreter symlink target is missing")
3238
return [path for path in dict.fromkeys(prefixes) if path.exists()]

‎tests/test_v100_deployment.py‎

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
code_lab,
1313
hardware_acceptance,
1414
mission,
15+
public_benchmarks,
1516
sandbox_python,
1617
supervisor,
1718
)
@@ -32,7 +33,7 @@ def download(package, download_dir, quiet):
3233

3334
monkeypatch.setitem(sys.modules, "nltk", SimpleNamespace(download=download))
3435
benchmark_worker.prepare_nltk(tmp_path)
35-
assert len(calls) == 3 and tmp_path.stat().st_mode & 0o777 == 0o775
36+
assert len(calls) == 4 and tmp_path.stat().st_mode & 0o777 == 0o775
3637

3738

3839
@pytest.mark.parametrize("unsafe", ["writable", "link"])
@@ -159,6 +160,62 @@ def test_uv_python_chain_mounts_intermediate_bin_without_exposing_project_root(t
159160
assert tmp_path not in mounts and tmp_path / "venvs" not in mounts
160161

161162

163+
def test_managed_python_runtime_alias_mounts_its_stdlib_not_just_bin(tmp_path, monkeypatch):
164+
distribution = tmp_path / "python/cpython-3.11.15-linux-x86_64-gnu"
165+
alias = distribution.with_name("cpython-3.11-linux-x86_64-gnu")
166+
python = distribution / "bin/python3.11"
167+
python.parent.mkdir(parents=True)
168+
python.write_text("managed interpreter fixture")
169+
stdlib = distribution / "lib/python3.11/encodings"
170+
stdlib.mkdir(parents=True)
171+
(stdlib / "__init__.py").write_text("codec fixture")
172+
alias.symlink_to(distribution, target_is_directory=True)
173+
venv_python = tmp_path / "venvs/continual/bin/python"
174+
venv_python.parent.mkdir(parents=True)
175+
venv_python.symlink_to(alias / "bin/python3.11")
176+
monkeypatch.setattr(sandbox_python.sys, "base_prefix", str(distribution))
177+
mounts = sandbox_python.runtime_mounts(venv_python)
178+
assert alias in mounts and (alias / "lib/python3.11/encodings").is_dir()
179+
assert alias / "bin" not in mounts
180+
assert tmp_path not in mounts and distribution.parent not in mounts
181+
182+
183+
def test_official_grader_installation_targets_its_own_environment(tmp_path, monkeypatch):
184+
monkeypatch.setenv("VIRTUAL_ENV", "/wrong/train-venv")
185+
monkeypatch.setenv("UV_PYTHON", "/wrong/system-python")
186+
monkeypatch.setenv("PATH", "/usr/bin")
187+
environment = tmp_path / "venvs/official-benchmarks"
188+
selected = public_benchmarks.preparation_environment(environment)
189+
assert selected["VIRTUAL_ENV"] == str(environment)
190+
assert selected["UV_PYTHON"] == str(environment / "bin/python")
191+
assert selected["PATH"] == str(environment / "bin") + ":/usr/bin"
192+
assert os.environ["VIRTUAL_ENV"] == "/wrong/train-venv"
193+
resources = tmp_path / "snapshot/nltk"
194+
assert public_benchmarks.preparation_environment(environment, resources)["NLTK_DATA"] == str(
195+
resources
196+
)
197+
198+
199+
def test_offline_grader_requires_actual_frozen_nltk_resources_without_network(monkeypatch):
200+
found = []
201+
202+
def find(path):
203+
found.append(path)
204+
if path == "tokenizers/punkt":
205+
raise LookupError("Missing frozen punkt")
206+
return path
207+
208+
nltk = SimpleNamespace(data=SimpleNamespace(find=find))
209+
monkeypatch.setitem(sys.modules, "nltk", nltk)
210+
benchmark_worker.offline_nltk()
211+
assert nltk.download("stopwords")
212+
assert found == ["corpora/stopwords"]
213+
with pytest.raises(LookupError, match="frozen punkt"):
214+
nltk.download("punkt")
215+
with pytest.raises(ValueError, match="Unprepared"):
216+
nltk.download("unapproved")
217+
218+
162219
def test_sandbox_probe_failure_preserves_actual_child_error_and_log(tmp_path, monkeypatch):
163220
monkeypatch.setattr(code_lab, "sandbox_command", lambda *args: ["isolated-fixture"])
164221

‎tests/test_v100_remote_helper.py‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,24 @@ def test_canonical_migration_still_rejects_semantic_changes_or_unloaded_model(tr
141141
assert path.read_bytes() == original
142142

143143

144+
def test_late_helper_preparation_applies_low_workload_only_after_verified_identity(
145+
transport, tmp_path
146+
):
147+
from rlm.v100.campaign import configure_helper
148+
149+
path, _ = prepared(tmp_path)
150+
result = configure_helper(tmp_path)
151+
actual = load_profile(path, tmp_path)
152+
assert actual["resources"]["helper_batch_tokens"] == 16
153+
assert actual["resources"]["helper_duty_percent"] == 15
154+
assert result["loaded"]["context_length"] == 32768
155+
transport[1]["info"]["template"] = "unauthorized template"
156+
previous = path.read_bytes()
157+
with pytest.raises(ValueError, match="metadata"):
158+
configure_helper(tmp_path)
159+
assert path.read_bytes() == previous
160+
161+
144162
def test_stable_metadata_ignores_only_date_and_keeps_legacy_semantics(transport):
145163
first = {**INFO, "modified_at": "before"}
146164
second = {**INFO, "modified_at": "after"}

0 commit comments

Comments
 (0)